mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-24 15:44:32 +00:00
add more propose block handler test
This commit is contained in:
parent
2a94cdebe5
commit
5f9fd80733
5 changed files with 158 additions and 80 deletions
|
|
@ -74,9 +74,20 @@ func New(config *params.XDPoSConfig, db ethdb.Database) *XDPoS_v2 {
|
|||
timeoutPool: timeoutPool,
|
||||
votePool: votePool,
|
||||
|
||||
highestTimeoutCert: nil,
|
||||
highestQuorumCert: nil,
|
||||
highestTimeoutCert: &utils.TimeoutCert{
|
||||
Round: utils.Round(0),
|
||||
Signatures: []utils.Signature{},
|
||||
},
|
||||
highestQuorumCert: &utils.QuorumCert{
|
||||
ProposedBlockInfo: &utils.BlockInfo{
|
||||
Hash: common.Hash{},
|
||||
Round: utils.Round(0),
|
||||
Number: big.NewInt(0),
|
||||
},
|
||||
Signatures: []utils.Signature{},
|
||||
},
|
||||
highestVotedRound: utils.Round(0),
|
||||
highestCommitBlock: nil,
|
||||
}
|
||||
// Add callback to the timer
|
||||
timer.OnTimeoutFn = engine.onCountdownTimeout
|
||||
|
|
@ -436,13 +447,6 @@ func (x *XDPoS_v2) VerifyHeader(chain consensus.ChainReader, header *types.Heade
|
|||
return nil
|
||||
}
|
||||
|
||||
// Utils for test to check currentRound value
|
||||
func (x *XDPoS_v2) GetProperties() (utils.Round, *utils.QuorumCert, *utils.QuorumCert, utils.Round) {
|
||||
x.lock.Lock()
|
||||
defer x.lock.Unlock()
|
||||
return x.currentRound, x.lockQuorumCert, x.highestQuorumCert, x.highestVotedRound
|
||||
}
|
||||
|
||||
/*
|
||||
SyncInfo workflow
|
||||
*/
|
||||
|
|
@ -704,7 +708,7 @@ func (x *XDPoS_v2) verifyTC(timeoutCert *utils.TimeoutCert) error {
|
|||
func (x *XDPoS_v2) processQC(blockChainReader consensus.ChainReader, quorumCert *utils.QuorumCert) error {
|
||||
log.Trace("[ProcessQC][Before]", "HighQC", x.highestQuorumCert)
|
||||
// 1. Update HighestQC
|
||||
if x.highestQuorumCert == nil || (quorumCert.ProposedBlockInfo.Round > x.highestQuorumCert.ProposedBlockInfo.Round) {
|
||||
if quorumCert.ProposedBlockInfo.Round > x.highestQuorumCert.ProposedBlockInfo.Round {
|
||||
x.highestQuorumCert = quorumCert
|
||||
}
|
||||
// 2. Get QC from header and update lockQuorumCert(lockQuorumCert is the parent of highestQC)
|
||||
|
|
@ -745,7 +749,7 @@ func (x *XDPoS_v2) processQC(blockChainReader consensus.ChainReader, quorumCert
|
|||
2. Check TC round >= node's currentRound. If yes, call setNewRound
|
||||
*/
|
||||
func (x *XDPoS_v2) processTC(timeoutCert *utils.TimeoutCert) error {
|
||||
if x.highestTimeoutCert == nil || timeoutCert.Round > x.highestTimeoutCert.Round {
|
||||
if timeoutCert.Round > x.highestTimeoutCert.Round {
|
||||
x.highestTimeoutCert = timeoutCert
|
||||
}
|
||||
if timeoutCert.Round >= x.currentRound {
|
||||
|
|
@ -898,14 +902,6 @@ func (x *XDPoS_v2) getCurrentRoundMasterNodes() []common.Address {
|
|||
return []common.Address{}
|
||||
}
|
||||
|
||||
/*
|
||||
Testing tools
|
||||
*/
|
||||
|
||||
func (x *XDPoS_v2) SetHighestQuorumCert(qc *utils.QuorumCert) {
|
||||
x.highestQuorumCert = qc
|
||||
}
|
||||
|
||||
func (x *XDPoS_v2) getSyncInfo() *utils.SyncInfo {
|
||||
return &utils.SyncInfo{
|
||||
HighestQuorumCert: x.highestQuorumCert,
|
||||
|
|
@ -913,21 +909,6 @@ func (x *XDPoS_v2) getSyncInfo() *utils.SyncInfo {
|
|||
}
|
||||
}
|
||||
|
||||
func (x *XDPoS_v2) SetNewRoundFaker(newRound utils.Round, resetTimer bool) {
|
||||
x.lock.Lock()
|
||||
defer x.lock.Unlock()
|
||||
// Reset a bunch of things
|
||||
if resetTimer {
|
||||
x.timeoutWorker.Reset()
|
||||
}
|
||||
x.currentRound = newRound
|
||||
}
|
||||
|
||||
// Utils for test to check currentRound value
|
||||
func (x *XDPoS_v2) GetCurrentRound() utils.Round {
|
||||
return x.currentRound
|
||||
}
|
||||
|
||||
//TODO: find parent and grandparent and grandgrandparent block, check round number, if so, commit grandgrandparent
|
||||
func (x *XDPoS_v2) commitBlocks(blockCahinReader consensus.ChainReader, proposedBlockHeader *types.Header, proposedBlockRound *utils.Round) (bool, error) {
|
||||
// XDPoS v1.0 switch to v2.0, skip commit
|
||||
|
|
@ -978,3 +959,29 @@ func (x *XDPoS_v2) isExtendingFromAncestor(blockChainReader consensus.ChainReade
|
|||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
/*
|
||||
Testing tools
|
||||
*/
|
||||
|
||||
func (x *XDPoS_v2) SetNewRoundFaker(newRound utils.Round, resetTimer bool) {
|
||||
x.lock.Lock()
|
||||
defer x.lock.Unlock()
|
||||
// Reset a bunch of things
|
||||
if resetTimer {
|
||||
x.timeoutWorker.Reset()
|
||||
}
|
||||
x.currentRound = newRound
|
||||
}
|
||||
|
||||
// Utils for test to check currentRound value
|
||||
func (x *XDPoS_v2) GetCurrentRound() utils.Round {
|
||||
return x.currentRound
|
||||
}
|
||||
|
||||
// Utils for test to check currentRound value
|
||||
func (x *XDPoS_v2) GetProperties() (utils.Round, *utils.QuorumCert, *utils.QuorumCert, utils.Round) {
|
||||
x.lock.Lock()
|
||||
defer x.lock.Unlock()
|
||||
return x.currentRound, x.lockQuorumCert, x.highestQuorumCert, x.highestVotedRound
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,33 +157,63 @@ func TestShouldNotSendVoteMsgIfBlockInfoRoundNotEqualCurrentRound(t *testing.T)
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Uncomment once confirmed the lockQuorumCert usage
|
||||
// func TestShouldNotSendVoteMsgIfBlockNotExtendedFromAncestor(t *testing.T) {
|
||||
// blockchain, _, currentBlock, _, forkedBlock := PrepareXDCTestBlockChainForV2Engine(t, 16, params.TestXDPoSMockChainConfigWithV2Engine, 16)
|
||||
// engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2
|
||||
/*
|
||||
Block and round relationship diagram for this test
|
||||
... - 13(3) - 14(4) - 15(5) - 16(6)
|
||||
\ 14'(7)
|
||||
*/
|
||||
func TestShouldNotSendVoteMsgIfBlockNotExtendedFromAncestor(t *testing.T) {
|
||||
// Block number 15, 16 have forks and forkedBlock is the 16th
|
||||
blockchain, _, currentBlock, _, forkedBlock := PrepareXDCTestBlockChainForV2Engine(t, 16, params.TestXDPoSMockChainConfigWithV2Engine, 3)
|
||||
engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2
|
||||
|
||||
// var extraField utils.ExtraFields_v2
|
||||
// err := utils.DecodeBytesExtraFields(forkedBlock.Extra(), &extraField)
|
||||
// if err != nil {
|
||||
// t.Fatal("Fail to decode extra data", err)
|
||||
// }
|
||||
// // Set the lockQC and other pre-requist properties by block 16
|
||||
// err = engineV2.ProposedBlockHandler(blockchain, currentBlock.Header())
|
||||
// if err != nil {
|
||||
// t.Fatal("Error while handling block 16", err)
|
||||
// }
|
||||
// // Now try with block 17 but from a different chain
|
||||
// err = engineV2.ProposedBlockHandler(blockchain, forkedBlock.Header())
|
||||
// if err != nil {
|
||||
// t.Fatal("Fail propose proposedBlock handler", err)
|
||||
// }
|
||||
// // Should not receive anything from the channel
|
||||
// select {
|
||||
// case <-engineV2.BroadcastCh:
|
||||
// t.Fatal("Should not trigger vote")
|
||||
// case <-time.After(5 * time.Second):
|
||||
// // Shoud not trigger setNewRound
|
||||
// round, _, _, _ := engineV2.GetProperties()
|
||||
// assert.Equal(t, utils.Round(8), round)
|
||||
// }
|
||||
// }
|
||||
var extraField utils.ExtraFields_v2
|
||||
err := utils.DecodeBytesExtraFields(forkedBlock.Extra(), &extraField)
|
||||
if err != nil {
|
||||
t.Fatal("Fail to decode extra data", err)
|
||||
}
|
||||
assert.Equal(t, utils.Round(9), extraField.Round)
|
||||
// Set the lockQC and other pre-requist properties by block 16
|
||||
err = engineV2.ProposedBlockHandler(blockchain, currentBlock.Header())
|
||||
if err != nil {
|
||||
t.Fatal("Error while handling block 16", err)
|
||||
}
|
||||
vote := <-engineV2.BroadcastCh
|
||||
assert.Equal(t, utils.Round(6), vote.(*utils.Vote).ProposedBlockInfo.Round)
|
||||
|
||||
// Find the first forked block at block 14th
|
||||
firstForkedBlock := blockchain.GetBlockByHash(blockchain.GetBlockByHash(forkedBlock.ParentHash()).ParentHash())
|
||||
engineV2.SetNewRoundFaker(utils.Round(7), false)
|
||||
err = engineV2.ProposedBlockHandler(blockchain, firstForkedBlock.Header())
|
||||
if err != nil {
|
||||
t.Fatal("Fail propose proposedBlock handler", err)
|
||||
}
|
||||
// Should not receive anything from the channel
|
||||
select {
|
||||
case <-engineV2.BroadcastCh:
|
||||
t.Fatal("Should not trigger vote")
|
||||
case <-time.After(5 * time.Second):
|
||||
// Shoud not trigger setNewRound
|
||||
round, _, _, _ := engineV2.GetProperties()
|
||||
assert.Equal(t, utils.Round(7), round)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShouldSendVoteMsg(t *testing.T) {
|
||||
// Block number 15, 16 have forks and forkedBlock is the 16th
|
||||
blockchain, _, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 13, params.TestXDPoSMockChainConfigWithV2Engine, 0)
|
||||
engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2
|
||||
|
||||
// Block 11 is first v2 block
|
||||
for i := 11; i < 14; i++ {
|
||||
blockHeader := blockchain.GetBlockByNumber(uint64(i)).Header()
|
||||
err := engineV2.ProposedBlockHandler(blockchain, blockHeader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
round, _, _, _ := engineV2.GetProperties()
|
||||
assert.Equal(t, utils.Round(i-10), round)
|
||||
vote := <-engineV2.BroadcastCh
|
||||
assert.Equal(t, round, vote.(*utils.Vote).ProposedBlockInfo.Round)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
31
consensus/tests/sync_info_test.go
Normal file
31
consensus/tests/sync_info_test.go
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
package tests
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
|
||||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
)
|
||||
|
||||
func TestSyncInfoForFirstV2BlockMsgWithoutQC(t *testing.T) {
|
||||
// Block 11 is the first v2 block with starting round of 0
|
||||
blockchain, _, currentBlock, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 11, params.TestXDPoSMockChainConfigWithV2Engine, 0)
|
||||
engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2
|
||||
|
||||
var extraField utils.ExtraFields_v2
|
||||
err := utils.DecodeBytesExtraFields(currentBlock.Extra(), &extraField)
|
||||
if err != nil {
|
||||
t.Fatal("Fail to decode extra data", err)
|
||||
}
|
||||
|
||||
syncInfoMsg := &utils.SyncInfo{
|
||||
HighestQuorumCert: extraField.QuorumCert,
|
||||
HighestTimeoutCert: nil, // Initial value?
|
||||
}
|
||||
|
||||
err = engineV2.SyncInfoHandler(blockchain, syncInfoMsg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
|
@ -283,28 +283,28 @@ func PrepareXDCTestBlockChainForV2Engine(t *testing.T, numOfBlocks int, chainCon
|
|||
currentBlock := blockchain.Genesis()
|
||||
|
||||
var currentForkBlock *types.Block
|
||||
if numOfForkedBlocks != 0 {
|
||||
currentForkBlock = blockchain.Genesis()
|
||||
}
|
||||
|
||||
// Insert initial blocks
|
||||
for i := 1; i <= numOfBlocks; i++ {
|
||||
blockCoinBase := fmt.Sprintf("0x111000000000000000000000000000000%03d", i)
|
||||
|
||||
header := createBlock(chainConfig, currentBlock, i, blockCoinBase, signer, signFn)
|
||||
roundNumber := int64(i) - chainConfig.XDPoS.XDPoSV2Block.Int64()
|
||||
header := createBlock(chainConfig, currentBlock, i, roundNumber, blockCoinBase, signer, signFn)
|
||||
|
||||
block, err := insertBlock(blockchain, header)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
currentBlock = block
|
||||
|
||||
}
|
||||
if numOfForkedBlocks != 0 {
|
||||
for i := 1; i <= numOfForkedBlocks; i++ {
|
||||
// Produce forked block for the last numOfForkedBlocks'th blocks
|
||||
if numOfForkedBlocks != 0 && i > numOfBlocks-numOfForkedBlocks {
|
||||
if currentForkBlock == nil {
|
||||
currentForkBlock = currentBlock
|
||||
}
|
||||
forkedBlockCoinBase := fmt.Sprintf("0x222000000000000000000000000000000%03d", i)
|
||||
|
||||
forkedBlockHeader := createBlock(chainConfig, currentForkBlock, i, forkedBlockCoinBase, signer, signFn)
|
||||
forkedBlockRoundNumber := roundNumber + int64(numOfForkedBlocks)
|
||||
|
||||
forkedBlockHeader := createBlock(chainConfig, currentForkBlock, i, forkedBlockRoundNumber, forkedBlockCoinBase, signer, signFn)
|
||||
|
||||
forkedBlock, err := insertBlock(blockchain, forkedBlockHeader)
|
||||
if err != nil {
|
||||
|
|
@ -312,7 +312,9 @@ func PrepareXDCTestBlockChainForV2Engine(t *testing.T, numOfBlocks int, chainCon
|
|||
}
|
||||
currentForkBlock = forkedBlock
|
||||
}
|
||||
currentBlock = block
|
||||
}
|
||||
|
||||
// Update Signer as there is no previous signer assigned
|
||||
err = UpdateSigner(blockchain)
|
||||
if err != nil {
|
||||
|
|
@ -322,18 +324,26 @@ func PrepareXDCTestBlockChainForV2Engine(t *testing.T, numOfBlocks int, chainCon
|
|||
return blockchain, backend, currentBlock, signer, currentForkBlock
|
||||
}
|
||||
|
||||
func createBlock(chainConfig *params.ChainConfig, startingBlock *types.Block, blockNumIteration int, blockCoinBase string, signer common.Address, signFn func(account accounts.Account, hash []byte) ([]byte, error)) *types.Header {
|
||||
func createBlock(chainConfig *params.ChainConfig, startingBlock *types.Block, blockNumIteration int, roundNumber int64, blockCoinBase string, signer common.Address, signFn func(account accounts.Account, hash []byte) ([]byte, error)) *types.Header {
|
||||
currentBlock := startingBlock
|
||||
merkleRoot := "35999dded35e8db12de7e6c1471eb9670c162eec616ecebbaf4fddd4676fb930"
|
||||
var header *types.Header
|
||||
// Build engine v2 compatible extra data field
|
||||
if big.NewInt(int64(blockNumIteration)).Cmp(chainConfig.XDPoS.XDPoSV2Block) == 1 {
|
||||
roundNumber := int64(blockNumIteration) - chainConfig.XDPoS.XDPoSV2Block.Int64()
|
||||
|
||||
var extraField utils.ExtraFields_v2
|
||||
var round utils.Round
|
||||
err := utils.DecodeBytesExtraFields(currentBlock.Extra(), &extraField)
|
||||
if err != nil {
|
||||
round = utils.Round(0)
|
||||
} else {
|
||||
round = extraField.Round
|
||||
}
|
||||
|
||||
proposedBlockInfo := &utils.BlockInfo{
|
||||
Hash: currentBlock.Hash(),
|
||||
Round: utils.Round(roundNumber - 1),
|
||||
Number: big.NewInt(int64(blockNumIteration - 1)),
|
||||
Round: round,
|
||||
Number: currentBlock.Number(),
|
||||
}
|
||||
// Genrate QC
|
||||
signedHash, err := signFn(accounts.Account{Address: signer}, utils.VoteSigHash(proposedBlockInfo).Bytes())
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ func TestVoteMessageHandlerSuccessfullyGeneratedAndProcessQCForFistV2Round(t *te
|
|||
err := engineV2.VoteHandler(blockchain, voteMsg)
|
||||
assert.Nil(t, err)
|
||||
currentRound, lockQuorumCert, highestQuorumCert, _ := engineV2.GetProperties()
|
||||
// Inilised with nil and 0 round
|
||||
// initialised with nil and 0 round
|
||||
assert.Nil(t, lockQuorumCert)
|
||||
assert.Nil(t, highestQuorumCert)
|
||||
assert.Equal(t, utils.Round(1), currentRound)
|
||||
|
|
@ -88,7 +88,7 @@ func TestVoteMessageHandlerSuccessfullyGeneratedAndProcessQC(t *testing.T) {
|
|||
err := engineV2.VoteHandler(blockchain, voteMsg)
|
||||
assert.Nil(t, err)
|
||||
currentRound, lockQuorumCert, highestQuorumCert, _ := engineV2.GetProperties()
|
||||
// Inilised with nil and 0 round
|
||||
// initialised with nil and 0 round
|
||||
assert.Nil(t, lockQuorumCert)
|
||||
assert.Nil(t, highestQuorumCert)
|
||||
assert.Equal(t, utils.Round(5), currentRound)
|
||||
|
|
@ -174,7 +174,7 @@ func TestProcessVoteMsgThenTimeoutMsg(t *testing.T) {
|
|||
err := engineV2.VoteHandler(blockchain, voteMsg)
|
||||
assert.Nil(t, err)
|
||||
currentRound, lockQuorumCert, highestQuorumCert, _ := engineV2.GetProperties()
|
||||
// Inilised with nil and 0 round
|
||||
// initialised with nil and 0 round
|
||||
assert.Nil(t, lockQuorumCert)
|
||||
assert.Nil(t, highestQuorumCert)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue