Skip to content

consensus/XDPoS: guard decodeMasternodesFromHeaderExtra against short extra - #2477

Open
SAY-5 wants to merge 5 commits into
XinFinOrg:dev-upgradefrom
SAY-5:fix-decode-masternodes-short-extra
Open

consensus/XDPoS: guard decodeMasternodesFromHeaderExtra against short extra#2477
SAY-5 wants to merge 5 commits into
XinFinOrg:dev-upgradefrom
SAY-5:fix-decode-masternodes-short-extra

Conversation

@SAY-5

@SAY-5 SAY-5 commented Jul 20, 2026

Copy link
Copy Markdown

Proposed changes

decodeMasternodesFromHeaderExtra in both engine_v1 and engine_v2 computes a slice length from header.Extra with no length precondition: make([]common.Address, (len(Extra)-ExtraVanity-ExtraSeal)/AddressLength). When len(Extra) <= 77 the length is negative and make panics with runtime: makeslice: len out of range. The v1 verifyHeader already validates this length before decoding, but the shared helper does not, so a short Extra reaching the helper crashes instead of returning no masternodes.

This adds the missing length guard to both engines: when Extra is shorter than ExtraVanity+ExtraSeal, the helper returns nil (no masternodes) rather than panicking. A well-formed Extra still decodes exactly as before. Fixes #2362.

Types of changes

What types of changes does your code introduce to XDC network?
Put an in the boxes that apply

  • build: Changes that affect the build system or external dependencies
  • ci: Changes to CI configuration files and scripts
  • chore: Changes that don't change source code or tests
  • docs: Documentation only changes
  • feat: A new feature
  • fix: A bug fix
  • perf: A code change that improves performance
  • refactor: A code change that neither fixes a bug nor adds a feature
  • revert: Revert something
  • style: Changes that do not affect the meaning of the code
  • test: Adding missing tests or correcting existing tests

Impacted Components

Which parts of the codebase does this PR touch?
Put an in the boxes that apply

  • Consensus
  • Account
  • Network
  • Geth
  • Smart Contract
  • External components
  • Not sure (Please specify below)

Checklist

Put an in the boxes once you have confirmed below actions (or provide reasons on not doing so) that

  • This PR has sufficient test coverage (unit/integration test) OR I have provided reason in the PR description for not having test coverage
  • Tested on a private network from the genesis block and monitored the chain operating correctly for multiple epochs.
  • Provide an end-to-end test plan in the PR description on how to manually test it on the devnet/testnet.
  • Tested the backwards compatibility.
  • Tested with XDC nodes running this version co-exist with those running the previous version.
  • Relevant documentation has been updated as part of this PR
  • N/A

Added engine_v1 unit tests covering a short Extra (no panic, returns nil) and a well-formed Extra (correct masternodes). Behavior is unchanged for valid inputs, so this is backwards compatible; the private-network / co-existence / docs items are N/A for a defensive nil guard on an internal decode helper.

Summary by CodeRabbit

  • Bug Fixes

    • Improved handling of malformed blockchain header data to prevent crashes when required metadata is missing or incomplete.
    • Preserved correct masternode address decoding for valid header data.
  • Tests

    • Added coverage for both incomplete and valid header metadata scenarios.

benjamin202410 and others added 3 commits June 9, 2026 16:54
2026 Summer Release v2.8.0 dev upgrade merge
… extra

Signed-off-by: Sai Asish Y <say.apm35@gmail.com>
@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5ada93ef-cb33-4b92-b219-6c6da9cf18af

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The XDPoS masternode decoder now handles short header Extra data safely in engine v1, uses a local Extra value in engine v2, and adds tests for short and valid payloads.

Changes

Masternode Extra decoding

