Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
c5c0950
feat: try to make full sync work. add log in syncState
wgr523 Jan 25, 2026
73e04a4
fix: when error getting snapshot, skip the error
wgr523 Feb 9, 2026
ae30326
feat(downloader): add configurable pivot block for fast sync
wgr523 Feb 27, 2026
446ba17
chore: add fast sync args into docker entry start.sh
wgr523 Feb 28, 2026
6cc2043
style: more log about pivot
wgr523 Feb 28, 2026
6aa00e2
feat: add FASTSYNC_PIVOT_ROOT, remove unnecessary verify
wgr523 Mar 1, 2026
2206e0f
feat: re-add verify header for block after pivot
wgr523 Mar 2, 2026
0e306cb
feat(downloader): sync multiple gap pivots during fast sync
wgr523 Mar 16, 2026
c48be7b
feat: move gap sync state after pivot sync state
wgr523 Mar 16, 2026
182db43
feat: let processHeader wiat for state sync
wgr523 Mar 17, 2026
c23c181
feat: add generateSnapshot in downloader for state sync
wgr523 Mar 18, 2026
fd6a008
feat: generate snapshot after state sync
wgr523 Mar 18, 2026
5158ac4
skip all header full verify during fast sync
wgr523 Mar 19, 2026
d8a9883
chore: add fastsync args to devnet start.sh
wgr523 Mar 20, 2026
52351b0
fix: statedb function, and better root choice in fast sync
wgr523 Mar 22, 2026
fdfeb9f
feat: when fullVerify=false, skip checkSignersOnCheckpoint
wgr523 Mar 29, 2026
16f35fd
fix: gen_config.go
wgr523 Mar 29, 2026
06dafce
style: clean code comment
wgr523 Apr 2, 2026
0f21ff8
feat: add fastsync args in start.sh
wgr523 Apr 3, 2026
1c1f905
Update cmd/utils/flags.go or better check on flags
wgr523 Apr 6, 2026
57ca2c9
fix: use xdc_sort; better flags
wgr523 Apr 6, 2026
be33591
test: add fast sync pivot gap tests
wgr523 Apr 6, 2026
47611b7
chore: require all three fastsync pivot params together in cicd start.sh
wgr523 Apr 19, 2026
4010320
feat: in fastsync make multiple headers feasible rather than one-by-one
wgr523 Apr 2, 2026
25123fa
fix: if configured pivot <= origin, start at origin. fix comment
wgr523 Apr 30, 2026
3bd1aca
fix: fix by PR comment
wgr523 May 27, 2026
a6da06f
fix: validate fastsync pivot flags strictly
wgr523 May 28, 2026
379902e
style: better v1 verifyheader style, better start.sh
wgr523 May 29, 2026
e468601
update log title
benjamin202410 May 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions cicd/devnet/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,24 @@ else
gc_mode=$GC_MODE
fi

fastsync_args=()
if test -n "$FASTSYNC_PIVOT_NUMBER" || test -n "$FASTSYNC_PIVOT_HASH" || test -n "$FASTSYNC_PIVOT_ROOT"
then
if test -z "$FASTSYNC_PIVOT_NUMBER" || test -z "$FASTSYNC_PIVOT_HASH" || test -z "$FASTSYNC_PIVOT_ROOT"
then
echo "Error: FASTSYNC_PIVOT_NUMBER, FASTSYNC_PIVOT_HASH, and FASTSYNC_PIVOT_ROOT must all be set together."
exit 1
fi
echo "FASTSYNC_PIVOT_NUMBER found, set to $FASTSYNC_PIVOT_NUMBER"
echo "FASTSYNC_PIVOT_HASH found, set to $FASTSYNC_PIVOT_HASH"
echo "FASTSYNC_PIVOT_ROOT found, set to $FASTSYNC_PIVOT_ROOT"
fastsync_args=(
--fastsyncpivotnumber "${FASTSYNC_PIVOT_NUMBER}"
--fastsyncpivothash "${FASTSYNC_PIVOT_HASH}"
--fastsyncpivotroot "${FASTSYNC_PIVOT_ROOT}"
)
fi

