From d9c0ecba11503b9a35981b14cd880097825605a6 Mon Sep 17 00:00:00 2001 From: wanwiset25 Date: Wed, 26 Jun 2024 13:44:38 +0400 Subject: [PATCH] changes to support xdpos2 protocol from block 0 --- consensus/XDPoS/engines/engine_v2/engine.go | 13 +++++++++++- .../XDPoS/engines/engine_v2/epochSwitch.go | 20 +++++++++++++++++++ consensus/XDPoS/engines/engine_v2/snapshot.go | 4 ++++ consensus/XDPoS/engines/engine_v2/timeout.go | 8 ++++++++ consensus/XDPoS/engines/engine_v2/vote.go | 4 ++++ eth/hooks/engine_v2_hooks.go | 9 +++++++++ 6 files changed, 57 insertions(+), 1 deletion(-) diff --git a/consensus/XDPoS/engines/engine_v2/engine.go b/consensus/XDPoS/engines/engine_v2/engine.go index c2235f5d32a9..e819d75a9e88 100644 --- a/consensus/XDPoS/engines/engine_v2/engine.go +++ b/consensus/XDPoS/engines/engine_v2/engine.go @@ -188,7 +188,10 @@ func (x *XDPoS_v2) initial(chain consensus.ChainReader, header *types.Header) er Signatures: nil, GapNumber: header.Number.Uint64() - x.config.Gap, } - + // prevent overflow + if header.Number.Uint64() < x.config.Gap { + quorumCert.GapNumber = 0 + } // can not call processQC because round is equal to default x.currentRound = 1 x.highestQuorumCert = quorumCert @@ -207,6 +210,10 @@ func (x *XDPoS_v2) initial(chain consensus.ChainReader, header *types.Header) er // Initial first v2 snapshot lastGapNum := x.config.V2.SwitchBlock.Uint64() - x.config.Gap + // prevent overflow + if x.config.V2.SwitchBlock.Uint64() < x.config.Gap { + lastGapNum = 0 + } lastGapHeader := chain.GetHeaderByNumber(lastGapNum) snap, _ := loadSnapshot(x.db, lastGapHeader.Hash()) @@ -839,6 +846,10 @@ func (x *XDPoS_v2) verifyQC(blockChainReader consensus.ChainReader, quorumCert * } epochSwitchNumber := epochInfo.EpochSwitchBlockInfo.Number.Uint64() gapNumber := epochSwitchNumber - epochSwitchNumber%x.config.Epoch - x.config.Gap + // prevent overflow + if epochSwitchNumber-epochSwitchNumber%x.config.Epoch < x.config.Gap { + gapNumber = 0 + } if gapNumber != quorumCert.GapNumber { log.Error("[verifyQC] QC gap number mismatch", "epochSwitchNumber", epochSwitchNumber, "BlockNum", quorumCert.ProposedBlockInfo.Number, "BlockInfoHash", quorumCert.ProposedBlockInfo.Hash, "Gap", quorumCert.GapNumber, "GapShouldBe", gapNumber) return fmt.Errorf("gap number mismatch QC Gap %d, shouldBe %d", quorumCert.GapNumber, gapNumber) diff --git a/consensus/XDPoS/engines/engine_v2/epochSwitch.go b/consensus/XDPoS/engines/engine_v2/epochSwitch.go index 981c46ff9a06..092d847dd510 100644 --- a/consensus/XDPoS/engines/engine_v2/epochSwitch.go +++ b/consensus/XDPoS/engines/engine_v2/epochSwitch.go @@ -51,6 +51,26 @@ func (x *XDPoS_v2) getEpochSwitchInfo(chain consensus.ChainReader, header *types } if isEpochSwitch { log.Debug("[getEpochSwitchInfo] header is epoch switch", "hash", hash.Hex(), "number", h.Number.Uint64()) + if h.Number.Uint64() == 0 { + log.Warn("[getEpochSwitchInfo] block 0, init epoch differently") + // handle genesis block differently as follows + masternodes := common.ExtractAddressFromBytes(h.Extra[32 : len(h.Extra)-65]) + penalties := []common.Address{} + standbynodes := []common.Address{} + epochSwitchInfo := &types.EpochSwitchInfo{ + Penalties: penalties, + Standbynodes: standbynodes, + Masternodes: masternodes, + MasternodesLen: len(masternodes), + EpochSwitchBlockInfo: &types.BlockInfo{ + Hash: hash, + Number: h.Number, + Round: 0, + }, + } + x.epochSwitches.Add(hash, epochSwitchInfo) + return epochSwitchInfo, nil + } quorumCert, round, masternodes, err := x.getExtraFields(h) if err != nil { log.Error("[getEpochSwitchInfo] get extra field", "err", err, "number", h.Number.Uint64()) diff --git a/consensus/XDPoS/engines/engine_v2/snapshot.go b/consensus/XDPoS/engines/engine_v2/snapshot.go index ccae59841278..773f7727ac2f 100644 --- a/consensus/XDPoS/engines/engine_v2/snapshot.go +++ b/consensus/XDPoS/engines/engine_v2/snapshot.go @@ -78,6 +78,10 @@ func (x *XDPoS_v2) getSnapshot(chain consensus.ChainReader, number uint64, isGap gapBlockNum = number } else { gapBlockNum = number - number%x.config.Epoch - x.config.Gap + //prevent overflow + if number-number%x.config.Epoch < x.config.Gap { + gapBlockNum = 0 + } } gapBlockHash := chain.GetHeaderByNumber(gapBlockNum).Hash() diff --git a/consensus/XDPoS/engines/engine_v2/timeout.go b/consensus/XDPoS/engines/engine_v2/timeout.go index 2f077b2a0018..8fcf9d6b7bd3 100644 --- a/consensus/XDPoS/engines/engine_v2/timeout.go +++ b/consensus/XDPoS/engines/engine_v2/timeout.go @@ -195,6 +195,10 @@ func (x *XDPoS_v2) sendTimeout(chain consensus.ChainReader) error { // Notice this +1 is because we expect a block whos is the child of currentHeader currentNumber := currentBlockHeader.Number.Uint64() + 1 gapNumber = currentNumber - currentNumber%x.config.Epoch - x.config.Gap + // prevent overflow + if currentNumber-currentNumber%x.config.Epoch < x.config.Gap { + gapNumber = 0 + } log.Debug("[sendTimeout] is epoch switch when sending out timeout message", "currentNumber", currentNumber, "gapNumber", gapNumber) } else { epochSwitchInfo, err := x.getEpochSwitchInfo(chain, currentBlockHeader, currentBlockHeader.Hash()) @@ -203,6 +207,10 @@ func (x *XDPoS_v2) sendTimeout(chain consensus.ChainReader) error { return err } gapNumber = epochSwitchInfo.EpochSwitchBlockInfo.Number.Uint64() - epochSwitchInfo.EpochSwitchBlockInfo.Number.Uint64()%x.config.Epoch - x.config.Gap + // prevent overflow + if epochSwitchInfo.EpochSwitchBlockInfo.Number.Uint64()-epochSwitchInfo.EpochSwitchBlockInfo.Number.Uint64()%x.config.Epoch < x.config.Gap { + gapNumber = 0 + } log.Debug("[sendTimeout] non-epoch-switch block found its epoch block and calculated the gapNumber", "epochSwitchInfo.EpochSwitchBlockInfo.Number", epochSwitchInfo.EpochSwitchBlockInfo.Number.Uint64(), "gapNumber", gapNumber) } diff --git a/consensus/XDPoS/engines/engine_v2/vote.go b/consensus/XDPoS/engines/engine_v2/vote.go index de79585297af..957abe9182bf 100644 --- a/consensus/XDPoS/engines/engine_v2/vote.go +++ b/consensus/XDPoS/engines/engine_v2/vote.go @@ -30,6 +30,10 @@ func (x *XDPoS_v2) sendVote(chainReader consensus.ChainReader, blockInfo *types. } epochSwitchNumber := epochSwitchInfo.EpochSwitchBlockInfo.Number.Uint64() gapNumber := epochSwitchNumber - epochSwitchNumber%x.config.Epoch - x.config.Gap + // prevent overflow + if epochSwitchNumber-epochSwitchNumber%x.config.Epoch < x.config.Gap { + gapNumber = 0 + } signedHash, err := x.signSignature(types.VoteSigHash(&types.VoteForSign{ ProposedBlockInfo: blockInfo, GapNumber: gapNumber, diff --git a/eth/hooks/engine_v2_hooks.go b/eth/hooks/engine_v2_hooks.go index f356af27a74c..7882cbba3e4a 100644 --- a/eth/hooks/engine_v2_hooks.go +++ b/eth/hooks/engine_v2_hooks.go @@ -224,6 +224,11 @@ func GetSigningTxCount(c *XDPoS.XDPoS, chain consensus.ChainReader, header *type signers := make(map[common.Address]*contracts.RewardLog) mapBlkHash := map[uint64]common.Hash{} + // prevent overflow + if number == 0 { + return signers, nil + } + data := make(map[common.Hash][]common.Address) epochCount := 0 var masternodes []common.Address @@ -259,6 +264,10 @@ func GetSigningTxCount(c *XDPoS.XDPoS, chain consensus.ChainReader, header *type from := *tx.From() data[blkHash] = append(data[blkHash], from) } + // prevent overflow + if i == 0 { + return signers, nil + } } for i := startBlockNumber; i <= endBlockNumber; i++ {