move config into code (#54)

* move config into code

* set devnet switch block number very high

* increase timeout and certThreshold for devnet config

Co-authored-by: Jianrong <wjrjerome@gmail.com>
This commit is contained in:
Liam 2022-02-12 05:36:08 +03:00 committed by GitHub
parent 76724b06d7
commit 4424c7d01e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 58 additions and 47 deletions

View file

@ -65,22 +65,25 @@ type XDPoS struct {
// New creates a XDPoS delegated-proof-of-stake consensus engine with the initial
// signers set to the ones provided by the user.
func New(config *params.XDPoSConfig, db ethdb.Database) *XDPoS {
log.Info("[New] initial conensus engines")
// Set any missing consensus parameters to their defaults
conf := *config
if conf.Epoch == 0 {
conf.Epoch = utils.EpochLength
if config.Epoch == 0 {
config.Epoch = utils.EpochLength
}
// TODO: This shall be configurable or replaced
config.V2 = params.DevnetXDPoSV2Config
// Allocate the snapshot caches and create the engine
signingTxsCache, _ := lru.New(utils.BlockSignersCacheLimit)
return &XDPoS{
config: &conf,
config: config,
db: db,
signingTxsCache: signingTxsCache,
EngineV1: engine_v1.New(&conf, db),
EngineV2: engine_v2.New(&conf, db),
EngineV1: engine_v1.New(config, db),
EngineV2: engine_v2.New(config, db),
}
}
@ -300,8 +303,10 @@ func (x *XDPoS) GetMasternodesByNumber(chain consensus.ChainReader, blockNumber
}
func (x *XDPoS) YourTurn(chain consensus.ChainReader, parent *types.Header, signer common.Address) (bool, error) {
if parent.Number.Cmp(x.config.XDPoSV2Block) == 0 {
x.initialV2(chain, parent)
if x.config.V2.SwitchBlock != nil && parent.Number.Cmp(x.config.V2.SwitchBlock) == 0 {
err := x.initialV2(chain, parent)
log.Error("[YourTurn] Error when initialise v2", "Error", err, "ParentBlock", parent)
return false, err
}
switch x.config.BlockConsensusVersion(big.NewInt(parent.Number.Int64() + 1)) {
case params.ConsensusEngineVersion2:

View file

@ -340,10 +340,10 @@ func (x *XDPoS_v2) YourTurn(chain consensus.ChainReader, parent *types.Header, s
}
var masterNodes []common.Address
if isEpochSwitch {
if x.config.XDPoSV2Block.Cmp(parent.Number) == 0 {
snap, err := x.getSnapshot(chain, x.config.XDPoSV2Block.Uint64())
if x.config.V2.SwitchBlock.Cmp(parent.Number) == 0 {
snap, err := x.getSnapshot(chain, x.config.V2.SwitchBlock.Uint64())
if err != nil {
log.Error("[YourTurn] Cannot find snapshot at gap num of last V1", "err", err, "number", x.config.XDPoSV2Block.Uint64())
log.Error("[YourTurn] Cannot find snapshot at gap num of last V1", "err", err, "number", x.config.V2.SwitchBlock.Uint64())
return false, err
}
// the initial snapshot of v1->v2 switch containes penalites node
@ -351,7 +351,7 @@ func (x *XDPoS_v2) YourTurn(chain consensus.ChainReader, parent *types.Header, s
} else {
snap, err := x.getSnapshot(chain, parent.Number.Uint64()+1)
if err != nil {
log.Error("[YourTurn] Cannot find snapshot at gap block", "err", err, "number", x.config.XDPoSV2Block.Uint64())
log.Error("[YourTurn] Cannot find snapshot at gap block", "err", err, "number", x.config.V2.SwitchBlock.Uint64())
return false, err
}
masterNodes = snap.NextEpochMasterNodes
@ -873,7 +873,7 @@ func (x *XDPoS_v2) processQC(blockChainReader consensus.ChainReader, quorumCert
}
// 2. Get QC from header and update lockQuorumCert(lockQuorumCert is the parent of highestQC)
proposedBlockHeader := blockChainReader.GetHeaderByHash(quorumCert.ProposedBlockInfo.Hash)
if proposedBlockHeader.Number.Cmp(x.config.XDPoSV2Block) > 0 {
if proposedBlockHeader.Number.Cmp(x.config.V2.SwitchBlock) > 0 {
// Extra field contain parent information
var decodedExtraField utils.ExtraFields_v2
err := utils.DecodeBytesExtraFields(proposedBlockHeader.Extra, &decodedExtraField)
@ -1093,7 +1093,7 @@ func (x *XDPoS_v2) getSyncInfo() *utils.SyncInfo {
//Find parent and grandparent, check round number, if so, commit grandparent(grandGrandParent of currentBlock)
func (x *XDPoS_v2) commitBlocks(blockChainReader consensus.ChainReader, proposedBlockHeader *types.Header, proposedBlockRound *utils.Round) (bool, error) {
// XDPoS v1.0 switch to v2.0, skip commit
if big.NewInt(0).Sub(proposedBlockHeader.Number, big.NewInt(2)).Cmp(x.config.XDPoSV2Block) <= 0 {
if big.NewInt(0).Sub(proposedBlockHeader.Number, big.NewInt(2)).Cmp(x.config.V2.SwitchBlock) <= 0 {
return false, nil
}
// Find the last two parent block and check their rounds are the continuous
@ -1199,7 +1199,7 @@ func (x *XDPoS_v2) GetMasternodesFromEpochSwitchHeader(epochSwitchHeader *types.
func (x *XDPoS_v2) IsEpochSwitch(header *types.Header) (bool, uint64, error) {
// Return true directly if we are examing the last v1 block. This could happen if the calling function is examing parent block
if header.Number.Cmp(x.config.XDPoSV2Block) == 0 {
if header.Number.Cmp(x.config.V2.SwitchBlock) == 0 {
log.Info("[IsEpochSwitch] examing last v1 block 👯‍♂️")
return true, header.Number.Uint64() / x.config.Epoch, nil
}
@ -1213,10 +1213,10 @@ func (x *XDPoS_v2) IsEpochSwitch(header *types.Header) (bool, uint64, error) {
parentRound := decodedExtraField.QuorumCert.ProposedBlockInfo.Round
round := decodedExtraField.Round
epochStartRound := round - round%utils.Round(x.config.Epoch)
epochNum := x.config.XDPoSV2Block.Uint64()/x.config.Epoch + uint64(round)/x.config.Epoch
epochNum := x.config.V2.SwitchBlock.Uint64()/x.config.Epoch + uint64(round)/x.config.Epoch
// if parent is last v1 block and this is first v2 block, this is treated as epoch switch
if decodedExtraField.QuorumCert.ProposedBlockInfo.Number.Cmp(x.config.XDPoSV2Block) == 0 {
log.Info("[IsEpochSwitch] true, parent equals XDPoSV2Block", "round", round, "number", header.Number.Uint64(), "hash", header.Hash())
if decodedExtraField.QuorumCert.ProposedBlockInfo.Number.Cmp(x.config.V2.SwitchBlock) == 0 {
log.Info("[IsEpochSwitch] true, parent equals V2.SwitchBlock", "round", round, "number", header.Number.Uint64(), "hash", header.Hash())
return true, epochNum, nil
}
log.Info("[IsEpochSwitch]", "parent round", parentRound, "round", round, "number", header.Number.Uint64(), "hash", header.Hash())
@ -1225,9 +1225,9 @@ func (x *XDPoS_v2) IsEpochSwitch(header *types.Header) (bool, uint64, error) {
// IsEpochSwitchAtRound() is used by miner to check whether it mines a block in the same epoch with parent
func (x *XDPoS_v2) IsEpochSwitchAtRound(round utils.Round, parentHeader *types.Header) (bool, uint64, error) {
epochNum := x.config.XDPoSV2Block.Uint64()/x.config.Epoch + uint64(round)/x.config.Epoch
epochNum := x.config.V2.SwitchBlock.Uint64()/x.config.Epoch + uint64(round)/x.config.Epoch
// if parent is last v1 block and this is first v2 block, this is treated as epoch switch
if parentHeader.Number.Cmp(x.config.XDPoSV2Block) == 0 {
if parentHeader.Number.Cmp(x.config.V2.SwitchBlock) == 0 {
return true, epochNum, nil
}
var decodedExtraField utils.ExtraFields_v2
@ -1263,7 +1263,7 @@ func (x *XDPoS_v2) getEpochSwitchInfo(chain consensus.ChainReader, header *types
log.Debug("[getEpochSwitchInfo] header is epoch switch", "hash", hash.Hex(), "number", h.Number.Uint64())
var epochSwitchInfo *utils.EpochSwitchInfo
// Special case, in case of last v1 block, we manually build the epoch switch info
if h.Number.Cmp(x.config.XDPoSV2Block) == 0 {
if h.Number.Cmp(x.config.V2.SwitchBlock) == 0 {
masternodes := decodeMasternodesFromHeaderExtra(h)
epochSwitchInfo = &utils.EpochSwitchInfo{
Masternodes: masternodes,
@ -1325,6 +1325,6 @@ func (x *XDPoS_v2) GetCurrentEpochSwitchBlock(chain consensus.ChainReader, block
}
currentCheckpointNumber := epochSwitchInfo.EpochSwitchBlockInfo.Number.Uint64()
epochNum := x.config.XDPoSV2Block.Uint64()/x.config.Epoch + uint64(epochSwitchInfo.EpochSwitchBlockInfo.Round)/x.config.Epoch
epochNum := x.config.V2.SwitchBlock.Uint64()/x.config.Epoch + uint64(epochSwitchInfo.EpochSwitchBlockInfo.Round)/x.config.Epoch
return currentCheckpointNumber, epochNum, nil
}

View file

@ -69,7 +69,7 @@ func TestAdaptorGetMasternodesFromCheckpointHeader(t *testing.T) {
headerV1.Extra = common.Hex2Bytes("d7830100018358444388676f312e31352e38856c696e757800000000000000000278c350152e15fa6ffc712a5a73d704ce73e2e103d9e17ae3ff2c6712e44e25b09ac5ee91f6c9ff065551f0dcac6f00cae11192d462db709be3758ccef312ee5eea8d7bad5374c6a652150515d744508b61c1a4deb4e4e7bf057e4e3824c11fd2569bcb77a52905cda63b5a58507910bed335e4c9d87ae0ecdfafd400")
masternodesV1 := adaptor.GetMasternodesFromCheckpointHeader(headerV1)
headerV2 := currentBlock.Header()
headerV2.Number.Add(blockchain.Config().XDPoS.XDPoSV2Block, big.NewInt(1))
headerV2.Number.Add(blockchain.Config().XDPoS.V2.SwitchBlock, big.NewInt(1))
headerV2.Validators = common.Hex2Bytes("0278c350152e15fa6ffc712a5a73d704ce73e2e103d9e17ae3ff2c6712e44e25b09ac5ee91f6c9ff065551f0dcac6f00cae11192d462db709be3758c")
masternodesV2 := adaptor.GetMasternodesFromCheckpointHeader(headerV2)
assert.True(t, reflect.DeepEqual(masternodesV1, masternodesV2), "GetMasternodesFromCheckpointHeader in adaptor for v1 v2 not equal", "v1", masternodesV1, "v2", masternodesV2)
@ -93,7 +93,7 @@ func TestAdaptorIsEpochSwitch(t *testing.T) {
parentBlockInfo := &utils.BlockInfo{
Hash: header.ParentHash,
Round: utils.Round(0),
Number: big.NewInt(0).Set(blockchain.Config().XDPoS.XDPoSV2Block),
Number: big.NewInt(0).Set(blockchain.Config().XDPoS.V2.SwitchBlock),
}
quorumCert := &utils.QuorumCert{
ProposedBlockInfo: parentBlockInfo,
@ -106,14 +106,14 @@ func TestAdaptorIsEpochSwitch(t *testing.T) {
extraBytes, err := extra.EncodeToBytes()
assert.Nil(t, err)
header.Extra = extraBytes
header.Number.Add(blockchain.Config().XDPoS.XDPoSV2Block, big.NewInt(1))
header.Number.Add(blockchain.Config().XDPoS.V2.SwitchBlock, big.NewInt(1))
isEpochSwitchBlock, _, err = adaptor.IsEpochSwitch(header)
assert.Nil(t, err)
assert.True(t, isEpochSwitchBlock, "header should be epoch switch", header)
parentBlockInfo = &utils.BlockInfo{
Hash: header.ParentHash,
Round: utils.Round(1),
Number: big.NewInt(0).Add(blockchain.Config().XDPoS.XDPoSV2Block, big.NewInt(1)),
Number: big.NewInt(0).Add(blockchain.Config().XDPoS.V2.SwitchBlock, big.NewInt(1)),
}
quorumCert = &utils.QuorumCert{
ProposedBlockInfo: parentBlockInfo,
@ -126,14 +126,14 @@ func TestAdaptorIsEpochSwitch(t *testing.T) {
extraBytes, err = extra.EncodeToBytes()
assert.Nil(t, err)
header.Extra = extraBytes
header.Number.Add(blockchain.Config().XDPoS.XDPoSV2Block, big.NewInt(2))
header.Number.Add(blockchain.Config().XDPoS.V2.SwitchBlock, big.NewInt(2))
isEpochSwitchBlock, _, err = adaptor.IsEpochSwitch(header)
assert.Nil(t, err)
assert.False(t, isEpochSwitchBlock, "header should not be epoch switch", header)
parentBlockInfo = &utils.BlockInfo{
Hash: header.ParentHash,
Round: utils.Round(blockchain.Config().XDPoS.Epoch) - 1,
Number: big.NewInt(0).Add(blockchain.Config().XDPoS.XDPoSV2Block, big.NewInt(100)),
Number: big.NewInt(0).Add(blockchain.Config().XDPoS.V2.SwitchBlock, big.NewInt(100)),
}
quorumCert = &utils.QuorumCert{
ProposedBlockInfo: parentBlockInfo,
@ -146,14 +146,14 @@ func TestAdaptorIsEpochSwitch(t *testing.T) {
extraBytes, err = extra.EncodeToBytes()
assert.Nil(t, err)
header.Extra = extraBytes
header.Number.Add(blockchain.Config().XDPoS.XDPoSV2Block, big.NewInt(101))
header.Number.Add(blockchain.Config().XDPoS.V2.SwitchBlock, big.NewInt(101))
isEpochSwitchBlock, _, err = adaptor.IsEpochSwitch(header)
assert.Nil(t, err)
assert.True(t, isEpochSwitchBlock, "header should be epoch switch", header)
parentBlockInfo = &utils.BlockInfo{
Hash: header.ParentHash,
Round: utils.Round(blockchain.Config().XDPoS.Epoch) + 1,
Number: big.NewInt(0).Add(blockchain.Config().XDPoS.XDPoSV2Block, big.NewInt(100)),
Number: big.NewInt(0).Add(blockchain.Config().XDPoS.V2.SwitchBlock, big.NewInt(100)),
}
quorumCert = &utils.QuorumCert{
ProposedBlockInfo: parentBlockInfo,
@ -166,7 +166,7 @@ func TestAdaptorIsEpochSwitch(t *testing.T) {
extraBytes, err = extra.EncodeToBytes()
assert.Nil(t, err)
header.Extra = extraBytes
header.Number.Add(blockchain.Config().XDPoS.XDPoSV2Block, big.NewInt(101))
header.Number.Add(blockchain.Config().XDPoS.V2.SwitchBlock, big.NewInt(101))
isEpochSwitchBlock, _, err = adaptor.IsEpochSwitch(header)
assert.Nil(t, err)
assert.False(t, isEpochSwitchBlock, "header should not be epoch switch", header)

View file

@ -354,7 +354,7 @@ func PrepareXDCTestBlockChainForV2Engine(t *testing.T, numOfBlocks int, chainCon
// Insert initial blocks
for i := 1; i <= numOfBlocks; i++ {
blockCoinBase := fmt.Sprintf("0x111000000000000000000000000000000%03d", i)
roundNumber := int64(i) - chainConfig.XDPoS.XDPoSV2Block.Int64()
roundNumber := int64(i) - chainConfig.XDPoS.V2.SwitchBlock.Int64()
block := CreateBlock(blockchain, chainConfig, currentBlock, i, roundNumber, blockCoinBase, signer, signFn)
err = blockchain.InsertBlock(block)
@ -392,7 +392,7 @@ func CreateBlock(blockchain *BlockChain, chainConfig *params.ChainConfig, starti
merkleRoot := "35999dded35e8db12de7e6c1471eb9670c162eec616ecebbaf4fddd4676fb930"
var header *types.Header
if big.NewInt(int64(blockNumber)).Cmp(chainConfig.XDPoS.XDPoSV2Block) == 1 { // Build engine v2 compatible extra data field
if big.NewInt(int64(blockNumber)).Cmp(chainConfig.XDPoS.V2.SwitchBlock) == 1 { // Build engine v2 compatible extra data field
var extraField utils.ExtraFields_v2
var round utils.Round
err := utils.DecodeBytesExtraFields(currentBlock.Extra(), &extraField)
@ -435,9 +435,9 @@ func CreateBlock(blockchain *BlockChain, chainConfig *params.ChainConfig, starti
Extra: extraInBytes,
Validator: signedHash,
}
if int64(blockNumber) == (chainConfig.XDPoS.XDPoSV2Block.Int64() + 1) { // This is the first v2 block, we need to copy the last v1 epoch master node list and inject into v2 validators
if int64(blockNumber) == (chainConfig.XDPoS.V2.SwitchBlock.Int64() + 1) { // This is the first v2 block, we need to copy the last v1 epoch master node list and inject into v2 validators
// Get last master node list from last v1 block
lastv1Block := blockchain.GetBlockByNumber(chainConfig.XDPoS.XDPoSV2Block.Uint64())
lastv1Block := blockchain.GetBlockByNumber(chainConfig.XDPoS.V2.SwitchBlock.Uint64())
masternodesFromV1LastEpoch := decodeMasternodesFromHeaderExtra(lastv1Block.Header())
for _, v := range masternodesFromV1LastEpoch {
header.Validators = append(header.Validators, v[:]...)
@ -454,7 +454,7 @@ func CreateBlock(blockchain *BlockChain, chainConfig *params.ChainConfig, starti
}
// Inject the hardcoded master node list for the last v1 epoch block
if big.NewInt(int64(blockNumber)).Cmp(chainConfig.XDPoS.XDPoSV2Block) == 0 {
if big.NewInt(int64(blockNumber)).Cmp(chainConfig.XDPoS.V2.SwitchBlock) == 0 {
// reset extra
header.Extra = []byte{}
if len(header.Extra) < utils.ExtraVanity {

View file

@ -42,6 +42,12 @@ var (
TestXDPoSV2Config = &V2{
TimeoutWorkerDuration: 10,
CertThreshold: 3,
SwitchBlock: big.NewInt(10),
}
DevnetXDPoSV2Config = &V2{
SwitchBlock: big.NewInt(9999999), // Temporary set it to very high
TimeoutWorkerDuration: 50,
CertThreshold: 6,
}
// XDPoSChain mainnet config
@ -60,7 +66,7 @@ var (
RewardCheckpoint: 900,
Gap: 5,
FoudationWalletAddr: common.HexToAddress("0x0000000000000000000000000000000000000068"),
V2: *XDPoSV2Config,
V2: XDPoSV2Config,
},
}
@ -109,7 +115,7 @@ var (
XDPoS: &XDPoSConfig{
Period: 15,
Epoch: 30000,
V2: *XDPoSV2Config,
V2: XDPoSV2Config,
},
}
@ -128,13 +134,13 @@ var (
AllXDPoSProtocolChanges = &ChainConfig{big.NewInt(89), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, &XDPoSConfig{Period: 0, Epoch: 30000}}
AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}, nil}
TestXDPoSChanConfig = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, &XDPoSConfig{Period: 2, Epoch: 900, Reward: 250, RewardCheckpoint: 900, Gap: 890, FoudationWalletAddr: common.HexToAddress("0x0000000000000000000000000000000000000068"), V2: *XDPoSV2Config}}
TestXDPoSChanConfig = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, &XDPoSConfig{Period: 2, Epoch: 900, Reward: 250, RewardCheckpoint: 900, Gap: 890, FoudationWalletAddr: common.HexToAddress("0x0000000000000000000000000000000000000068"), V2: XDPoSV2Config}}
// XDPoS config in use for v1 engine only
TestXDPoSMockChainConfig = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, &XDPoSConfig{Epoch: 900, Gap: 450, SkipValidation: true, V2: *TestXDPoSV2Config}}
TestXDPoSMockChainConfig = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, &XDPoSConfig{Epoch: 900, Gap: 450, SkipValidation: true, V2: &V2{CertThreshold: 3, TimeoutWorkerDuration: 10}}}
// XDPoS config with v2 engine after block 10
TestXDPoSMockChainConfigWithV2Engine = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, &XDPoSConfig{Epoch: 900, Gap: 450, SkipValidation: true, XDPoSV2Block: big.NewInt(10), V2: *TestXDPoSV2Config}}
TestXDPoSMockChainConfigWithV2Engine = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, &XDPoSConfig{Epoch: 900, Gap: 450, SkipValidation: true, V2: TestXDPoSV2Config}}
// XDPoS config with v2 engine after block 901
TestXDPoSMockChainConfigWithV2EngineEpochSwitch = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, &XDPoSConfig{Epoch: 900, Gap: 450, SkipValidation: true, XDPoSV2Block: big.NewInt(900), V2: *TestXDPoSV2Config}}
TestXDPoSMockChainConfigWithV2EngineEpochSwitch = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, &XDPoSConfig{Epoch: 900, Gap: 450, SkipValidation: true, V2: &V2{CertThreshold: 3, TimeoutWorkerDuration: 10, SwitchBlock: big.NewInt(900)}}}
TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, nil}
TestRules = TestChainConfig.Rules(new(big.Int))
@ -197,13 +203,13 @@ type XDPoSConfig struct {
Gap uint64 `json:"gap"` // Gap time preparing for the next epoch
FoudationWalletAddr common.Address `json:"foudationWalletAddr"` // Foundation Address Wallet
SkipValidation bool //Skip Block Validation for testing purpose
XDPoSV2Block *big.Int `json:"v2Block"`
V2 V2 `json:"v2"`
V2 *V2 `json:"v2"`
}
type V2 struct {
TimeoutWorkerDuration int64 `json:"timeoutWorkerDuration"` // Duration in ms
CertThreshold int `json:"certificateThreshold"` // Necessary number of messages from master nodes to form a certificate
SwitchBlock *big.Int `json:"switchBlock"` // v1 to v2 switch block number
TimeoutWorkerDuration int64 `json:"timeoutWorkerDuration"` // Duration in ms
CertThreshold int `json:"certificateThreshold"` // Necessary number of messages from master nodes to form a certificate
}
// String implements the stringer interface, returning the consensus engine details.
@ -216,7 +222,7 @@ ConsensusVersion will return the consensus version to use for the provided block
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 {
if c.XDPoSV2Block != nil && num.Cmp(c.XDPoSV2Block) > 0 {
if c.V2 != nil && c.V2.SwitchBlock != nil && num.Cmp(c.V2.SwitchBlock) > 0 {
return ConsensusEngineVersion2
}
return ConsensusEngineVersion1