mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-18 10:50:44 +00:00
implemente proposeblock handler and SyncInfo handler
This commit is contained in:
parent
17eb4c6c65
commit
249d2b5b6d
6 changed files with 225 additions and 111 deletions
|
|
@ -2,6 +2,7 @@ package engine_v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/big"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -56,6 +57,7 @@ func New(config *params.XDPoSConfig, db ethdb.Database) *XDPoS_v2 {
|
||||||
votePool: votePool,
|
votePool: votePool,
|
||||||
highestTimeoutCert: &utils.TimeoutCert{},
|
highestTimeoutCert: &utils.TimeoutCert{},
|
||||||
highestQuorumCert: &utils.QuorumCert{},
|
highestQuorumCert: &utils.QuorumCert{},
|
||||||
|
highestVotedRound: utils.Round(0),
|
||||||
}
|
}
|
||||||
// Add callback to the timer
|
// Add callback to the timer
|
||||||
timer.OnTimeoutFn = engine.onCountdownTimeout
|
timer.OnTimeoutFn = engine.onCountdownTimeout
|
||||||
|
|
@ -124,12 +126,16 @@ func (x *XDPoS_v2) VerifySyncInfoMessage(syncInfo *utils.SyncInfo) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *XDPoS_v2) SyncInfoHandler(syncInfo *utils.SyncInfo) error {
|
func (x *XDPoS_v2) SyncInfoHandler(chain consensus.ChainReader, syncInfo *utils.SyncInfo) error {
|
||||||
/*
|
/*
|
||||||
1. processQC
|
1. processQC
|
||||||
2. processTC
|
2. processTC
|
||||||
*/
|
*/
|
||||||
return nil
|
err := x.processQC(chain, syncInfo.HighestQuorumCert)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return x.processTC(syncInfo.HighestTimeoutCert)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -267,26 +273,38 @@ func (x *XDPoS_v2) onTimeoutPoolThresholdReached(pooledTimeouts map[common.Hash]
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Process Block workflow
|
Proposed Block workflow
|
||||||
*/
|
*/
|
||||||
func (x *XDPoS_v2) ProcessBlockHandler() {
|
func (x *XDPoS_v2) ProposedBlockHandler(blockCahinReader consensus.ChainReader, blockInfo *utils.BlockInfo, quorumCert *utils.QuorumCert) error {
|
||||||
|
x.lock.Lock()
|
||||||
|
defer x.lock.Unlock()
|
||||||
|
|
||||||
/*
|
/*
|
||||||
1. processQC()
|
1. processQC()
|
||||||
2. verifyVotingRule()
|
2. verifyVotingRule()
|
||||||
3. sendVote()
|
3. sendVote()
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
err := x.processQC(blockCahinReader, quorumCert)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
verified, err := x.verifyVotingRule(blockCahinReader, blockInfo, quorumCert)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if verified {
|
||||||
|
return x.sendVote(blockInfo)
|
||||||
|
} else {
|
||||||
|
log.Info("Failed to pass the voting rule verification", "ProposeBlockHash", blockInfo.Hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
QC & TC Utils
|
QC & TC Utils
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Genrate blockInfo which contains Hash, round and blockNumber and send to queue
|
|
||||||
func (x *XDPoS_v2) generateBlockInfo() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// To be used by different message verification. Verify local DB block info against the received block information(i.e hash, blockNum, round)
|
// To be used by different message verification. Verify local DB block info against the received block information(i.e hash, blockNum, round)
|
||||||
func (x *XDPoS_v2) VerifyBlockInfo(blockInfo *utils.BlockInfo) error {
|
func (x *XDPoS_v2) VerifyBlockInfo(blockInfo *utils.BlockInfo) error {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -317,7 +335,6 @@ func (x *XDPoS_v2) verifyTC(timeoutCert *utils.TimeoutCert) error {
|
||||||
func (x *XDPoS_v2) processQC(blockCahinReader consensus.ChainReader, quorumCert *utils.QuorumCert) error {
|
func (x *XDPoS_v2) processQC(blockCahinReader consensus.ChainReader, quorumCert *utils.QuorumCert) error {
|
||||||
// 1. Update HighestQC
|
// 1. Update HighestQC
|
||||||
if x.highestQuorumCert == nil || (quorumCert.ProposedBlockInfo.Round > x.highestQuorumCert.ProposedBlockInfo.Round) {
|
if x.highestQuorumCert == nil || (quorumCert.ProposedBlockInfo.Round > x.highestQuorumCert.ProposedBlockInfo.Round) {
|
||||||
//TODO: do I need a clone?
|
|
||||||
x.highestQuorumCert = quorumCert
|
x.highestQuorumCert = quorumCert
|
||||||
}
|
}
|
||||||
// 2. Get QC from header and update lockQuorumCert(lockQuorumCert is the parent of highestQC)
|
// 2. Get QC from header and update lockQuorumCert(lockQuorumCert is the parent of highestQC)
|
||||||
|
|
@ -376,15 +393,29 @@ func (x *XDPoS_v2) setNewRound(round utils.Round) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hot stuff rule to decide whether this node is eligible to vote for the received block
|
// Hot stuff rule to decide whether this node is eligible to vote for the received block
|
||||||
func (x *XDPoS_v2) verifyVotingRule(header *types.Header) error {
|
func (x *XDPoS_v2) verifyVotingRule(blockCahinReader consensus.ChainReader, blockInfo *utils.BlockInfo, quorumCert *utils.QuorumCert) (bool, error) {
|
||||||
|
// Make sure this node has not voted for this round. We can have a variable highestVotedRound, and check currentRound > highestVotedRound.
|
||||||
|
if x.currentRound <= x.highestVotedRound {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
Make sure this node has not voted for this round. We can have a variable highestVotedRound, and check currentRound > highestVotedRound.
|
|
||||||
HotStuff Voting rule:
|
HotStuff Voting rule:
|
||||||
header's round == local current round, AND (one of the following two:)
|
header's round == local current round, AND (one of the following two:)
|
||||||
header's block extends lockQuorumCert's ProposedBlockInfo (we need a isExtending(block_a, block_b) function), OR
|
header's block extends lockQuorumCert's ProposedBlockInfo (we need a isExtending(block_a, block_b) function), OR
|
||||||
header's QC's ProposedBlockInfo.Round > lockQuorumCert's ProposedBlockInfo.Round
|
header's QC's ProposedBlockInfo.Round > lockQuorumCert's ProposedBlockInfo.Round
|
||||||
*/
|
*/
|
||||||
return nil
|
if blockInfo.Round != x.currentRound {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
isExtended, err := x.isExtendingFromAncestor(blockCahinReader, blockInfo, &x.lockQuorumCert.ProposedBlockInfo)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if isExtended || (quorumCert.ProposedBlockInfo.Round > x.lockQuorumCert.ProposedBlockInfo.Round) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Once Hot stuff voting rule has verified, this node can then send vote
|
// Once Hot stuff voting rule has verified, this node can then send vote
|
||||||
|
|
@ -392,6 +423,7 @@ func (x *XDPoS_v2) sendVote(blockInfo *utils.BlockInfo) error {
|
||||||
// First step: Generate the signature by using node's private key(The signature is the blockInfo signature)
|
// First step: Generate the signature by using node's private key(The signature is the blockInfo signature)
|
||||||
// Second step: Construct the vote struct with the above signature & blockinfo struct
|
// Second step: Construct the vote struct with the above signature & blockinfo struct
|
||||||
// Third step: Send the vote to broadcast channel
|
// Third step: Send the vote to broadcast channel
|
||||||
|
// Forth step: Update the highest Voted round
|
||||||
signedHash, err := x.signSignature(utils.VoteSigHash(blockInfo))
|
signedHash, err := x.signSignature(utils.VoteSigHash(blockInfo))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -401,6 +433,7 @@ func (x *XDPoS_v2) sendVote(blockInfo *utils.BlockInfo) error {
|
||||||
Signature: signedHash,
|
Signature: signedHash,
|
||||||
}
|
}
|
||||||
x.broadcastToBftChannel(voteMsg)
|
x.broadcastToBftChannel(voteMsg)
|
||||||
|
x.highestVotedRound = x.currentRound
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -519,3 +552,22 @@ func (x *XDPoS_v2) commitBlocks(blockCahinReader consensus.ChainReader, proposed
|
||||||
|
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *XDPoS_v2) isExtendingFromAncestor(blockCahinReader consensus.ChainReader, currentBlock *utils.BlockInfo, ancestorBlock *utils.BlockInfo) (bool, error) {
|
||||||
|
blockNumDiff := int(big.NewInt(0).Sub(currentBlock.Number, ancestorBlock.Number).Int64())
|
||||||
|
|
||||||
|
nextBlockHash := currentBlock.Hash
|
||||||
|
for i := 0; i < blockNumDiff; i++ {
|
||||||
|
parentBlock := blockCahinReader.GetHeaderByHash(nextBlockHash)
|
||||||
|
if parentBlock == nil {
|
||||||
|
return false, fmt.Errorf("Could not find its parent block when checking whether currentBlock %v is extending from the ancestorBlock %v", currentBlock.Number, ancestorBlock.Number)
|
||||||
|
} else {
|
||||||
|
nextBlockHash = parentBlock.ParentHash
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if nextBlockHash == ancestorBlock.Hash {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ type ConsensusFns struct {
|
||||||
timeoutHandler func(*utils.Timeout) error
|
timeoutHandler func(*utils.Timeout) error
|
||||||
|
|
||||||
verifySyncInfo func(*utils.SyncInfo) error
|
verifySyncInfo func(*utils.SyncInfo) error
|
||||||
syncInfoHandler func(*utils.SyncInfo) error
|
syncInfoHandler func(consensus.ChainReader, *utils.SyncInfo) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type BroadcastFns struct {
|
type BroadcastFns struct {
|
||||||
|
|
@ -136,7 +136,7 @@ func (b *Bfter) SyncInfo(syncInfo *utils.SyncInfo) error {
|
||||||
b.knownSyncInfos.Add(syncInfo.Hash(), true)
|
b.knownSyncInfos.Add(syncInfo.Hash(), true)
|
||||||
b.broadcastCh <- syncInfo
|
b.broadcastCh <- syncInfo
|
||||||
|
|
||||||
err = b.consensus.syncInfoHandler(syncInfo)
|
err = b.consensus.syncInfoHandler(b.blockCahinReader, syncInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("handle BFT SyncInfo", "error", err)
|
log.Error("handle BFT SyncInfo", "error", err)
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
26
tests/consensus/countdown_test.go
Normal file
26
tests/consensus/countdown_test.go
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
package consensus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/params"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCountdownTimeoutToSendTimeoutMessage(t *testing.T) {
|
||||||
|
blockchain, _, _, _ := PrepareXDCTestBlockChain(t, 11, params.TestXDPoSMockChainConfigWithV2Engine)
|
||||||
|
engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2
|
||||||
|
|
||||||
|
engineV2.SetNewRoundFaker(utils.Round(1), true)
|
||||||
|
|
||||||
|
timeoutMsg := <-engineV2.BroadcastCh
|
||||||
|
assert.NotNil(t, timeoutMsg)
|
||||||
|
|
||||||
|
valid, err := engineV2.VerifyTimeoutMessage(timeoutMsg.(*utils.Timeout))
|
||||||
|
// We can only test valid = false for now as the implementation for getCurrentRoundMasterNodes is not complete
|
||||||
|
assert.False(t, valid)
|
||||||
|
// This shows we are able to decode the timeout message, which is what this test is all about
|
||||||
|
assert.Regexp(t, "^Masternodes does not contain signer addres.*", err.Error())
|
||||||
|
}
|
||||||
45
tests/consensus/proposed_block_test.go
Normal file
45
tests/consensus/proposed_block_test.go
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
package consensus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/params"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ProposeBlock handler
|
||||||
|
func TestProposedBlockMessageHandlerSuccessfullyGenerateVote(t *testing.T) {
|
||||||
|
blockchain, _, currentBlock, _ := PrepareXDCTestBlockChainForV2Engine(t, 11, params.TestXDPoSMockChainConfigWithV2Engine)
|
||||||
|
engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2
|
||||||
|
|
||||||
|
// Set round to 11
|
||||||
|
engineV2.SetNewRoundFaker(utils.Round(11), false)
|
||||||
|
|
||||||
|
var extraField utils.ExtraFields_v2
|
||||||
|
err := utils.DecodeBytesExtraFields(currentBlock.Extra(), &extraField)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Fail to decode extra data", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
proposedBlockInfo := &utils.BlockInfo{
|
||||||
|
Hash: currentBlock.Hash(),
|
||||||
|
Round: utils.Round(12),
|
||||||
|
Number: big.NewInt(12),
|
||||||
|
}
|
||||||
|
|
||||||
|
err = engineV2.ProposedBlockHandler(blockchain, proposedBlockInfo, &extraField.QuorumCert)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Fail propose proposedBlock handler", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
voteMsg := <-engineV2.BroadcastCh
|
||||||
|
assert.NotNil(t, voteMsg)
|
||||||
|
assert.Equal(t, proposedBlockInfo.Hash, voteMsg.(*utils.Vote).ProposedBlockInfo.Hash)
|
||||||
|
|
||||||
|
round, _, highestQC := engineV2.GetProperties()
|
||||||
|
assert.Equal(t, utils.Round(12), round)
|
||||||
|
assert.Equal(t, extraField.QuorumCert.Signatures, highestQC.Signatures)
|
||||||
|
}
|
||||||
86
tests/consensus/timeout_test.go
Normal file
86
tests/consensus/timeout_test.go
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
package consensus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/params"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Timeout handler
|
||||||
|
func TestTimeoutMessageHandlerSuccessfullyGenerateTCandSyncInfo(t *testing.T) {
|
||||||
|
blockchain, _, _, _ := PrepareXDCTestBlockChain(t, 11, params.TestXDPoSMockChainConfigWithV2Engine)
|
||||||
|
engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2
|
||||||
|
|
||||||
|
// Set round to 1
|
||||||
|
engineV2.SetNewRoundFaker(utils.Round(1), false)
|
||||||
|
// Create two timeout message which will not reach timeout pool threshold
|
||||||
|
timeoutMsg := &utils.Timeout{
|
||||||
|
Round: utils.Round(1),
|
||||||
|
Signature: []byte{1},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := engineV2.TimeoutHandler(timeoutMsg)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
currentRound, _, _ := engineV2.GetProperties()
|
||||||
|
assert.Equal(t, utils.Round(1), currentRound)
|
||||||
|
timeoutMsg = &utils.Timeout{
|
||||||
|
Round: utils.Round(1),
|
||||||
|
Signature: []byte{2},
|
||||||
|
}
|
||||||
|
err = engineV2.TimeoutHandler(timeoutMsg)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
currentRound, _, _ = engineV2.GetProperties()
|
||||||
|
assert.Equal(t, utils.Round(1), currentRound)
|
||||||
|
// Create a timeout message that should trigger timeout pool hook
|
||||||
|
timeoutMsg = &utils.Timeout{
|
||||||
|
Round: utils.Round(1),
|
||||||
|
Signature: []byte{3},
|
||||||
|
}
|
||||||
|
|
||||||
|
err = engineV2.TimeoutHandler(timeoutMsg)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
syncInfoMsg := <-engineV2.BroadcastCh
|
||||||
|
|
||||||
|
currentRound, _, _ = engineV2.GetProperties()
|
||||||
|
|
||||||
|
assert.NotNil(t, syncInfoMsg)
|
||||||
|
|
||||||
|
// Should have QC, however, we did not inilise it, hence will show default empty value
|
||||||
|
qc := syncInfoMsg.(utils.SyncInfo).HighestQuorumCert
|
||||||
|
assert.NotNil(t, qc)
|
||||||
|
|
||||||
|
tc := syncInfoMsg.(utils.SyncInfo).HighestTimeoutCert
|
||||||
|
assert.NotNil(t, tc)
|
||||||
|
assert.Equal(t, tc.Round, utils.Round(1))
|
||||||
|
sigatures := []utils.Signature{[]byte{1}, []byte{2}, []byte{3}}
|
||||||
|
assert.ElementsMatch(t, tc.Signatures, sigatures)
|
||||||
|
assert.Equal(t, utils.Round(2), currentRound)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestThrowErrorIfTimeoutMsgRoundNotEqualToCurrentRound(t *testing.T) {
|
||||||
|
blockchain, _, _, _ := PrepareXDCTestBlockChain(t, 11, params.TestXDPoSMockChainConfigWithV2Engine)
|
||||||
|
engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2
|
||||||
|
|
||||||
|
// Set round to 3
|
||||||
|
engineV2.SetNewRoundFaker(utils.Round(3), false)
|
||||||
|
timeoutMsg := &utils.Timeout{
|
||||||
|
Round: utils.Round(2),
|
||||||
|
Signature: []byte{1},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := engineV2.TimeoutHandler(timeoutMsg)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
// Timeout msg round > currentRound
|
||||||
|
assert.Equal(t, "Timeout message round number: 2 does not match currentRound: 3", err.Error())
|
||||||
|
|
||||||
|
// Set round to 1
|
||||||
|
engineV2.SetNewRoundFaker(utils.Round(1), false)
|
||||||
|
err = engineV2.TimeoutHandler(timeoutMsg)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
// Timeout msg round < currentRound
|
||||||
|
assert.Equal(t, "Timeout message round number: 2 does not match currentRound: 1", err.Error())
|
||||||
|
}
|
||||||
|
|
@ -11,106 +11,11 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCountdownTimeoutToSendTimeoutMessage(t *testing.T) {
|
|
||||||
blockchain, _, _, _ := PrepareXDCTestBlockChain(t, 11, params.TestXDPoSMockChainConfigWithV2Engine)
|
|
||||||
engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2
|
|
||||||
|
|
||||||
engineV2.SetNewRoundFaker(utils.Round(1), true)
|
|
||||||
|
|
||||||
timeoutMsg := <-engineV2.BroadcastCh
|
|
||||||
assert.NotNil(t, timeoutMsg)
|
|
||||||
|
|
||||||
valid, err := engineV2.VerifyTimeoutMessage(timeoutMsg.(*utils.Timeout))
|
|
||||||
// We can only test valid = false for now as the implementation for getCurrentRoundMasterNodes is not complete
|
|
||||||
assert.False(t, valid)
|
|
||||||
// This shows we are able to decode the timeout message, which is what this test is all about
|
|
||||||
assert.Regexp(t, "^Masternodes does not contain signer addres.*", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Timeout handler
|
|
||||||
func TestTimeoutMessageHandlerSuccessfullyGenerateTCandSyncInfo(t *testing.T) {
|
|
||||||
blockchain, _, _, _ := PrepareXDCTestBlockChain(t, 11, params.TestXDPoSMockChainConfigWithV2Engine)
|
|
||||||
engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2
|
|
||||||
|
|
||||||
// Set round to 1
|
|
||||||
engineV2.SetNewRoundFaker(utils.Round(1), false)
|
|
||||||
// Create two timeout message which will not reach timeout pool threshold
|
|
||||||
timeoutMsg := &utils.Timeout{
|
|
||||||
Round: utils.Round(1),
|
|
||||||
Signature: []byte{1},
|
|
||||||
}
|
|
||||||
|
|
||||||
err := engineV2.TimeoutHandler(timeoutMsg)
|
|
||||||
assert.Nil(t, err)
|
|
||||||
currentRound, _, _ := engineV2.GetProperties()
|
|
||||||
assert.Equal(t, utils.Round(1), currentRound)
|
|
||||||
timeoutMsg = &utils.Timeout{
|
|
||||||
Round: utils.Round(1),
|
|
||||||
Signature: []byte{2},
|
|
||||||
}
|
|
||||||
err = engineV2.TimeoutHandler(timeoutMsg)
|
|
||||||
assert.Nil(t, err)
|
|
||||||
currentRound, _, _ = engineV2.GetProperties()
|
|
||||||
assert.Equal(t, utils.Round(1), currentRound)
|
|
||||||
// Create a timeout message that should trigger timeout pool hook
|
|
||||||
timeoutMsg = &utils.Timeout{
|
|
||||||
Round: utils.Round(1),
|
|
||||||
Signature: []byte{3},
|
|
||||||
}
|
|
||||||
|
|
||||||
err = engineV2.TimeoutHandler(timeoutMsg)
|
|
||||||
assert.Nil(t, err)
|
|
||||||
|
|
||||||
syncInfoMsg := <-engineV2.BroadcastCh
|
|
||||||
|
|
||||||
currentRound, _, _ = engineV2.GetProperties()
|
|
||||||
|
|
||||||
assert.NotNil(t, syncInfoMsg)
|
|
||||||
|
|
||||||
// Should have QC, however, we did not inilise it, hence will show default empty value
|
|
||||||
qc := syncInfoMsg.(utils.SyncInfo).HighestQuorumCert
|
|
||||||
assert.NotNil(t, qc)
|
|
||||||
|
|
||||||
tc := syncInfoMsg.(utils.SyncInfo).HighestTimeoutCert
|
|
||||||
assert.NotNil(t, tc)
|
|
||||||
assert.Equal(t, tc.Round, utils.Round(1))
|
|
||||||
sigatures := []utils.Signature{[]byte{1}, []byte{2}, []byte{3}}
|
|
||||||
assert.ElementsMatch(t, tc.Signatures, sigatures)
|
|
||||||
assert.Equal(t, utils.Round(2), currentRound)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestThrowErrorIfTimeoutMsgRoundNotEqualToCurrentRound(t *testing.T) {
|
|
||||||
blockchain, _, _, _ := PrepareXDCTestBlockChain(t, 11, params.TestXDPoSMockChainConfigWithV2Engine)
|
|
||||||
engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2
|
|
||||||
|
|
||||||
// Set round to 3
|
|
||||||
engineV2.SetNewRoundFaker(utils.Round(3), false)
|
|
||||||
timeoutMsg := &utils.Timeout{
|
|
||||||
Round: utils.Round(2),
|
|
||||||
Signature: []byte{1},
|
|
||||||
}
|
|
||||||
|
|
||||||
err := engineV2.TimeoutHandler(timeoutMsg)
|
|
||||||
assert.NotNil(t, err)
|
|
||||||
// Timeout msg round > currentRound
|
|
||||||
assert.Equal(t, "Timeout message round number: 2 does not match currentRound: 3", err.Error())
|
|
||||||
|
|
||||||
// Set round to 1
|
|
||||||
engineV2.SetNewRoundFaker(utils.Round(1), false)
|
|
||||||
err = engineV2.TimeoutHandler(timeoutMsg)
|
|
||||||
assert.NotNil(t, err)
|
|
||||||
// Timeout msg round < currentRound
|
|
||||||
assert.Equal(t, "Timeout message round number: 2 does not match currentRound: 1", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
// VoteHandler
|
// VoteHandler
|
||||||
func TestVoteMessageHandlerSuccessfullyGeneratedAndProcessQC(t *testing.T) {
|
func TestVoteMessageHandlerSuccessfullyGeneratedAndProcessQC(t *testing.T) {
|
||||||
blockchain, _, currentBlock, _ := PrepareXDCTestBlockChainForV2Engine(t, 11, params.TestXDPoSMockChainConfigWithV2Engine)
|
blockchain, _, currentBlock, _ := PrepareXDCTestBlockChainForV2Engine(t, 11, params.TestXDPoSMockChainConfigWithV2Engine)
|
||||||
engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2
|
engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2
|
||||||
|
|
||||||
// parentBlock := blockchain.GetBlockByHash(currentBlock.ParentHash())
|
|
||||||
// grandParentBlock := blockchain.GetBlockByHash(parentBlock.ParentHash())
|
|
||||||
|
|
||||||
blockInfo := &utils.BlockInfo{
|
blockInfo := &utils.BlockInfo{
|
||||||
Hash: currentBlock.Hash(),
|
Hash: currentBlock.Hash(),
|
||||||
Round: utils.Round(11),
|
Round: utils.Round(11),
|
||||||
Loading…
Reference in a new issue