From 2b3e059abfd62afb17f623b9c6867d938bbd7187 Mon Sep 17 00:00:00 2001 From: Liam Date: Tue, 4 Oct 2022 23:33:13 +0800 Subject: [PATCH] xin-244 re-snyc blocks from v1 to v2 (#186) * xin-244 re-snyc blocks from v1 to v2 * remove log * correct log * constant value * remove comment --- consensus/XDPoS/XDPoS.go | 58 ++++++++++--------- consensus/XDPoS/engines/engine_v2/engine.go | 2 +- .../XDPoS/engines/engine_v2/verifyHeader.go | 1 + consensus/XDPoS/utils/utils.go | 4 +- .../tests/engine_v2_tests/adaptor_test.go | 1 + .../engine_v2_tests/verify_header_test.go | 2 +- params/config.go | 14 +++-- 7 files changed, 45 insertions(+), 37 deletions(-) diff --git a/consensus/XDPoS/XDPoS.go b/consensus/XDPoS/XDPoS.go index 0805719da9..97b99bdb3f 100644 --- a/consensus/XDPoS/XDPoS.go +++ b/consensus/XDPoS/XDPoS.go @@ -36,8 +36,13 @@ import ( lru "github.com/hashicorp/golang-lru" ) +const ( + ExtraFieldCheck = false + SkipExtraFieldCheck = true +) + func (x *XDPoS) SigHash(header *types.Header) (hash common.Hash) { - switch x.config.BlockConsensusVersion(header.Number) { + switch x.config.BlockConsensusVersion(header.Number, header.Extra, ExtraFieldCheck) { case params.ConsensusEngineVersion2: return x.EngineV2.SignHash(header) default: // Default "v1" @@ -136,7 +141,7 @@ func NewFaker(db ethdb.Database, chainConfig *params.ChainConfig) *XDPoS { } func (x *XDPoS) Initial(chain consensus.ChainReader, header *types.Header) error { - switch x.config.BlockConsensusVersion(header.Number) { + switch x.config.BlockConsensusVersion(header.Number, header.Extra, ExtraFieldCheck) { case params.ConsensusEngineVersion2: return x.EngineV2.Initial(chain, header) default: // Default "v1" @@ -161,7 +166,7 @@ func (x *XDPoS) APIs(chain consensus.ChainReader) []rpc.API { // Author implements consensus.Engine, returning the Ethereum address recovered // from the signature in the header's extra-data section. func (x *XDPoS) Author(header *types.Header) (common.Address, error) { - switch x.config.BlockConsensusVersion(header.Number) { + switch x.config.BlockConsensusVersion(header.Number, header.Extra, ExtraFieldCheck) { case params.ConsensusEngineVersion2: return x.EngineV2.Author(header) default: // Default "v1" @@ -171,7 +176,7 @@ func (x *XDPoS) Author(header *types.Header) (common.Address, error) { // VerifyHeader checks whether a header conforms to the consensus rules. func (x *XDPoS) VerifyHeader(chain consensus.ChainReader, header *types.Header, fullVerify bool) error { - switch x.config.BlockConsensusVersion(header.Number) { + switch x.config.BlockConsensusVersion(header.Number, header.Extra, ExtraFieldCheck) { case params.ConsensusEngineVersion2: return x.EngineV2.VerifyHeader(chain, header, fullVerify) default: // Default "v1" @@ -191,7 +196,7 @@ func (x *XDPoS) VerifyHeaders(chain consensus.ChainReader, headers []*types.Head var v2headers []*types.Header for _, header := range headers { - switch x.config.BlockConsensusVersion(header.Number) { + switch x.config.BlockConsensusVersion(header.Number, header.Extra, ExtraFieldCheck) { case params.ConsensusEngineVersion2: v2headers = append(v2headers, header) default: // Default "v1" @@ -212,7 +217,7 @@ func (x *XDPoS) VerifyHeaders(chain consensus.ChainReader, headers []*types.Head // VerifyUncles implements consensus.Engine, always returning an error for any // uncles as this consensus mechanism doesn't permit uncles. func (x *XDPoS) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { - switch x.config.BlockConsensusVersion(block.Number()) { + switch x.config.BlockConsensusVersion(block.Number(), block.Extra(), ExtraFieldCheck) { case params.ConsensusEngineVersion2: return nil default: // Default "v1" @@ -223,7 +228,7 @@ func (x *XDPoS) VerifyUncles(chain consensus.ChainReader, block *types.Block) er // VerifySeal implements consensus.Engine, checking whether the signature contained // in the header satisfies the consensus protocol requirements. func (x *XDPoS) VerifySeal(chain consensus.ChainReader, header *types.Header) error { - switch x.config.BlockConsensusVersion(header.Number) { + switch x.config.BlockConsensusVersion(header.Number, header.Extra, ExtraFieldCheck) { case params.ConsensusEngineVersion2: return nil default: // Default "v1" @@ -234,7 +239,7 @@ func (x *XDPoS) VerifySeal(chain consensus.ChainReader, header *types.Header) er // Prepare implements consensus.Engine, preparing all the consensus fields of the // header for running the transactions on top. func (x *XDPoS) Prepare(chain consensus.ChainReader, header *types.Header) error { - switch x.config.BlockConsensusVersion(header.Number) { + switch x.config.BlockConsensusVersion(header.Number, nil, SkipExtraFieldCheck) { case params.ConsensusEngineVersion2: return x.EngineV2.Prepare(chain, header) default: // Default "v1" @@ -245,7 +250,7 @@ func (x *XDPoS) Prepare(chain consensus.ChainReader, header *types.Header) error // Finalize implements consensus.Engine, ensuring no uncles are set, nor block // rewards given, and returns the final block. func (x *XDPoS) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, parentState *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { - switch x.config.BlockConsensusVersion(header.Number) { + switch x.config.BlockConsensusVersion(header.Number, header.Extra, ExtraFieldCheck) { case params.ConsensusEngineVersion2: return x.EngineV2.Finalize(chain, header, state, parentState, txs, uncles, receipts) default: // Default "v1" @@ -256,7 +261,7 @@ func (x *XDPoS) Finalize(chain consensus.ChainReader, header *types.Header, stat // Seal implements consensus.Engine, attempting to create a sealed block using // the local signing credentials. func (x *XDPoS) Seal(chain consensus.ChainReader, block *types.Block, stop <-chan struct{}) (*types.Block, error) { - switch x.config.BlockConsensusVersion(block.Number()) { + switch x.config.BlockConsensusVersion(block.Number(), block.Extra(), ExtraFieldCheck) { case params.ConsensusEngineVersion2: return x.EngineV2.Seal(chain, block, stop) default: // Default "v1" @@ -268,7 +273,7 @@ func (x *XDPoS) Seal(chain consensus.ChainReader, block *types.Block, stop <-cha // that a new block should have based on the previous blocks in the chain and the // current signer. func (x *XDPoS) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int { - switch x.config.BlockConsensusVersion(parent.Number) { + switch x.config.BlockConsensusVersion(parent.Number, parent.Extra, ExtraFieldCheck) { case params.ConsensusEngineVersion2: return x.EngineV2.CalcDifficulty(chain, time, parent) default: // Default "v1" @@ -277,7 +282,7 @@ func (x *XDPoS) CalcDifficulty(chain consensus.ChainReader, time uint64, parent } func (x *XDPoS) HandleProposedBlock(chain consensus.ChainReader, header *types.Header) error { - switch x.config.BlockConsensusVersion(header.Number) { + switch x.config.BlockConsensusVersion(header.Number, header.Extra, ExtraFieldCheck) { case params.ConsensusEngineVersion2: return x.EngineV2.ProposedBlockHandler(chain, header) default: // Default "v1" @@ -302,7 +307,7 @@ func (x *XDPoS) GetPeriod() uint64 { } func (x *XDPoS) IsAuthorisedAddress(chain consensus.ChainReader, header *types.Header, address common.Address) bool { - switch x.config.BlockConsensusVersion(header.Number) { + switch x.config.BlockConsensusVersion(header.Number, header.Extra, ExtraFieldCheck) { case params.ConsensusEngineVersion2: return x.EngineV2.IsAuthorisedAddress(chain, header, address) default: // Default "v1" @@ -311,7 +316,7 @@ func (x *XDPoS) IsAuthorisedAddress(chain consensus.ChainReader, header *types.H } func (x *XDPoS) GetMasternodes(chain consensus.ChainReader, header *types.Header) []common.Address { - switch x.config.BlockConsensusVersion(header.Number) { + switch x.config.BlockConsensusVersion(header.Number, header.Extra, ExtraFieldCheck) { case params.ConsensusEngineVersion2: return x.EngineV2.GetMasternodes(chain, header) default: // Default "v1" @@ -325,7 +330,7 @@ func (x *XDPoS) GetMasternodesByNumber(chain consensus.ChainReader, blockNumber log.Error("[GetMasternodesByNumber] Unable to find block", "Num", blockNumber) return []common.Address{} } - switch x.config.BlockConsensusVersion(big.NewInt(int64(blockNumber))) { + switch x.config.BlockConsensusVersion(big.NewInt(int64(blockNumber)), blockHeader.Extra, ExtraFieldCheck) { case params.ConsensusEngineVersion2: return x.EngineV2.GetMasternodes(chain, blockHeader) default: // Default "v1" @@ -334,7 +339,7 @@ func (x *XDPoS) GetMasternodesByNumber(chain consensus.ChainReader, blockNumber } func (x *XDPoS) YourTurn(chain consensus.ChainReader, parent *types.Header, signer common.Address) (bool, error) { - switch x.config.BlockConsensusVersion(big.NewInt(parent.Number.Int64() + 1)) { + switch x.config.BlockConsensusVersion(big.NewInt(parent.Number.Int64()+1), nil, SkipExtraFieldCheck) { case params.ConsensusEngineVersion2: return x.EngineV2.YourTurn(chain, parent, signer) default: // Default "v1" @@ -343,7 +348,7 @@ func (x *XDPoS) YourTurn(chain consensus.ChainReader, parent *types.Header, sign } func (x *XDPoS) GetValidator(creator common.Address, chain consensus.ChainReader, header *types.Header) (common.Address, error) { - switch x.config.BlockConsensusVersion(header.Number) { + switch x.config.BlockConsensusVersion(header.Number, header.Extra, ExtraFieldCheck) { default: // Default "v1", v2 does not need this function return x.EngineV1.GetValidator(creator, chain, header) } @@ -351,7 +356,7 @@ func (x *XDPoS) GetValidator(creator common.Address, chain consensus.ChainReader func (x *XDPoS) UpdateMasternodes(chain consensus.ChainReader, header *types.Header, ms []utils.Masternode) error { // fmt.Println("UpdateMasternodes") - switch x.config.BlockConsensusVersion(header.Number) { + switch x.config.BlockConsensusVersion(header.Number, header.Extra, ExtraFieldCheck) { case params.ConsensusEngineVersion2: return x.EngineV2.UpdateMasternodes(chain, header, ms) default: // Default "v1" @@ -360,7 +365,7 @@ func (x *XDPoS) UpdateMasternodes(chain consensus.ChainReader, header *types.Hea } func (x *XDPoS) RecoverSigner(header *types.Header) (common.Address, error) { - switch x.config.BlockConsensusVersion(header.Number) { + switch x.config.BlockConsensusVersion(header.Number, header.Extra, ExtraFieldCheck) { case params.ConsensusEngineVersion2: return common.Address{}, nil default: // Default "v1" @@ -369,7 +374,7 @@ func (x *XDPoS) RecoverSigner(header *types.Header) (common.Address, error) { } func (x *XDPoS) RecoverValidator(header *types.Header) (common.Address, error) { - switch x.config.BlockConsensusVersion(header.Number) { + switch x.config.BlockConsensusVersion(header.Number, header.Extra, ExtraFieldCheck) { case params.ConsensusEngineVersion2: return common.Address{}, nil default: // Default "v1" @@ -379,7 +384,7 @@ func (x *XDPoS) RecoverValidator(header *types.Header) (common.Address, error) { // Get master nodes over extra data of previous checkpoint block. func (x *XDPoS) GetMasternodesFromCheckpointHeader(checkpointHeader *types.Header) []common.Address { - switch x.config.BlockConsensusVersion(checkpointHeader.Number) { + switch x.config.BlockConsensusVersion(checkpointHeader.Number, checkpointHeader.Extra, ExtraFieldCheck) { case params.ConsensusEngineVersion2: return x.EngineV2.GetMasternodesFromEpochSwitchHeader(checkpointHeader) default: // Default "v1" @@ -389,7 +394,7 @@ func (x *XDPoS) GetMasternodesFromCheckpointHeader(checkpointHeader *types.Heade // Check is epoch switch (checkpoint) block func (x *XDPoS) IsEpochSwitch(header *types.Header) (bool, uint64, error) { - switch x.config.BlockConsensusVersion(header.Number) { + switch x.config.BlockConsensusVersion(header.Number, header.Extra, ExtraFieldCheck) { case params.ConsensusEngineVersion2: return x.EngineV2.IsEpochSwitch(header) default: // Default "v1" @@ -398,7 +403,8 @@ func (x *XDPoS) IsEpochSwitch(header *types.Header) (bool, uint64, error) { } func (x *XDPoS) GetCurrentEpochSwitchBlock(chain consensus.ChainReader, blockNumber *big.Int) (uint64, uint64, error) { - switch x.config.BlockConsensusVersion(blockNumber) { + header := chain.GetHeaderByNumber(blockNumber.Uint64()) + switch x.config.BlockConsensusVersion(blockNumber, header.Extra, ExtraFieldCheck) { case params.ConsensusEngineVersion2: return x.EngineV2.GetCurrentEpochSwitchBlock(chain, blockNumber) default: // Default "v1" @@ -412,7 +418,7 @@ func (x *XDPoS) GetDb() ethdb.Database { } func (x *XDPoS) GetSnapshot(chain consensus.ChainReader, header *types.Header) (*utils.PublicApiSnapshot, error) { - switch x.config.BlockConsensusVersion(header.Number) { + switch x.config.BlockConsensusVersion(header.Number, header.Extra, ExtraFieldCheck) { case params.ConsensusEngineVersion2: sp, err := x.EngineV2.GetSnapshot(chain, header) return &utils.PublicApiSnapshot{ @@ -435,7 +441,7 @@ func (x *XDPoS) GetSnapshot(chain consensus.ChainReader, header *types.Header) ( } func (x *XDPoS) GetAuthorisedSignersFromSnapshot(chain consensus.ChainReader, header *types.Header) ([]common.Address, error) { - switch x.config.BlockConsensusVersion(header.Number) { + switch x.config.BlockConsensusVersion(header.Number, header.Extra, ExtraFieldCheck) { case params.ConsensusEngineVersion2: return []common.Address{}, nil default: // Default "v1" @@ -444,7 +450,7 @@ func (x *XDPoS) GetAuthorisedSignersFromSnapshot(chain consensus.ChainReader, he } func (x *XDPoS) FindParentBlockToAssign(chain consensus.ChainReader, currentBlock *types.Block) *types.Block { - switch x.config.BlockConsensusVersion(currentBlock.Number()) { + switch x.config.BlockConsensusVersion(currentBlock.Number(), currentBlock.Extra(), ExtraFieldCheck) { case params.ConsensusEngineVersion2: block := x.EngineV2.FindParentBlockToAssign(chain) if block == nil { diff --git a/consensus/XDPoS/engines/engine_v2/engine.go b/consensus/XDPoS/engines/engine_v2/engine.go index 530233349d..da52ae2604 100644 --- a/consensus/XDPoS/engines/engine_v2/engine.go +++ b/consensus/XDPoS/engines/engine_v2/engine.go @@ -902,7 +902,7 @@ func (x *XDPoS_v2) commitBlocks(blockChainReader consensus.ChainReader, proposed Hash: grandParentBlock.Hash(), Round: round, } - log.Info("Successfully committed block", "num", x.highestCommitBlock.Number, "round", x.highestCommitBlock.Round, "hash", x.highestCommitBlock.Hash) + log.Info("Successfully commit and confirm block from continuous 3 blocks", "num", x.highestCommitBlock.Number, "round", x.highestCommitBlock.Round, "hash", x.highestCommitBlock.Hash) // Perform forensics related operation headerQcToBeCommitted := []types.Header{*parentBlock, *proposedBlockHeader} go x.ForensicsProcessor.ForensicsMonitoring(blockChainReader, x, headerQcToBeCommitted, *incomingQc) diff --git a/consensus/XDPoS/engines/engine_v2/verifyHeader.go b/consensus/XDPoS/engines/engine_v2/verifyHeader.go index 8805f38105..f727e19808 100644 --- a/consensus/XDPoS/engines/engine_v2/verifyHeader.go +++ b/consensus/XDPoS/engines/engine_v2/verifyHeader.go @@ -65,6 +65,7 @@ func (x *XDPoS_v2) verifyHeader(chain consensus.ChainReader, header *types.Heade // Verify this is truely a v2 block first quorumCert, round, _, err := x.getExtraFields(header) if err != nil { + log.Warn("[verifyHeader] decode extra field error", "err", err) return utils.ErrInvalidV2Extra } if round <= quorumCert.ProposedBlockInfo.Round { diff --git a/consensus/XDPoS/utils/utils.go b/consensus/XDPoS/utils/utils.go index 8b4a5a6667..42c7fa8946 100644 --- a/consensus/XDPoS/utils/utils.go +++ b/consensus/XDPoS/utils/utils.go @@ -82,12 +82,10 @@ func DecodeBytesExtraFields(b []byte, val interface{}) error { return fmt.Errorf("extra field is 0 length") } switch b[0] { - case 1: - return fmt.Errorf("consensus version 1 is not applicable for decoding extra fields") case 2: return rlp.DecodeBytes(b[1:], val) default: - return fmt.Errorf("consensus version %d is not defined", b[0]) + return fmt.Errorf("consensus version %d is not defined, or this block is v1 block", b[0]) } } diff --git a/consensus/tests/engine_v2_tests/adaptor_test.go b/consensus/tests/engine_v2_tests/adaptor_test.go index 1c1649ccca..6eb2ff65e1 100644 --- a/consensus/tests/engine_v2_tests/adaptor_test.go +++ b/consensus/tests/engine_v2_tests/adaptor_test.go @@ -68,6 +68,7 @@ func TestAdaptorGetMasternodesFromCheckpointHeader(t *testing.T) { headerV2 := currentBlock.Header() headerV2.Number.Add(blockchain.Config().XDPoS.V2.SwitchBlock, big.NewInt(1)) headerV2.Validators = common.Hex2Bytes("0278c350152e15fa6ffc712a5a73d704ce73e2e103d9e17ae3ff2c6712e44e25b09ac5ee91f6c9ff065551f0dcac6f00cae11192d462db709be3758c") + headerV2.Extra = []byte{2} masternodesV2 := adaptor.GetMasternodesFromCheckpointHeader(headerV2) assert.True(t, reflect.DeepEqual(masternodesV1, masternodesV2), "GetMasternodesFromCheckpointHeader in adaptor for v1 v2 not equal", "v1", masternodesV1, "v2", masternodesV2) } diff --git a/consensus/tests/engine_v2_tests/verify_header_test.go b/consensus/tests/engine_v2_tests/verify_header_test.go index bdd5d8784f..e5e9236953 100644 --- a/consensus/tests/engine_v2_tests/verify_header_test.go +++ b/consensus/tests/engine_v2_tests/verify_header_test.go @@ -60,7 +60,7 @@ func TestShouldVerifyBlock(t *testing.T) { assert.Equal(t, consensus.ErrFutureBlock, err) invalidQcBlock := blockchain.GetBlockByNumber(902).Header() - invalidQcBlock.Extra = []byte{} + invalidQcBlock.Extra = []byte{2} err = adaptor.VerifyHeader(blockchain, invalidQcBlock, true) assert.Equal(t, utils.ErrInvalidV2Extra, err) diff --git a/params/config.go b/params/config.go index ae4133c5d0..3fd99ae176 100644 --- a/params/config.go +++ b/params/config.go @@ -55,7 +55,7 @@ var ( } DevnetXDPoSV2Config = &V2{ SwitchBlock: big.NewInt(7060500), - CertThreshold: 6, + CertThreshold: 4, TimeoutSyncThreshold: 5, TimeoutPeriod: 10, WaitPeriod: 5, @@ -256,12 +256,14 @@ func (c *XDPoSConfig) String() string { return "XDPoS" } -/** -ConsensusVersion will return the consensus version to use for the provided block number. The returned int represent its version -TODO: It's a dummy value for now until the 2.0 consensus engine is fully implemented. -*/ -func (c *XDPoSConfig) BlockConsensusVersion(num *big.Int) string { +func (c *XDPoSConfig) BlockConsensusVersion(num *big.Int, extraByte []byte, skipExtraCheck bool) string { if c.V2 != nil && c.V2.SwitchBlock != nil && num.Cmp(c.V2.SwitchBlock) > 0 { + if skipExtraCheck { + return ConsensusEngineVersion2 + } + if len(extraByte) == 0 || extraByte[0] != 2 { + return ConsensusEngineVersion1 + } return ConsensusEngineVersion2 } return ConsensusEngineVersion1