miner_gaslimit=50000000
if test -z "$MINER_GASLIMIT"
then
Expand Down Expand Up @@ -147,5 +165,6 @@ XDC ${config_arg} --ethstats ${netstats} \
--miner-gasprice "1" --miner-gaslimit "${miner_gaslimit}" --verbosity ${log_level} \
--debugdatadir /work/xdcchain \
--store-reward \
"${fastsync_args[@]}" \
--ws --ws-addr=0.0.0.0 --ws-port $ws_port \
--ws-origins "*" 2>&1 >>/work/xdcchain/xdc.log | tee -a /work/xdcchain/xdc.log
18 changes: 18 additions & 0 deletions cicd/local/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,23 @@ else
fi

netstats="${NODE_NAME}-${wallet}:$ethstats_secret@$ethstats_address"
fastsync_args=()
if test -n "$FASTSYNC_PIVOT_NUMBER" || test -n "$FASTSYNC_PIVOT_HASH" || test -n "$FASTSYNC_PIVOT_ROOT"
then
if test -z "$FASTSYNC_PIVOT_NUMBER" || test -z "$FASTSYNC_PIVOT_HASH" || test -z "$FASTSYNC_PIVOT_ROOT"
then
echo "Error: FASTSYNC_PIVOT_NUMBER, FASTSYNC_PIVOT_HASH, and FASTSYNC_PIVOT_ROOT must all be set together."
exit 1
fi
echo "FASTSYNC_PIVOT_NUMBER found, set to $FASTSYNC_PIVOT_NUMBER"
echo "FASTSYNC_PIVOT_HASH found, set to $FASTSYNC_PIVOT_HASH"
echo "FASTSYNC_PIVOT_ROOT found, set to $FASTSYNC_PIVOT_ROOT"
fastsync_args=(
--fastsyncpivotnumber "${FASTSYNC_PIVOT_NUMBER}"
--fastsyncpivothash "${FASTSYNC_PIVOT_HASH}"
--fastsyncpivotroot "${FASTSYNC_PIVOT_ROOT}"
)
fi

echo "Running a node with wallet: ${wallet} at IP: ${instance_ip}"
echo "Starting nodes with $bootnodes ..."
Expand All @@ -148,5 +165,6 @@ XDC \
--miner-gasprice "1" --miner-gaslimit "${miner_gaslimit}" --verbosity ${log_level} \
--debugdatadir /work/xdcchain \
--store-reward \
"${fastsync_args[@]}" \
--ws --ws-addr=0.0.0.0 --ws-port $ws_port \
--ws-origins "*" 2>&1 >>/work/xdcchain/xdc.log | tee -a /work/xdcchain/xdc.log
15 changes: 15 additions & 0 deletions cicd/mainnet/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,20 @@ fi

netstats="${NODE_NAME}-${wallet}:$ethstats_secret@$ethstats_address"

fastsync_args=""
if test -n "$FASTSYNC_PIVOT_NUMBER" || test -n "$FASTSYNC_PIVOT_HASH" || test -n "$FASTSYNC_PIVOT_ROOT"
then
if test -z "$FASTSYNC_PIVOT_NUMBER" || test -z "$FASTSYNC_PIVOT_HASH" || test -z "$FASTSYNC_PIVOT_ROOT"
then
echo "Error: FASTSYNC_PIVOT_NUMBER, FASTSYNC_PIVOT_HASH, and FASTSYNC_PIVOT_ROOT must all be set together."
exit 1
fi
echo "FASTSYNC_PIVOT_NUMBER found, set to $FASTSYNC_PIVOT_NUMBER"
echo "FASTSYNC_PIVOT_HASH found, set to $FASTSYNC_PIVOT_HASH"
echo "FASTSYNC_PIVOT_ROOT found, set to $FASTSYNC_PIVOT_ROOT"
fastsync_args="--fastsyncpivotnumber ${FASTSYNC_PIVOT_NUMBER} --fastsyncpivothash ${FASTSYNC_PIVOT_HASH} --fastsyncpivotroot ${FASTSYNC_PIVOT_ROOT}"
fi

