mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-17 18:30:45 +00:00
implement verify functions (#43)
* implement verify functions * Use go routine to call verifyMsgSignature * verify timeout msg shall use round from the msg * add comment for verifyQC
This commit is contained in:
parent
646042a651
commit
e063f67f34
4 changed files with 153 additions and 48 deletions
|
|
@ -483,14 +483,14 @@ func (x *XDPoS_v2) GetTimeoutPoolSize(timeout *utils.Timeout) int {
|
||||||
SyncInfo workflow
|
SyncInfo workflow
|
||||||
*/
|
*/
|
||||||
// Verify syncInfo and trigger process QC or TC if successful
|
// Verify syncInfo and trigger process QC or TC if successful
|
||||||
func (x *XDPoS_v2) VerifySyncInfoMessage(syncInfo *utils.SyncInfo) error {
|
func (x *XDPoS_v2) VerifySyncInfoMessage(chain consensus.ChainReader, syncInfo *utils.SyncInfo) error {
|
||||||
/*
|
/*
|
||||||
1. Verify items including:
|
1. Verify items including:
|
||||||
- verifyQC
|
- verifyQC
|
||||||
- verifyTC
|
- verifyTC
|
||||||
2. Broadcast(Not part of consensus)
|
2. Broadcast(Not part of consensus)
|
||||||
*/
|
*/
|
||||||
err := x.verifyQC(syncInfo.HighestQuorumCert)
|
err := x.verifyQC(chain, syncInfo.HighestQuorumCert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn("SyncInfo message verification failed due to QC", err)
|
log.Warn("SyncInfo message verification failed due to QC", err)
|
||||||
return err
|
return err
|
||||||
|
|
@ -520,16 +520,21 @@ func (x *XDPoS_v2) SyncInfoHandler(chain consensus.ChainReader, syncInfo *utils.
|
||||||
/*
|
/*
|
||||||
Vote workflow
|
Vote workflow
|
||||||
*/
|
*/
|
||||||
func (x *XDPoS_v2) VerifyVoteMessage(vote *utils.Vote) (bool, error) {
|
func (x *XDPoS_v2) VerifyVoteMessage(chain consensus.ChainReader, vote *utils.Vote) (bool, error) {
|
||||||
/*
|
/*
|
||||||
1. Check signature:
|
1. Get masterNode list belong to this epoch by hash
|
||||||
|
2. Check signature:
|
||||||
- Use ecRecover to get the public key
|
- Use ecRecover to get the public key
|
||||||
- Use the above public key to find out the xdc address
|
- Use the above public key to find out the xdc address
|
||||||
- Use the above xdc address to check against the master node list(For the running epoch)
|
- Use the above xdc address to check against the master node list from step 1(For the running epoch)
|
||||||
2. Verify blockInfo
|
3. Verify blockInfo
|
||||||
3. Broadcast(Not part of consensus)
|
4. Broadcast(Not part of consensus)
|
||||||
*/
|
*/
|
||||||
return x.verifyMsgSignature(utils.VoteSigHash(vote.ProposedBlockInfo), vote.Signature)
|
epochInfo, err := x.getEpochSwitchInfo(chain, nil, vote.ProposedBlockInfo.Hash)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("[VerifyVoteMessage] Error when getting epoch switch Info to verify vote message", "Error", err)
|
||||||
|
}
|
||||||
|
return x.verifyMsgSignature(utils.VoteSigHash(vote.ProposedBlockInfo), vote.Signature, epochInfo.Masternodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consensus entry point for processing vote message to produce QC
|
// Consensus entry point for processing vote message to produce QC
|
||||||
|
|
@ -591,14 +596,17 @@ func (x *XDPoS_v2) onVotePoolThresholdReached(chain consensus.ChainReader, poole
|
||||||
*/
|
*/
|
||||||
// Verify timeout message type from peers in bft.go
|
// Verify timeout message type from peers in bft.go
|
||||||
/*
|
/*
|
||||||
1. Check signature:
|
1. Get master node list by timeout msg round
|
||||||
|
2. Check signature:
|
||||||
- Use ecRecover to get the public key
|
- Use ecRecover to get the public key
|
||||||
- Use the above public key to find out the xdc address
|
- Use the above public key to find out the xdc address
|
||||||
- Use the above xdc address to check against the master node(For the running epoch)
|
- Use the above xdc address to check against the master node list from step 1(For the running epoch)
|
||||||
2. Broadcast(Not part of consensus)
|
3. Broadcast(Not part of consensus)
|
||||||
*/
|
*/
|
||||||
func (x *XDPoS_v2) VerifyTimeoutMessage(timeoutMsg *utils.Timeout) (bool, error) {
|
func (x *XDPoS_v2) VerifyTimeoutMessage(chain consensus.ChainReader, timeoutMsg *utils.Timeout) (bool, error) {
|
||||||
return x.verifyMsgSignature(utils.TimeoutSigHash(&timeoutMsg.Round), timeoutMsg.Signature)
|
|
||||||
|
masternodes := x.GetMasternodesAtRound(chain, timeoutMsg.Round, chain.CurrentHeader())
|
||||||
|
return x.verifyMsgSignature(utils.TimeoutSigHash(&timeoutMsg.Round), timeoutMsg.Signature, masternodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -689,7 +697,7 @@ func (x *XDPoS_v2) ProposedBlockHandler(blockChainReader consensus.ChainReader,
|
||||||
quorumCert := decodedExtraField.QuorumCert
|
quorumCert := decodedExtraField.QuorumCert
|
||||||
round := decodedExtraField.Round
|
round := decodedExtraField.Round
|
||||||
|
|
||||||
err = x.verifyQC(quorumCert)
|
err = x.verifyQC(blockChainReader, quorumCert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("[ProposedBlockHandler] Fail to verify QC", "Extra round", round, "QC proposed BlockInfo Hash", quorumCert.ProposedBlockInfo.Hash)
|
log.Error("[ProposedBlockHandler] Fail to verify QC", "Extra round", round, "QC proposed BlockInfo Hash", quorumCert.ProposedBlockInfo.Hash)
|
||||||
return err
|
return err
|
||||||
|
|
@ -728,23 +736,57 @@ func (x *XDPoS_v2) VerifyBlockInfo(blockInfo *utils.BlockInfo) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *XDPoS_v2) verifyQC(quorumCert *utils.QuorumCert) error {
|
func (x *XDPoS_v2) verifyQC(blockChainReader consensus.ChainReader, quorumCert *utils.QuorumCert) error {
|
||||||
/*
|
/*
|
||||||
1. Verify signer signatures: (List of signatures)
|
1. Check if num of QC signatures is >= x.config.v2.CertThreshold
|
||||||
|
2. Get epoch master node list by hash
|
||||||
|
3. Verify signer signatures: (List of signatures)
|
||||||
- Use ecRecover to get the public key
|
- Use ecRecover to get the public key
|
||||||
- Use the above public key to find out the xdc address
|
- Use the above public key to find out the xdc address
|
||||||
- Use the above xdc address to check against the master node list(For the received QC epoch)
|
- Use the above xdc address to check against the master node list from step 1(For the received QC epoch)
|
||||||
2. Verify blockInfo
|
4. Verify blockInfo
|
||||||
*/
|
*/
|
||||||
return nil
|
epochInfo, err := x.getEpochSwitchInfo(blockChainReader, nil, quorumCert.ProposedBlockInfo.Hash)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("[verifyQC] Error when getting epoch switch Info to verify QC", "Error", err)
|
||||||
|
return fmt.Errorf("Fail to verify QC due to failure in getting epoch switch info")
|
||||||
|
}
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(len(quorumCert.Signatures))
|
||||||
|
var haveError error
|
||||||
|
|
||||||
|
for _, signature := range quorumCert.Signatures {
|
||||||
|
go func(sig utils.Signature) {
|
||||||
|
defer wg.Done()
|
||||||
|
verified, err := x.verifyMsgSignature(utils.VoteSigHash(quorumCert.ProposedBlockInfo), sig, epochInfo.Masternodes)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("[verifyQC] Error while verfying QC message signatures", "Error", err)
|
||||||
|
haveError = fmt.Errorf("Error while verfying QC message signatures")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !verified {
|
||||||
|
log.Warn("[verifyQC] Signature not verified doing QC verification", "QC", quorumCert)
|
||||||
|
haveError = fmt.Errorf("Fail to verify QC due to signature mis-match")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}(signature)
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
if haveError != nil {
|
||||||
|
return haveError
|
||||||
|
}
|
||||||
|
|
||||||
|
return x.VerifyBlockInfo(quorumCert.ProposedBlockInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *XDPoS_v2) verifyTC(timeoutCert *utils.TimeoutCert) error {
|
func (x *XDPoS_v2) verifyTC(timeoutCert *utils.TimeoutCert) error {
|
||||||
/*
|
/*
|
||||||
1. Verify signer signature: (List of signatures)
|
1. Get epoch master node list by round/number
|
||||||
|
2. Verify signer signature: (List of signatures)
|
||||||
- Use ecRecover to get the public key
|
- Use ecRecover to get the public key
|
||||||
- Use the above public key to find out the xdc address
|
- Use the above public key to find out the xdc address
|
||||||
- Use the above xdc address to check against the master node list(For the received TC epoch)
|
- Use the above xdc address to check against the master node list from step 1(For the received TC epoch)
|
||||||
*/
|
*/
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -917,7 +959,7 @@ func (x *XDPoS_v2) signSignature(signingHash common.Hash) (utils.Signature, erro
|
||||||
return signedHash, nil
|
return signedHash, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *XDPoS_v2) verifyMsgSignature(signedHashToBeVerified common.Hash, signature utils.Signature) (bool, error) {
|
func (x *XDPoS_v2) verifyMsgSignature(signedHashToBeVerified common.Hash, signature utils.Signature, masternodes []common.Address) (bool, error) {
|
||||||
// Recover the public key and the Ethereum address
|
// Recover the public key and the Ethereum address
|
||||||
pubkey, err := crypto.Ecrecover(signedHashToBeVerified.Bytes(), signature)
|
pubkey, err := crypto.Ecrecover(signedHashToBeVerified.Bytes(), signature)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -925,7 +967,6 @@ func (x *XDPoS_v2) verifyMsgSignature(signedHashToBeVerified common.Hash, signat
|
||||||
}
|
}
|
||||||
var signerAddress common.Address
|
var signerAddress common.Address
|
||||||
copy(signerAddress[:], crypto.Keccak256(pubkey[1:])[12:])
|
copy(signerAddress[:], crypto.Keccak256(pubkey[1:])[12:])
|
||||||
masternodes := x.getCurrentRoundMasterNodes()
|
|
||||||
for _, mn := range masternodes {
|
for _, mn := range masternodes {
|
||||||
if mn == signerAddress {
|
if mn == signerAddress {
|
||||||
return true, nil
|
return true, nil
|
||||||
|
|
@ -957,7 +998,7 @@ func (x *XDPoS_v2) broadcastToBftChannel(msg interface{}) {
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *XDPoS_v2) getCurrentRoundMasterNodes() []common.Address {
|
func (x *XDPoS_v2) GetMasternodesAtRound(chain consensus.ChainReader, round utils.Round, currentHeader *types.Header) []common.Address {
|
||||||
return []common.Address{}
|
return []common.Address{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1076,6 +1117,12 @@ func (x *XDPoS_v2) GetMasternodesFromEpochSwitchHeader(epochSwitchHeader *types.
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *XDPoS_v2) IsEpochSwitch(header *types.Header) (bool, uint64, error) {
|
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 {
|
||||||
|
log.Info("[IsEpochSwitch] examing last v1 block 👯♂️")
|
||||||
|
return true, header.Number.Uint64() / x.config.Epoch, nil
|
||||||
|
}
|
||||||
|
|
||||||
var decodedExtraField utils.ExtraFields_v2
|
var decodedExtraField utils.ExtraFields_v2
|
||||||
err := utils.DecodeBytesExtraFields(header.Extra, &decodedExtraField)
|
err := utils.DecodeBytesExtraFields(header.Extra, &decodedExtraField)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -1133,22 +1180,38 @@ func (x *XDPoS_v2) getEpochSwitchInfo(chain consensus.ChainReader, header *types
|
||||||
}
|
}
|
||||||
if isEpochSwitch {
|
if isEpochSwitch {
|
||||||
log.Debug("[getEpochSwitchInfo] header is epoch switch", "hash", hash.Hex(), "number", h.Number.Uint64())
|
log.Debug("[getEpochSwitchInfo] header is epoch switch", "hash", hash.Hex(), "number", h.Number.Uint64())
|
||||||
masternodes := x.GetMasternodesFromEpochSwitchHeader(h)
|
var epochSwitchInfo *utils.EpochSwitchInfo
|
||||||
// create the epoch switch info and cache it
|
// Special case, in case of last v1 block, we manually build the epoch switch info
|
||||||
var decodedExtraField utils.ExtraFields_v2
|
if h.Number.Cmp(x.config.XDPoSV2Block) == 0 {
|
||||||
err = utils.DecodeBytesExtraFields(h.Extra, &decodedExtraField)
|
masternodes := decodeMasternodesFromHeaderExtra(h)
|
||||||
if err != nil {
|
epochSwitchInfo = &utils.EpochSwitchInfo{
|
||||||
return nil, err
|
Masternodes: masternodes,
|
||||||
}
|
EpochSwitchBlockInfo: &utils.BlockInfo{
|
||||||
epochSwitchInfo := &utils.EpochSwitchInfo{
|
Hash: hash,
|
||||||
Masternodes: masternodes,
|
Number: h.Number,
|
||||||
EpochSwitchBlockInfo: &utils.BlockInfo{
|
Round: utils.Round(0),
|
||||||
Hash: hash,
|
},
|
||||||
Number: h.Number,
|
EpochSwitchParentBlockInfo: nil,
|
||||||
Round: decodedExtraField.Round,
|
}
|
||||||
},
|
} else { // v2 normal flow
|
||||||
EpochSwitchParentBlockInfo: decodedExtraField.QuorumCert.ProposedBlockInfo,
|
masternodes := x.GetMasternodesFromEpochSwitchHeader(h)
|
||||||
|
// create the epoch switch info and cache it
|
||||||
|
var decodedExtraField utils.ExtraFields_v2
|
||||||
|
err = utils.DecodeBytesExtraFields(h.Extra, &decodedExtraField)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
epochSwitchInfo = &utils.EpochSwitchInfo{
|
||||||
|
Masternodes: masternodes,
|
||||||
|
EpochSwitchBlockInfo: &utils.BlockInfo{
|
||||||
|
Hash: hash,
|
||||||
|
Number: h.Number,
|
||||||
|
Round: decodedExtraField.Round,
|
||||||
|
},
|
||||||
|
EpochSwitchParentBlockInfo: decodedExtraField.QuorumCert.ProposedBlockInfo,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
x.epochSwitches.Add(hash, epochSwitchInfo)
|
x.epochSwitches.Add(hash, epochSwitchInfo)
|
||||||
return epochSwitchInfo, nil
|
return epochSwitchInfo, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package engine_v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/common"
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||||
"github.com/XinFinOrg/XDPoSChain/crypto/sha3"
|
"github.com/XinFinOrg/XDPoSChain/crypto/sha3"
|
||||||
|
|
@ -56,4 +57,14 @@ func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, er
|
||||||
|
|
||||||
sigcache.Add(hash, signer)
|
sigcache.Add(hash, signer)
|
||||||
return signer, nil
|
return signer, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get masternodes address from checkpoint Header. Only used for v1 last block
|
||||||
|
func decodeMasternodesFromHeaderExtra(checkpointHeader *types.Header) []common.Address {
|
||||||
|
masternodes := make([]common.Address, (len(checkpointHeader.Extra)-utils.ExtraVanity-utils.ExtraSeal)/common.AddressLength)
|
||||||
|
for i := 0; i < len(masternodes); i++ {
|
||||||
|
copy(masternodes[i][:], checkpointHeader.Extra[utils.ExtraVanity+i*common.AddressLength:])
|
||||||
|
}
|
||||||
|
return masternodes
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ func TestCountdownTimeoutToSendTimeoutMessage(t *testing.T) {
|
||||||
assert.Equal(t, poolSize, 1)
|
assert.Equal(t, poolSize, 1)
|
||||||
assert.NotNil(t, timeoutMsg)
|
assert.NotNil(t, timeoutMsg)
|
||||||
|
|
||||||
valid, err := engineV2.VerifyTimeoutMessage(timeoutMsg.(*utils.Timeout))
|
valid, err := engineV2.VerifyTimeoutMessage(blockchain, timeoutMsg.(*utils.Timeout))
|
||||||
// We can only test valid = false for now as the implementation for getCurrentRoundMasterNodes is not complete
|
// We can only test valid = false for now as the implementation for getCurrentRoundMasterNodes is not complete
|
||||||
assert.False(t, valid)
|
assert.False(t, valid)
|
||||||
// This shows we are able to decode the timeout message, which is what this test is all about
|
// This shows we are able to decode the timeout message, which is what this test is all about
|
||||||
|
|
|
||||||
|
|
@ -241,6 +241,11 @@ func PrepareXDCTestBlockChain(t *testing.T, numOfBlocks int, chainConfig *params
|
||||||
|
|
||||||
currentBlock := blockchain.Genesis()
|
currentBlock := blockchain.Genesis()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
checkpointChanMsg := <-core.CheckpointCh
|
||||||
|
log.Info("[V1] Got a message from core CheckpointChan!", "msg", checkpointChanMsg)
|
||||||
|
}()
|
||||||
|
|
||||||
// Insert initial blocks
|
// Insert initial blocks
|
||||||
for i := 1; i <= numOfBlocks; i++ {
|
for i := 1; i <= numOfBlocks; i++ {
|
||||||
blockCoinBase := fmt.Sprintf("0x111000000000000000000000000000000%03d", i)
|
blockCoinBase := fmt.Sprintf("0x111000000000000000000000000000000%03d", i)
|
||||||
|
|
@ -262,10 +267,6 @@ func PrepareXDCTestBlockChain(t *testing.T, numOfBlocks int, chainConfig *params
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
go func() {
|
|
||||||
checkpointChanMsg := <-core.CheckpointCh
|
|
||||||
log.Info("[V1] Got a message from core CheckpointChan!", "msg", checkpointChanMsg)
|
|
||||||
}()
|
|
||||||
|
|
||||||
return blockchain, backend, currentBlock, signer
|
return blockchain, backend, currentBlock, signer
|
||||||
}
|
}
|
||||||
|
|
@ -288,11 +289,45 @@ func PrepareXDCTestBlockChainForV2Engine(t *testing.T, numOfBlocks int, chainCon
|
||||||
|
|
||||||
var currentForkBlock *types.Block
|
var currentForkBlock *types.Block
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
checkpointChanMsg := <-core.CheckpointCh
|
||||||
|
log.Info("[V2] Got a message from core CheckpointChan!", "msg", checkpointChanMsg)
|
||||||
|
}()
|
||||||
|
|
||||||
|
var masternodesFromV1LastEpoch []common.Address
|
||||||
|
|
||||||
// Insert initial blocks
|
// Insert initial blocks
|
||||||
for i := 1; i <= numOfBlocks; i++ {
|
for i := 1; i <= numOfBlocks; i++ {
|
||||||
blockCoinBase := fmt.Sprintf("0x111000000000000000000000000000000%03d", i)
|
blockCoinBase := fmt.Sprintf("0x111000000000000000000000000000000%03d", i)
|
||||||
roundNumber := int64(i) - chainConfig.XDPoS.XDPoSV2Block.Int64()
|
roundNumber := int64(i) - chainConfig.XDPoS.XDPoSV2Block.Int64()
|
||||||
header := createBlock(chainConfig, currentBlock, i, roundNumber, blockCoinBase, signer, signFn)
|
header := createBlock(chainConfig, currentBlock, i, roundNumber, blockCoinBase, signer, signFn)
|
||||||
|
// Inject the hardcoded master node list for the last v1 epoch block
|
||||||
|
if int64(i) == chainConfig.XDPoS.XDPoSV2Block.Int64() {
|
||||||
|
// reset extra
|
||||||
|
header.Extra = []byte{}
|
||||||
|
if len(header.Extra) < utils.ExtraVanity {
|
||||||
|
header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, utils.ExtraVanity-len(header.Extra))...)
|
||||||
|
}
|
||||||
|
header.Extra = header.Extra[:utils.ExtraVanity]
|
||||||
|
var masternodes []common.Address
|
||||||
|
masternodes = append(masternodes, acc1Addr, acc2Addr, acc3Addr, signer)
|
||||||
|
masternodesFromV1LastEpoch = masternodes
|
||||||
|
for _, masternode := range masternodes {
|
||||||
|
header.Extra = append(header.Extra, masternode[:]...)
|
||||||
|
}
|
||||||
|
header.Extra = append(header.Extra, make([]byte, utils.ExtraSeal)...)
|
||||||
|
|
||||||
|
// Sign all the things for v1 block use v1 sigHash function
|
||||||
|
sighash, err := signFn(accounts.Account{Address: signer}, blockchain.Engine().(*XDPoS.XDPoS).SigHash(header).Bytes())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
copy(header.Extra[len(header.Extra)-utils.ExtraSeal:], sighash)
|
||||||
|
} else if (int64(i) == (chainConfig.XDPoS.XDPoSV2Block.Int64() + 1)) && masternodesFromV1LastEpoch != nil { // This is the first v2 block, we need to copy the last v1 epoch master node list and inject into v2 validators
|
||||||
|
for _, v := range masternodesFromV1LastEpoch {
|
||||||
|
header.Validators = append(header.Validators, v[:]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
block, err := insertBlock(blockchain, header)
|
block, err := insertBlock(blockchain, header)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -324,10 +359,6 @@ func PrepareXDCTestBlockChainForV2Engine(t *testing.T, numOfBlocks int, chainCon
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
go func() {
|
|
||||||
checkpointChanMsg := <-core.CheckpointCh
|
|
||||||
log.Info("[V2] Got a message from core CheckpointChan!", "msg", checkpointChanMsg)
|
|
||||||
}()
|
|
||||||
|
|
||||||
return blockchain, backend, currentBlock, signer, signFn, currentForkBlock
|
return blockchain, backend, currentBlock, signer, signFn, currentForkBlock
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue