-
Notifications
You must be signed in to change notification settings - Fork 70
fix(cicd,cmd,consensus/XDPoS,eth): fix fast sync #2272
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev-upgrade
Are you sure you want to change the base?
Changes from all commits
c0f15e9
23fcba6
cee5d89
3724c25
e6bd9b1
144522d
0283f08
7c90905
3493c0d
1d56bf3
fbd8f9f
ba6eb2d
e55af5f
1845dab
f499084
5b3204b
d403c2b
8f0705a
4025516
5349447
868149d
7b85d50
39d33bf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -179,6 +179,24 @@ var ( | |||||||||||||||||||||||||||||||||||||||||||||||||||||
| Value: ethconfig.Defaults.SyncMode.String(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Category: flags.EthCategory, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| FastSyncPivotNumberFlag = &cli.Uint64Flag{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Name: "fastsyncpivotnumber", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Usage: "Pivot block number for fast sync (0 = use default calculation)", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Value: 0, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Category: flags.EthCategory, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| FastSyncPivotHashFlag = &cli.StringFlag{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Name: "fastsyncpivothash", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Usage: "Pivot block hash for fast sync verification (hex string, must be set if fastsyncpivotnumber is set)", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Value: "", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Category: flags.EthCategory, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| FastSyncPivotRootFlag = &cli.StringFlag{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Name: "fastsyncpivotroot", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Usage: "State root of pivot block for fast sync state download (hex string, zero = use latest.Root)", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Value: "", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Category: flags.EthCategory, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| GCModeFlag = &cli.StringFlag{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Name: "gcmode", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Usage: `Blockchain garbage collection mode ("full", "archive")`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -1521,6 +1539,30 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||
| Fatalf("invalid --syncmode flag: %v", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pivotNumberSet := ctx.IsSet(FastSyncPivotNumberFlag.Name) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pivotHashSet := ctx.IsSet(FastSyncPivotHashFlag.Name) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pivotRootSet := ctx.IsSet(FastSyncPivotRootFlag.Name) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pivotHash := ctx.String(FastSyncPivotHashFlag.Name) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pivotRoot := ctx.String(FastSyncPivotRootFlag.Name) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if pivotNumberSet { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if !pivotHashSet || pivotHash == "" { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Fatalf("--%s must be set if --%s is set", FastSyncPivotHashFlag.Name, FastSyncPivotNumberFlag.Name) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if !pivotRootSet || pivotRoot == "" { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Fatalf("--%s must be set if --%s is set", FastSyncPivotRootFlag.Name, FastSyncPivotNumberFlag.Name) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cfg.FastSyncPivotNumber = ctx.Uint64(FastSyncPivotNumberFlag.Name) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1549
to
+1555
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if !pivotHashSet || pivotHash == "" { | |
| Fatalf("--%s must be set if --%s is set", FastSyncPivotHashFlag.Name, FastSyncPivotNumberFlag.Name) | |
| } | |
| if !pivotRootSet || pivotRoot == "" { | |
| Fatalf("--%s must be set if --%s is set", FastSyncPivotRootFlag.Name, FastSyncPivotNumberFlag.Name) | |
| } | |
| cfg.FastSyncPivotNumber = ctx.Uint64(FastSyncPivotNumberFlag.Name) | |
| pivotNumber := ctx.Uint64(FastSyncPivotNumberFlag.Name) | |
| if pivotNumber == 0 { | |
| Fatalf("--%s must be greater than 0 when explicitly set", FastSyncPivotNumberFlag.Name) | |
| } | |
| if !pivotHashSet || pivotHash == "" { | |
| Fatalf("--%s must be set if --%s is set", FastSyncPivotHashFlag.Name, FastSyncPivotNumberFlag.Name) | |
| } | |
| if !pivotRootSet || pivotRoot == "" { | |
| Fatalf("--%s must be set if --%s is set", FastSyncPivotRootFlag.Name, FastSyncPivotNumberFlag.Name) | |
| } | |
| cfg.FastSyncPivotNumber = pivotNumber |
Copilot
AI
Apr 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The pivot hash/root flags are parsed with common.HexToHash, which silently converts invalid hex strings into the zero hash (hex decoding errors are ignored in common.FromHex/Hex2Bytes). This can accidentally bypass pivot verification or state-root selection. Please validate the input as a 32-byte hex value (e.g., via hexutil.Decode/UnmarshalFixedText) and fail fast on parse/length errors; also reconcile the behavior/usage text that says the root can be zero with the current requirement that the flag must be non-empty.
| if !pivotHashSet || pivotHash == "" { | |
| Fatalf("--%s must be set if --%s is set", FastSyncPivotHashFlag.Name, FastSyncPivotNumberFlag.Name) | |
| } | |
| if !pivotRootSet || pivotRoot == "" { | |
| Fatalf("--%s must be set if --%s is set", FastSyncPivotRootFlag.Name, FastSyncPivotNumberFlag.Name) | |
| } | |
| cfg.FastSyncPivotNumber = ctx.Uint64(FastSyncPivotNumberFlag.Name) | |
| cfg.FastSyncPivotHash = common.HexToHash(pivotHash) | |
| cfg.FastSyncPivotRoot = common.HexToHash(pivotRoot) | |
| if !pivotHashSet { | |
| Fatalf("--%s must be set if --%s is set", FastSyncPivotHashFlag.Name, FastSyncPivotNumberFlag.Name) | |
| } | |
| if !pivotRootSet { | |
| Fatalf("--%s must be set if --%s is set", FastSyncPivotRootFlag.Name, FastSyncPivotNumberFlag.Name) | |
| } | |
| var parsedPivotHash common.Hash | |
| if err = parsedPivotHash.UnmarshalText([]byte(pivotHash)); err != nil { | |
| Fatalf("invalid --%s flag: %v", FastSyncPivotHashFlag.Name, err) | |
| } | |
| var parsedPivotRoot common.Hash | |
| if err = parsedPivotRoot.UnmarshalText([]byte(pivotRoot)); err != nil { | |
| Fatalf("invalid --%s flag: %v", FastSyncPivotRootFlag.Name, err) | |
| } | |
| cfg.FastSyncPivotNumber = ctx.Uint64(FastSyncPivotNumberFlag.Name) | |
| cfg.FastSyncPivotHash = parsedPivotHash | |
| cfg.FastSyncPivotRoot = parsedPivotRoot |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -243,32 +243,34 @@ func (x *XDPoS_v1) verifyCascadingFields(chain consensus.ChainReader, header *ty | |
| return x.verifySeal(chain, header, parents, fullVerify) | ||
| } | ||
|
|
||
| /* | ||
| BUG: snapshot returns wrong signers sometimes | ||
| when it happens we get the signers list by requesting smart contract | ||
| */ | ||
| // Retrieve the snapshot needed to verify this header and cache it | ||
| snap, err := x.snapshot(chain, number-1, header.ParentHash, parents, nil) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| if fullVerify { | ||
| /* | ||
| BUG: snapshot returns wrong signers sometimes | ||
| when it happens we get the signers list by requesting smart contract | ||
| */ | ||
| // Retrieve the snapshot needed to verify this header and cache it | ||
| snap, err := x.snapshot(chain, number-1, header.ParentHash, parents, nil) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| signers := snap.GetSigners() | ||
| err = x.checkSignersOnCheckpoint(chain, header, signers) | ||
| if err == nil { | ||
| return x.verifySeal(chain, header, parents, fullVerify) | ||
| } | ||
| signers := snap.GetSigners() | ||
| err = x.checkSignersOnCheckpoint(chain, header, signers) | ||
| if err == nil { | ||
| return x.verifySeal(chain, header, parents, fullVerify) | ||
| } | ||
|
|
||
| signers, err = x.getSignersFromContract(chain, header) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| err = x.checkSignersOnCheckpoint(chain, header, signers) | ||
| if err == nil { | ||
| return x.verifySeal(chain, header, parents, fullVerify) | ||
| signers, err = x.getSignersFromContract(chain, header) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| err = x.checkSignersOnCheckpoint(chain, header, signers) | ||
| if err == nil { | ||
| return x.verifySeal(chain, header, parents, fullVerify) | ||
| } | ||
| } | ||
|
|
||
| return err | ||
| return x.verifySeal(chain, header, parents, fullVerify) | ||
| } | ||
|
Comment on lines
+246
to
274
|
||
|
|
||
| func (x *XDPoS_v1) checkSignersOnCheckpoint(chain consensus.ChainReader, header *types.Header, signers []common.Address) error { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -134,33 +134,38 @@ func (x *XDPoS_v2) verifyHeader(chain consensus.ChainReader, header *types.Heade | |
| return utils.ErrInvalidCheckpointSigners | ||
| } | ||
|
|
||
| localMasterNodes, localPenalties, err := x.calcMasternodes(chain, header.Number, header.ParentHash, round) | ||
| masterNodes = localMasterNodes | ||
| if err != nil { | ||
| log.Error("[verifyHeader] Fail to calculate master nodes list with penalty", "Number", header.Number, "Hash", header.Hash()) | ||
| return err | ||
| } | ||
|
|
||
| validatorsAddress := common.ExtractAddressFromBytes(header.Validators) | ||
| if !utils.CompareSignersLists(localMasterNodes, validatorsAddress) { | ||
| for i, addr := range localMasterNodes { | ||
| log.Warn("[verifyHeader] localMasterNodes", "i", i, "addr", addr.Hex()) | ||
| // if fullVerify, verify masternodes and penalties; else use them inside header | ||
| if fullVerify { | ||
| localMasterNodes, localPenalties, err := x.calcMasternodes(chain, header.Number, header.ParentHash, round) | ||
| masterNodes = localMasterNodes | ||
| if err != nil { | ||
| log.Error("[verifyHeader] Fail to calculate master nodes list with penalty", "Number", header.Number, "Hash", header.Hash()) | ||
| return err | ||
| } | ||
| for i, addr := range validatorsAddress { | ||
| log.Warn("[verifyHeader] validatorsAddress", "i", i, "addr", addr.Hex()) | ||
| } | ||
| return utils.ErrValidatorsNotLegit | ||
| } | ||
|
|
||
| penaltiesAddress := common.ExtractAddressFromBytes(header.Penalties) | ||
| if !utils.CompareSignersLists(localPenalties, penaltiesAddress) { | ||
| for i, addr := range localPenalties { | ||
| log.Warn("[verifyHeader] localPenalties", "i", i, "addr", addr.Hex()) | ||
| validatorsAddress := common.ExtractAddressFromBytes(header.Validators) | ||
| if !utils.CompareSignersLists(localMasterNodes, validatorsAddress) { | ||
| for i, addr := range localMasterNodes { | ||
| log.Warn("[verifyHeader] localMasterNodes", "i", i, "addr", addr.Hex()) | ||
| } | ||
| for i, addr := range validatorsAddress { | ||
| log.Warn("[verifyHeader] validatorsAddress", "i", i, "addr", addr.Hex()) | ||
| } | ||
| return utils.ErrValidatorsNotLegit | ||
| } | ||
| for i, addr := range penaltiesAddress { | ||
| log.Warn("[verifyHeader] penaltiesAddress", "i", i, "addr", addr.Hex()) | ||
|
|
||
| penaltiesAddress := common.ExtractAddressFromBytes(header.Penalties) | ||
| if !utils.CompareSignersLists(localPenalties, penaltiesAddress) { | ||
| for i, addr := range localPenalties { | ||
| log.Warn("[verifyHeader] localPenalties", "i", i, "addr", addr.Hex()) | ||
| } | ||
| for i, addr := range penaltiesAddress { | ||
| log.Warn("[verifyHeader] penaltiesAddress", "i", i, "addr", addr.Hex()) | ||
| } | ||
| return utils.ErrPenaltiesNotLegit | ||
| } | ||
| return utils.ErrPenaltiesNotLegit | ||
| } else { | ||
| masterNodes = common.ExtractAddressFromBytes(header.Validators) | ||
| } | ||
|
Comment on lines
+137
to
169
|
||
| } else { | ||
| if len(header.Validators) != 0 { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need both 3 parameters to be presented together? If yes we need to check them togethere
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.