INSTANCE_IP=$(curl https://checkip.amazonaws.com)

echo "Running a node with wallet: ${wallet} at IP: ${INSTANCE_IP}"
Expand All @@ -120,5 +134,6 @@ XDC --ethstats ${netstats} \
--miner-gasprice "1" --miner-gaslimit "420000000" --verbosity ${log_level} \
--debugdatadir /work/xdcchain \
--store-reward \
${fastsync_args} \
--ws --ws-addr=0.0.0.0 --ws-port $ws_port \
--ws-origins "*" 2>&1 >>/work/xdcchain/xdc.log | tee -a /work/xdcchain/xdc.log
15 changes: 15 additions & 0 deletions cicd/testnet/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,20 @@ fi

netstats="${NODE_NAME}-${wallet}:$ethstats_secret@$ethstats_address"

fastsync_args=""
if test -n "$FASTSYNC_PIVOT_NUMBER" || test -n "$FASTSYNC_PIVOT_HASH" || test -n "$FASTSYNC_PIVOT_ROOT"
then
if test -z "$FASTSYNC_PIVOT_NUMBER" || test -z "$FASTSYNC_PIVOT_HASH" || test -z "$FASTSYNC_PIVOT_ROOT"
then
echo "Error: FASTSYNC_PIVOT_NUMBER, FASTSYNC_PIVOT_HASH, and FASTSYNC_PIVOT_ROOT must all be set together."
exit 1
fi
echo "FASTSYNC_PIVOT_NUMBER found, set to $FASTSYNC_PIVOT_NUMBER"
echo "FASTSYNC_PIVOT_HASH found, set to $FASTSYNC_PIVOT_HASH"
echo "FASTSYNC_PIVOT_ROOT found, set to $FASTSYNC_PIVOT_ROOT"
fastsync_args="--fastsyncpivotnumber ${FASTSYNC_PIVOT_NUMBER} --fastsyncpivothash ${FASTSYNC_PIVOT_HASH} --fastsyncpivotroot ${FASTSYNC_PIVOT_ROOT}"
fi

INSTANCE_IP=$(curl https://checkip.amazonaws.com)


Expand All @@ -134,5 +148,6 @@ XDC --ethstats ${netstats} \
--miner-gasprice "1" --miner-gaslimit "420000000" --verbosity ${log_level} \
--debugdatadir /work/xdcchain \
--store-reward \
${fastsync_args} \
--ws --ws-addr=0.0.0.0 --ws-port $ws_port \
--ws-origins "*" 2>&1 >>/work/xdcchain/xdc.log | tee -a /work/xdcchain/xdc.log
3 changes: 3 additions & 0 deletions cmd/XDC/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ var (
utils.TxPoolGlobalQueueFlag,
utils.TxPoolLifetimeFlag,
utils.SyncModeFlag,
utils.FastSyncPivotNumberFlag,
utils.FastSyncPivotHashFlag,
utils.FastSyncPivotRootFlag,
utils.GCModeFlag,
// utils.LightServFlag, // deprecated
// utils.LightPeersFlag, // deprecated
Expand Down
49 changes: 49 additions & 0 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,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")`,
Expand Down Expand Up @@ -1528,6 +1546,37 @@ 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 thread
wgr523 marked this conversation as resolved.
if cfg.FastSyncPivotNumber == 0 {
Fatalf("--%s must be greater than 0 when explicitly set", FastSyncPivotNumberFlag.Name)
}
if err = cfg.FastSyncPivotHash.UnmarshalText([]byte(pivotHash)); err != nil {
Fatalf("invalid --%s flag: %v", FastSyncPivotHashFlag.Name, err)
}
if err = cfg.FastSyncPivotRoot.UnmarshalText([]byte(pivotRoot)); err != nil {
Fatalf("invalid --%s flag: %v", FastSyncPivotRootFlag.Name, err)
}
} else {
if pivotHashSet {
Fatalf("--%s must not be set without --%s", FastSyncPivotHashFlag.Name, FastSyncPivotNumberFlag.Name)
}
if pivotRootSet {
Fatalf("--%s must not be set without --%s", FastSyncPivotRootFlag.Name, FastSyncPivotNumberFlag.Name)
}
}

if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheDatabaseFlag.Name) {
cfg.DatabaseCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheDatabaseFlag.Name) / 100
Expand Down
50 changes: 28 additions & 22 deletions consensus/XDPoS/engines/engine_v1/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,32 +253,38 @@ 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
}