Layer / File(s) Summary
Header Extra validation and decoding
consensus/XDPoS/engines/engine_v1/utils.go, consensus/XDPoS/engines/engine_v2/utils.go, consensus/XDPoS/engines/engine_v1/utils_test.go
Engine v1 validates the required vanity and seal prefix before allocating masternodes; engine v2 reuses a local Extra value; tests cover undersized and valid header payloads.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: gzliudan

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The diff matches #2362 by adding the missing length guard in both engines and adding tests for short and valid extras.
Out of Scope Changes check ✅ Passed The changes stay focused on the guard fix and related tests, with no unrelated scope creep apparent.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The title clearly states the main bug fix and matches the changed code and tests.
Description check ✅ Passed The description follows the template and covers changes, impact, checklist, and testing notes.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens XDPoS consensus header parsing by preventing a runtime panic in decodeMasternodesFromHeaderExtra when header.Extra is shorter than the required ExtraVanity + ExtraSeal prefix, in both engine v1 and engine v2.

Changes:

  • Add a length precondition in decodeMasternodesFromHeaderExtra (v1 + v2) to return nil instead of panicking on short Extra.
  • Refactor decoding to reuse a local extra slice variable for clarity.
  • Add unit tests in engine_v1 covering short-Extra (no panic, returns nil) and valid-Extra (decodes expected masternodes).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
consensus/XDPoS/engines/engine_v2/utils.go Add short-Extra guard to prevent makeslice panic when decoding masternodes at the v1→v2 switch block.
consensus/XDPoS/engines/engine_v1/utils.go Add the same short-Extra guard to prevent makeslice panic when decoding masternodes from checkpoint headers.
consensus/XDPoS/engines/engine_v1/utils_test.go Add tests for short and valid Extra decoding behavior in v1.

Comment on lines 75 to 83
func decodeMasternodesFromHeaderExtra(checkpointHeader *types.Header) []common.Address {
masternodes := make([]common.Address, (len(checkpointHeader.Extra)-utils.ExtraVanity-utils.ExtraSeal)/common.AddressLength)
extra := checkpointHeader.Extra
if len(extra) < utils.ExtraVanity+utils.ExtraSeal {
return nil
}
masternodes := make([]common.Address, (len(extra)-utils.ExtraVanity-utils.ExtraSeal)/common.AddressLength)
for i := 0; i < len(masternodes); i++ {
copy(masternodes[i][:], checkpointHeader.Extra[utils.ExtraVanity+i*common.AddressLength:])
copy(masternodes[i][:], extra[utils.ExtraVanity+i*common.AddressLength:])
}
@gzliudan

gzliudan commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

Good finding ! How about this version ?

func decodeMasternodesFromHeaderExtra(checkpointHeader *types.Header) []common.Address {
	extra := checkpointHeader.Extra
	minRequiredLen := ExtraVanity + ExtraSeal

	// Skip processing if extra length is below minimum threshold
	if len(extra) < minRequiredLen {
		return nil
	}

	// Simplify calculation with pre-defined minRequiredLen
	addressTotalPayloadLen := len(extra) - minRequiredLen

	// Verify total payload length is exactly aligned to single address size
	if addressTotalPayloadLen%common.AddressLength != 0 {
		return nil
	}

	masternodeCount := addressTotalPayloadLen / common.AddressLength
	masternodes := make([]common.Address, masternodeCount)

	// Use incremental offset to avoid repeated multiplication calculation
	srcOffset := ExtraVanity
	for i := range masternodes {
		copy(masternodes[i][:], extra[srcOffset:])
		srcOffset += common.AddressLength
	}

	return masternodes
}

@gzliudan
gzliudan changed the base branch from main to dev-upgrade July 21, 2026 11:49
@gzliudan
gzliudan changed the base branch from dev-upgrade to main July 21, 2026 11:49
@gzliudan

Copy link
Copy Markdown
Collaborator

please change merge target branch to dev-upgrade

@SAY-5
SAY-5 changed the base branch from main to dev-upgrade July 22, 2026 18:48
…FromHeaderExtra

Signed-off-by: Sai Asish Y <say.apm35@gmail.com>
@SAY-5

SAY-5 commented Jul 22, 2026

Copy link
Copy Markdown
Author

Adopted your version in 09a4e9f across both engine_v1 and engine_v2, including the payload-alignment check so a non-multiple-of-AddressLength extra returns nil rather than truncating. Also retargeted the PR to dev-upgrade. The short-extra and valid-extra tests still pass.

# Conflicts:
#	contracts/utils_test.go
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: add length guard to decodeMasternodesFromHeaderExtra (both engines) to match verifyHeader

5 participants