signers := snap.GetSigners()
err = x.checkSignersOnCheckpoint(chain, header, signers)
if err == nil {
return x.verifySeal(chain, header, parents, fullVerify)
}
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 {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

add error log

log.Error("[verifyCascadingFields] Fail to get snapshot", "number", number, "hash", header.ParentHash, "err", err)
return err
}

signers, err = x.getSignersFromContract(chain, header)
if err != nil {
return err
}
err = x.checkSignersOnCheckpoint(chain, header, signers)
if err == nil {
signers := snap.GetSigners()
err = x.checkSignersOnCheckpoint(chain, header, signers)
if err == nil {
return x.verifySeal(chain, header, parents, fullVerify)
}
Copy link
Copy Markdown
Collaborator

@benjamin202410 benjamin202410 May 29, 2026

Choose a reason for hiding this comment

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

add error log, you can put info or debug level since you already handled it

log.Debug("[verifyCascadingFields] checkSignersOnCheckpoint failed, fallback to smart contract check", "number", number, "err", err)
signers, err = x.getSignersFromContract(chain, header)
if err != nil {
log.Error("[verifyCascadingFields] Fail to get signers from smart contract", "number", number, "hash", header.Hash(), "err", err)
return err
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

add error log

}
err = x.checkSignersOnCheckpoint(chain, header, signers)
if err != nil {
log.Error("[verifyCascadingFields] checkSignersOnCheckpoint failed with signers from smart contract", "number", number, "hash", header.Hash(), "err", err)
return err
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

what if it is still err != nil?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

re-written

return x.verifySeal(chain, header, parents, fullVerify)
}

return err
return x.verifySeal(chain, header, parents, fullVerify)
}
Comment thread
wgr523 marked this conversation as resolved.

func (x *XDPoS_v1) checkSignersOnCheckpoint(chain consensus.ChainReader, header *types.Header, signers []common.Address) error {
Expand Down
23 changes: 14 additions & 9 deletions consensus/XDPoS/engines/engine_v2/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,9 +263,9 @@ func (x *XDPoS_v2) initial(chain consensus.ChainReader, header *types.Header) er
return fmt.Errorf("masternodes are empty v2 switch number: %d", x.config.V2.SwitchBlock.Uint64())
}

snap := newSnapshot(lastGapNum, lastGapHeader.Hash(), masternodes)
snap := NewSnapshot(lastGapNum, lastGapHeader.Hash(), masternodes)
x.snapshots.Add(snap.Hash, snap)
err = storeSnapshot(snap, x.db)
err = StoreSnapshot(snap, x.db)
if err != nil {
log.Error("[initial] Error while store snapshot", "error", err)
return err
Expand Down Expand Up @@ -603,11 +603,11 @@ func (x *XDPoS_v2) UpdateMasternodes(chain consensus.ChainReader, header *types.
}

x.lock.RLock()
snap := newSnapshot(number, header.Hash(), masterNodes)
snap := NewSnapshot(number, header.Hash(), masterNodes)
log.Info("[UpdateMasternodes] take snapshot", "number", number, "hash", header.Hash())
x.lock.RUnlock()

err := storeSnapshot(snap, x.db)
err := StoreSnapshot(snap, x.db)
if err != nil {
log.Error("[UpdateMasternodes] Error while store snapshot", "hash", header.Hash(), "currentRound", x.currentRound, "error", err)
return err
Expand Down Expand Up @@ -890,13 +890,18 @@ func (x *XDPoS_v2) VerifyBlockInfo(blockChainReader consensus.ChainReader, block
return nil
}

func (x *XDPoS_v2) verifyQC(blockChainReader consensus.ChainReader, quorumCert *types.QuorumCert, parentHeader *types.Header) error {
func (x *XDPoS_v2) verifyQC(blockChainReader consensus.ChainReader, quorumCert *types.QuorumCert, parents []*types.Header) error {
if quorumCert == nil {
log.Warn("[verifyQC] QC is Nil")
return utils.ErrInvalidQC
}

epochInfo, err := x.getEpochSwitchInfo(blockChainReader, parentHeader, quorumCert.ProposedBlockInfo.Hash)
// Find the parent header from the parents slice if available
var parentHeader *types.Header
if len(parents) != 0 {
parentHeader = parents[len(parents)-1]
}
epochInfo, err := x.getEpochSwitchInfo(blockChainReader, parents, quorumCert.ProposedBlockInfo.Hash)
if err != nil {
log.Error("[verifyQC] Error when getting epoch switch Info to verify QC", "Error", err)
return errors.New("fail to verify QC due to failure in getting epoch switch info")
Expand Down Expand Up @@ -1121,7 +1126,7 @@ func (x *XDPoS_v2) GetMasternodesFromEpochSwitchHeader(epochSwitchHeader *types.

// Given header, get master node from the epoch switch block of that epoch
func (x *XDPoS_v2) GetMasternodes(chain consensus.ChainReader, header *types.Header) []common.Address {
epochSwitchInfo, err := x.getEpochSwitchInfo(chain, header, header.Hash())
epochSwitchInfo, err := x.getEpochSwitchInfo(chain, []*types.Header{header}, header.Hash())
if err != nil {
log.Error("[GetMasternodes] Adaptor v2 getEpochSwitchInfo has error", "err", err)
return []common.Address{}
Expand All @@ -1131,7 +1136,7 @@ func (x *XDPoS_v2) GetMasternodes(chain consensus.ChainReader, header *types.Hea

// Given header, get master node from the epoch switch block of that epoch
func (x *XDPoS_v2) GetPenalties(chain consensus.ChainReader, header *types.Header) []common.Address {
epochSwitchInfo, err := x.getEpochSwitchInfo(chain, header, header.Hash())
epochSwitchInfo, err := x.getEpochSwitchInfo(chain, []*types.Header{header}, header.Hash())
if err != nil {
log.Error("[GetPenalties] Adaptor v2 getEpochSwitchInfo has error", "err", err)
return []common.Address{}
Expand All @@ -1140,7 +1145,7 @@ func (x *XDPoS_v2) GetPenalties(chain consensus.ChainReader, header *types.Heade
}

func (x *XDPoS_v2) GetStandbynodes(chain consensus.ChainReader, header *types.Header) []common.Address {
epochSwitchInfo, err := x.getEpochSwitchInfo(chain, header, header.Hash())
epochSwitchInfo, err := x.getEpochSwitchInfo(chain, []*types.Header{header}, header.Hash())
if err != nil {
log.Error("[GetStandbynodes] Adaptor v2 getEpochSwitchInfo has error", "err", err)
return []common.Address{}
Expand Down
Loading
Loading