XIN-164 add GapNumber inside Vote, and tests (#74)

This commit is contained in:
wgr523 2022-03-25 23:22:24 +08:00 committed by GitHub
parent a3d5d82722
commit b790b077c9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 203 additions and 33 deletions

View file

@ -98,6 +98,7 @@ func New(config *params.XDPoSConfig, db ethdb.Database, waitPeriodCh chan int) *
Number: big.NewInt(0), Number: big.NewInt(0),
}, },
Signatures: []utils.Signature{}, Signatures: []utils.Signature{},
GapNumber: 0,
}, },
highestVotedRound: utils.Round(0), highestVotedRound: utils.Round(0),
highestCommitBlock: nil, highestCommitBlock: nil,
@ -142,6 +143,7 @@ func (x *XDPoS_v2) Initial(chain consensus.ChainReader, header *types.Header) er
quorumCert = &utils.QuorumCert{ quorumCert = &utils.QuorumCert{
ProposedBlockInfo: blockInfo, ProposedBlockInfo: blockInfo,
Signatures: nil, Signatures: nil,
GapNumber: header.Number.Uint64()-x.config.Gap,
} }
// can not call processQC because round is equal to default // can not call processQC because round is equal to default
@ -554,7 +556,7 @@ func (x *XDPoS_v2) SyncInfoHandler(chain consensus.ChainReader, syncInfo *utils.
func (x *XDPoS_v2) VerifyVoteMessage(chain consensus.ChainReader, vote *utils.Vote) (bool, error) { func (x *XDPoS_v2) VerifyVoteMessage(chain consensus.ChainReader, vote *utils.Vote) (bool, error) {
/* /*
1. Check vote round with current round for fast fail(disqualifed) 1. Check vote round with current round for fast fail(disqualifed)
2. Get masterNode list from snapshot 2. Get masterNode list from snapshot by using vote.GapNumber
3. Check signature: 3. 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
@ -566,11 +568,14 @@ func (x *XDPoS_v2) VerifyVoteMessage(chain consensus.ChainReader, vote *utils.Vo
return false, nil return false, nil
} }
snapshot, err := x.getSnapshot(chain, vote.ProposedBlockInfo.Number.Uint64(), false) snapshot, err := x.getSnapshot(chain, vote.GapNumber, true)
if err != nil { if err != nil {
log.Error("[VerifyVoteMessage] fail to get snapshot for a vote message", "BlockNum", vote.ProposedBlockInfo.Number, "Hash", vote.ProposedBlockInfo.Hash, "Error", err.Error()) log.Error("[VerifyVoteMessage] fail to get snapshot for a vote message", "BlockNum", vote.ProposedBlockInfo.Number, "Hash", vote.ProposedBlockInfo.Hash, "Error", err.Error())
} }
verified, _, err := x.verifyMsgSignature(utils.VoteSigHash(vote.ProposedBlockInfo), vote.Signature, snapshot.NextEpochMasterNodes) verified, _, err := x.verifyMsgSignature(utils.VoteSigHash(&utils.VoteForSign{
ProposedBlockInfo: vote.ProposedBlockInfo,
GapNumber: vote.GapNumber,
}), vote.Signature, snapshot.NextEpochMasterNodes)
if err != nil { if err != nil {
for i, mn := range snapshot.NextEpochMasterNodes { for i, mn := range snapshot.NextEpochMasterNodes {
log.Warn("[VerifyVoteMessage] Master node list item", "index", i, "Master node", mn.Hex()) log.Warn("[VerifyVoteMessage] Master node list item", "index", i, "Master node", mn.Hex())
@ -735,7 +740,8 @@ func (x *XDPoS_v2) verifyQC(blockChainReader consensus.ChainReader, quorumCert *
- 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 from step 1(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)
4. Verify blockInfo 4. Verify gapNumber = epochSwitchNumber - epochSwitchNumber%Epoch - Gap
5. Verify blockInfo
*/ */
epochInfo, err := x.getEpochSwitchInfo(blockChainReader, nil, quorumCert.ProposedBlockInfo.Hash) epochInfo, err := x.getEpochSwitchInfo(blockChainReader, nil, quorumCert.ProposedBlockInfo.Hash)
if err != nil { if err != nil {
@ -771,7 +777,10 @@ func (x *XDPoS_v2) verifyQC(blockChainReader consensus.ChainReader, quorumCert *
for _, signature := range signatures { for _, signature := range signatures {
go func(sig utils.Signature) { go func(sig utils.Signature) {
defer wg.Done() defer wg.Done()
verified, _, err := x.verifyMsgSignature(utils.VoteSigHash(quorumCert.ProposedBlockInfo), sig, epochInfo.Masternodes) verified, _, err := x.verifyMsgSignature(utils.VoteSigHash(&utils.VoteForSign{
ProposedBlockInfo: quorumCert.ProposedBlockInfo,
GapNumber: quorumCert.GapNumber,
}), sig, epochInfo.Masternodes)
if err != nil { if err != nil {
log.Error("[verifyQC] Error while verfying QC message signatures", "Error", err) log.Error("[verifyQC] Error while verfying QC message signatures", "Error", err)
haveError = fmt.Errorf("Error while verfying QC message signatures") haveError = fmt.Errorf("Error while verfying QC message signatures")
@ -788,7 +797,12 @@ func (x *XDPoS_v2) verifyQC(blockChainReader consensus.ChainReader, quorumCert *
if haveError != nil { if haveError != nil {
return haveError return haveError
} }
epochSwitchNumber := epochInfo.EpochSwitchBlockInfo.Number.Uint64()
gapNumber := epochSwitchNumber - epochSwitchNumber%x.config.Epoch - x.config.Gap
if gapNumber != quorumCert.GapNumber {
log.Error("[verifyQC] gap number mismatch", "BlockInfoHash", quorumCert.ProposedBlockInfo.Hash, "Gap", quorumCert.GapNumber, "GapShouldBe", gapNumber)
return fmt.Errorf("gap number mismatch %v", quorumCert)
}
return x.VerifyBlockInfo(blockChainReader, quorumCert.ProposedBlockInfo) return x.VerifyBlockInfo(blockChainReader, quorumCert.ProposedBlockInfo)
} }

View file

@ -19,7 +19,17 @@ func (x *XDPoS_v2) sendVote(chainReader consensus.ChainReader, blockInfo *utils.
// Third step: Construct the vote struct with the above signature & blockinfo struct // Third step: Construct the vote struct with the above signature & blockinfo struct
// Forth step: Send the vote to broadcast channel // Forth step: Send the vote to broadcast channel
signedHash, err := x.signSignature(utils.VoteSigHash(blockInfo)) epochSwitchInfo, err := x.getEpochSwitchInfo(chainReader, nil, blockInfo.Hash)
if err != nil {
log.Error("getEpochSwitchInfo when sending out Vote", "BlockInfoHash", blockInfo.Hash, "Error", err)
return err
}
epochSwitchNumber := epochSwitchInfo.EpochSwitchBlockInfo.Number.Uint64()
gapNumber := epochSwitchNumber - epochSwitchNumber%x.config.Epoch - x.config.Gap
signedHash, err := x.signSignature(utils.VoteSigHash(&utils.VoteForSign{
ProposedBlockInfo: blockInfo,
GapNumber: gapNumber,
}))
if err != nil { if err != nil {
log.Error("signSignature when sending out Vote", "BlockInfoHash", blockInfo.Hash, "Error", err) log.Error("signSignature when sending out Vote", "BlockInfoHash", blockInfo.Hash, "Error", err)
return err return err
@ -29,6 +39,7 @@ func (x *XDPoS_v2) sendVote(chainReader consensus.ChainReader, blockInfo *utils.
voteMsg := &utils.Vote{ voteMsg := &utils.Vote{
ProposedBlockInfo: blockInfo, ProposedBlockInfo: blockInfo,
Signature: signedHash, Signature: signedHash,
GapNumber: gapNumber,
} }
err = x.voteHandler(chainReader, voteMsg) err = x.voteHandler(chainReader, voteMsg)
@ -69,6 +80,18 @@ func (x *XDPoS_v2) voteHandler(chain consensus.ChainReader, voteMsg *utils.Vote)
x.votePool.ClearPoolKeyByObj(voteMsg) x.votePool.ClearPoolKeyByObj(voteMsg)
return err return err
} }
// verify vote.GapNumber
epochSwitchInfo, err := x.getEpochSwitchInfo(chain, nil, voteMsg.ProposedBlockInfo.Hash)
if err != nil {
log.Error("getEpochSwitchInfo when handle Vote", "BlockInfoHash", voteMsg.ProposedBlockInfo.Hash, "Error", err)
return err
}
epochSwitchNumber := epochSwitchInfo.EpochSwitchBlockInfo.Number.Uint64()
gapNumber := epochSwitchNumber - epochSwitchNumber%x.config.Epoch - x.config.Gap
if gapNumber != voteMsg.GapNumber {
log.Error("[voteHandler] gap number mismatch", "BlockInfoHash", voteMsg.ProposedBlockInfo.Hash, "Gap", voteMsg.GapNumber, "GapShouldBe", gapNumber)
return fmt.Errorf("gap number mismatch %v", voteMsg)
}
err = x.onVotePoolThresholdReached(chain, pooledVotes, voteMsg, proposedBlockHeader) err = x.onVotePoolThresholdReached(chain, pooledVotes, voteMsg, proposedBlockHeader)
if err != nil { if err != nil {
@ -95,7 +118,10 @@ func (x *XDPoS_v2) onVotePoolThresholdReached(chain consensus.ChainReader, poole
for h, vote := range pooledVotes { for h, vote := range pooledVotes {
go func(hash common.Hash, v *utils.Vote, i int) { go func(hash common.Hash, v *utils.Vote, i int) {
defer wg.Done() defer wg.Done()
verified, _, err := x.verifyMsgSignature(utils.VoteSigHash(v.ProposedBlockInfo), v.Signature, masternodes) verified, _, err := x.verifyMsgSignature(utils.VoteSigHash(&utils.VoteForSign{
ProposedBlockInfo: v.ProposedBlockInfo,
GapNumber: v.GapNumber,
}), v.Signature, masternodes)
if !verified || err != nil { if !verified || err != nil {
log.Warn("[onVotePoolThresholdReached] Skip not verified vote signatures when building QC", "Error", err.Error(), "verified", verified) log.Warn("[onVotePoolThresholdReached] Skip not verified vote signatures when building QC", "Error", err.Error(), "verified", verified)
} else { } else {
@ -123,6 +149,7 @@ func (x *XDPoS_v2) onVotePoolThresholdReached(chain consensus.ChainReader, poole
quorumCert := &utils.QuorumCert{ quorumCert := &utils.QuorumCert{
ProposedBlockInfo: currentVoteMsg.(*utils.Vote).ProposedBlockInfo, ProposedBlockInfo: currentVoteMsg.(*utils.Vote).ProposedBlockInfo,
Signatures: validSignatureSlice, Signatures: validSignatureSlice,
GapNumber: currentVoteMsg.(*utils.Vote).GapNumber,
} }
err := x.processQC(chain, quorumCert) err := x.processQC(chain, quorumCert)
if err != nil { if err != nil {

View file

@ -76,6 +76,7 @@ type BlockInfo struct {
type Vote struct { type Vote struct {
ProposedBlockInfo *BlockInfo ProposedBlockInfo *BlockInfo
Signature Signature Signature Signature
GapNumber uint64
} }
// Timeout message in XDPoS 2.0 // Timeout message in XDPoS 2.0
@ -95,6 +96,7 @@ type SyncInfo struct {
type QuorumCert struct { type QuorumCert struct {
ProposedBlockInfo *BlockInfo ProposedBlockInfo *BlockInfo
Signatures []Signature Signatures []Signature
GapNumber uint64
} }
// Timeout Certificate struct in XDPoS 2.0 // Timeout Certificate struct in XDPoS 2.0
@ -146,7 +148,12 @@ func (m *SyncInfo) Hash() common.Hash {
return rlpHash(m) return rlpHash(m)
} }
func VoteSigHash(m *BlockInfo) common.Hash { type VoteForSign struct {
ProposedBlockInfo *BlockInfo
GapNumber uint64
}
func VoteSigHash(m *VoteForSign) common.Hash {
return rlpHash(m) return rlpHash(m)
} }

View file

@ -10,10 +10,10 @@ import (
func toyExtraFields() *ExtraFields_v2 { func toyExtraFields() *ExtraFields_v2 {
round := Round(307) round := Round(307)
blockInfo := &BlockInfo{Hash: common.BigToHash(big.NewInt(2047)), Round: round - 1, Number: big.NewInt(1)} blockInfo := &BlockInfo{Hash: common.BigToHash(big.NewInt(2047)), Round: round - 1, Number: big.NewInt(900)}
signature := []byte{1, 2, 3, 4, 5, 6, 7, 8} signature := []byte{1, 2, 3, 4, 5, 6, 7, 8}
signatures := []Signature{signature} signatures := []Signature{signature}
quorumCert := &QuorumCert{ProposedBlockInfo: blockInfo, Signatures: signatures} quorumCert := &QuorumCert{ProposedBlockInfo: blockInfo, Signatures: signatures, GapNumber: 450}
e := &ExtraFields_v2{Round: round, QuorumCert: quorumCert} e := &ExtraFields_v2{Round: round, QuorumCert: quorumCert}
return e return e
} }
@ -35,16 +35,19 @@ func TestExtraFieldsEncodeDecode(t *testing.T) {
func TestHashAndSigHash(t *testing.T) { func TestHashAndSigHash(t *testing.T) {
round := Round(307) round := Round(307)
blockInfo1 := &BlockInfo{Hash: common.BigToHash(big.NewInt(2047)), Round: round - 1, Number: big.NewInt(1)} gapNumer := uint64(450)
blockInfo2 := &BlockInfo{Hash: common.BigToHash(big.NewInt(4095)), Round: round - 1, Number: big.NewInt(1)} blockInfo1 := &BlockInfo{Hash: common.BigToHash(big.NewInt(2047)), Round: round - 1, Number: big.NewInt(900)}
blockInfo2 := &BlockInfo{Hash: common.BigToHash(big.NewInt(4095)), Round: round - 1, Number: big.NewInt(900)}
voteForSign1 := &VoteForSign{ProposedBlockInfo: blockInfo1, GapNumber: gapNumer}
voteForSign2 := &VoteForSign{ProposedBlockInfo: blockInfo2, GapNumber: gapNumer}
signature1 := []byte{1, 2, 3, 4, 5, 6, 7, 8} signature1 := []byte{1, 2, 3, 4, 5, 6, 7, 8}
signature2 := []byte{1, 2, 3, 4, 5, 6, 7, 7} signature2 := []byte{1, 2, 3, 4, 5, 6, 7, 7}
signatures1 := []Signature{signature1} signatures1 := []Signature{signature1}
signatures2 := []Signature{signature2} signatures2 := []Signature{signature2}
quorumCert1 := &QuorumCert{ProposedBlockInfo: blockInfo1, Signatures: signatures1} quorumCert1 := &QuorumCert{ProposedBlockInfo: blockInfo1, Signatures: signatures1, GapNumber: 450}
quorumCert2 := &QuorumCert{ProposedBlockInfo: blockInfo1, Signatures: signatures2} quorumCert2 := &QuorumCert{ProposedBlockInfo: blockInfo1, Signatures: signatures2, GapNumber: 450}
vote1 := Vote{ProposedBlockInfo: blockInfo1, Signature: signature1} vote1 := Vote{ProposedBlockInfo: blockInfo1, Signature: signature1, GapNumber: gapNumer}
vote2 := Vote{ProposedBlockInfo: blockInfo1, Signature: signature2} vote2 := Vote{ProposedBlockInfo: blockInfo1, Signature: signature2, GapNumber: gapNumer}
if vote1.Hash() == vote2.Hash() { if vote1.Hash() == vote2.Hash() {
t.Fatalf("Hash of two votes shouldn't equal") t.Fatalf("Hash of two votes shouldn't equal")
} }
@ -58,7 +61,7 @@ func TestHashAndSigHash(t *testing.T) {
if syncInfo1.Hash() == syncInfo2.Hash() { if syncInfo1.Hash() == syncInfo2.Hash() {
t.Fatalf("Hash of two sync info shouldn't equal") t.Fatalf("Hash of two sync info shouldn't equal")
} }
if VoteSigHash(blockInfo1) == VoteSigHash(blockInfo2) { if VoteSigHash(voteForSign1) == VoteSigHash(voteForSign2) {
t.Fatalf("SigHash of two block info shouldn't equal") t.Fatalf("SigHash of two block info shouldn't equal")
} }
round2 := Round(999) round2 := Round(999)

View file

@ -96,6 +96,7 @@ func TestAdaptorIsEpochSwitch(t *testing.T) {
quorumCert := &utils.QuorumCert{ quorumCert := &utils.QuorumCert{
ProposedBlockInfo: parentBlockInfo, ProposedBlockInfo: parentBlockInfo,
Signatures: nil, Signatures: nil,
GapNumber: blockchain.Config().XDPoS.V2.SwitchBlock.Uint64()-blockchain.Config().XDPoS.Gap,
} }
extra := utils.ExtraFields_v2{ extra := utils.ExtraFields_v2{
Round: 1, Round: 1,
@ -116,6 +117,7 @@ func TestAdaptorIsEpochSwitch(t *testing.T) {
quorumCert = &utils.QuorumCert{ quorumCert = &utils.QuorumCert{
ProposedBlockInfo: parentBlockInfo, ProposedBlockInfo: parentBlockInfo,
Signatures: nil, Signatures: nil,
GapNumber: blockchain.Config().XDPoS.V2.SwitchBlock.Uint64()-blockchain.Config().XDPoS.Gap,
} }
extra = utils.ExtraFields_v2{ extra = utils.ExtraFields_v2{
Round: 2, Round: 2,
@ -136,6 +138,7 @@ func TestAdaptorIsEpochSwitch(t *testing.T) {
quorumCert = &utils.QuorumCert{ quorumCert = &utils.QuorumCert{
ProposedBlockInfo: parentBlockInfo, ProposedBlockInfo: parentBlockInfo,
Signatures: nil, Signatures: nil,
GapNumber: blockchain.Config().XDPoS.V2.SwitchBlock.Uint64()-blockchain.Config().XDPoS.Gap,
} }
extra = utils.ExtraFields_v2{ extra = utils.ExtraFields_v2{
Round: utils.Round(blockchain.Config().XDPoS.Epoch) + 1, Round: utils.Round(blockchain.Config().XDPoS.Epoch) + 1,
@ -156,6 +159,7 @@ func TestAdaptorIsEpochSwitch(t *testing.T) {
quorumCert = &utils.QuorumCert{ quorumCert = &utils.QuorumCert{
ProposedBlockInfo: parentBlockInfo, ProposedBlockInfo: parentBlockInfo,
Signatures: nil, Signatures: nil,
GapNumber: blockchain.Config().XDPoS.V2.SwitchBlock.Uint64()-blockchain.Config().XDPoS.Gap,
} }
extra = utils.ExtraFields_v2{ extra = utils.ExtraFields_v2{
Round: utils.Round(blockchain.Config().XDPoS.Epoch) + 2, Round: utils.Round(blockchain.Config().XDPoS.Epoch) + 2,

View file

@ -633,20 +633,26 @@ func generateV2Extra(roundNumber int64, currentBlock *types.Block, signer common
Round: round, Round: round,
Number: currentBlock.Number(), Number: currentBlock.Number(),
} }
gapNumber := currentBlock.Number().Uint64() - currentBlock.Number().Uint64()%params.TestXDPoSMockChainConfig.XDPoS.Epoch - params.TestXDPoSMockChainConfig.XDPoS.Gap
voteForSign := &utils.VoteForSign{
ProposedBlockInfo: proposedBlockInfo,
GapNumber: gapNumber,
}
signedHash, err := signFn(accounts.Account{Address: signer}, utils.VoteSigHash(proposedBlockInfo).Bytes()) signedHash, err := signFn(accounts.Account{Address: signer}, utils.VoteSigHash(voteForSign).Bytes())
if err != nil { if err != nil {
panic(fmt.Errorf("Error generate QC by creating signedHash: %v", err)) panic(fmt.Errorf("Error generate QC by creating signedHash: %v", err))
} }
// Sign from acc 1, 2, 3 // Sign from acc 1, 2, 3
acc1SignedHash := SignHashByPK(acc1Key, utils.VoteSigHash(proposedBlockInfo).Bytes()) acc1SignedHash := SignHashByPK(acc1Key, utils.VoteSigHash(voteForSign).Bytes())
acc2SignedHash := SignHashByPK(acc2Key, utils.VoteSigHash(proposedBlockInfo).Bytes()) acc2SignedHash := SignHashByPK(acc2Key, utils.VoteSigHash(voteForSign).Bytes())
acc3SignedHash := SignHashByPK(acc3Key, utils.VoteSigHash(proposedBlockInfo).Bytes()) acc3SignedHash := SignHashByPK(acc3Key, utils.VoteSigHash(voteForSign).Bytes())
var signatures []utils.Signature var signatures []utils.Signature
signatures = append(signatures, acc1SignedHash, acc2SignedHash, acc3SignedHash, signedHash) signatures = append(signatures, acc1SignedHash, acc2SignedHash, acc3SignedHash, signedHash)
quorumCert := &utils.QuorumCert{ quorumCert := &utils.QuorumCert{
ProposedBlockInfo: proposedBlockInfo, ProposedBlockInfo: proposedBlockInfo,
Signatures: signatures, Signatures: signatures,
GapNumber: gapNumber,
} }
extra := utils.ExtraFields_v2{ extra := utils.ExtraFields_v2{

View file

@ -33,6 +33,7 @@ func TestInitialFirstV2Blcok(t *testing.T) {
expectedQuorumCert := &utils.QuorumCert{ expectedQuorumCert := &utils.QuorumCert{
ProposedBlockInfo: blockInfo, ProposedBlockInfo: blockInfo,
Signatures: nil, Signatures: nil,
GapNumber: blockchain.Config().XDPoS.V2.SwitchBlock.Uint64()-blockchain.Config().XDPoS.Gap,
} }
assert.Equal(t, utils.Round(1), round) assert.Equal(t, utils.Round(1), round)
assert.Equal(t, expectedQuorumCert, highQC) assert.Equal(t, expectedQuorumCert, highQC)
@ -73,6 +74,7 @@ func TestInitialOtherV2Block(t *testing.T) {
quorumCert := &utils.QuorumCert{ quorumCert := &utils.QuorumCert{
ProposedBlockInfo: blockInfo, ProposedBlockInfo: blockInfo,
Signatures: nil, // after decode it got default value []utils.Signature{} Signatures: nil, // after decode it got default value []utils.Signature{}
GapNumber: 450,
} }
extra := utils.ExtraFields_v2{ extra := utils.ExtraFields_v2{
Round: 11, Round: 11,
@ -103,6 +105,7 @@ func TestInitialOtherV2Block(t *testing.T) {
expectedQuorumCert := &utils.QuorumCert{ expectedQuorumCert := &utils.QuorumCert{
ProposedBlockInfo: blockInfo, ProposedBlockInfo: blockInfo,
Signatures: []utils.Signature{}, Signatures: []utils.Signature{},
GapNumber: blockchain.Config().XDPoS.V2.SwitchBlock.Uint64()-blockchain.Config().XDPoS.Gap,
} }
assert.Equal(t, utils.Round(11), round) assert.Equal(t, utils.Round(11), round)
assert.Equal(t, expectedQuorumCert, highQC) assert.Equal(t, expectedQuorumCert, highQC)

View file

@ -108,20 +108,25 @@ func TestShouldVerifyBlock(t *testing.T) {
Round: utils.Round(2), Round: utils.Round(2),
Number: blockchain.GetBlockByNumber(902).Number(), Number: blockchain.GetBlockByNumber(902).Number(),
} }
voteForSign := &utils.VoteForSign{
ProposedBlockInfo: proposedBlockInfo,
GapNumber: 450,
}
// Genrate QC // Genrate QC
signedHash, err := signFn(accounts.Account{Address: signer}, utils.VoteSigHash(proposedBlockInfo).Bytes()) signedHash, err := signFn(accounts.Account{Address: signer}, utils.VoteSigHash(voteForSign).Bytes())
if err != nil { if err != nil {
panic(fmt.Errorf("Error generate QC by creating signedHash: %v", err)) panic(fmt.Errorf("Error generate QC by creating signedHash: %v", err))
} }
// Sign from acc 1, 2, 3 // Sign from acc 1, 2, 3
acc1SignedHash := SignHashByPK(acc1Key, utils.VoteSigHash(proposedBlockInfo).Bytes()) acc1SignedHash := SignHashByPK(acc1Key, utils.VoteSigHash(voteForSign).Bytes())
acc2SignedHash := SignHashByPK(acc2Key, utils.VoteSigHash(proposedBlockInfo).Bytes()) acc2SignedHash := SignHashByPK(acc2Key, utils.VoteSigHash(voteForSign).Bytes())
acc3SignedHash := SignHashByPK(acc3Key, utils.VoteSigHash(proposedBlockInfo).Bytes()) acc3SignedHash := SignHashByPK(acc3Key, utils.VoteSigHash(voteForSign).Bytes())
var signatures []utils.Signature var signatures []utils.Signature
signatures = append(signatures, signedHash, acc1SignedHash, acc2SignedHash, acc3SignedHash) signatures = append(signatures, signedHash, acc1SignedHash, acc2SignedHash, acc3SignedHash)
quorumCert := &utils.QuorumCert{ quorumCert := &utils.QuorumCert{
ProposedBlockInfo: proposedBlockInfo, ProposedBlockInfo: proposedBlockInfo,
Signatures: signatures, Signatures: signatures,
GapNumber: 450,
} }
extra := utils.ExtraFields_v2{ extra := utils.ExtraFields_v2{
@ -183,7 +188,11 @@ func TestShouldFailIfNotEnoughQCSignatures(t *testing.T) {
Round: utils.Round(1), Round: utils.Round(1),
Number: parentBlock.Number(), Number: parentBlock.Number(),
} }
signedHash, err := signFn(accounts.Account{Address: signer}, utils.VoteSigHash(proposedBlockInfo).Bytes()) voteForSign := &utils.VoteForSign{
ProposedBlockInfo: proposedBlockInfo,
GapNumber: 450,
}
signedHash, err := signFn(accounts.Account{Address: signer}, utils.VoteSigHash(voteForSign).Bytes())
assert.Nil(t, err) assert.Nil(t, err)
var signatures []utils.Signature var signatures []utils.Signature
// Duplicate the signatures // Duplicate the signatures
@ -191,6 +200,7 @@ func TestShouldFailIfNotEnoughQCSignatures(t *testing.T) {
quorumCert := &utils.QuorumCert{ quorumCert := &utils.QuorumCert{
ProposedBlockInfo: proposedBlockInfo, ProposedBlockInfo: proposedBlockInfo,
Signatures: signatures, Signatures: signatures,
GapNumber: 450,
} }
extra := utils.ExtraFields_v2{ extra := utils.ExtraFields_v2{

View file

@ -3,6 +3,7 @@ package engine_v2_tests
import ( import (
"fmt" "fmt"
"math/big" "math/big"
"strings"
"testing" "testing"
"github.com/XinFinOrg/XDPoSChain/accounts" "github.com/XinFinOrg/XDPoSChain/accounts"
@ -24,7 +25,11 @@ func TestVoteMessageHandlerSuccessfullyGeneratedAndProcessQCForFistV2Round(t *te
Round: utils.Round(1), Round: utils.Round(1),
Number: big.NewInt(901), Number: big.NewInt(901),
} }
voteSigningHash := utils.VoteSigHash(blockInfo) voteForSign := &utils.VoteForSign{
ProposedBlockInfo: blockInfo,
GapNumber: 450,
}
voteSigningHash := utils.VoteSigHash(voteForSign)
// Set round to 5 // Set round to 5
engineV2.SetNewRoundFaker(blockchain, utils.Round(1), false) engineV2.SetNewRoundFaker(blockchain, utils.Round(1), false)
@ -34,6 +39,7 @@ func TestVoteMessageHandlerSuccessfullyGeneratedAndProcessQCForFistV2Round(t *te
voteMsg := &utils.Vote{ voteMsg := &utils.Vote{
ProposedBlockInfo: blockInfo, ProposedBlockInfo: blockInfo,
Signature: signedHash, Signature: signedHash,
GapNumber: 450,
} }
err = engineV2.VoteHandler(blockchain, voteMsg) err = engineV2.VoteHandler(blockchain, voteMsg)
@ -49,6 +55,7 @@ func TestVoteMessageHandlerSuccessfullyGeneratedAndProcessQCForFistV2Round(t *te
voteMsg = &utils.Vote{ voteMsg = &utils.Vote{
ProposedBlockInfo: blockInfo, ProposedBlockInfo: blockInfo,
Signature: signedHash, Signature: signedHash,
GapNumber: 450,
} }
err = engineV2.VoteHandler(blockchain, voteMsg) err = engineV2.VoteHandler(blockchain, voteMsg)
assert.Nil(t, err) assert.Nil(t, err)
@ -64,6 +71,7 @@ func TestVoteMessageHandlerSuccessfullyGeneratedAndProcessQCForFistV2Round(t *te
voteMsg = &utils.Vote{ voteMsg = &utils.Vote{
ProposedBlockInfo: blockInfo, ProposedBlockInfo: blockInfo,
Signature: signedHash, Signature: signedHash,
GapNumber: 450,
} }
err = engineV2.VoteHandler(blockchain, voteMsg) err = engineV2.VoteHandler(blockchain, voteMsg)
@ -86,7 +94,11 @@ func TestVoteMessageHandlerSuccessfullyGeneratedAndProcessQC(t *testing.T) {
Round: utils.Round(5), Round: utils.Round(5),
Number: big.NewInt(905), Number: big.NewInt(905),
} }
voteSigningHash := utils.VoteSigHash(blockInfo) voteForSign := &utils.VoteForSign{
ProposedBlockInfo: blockInfo,
GapNumber: 450,
}
voteSigningHash := utils.VoteSigHash(voteForSign)
// Set round to 5 // Set round to 5
engineV2.SetNewRoundFaker(blockchain, utils.Round(5), false) engineV2.SetNewRoundFaker(blockchain, utils.Round(5), false)
@ -96,6 +108,7 @@ func TestVoteMessageHandlerSuccessfullyGeneratedAndProcessQC(t *testing.T) {
voteMsg := &utils.Vote{ voteMsg := &utils.Vote{
ProposedBlockInfo: blockInfo, ProposedBlockInfo: blockInfo,
Signature: signedHash, Signature: signedHash,
GapNumber: 450,
} }
err = engineV2.VoteHandler(blockchain, voteMsg) err = engineV2.VoteHandler(blockchain, voteMsg)
@ -109,6 +122,7 @@ func TestVoteMessageHandlerSuccessfullyGeneratedAndProcessQC(t *testing.T) {
voteMsg = &utils.Vote{ voteMsg = &utils.Vote{
ProposedBlockInfo: blockInfo, ProposedBlockInfo: blockInfo,
Signature: signedHash, Signature: signedHash,
GapNumber: 450,
} }
err = engineV2.VoteHandler(blockchain, voteMsg) err = engineV2.VoteHandler(blockchain, voteMsg)
assert.Nil(t, err) assert.Nil(t, err)
@ -127,6 +141,7 @@ func TestVoteMessageHandlerSuccessfullyGeneratedAndProcessQC(t *testing.T) {
voteMsg = &utils.Vote{ voteMsg = &utils.Vote{
ProposedBlockInfo: blockInfo, ProposedBlockInfo: blockInfo,
Signature: randomlySignedHash, Signature: randomlySignedHash,
GapNumber: 450,
} }
err = engineV2.VoteHandler(blockchain, voteMsg) err = engineV2.VoteHandler(blockchain, voteMsg)
assert.Nil(t, err) assert.Nil(t, err)
@ -141,6 +156,7 @@ func TestVoteMessageHandlerSuccessfullyGeneratedAndProcessQC(t *testing.T) {
voteMsg = &utils.Vote{ voteMsg = &utils.Vote{
ProposedBlockInfo: blockInfo, ProposedBlockInfo: blockInfo,
Signature: signedHash, Signature: signedHash,
GapNumber: 450,
} }
err = engineV2.VoteHandler(blockchain, voteMsg) err = engineV2.VoteHandler(blockchain, voteMsg)
@ -172,6 +188,7 @@ func TestThrowErrorIfVoteMsgRoundIsMoreThanOneRoundAwayFromCurrentRound(t *testi
voteMsg := &utils.Vote{ voteMsg := &utils.Vote{
ProposedBlockInfo: blockInfo, ProposedBlockInfo: blockInfo,
Signature: []byte{1}, Signature: []byte{1},
GapNumber: 450,
} }
// voteRound > currentRound // voteRound > currentRound
@ -204,12 +221,17 @@ func TestProcessVoteMsgThenTimeoutMsg(t *testing.T) {
Round: utils.Round(5), Round: utils.Round(5),
Number: big.NewInt(905), Number: big.NewInt(905),
} }
voteSigningHash := utils.VoteSigHash(blockInfo) voteForSign := &utils.VoteForSign{
ProposedBlockInfo: blockInfo,
GapNumber: 450,
}
voteSigningHash := utils.VoteSigHash(voteForSign)
// Create two vote message which will not reach vote pool threshold // Create two vote message which will not reach vote pool threshold
signedHash := SignHashByPK(acc1Key, voteSigningHash.Bytes()) signedHash := SignHashByPK(acc1Key, voteSigningHash.Bytes())
voteMsg := &utils.Vote{ voteMsg := &utils.Vote{
ProposedBlockInfo: blockInfo, ProposedBlockInfo: blockInfo,
Signature: signedHash, Signature: signedHash,
GapNumber: 450,
} }
err := engineV2.VoteHandler(blockchain, voteMsg) err := engineV2.VoteHandler(blockchain, voteMsg)
@ -223,6 +245,7 @@ func TestProcessVoteMsgThenTimeoutMsg(t *testing.T) {
voteMsg = &utils.Vote{ voteMsg = &utils.Vote{
ProposedBlockInfo: blockInfo, ProposedBlockInfo: blockInfo,
Signature: SignHashByPK(acc2Key, voteSigningHash.Bytes()), Signature: SignHashByPK(acc2Key, voteSigningHash.Bytes()),
GapNumber: 450,
} }
err = engineV2.VoteHandler(blockchain, voteMsg) err = engineV2.VoteHandler(blockchain, voteMsg)
assert.Nil(t, err) assert.Nil(t, err)
@ -233,6 +256,7 @@ func TestProcessVoteMsgThenTimeoutMsg(t *testing.T) {
voteMsg = &utils.Vote{ voteMsg = &utils.Vote{
ProposedBlockInfo: blockInfo, ProposedBlockInfo: blockInfo,
Signature: SignHashByPK(acc3Key, voteSigningHash.Bytes()), Signature: SignHashByPK(acc3Key, voteSigningHash.Bytes()),
GapNumber: 450,
} }
err = engineV2.VoteHandler(blockchain, voteMsg) err = engineV2.VoteHandler(blockchain, voteMsg)
@ -318,7 +342,11 @@ func TestVoteMessageShallNotThrowErrorIfBlockNotYetExist(t *testing.T) {
Round: utils.Round(6), Round: utils.Round(6),
Number: big.NewInt(906), Number: big.NewInt(906),
} }
voteSigningHash := utils.VoteSigHash(blockInfo) voteForSign := &utils.VoteForSign{
ProposedBlockInfo: blockInfo,
GapNumber: 450,
}
voteSigningHash := utils.VoteSigHash(voteForSign)
// Set round to 6 // Set round to 6
engineV2.SetNewRoundFaker(blockchain, utils.Round(6), false) engineV2.SetNewRoundFaker(blockchain, utils.Round(6), false)
@ -326,6 +354,7 @@ func TestVoteMessageShallNotThrowErrorIfBlockNotYetExist(t *testing.T) {
voteMsg := &utils.Vote{ voteMsg := &utils.Vote{
ProposedBlockInfo: blockInfo, ProposedBlockInfo: blockInfo,
Signature: SignHashByPK(acc1Key, voteSigningHash.Bytes()), Signature: SignHashByPK(acc1Key, voteSigningHash.Bytes()),
GapNumber: 450,
} }
err := engineV2.VoteHandler(blockchain, voteMsg) err := engineV2.VoteHandler(blockchain, voteMsg)
@ -334,6 +363,7 @@ func TestVoteMessageShallNotThrowErrorIfBlockNotYetExist(t *testing.T) {
voteMsg = &utils.Vote{ voteMsg = &utils.Vote{
ProposedBlockInfo: blockInfo, ProposedBlockInfo: blockInfo,
Signature: SignHashByPK(acc2Key, voteSigningHash.Bytes()), Signature: SignHashByPK(acc2Key, voteSigningHash.Bytes()),
GapNumber: 450,
} }
err = engineV2.VoteHandler(blockchain, voteMsg) err = engineV2.VoteHandler(blockchain, voteMsg)
assert.Nil(t, err) assert.Nil(t, err)
@ -342,6 +372,7 @@ func TestVoteMessageShallNotThrowErrorIfBlockNotYetExist(t *testing.T) {
voteMsg = &utils.Vote{ voteMsg = &utils.Vote{
ProposedBlockInfo: blockInfo, ProposedBlockInfo: blockInfo,
Signature: SignHashByPK(acc3Key, voteSigningHash.Bytes()), Signature: SignHashByPK(acc3Key, voteSigningHash.Bytes()),
GapNumber: 450,
} }
err = engineV2.VoteHandler(blockchain, voteMsg) err = engineV2.VoteHandler(blockchain, voteMsg)
@ -360,6 +391,7 @@ func TestVoteMessageShallNotThrowErrorIfBlockNotYetExist(t *testing.T) {
voteMsg = &utils.Vote{ voteMsg = &utils.Vote{
ProposedBlockInfo: blockInfo, ProposedBlockInfo: blockInfo,
Signature: SignHashByPK(voterKey, voteSigningHash.Bytes()), Signature: SignHashByPK(voterKey, voteSigningHash.Bytes()),
GapNumber: 450,
} }
err = engineV2.VoteHandler(blockchain, voteMsg) err = engineV2.VoteHandler(blockchain, voteMsg)
@ -389,12 +421,17 @@ func TestProcessVoteMsgFailIfVerifyBlockInfoFail(t *testing.T) {
Round: utils.Round(5), Round: utils.Round(5),
Number: big.NewInt(905), Number: big.NewInt(905),
} }
voteSigningHash := utils.VoteSigHash(blockInfo) voteForSign := &utils.VoteForSign{
ProposedBlockInfo: blockInfo,
GapNumber: 450,
}
voteSigningHash := utils.VoteSigHash(voteForSign)
// Create two vote message which will not reach vote pool threshold // Create two vote message which will not reach vote pool threshold
signedHash := SignHashByPK(acc1Key, voteSigningHash.Bytes()) signedHash := SignHashByPK(acc1Key, voteSigningHash.Bytes())
voteMsg := &utils.Vote{ voteMsg := &utils.Vote{
ProposedBlockInfo: blockInfo, ProposedBlockInfo: blockInfo,
Signature: signedHash, Signature: signedHash,
GapNumber: 450,
} }
err := engineV2.VoteHandler(blockchain, voteMsg) err := engineV2.VoteHandler(blockchain, voteMsg)
@ -408,6 +445,7 @@ func TestProcessVoteMsgFailIfVerifyBlockInfoFail(t *testing.T) {
voteMsg = &utils.Vote{ voteMsg = &utils.Vote{
ProposedBlockInfo: blockInfo, ProposedBlockInfo: blockInfo,
Signature: SignHashByPK(acc2Key, voteSigningHash.Bytes()), Signature: SignHashByPK(acc2Key, voteSigningHash.Bytes()),
GapNumber: 450,
} }
err = engineV2.VoteHandler(blockchain, voteMsg) err = engineV2.VoteHandler(blockchain, voteMsg)
assert.Nil(t, err) assert.Nil(t, err)
@ -418,6 +456,7 @@ func TestProcessVoteMsgFailIfVerifyBlockInfoFail(t *testing.T) {
voteMsg = &utils.Vote{ voteMsg = &utils.Vote{
ProposedBlockInfo: blockInfo, ProposedBlockInfo: blockInfo,
Signature: SignHashByPK(acc3Key, voteSigningHash.Bytes()), Signature: SignHashByPK(acc3Key, voteSigningHash.Bytes()),
GapNumber: 450,
} }
err = engineV2.VoteHandler(blockchain, voteMsg) err = engineV2.VoteHandler(blockchain, voteMsg)
@ -434,11 +473,16 @@ func TestVerifyVoteMsg(t *testing.T) {
Round: utils.Round(14), Round: utils.Round(14),
Number: big.NewInt(915), Number: big.NewInt(915),
} }
voteForSign := &utils.VoteForSign{
ProposedBlockInfo: blockInfo,
GapNumber: 450,
}
// Valid message but disqualified as the round does not match // Valid message but disqualified as the round does not match
voteMsg := &utils.Vote{ voteMsg := &utils.Vote{
ProposedBlockInfo: blockInfo, ProposedBlockInfo: blockInfo,
Signature: []byte{1}, Signature: []byte{1},
GapNumber: 450,
} }
engineV2.SetNewRoundFaker(blockchain, utils.Round(15), false) engineV2.SetNewRoundFaker(blockchain, utils.Round(15), false)
verified, err := engineV2.VerifyVoteMessage(blockchain, voteMsg) verified, err := engineV2.VerifyVoteMessage(blockchain, voteMsg)
@ -452,13 +496,64 @@ func TestVerifyVoteMsg(t *testing.T) {
assert.Equal(t, "Error while verifying message: invalid signature length", err.Error()) assert.Equal(t, "Error while verifying message: invalid signature length", err.Error())
// Valid vote message from a master node // Valid vote message from a master node
signHash, _ := signFn(accounts.Account{Address: signer}, utils.VoteSigHash(blockInfo).Bytes()) signHash, _ := signFn(accounts.Account{Address: signer}, utils.VoteSigHash(voteForSign).Bytes())
voteMsg = &utils.Vote{ voteMsg = &utils.Vote{
ProposedBlockInfo: blockInfo, ProposedBlockInfo: blockInfo,
Signature: signHash, Signature: signHash,
GapNumber: 450,
} }
verified, err = engineV2.VerifyVoteMessage(blockchain, voteMsg) verified, err = engineV2.VerifyVoteMessage(blockchain, voteMsg)
assert.True(t, verified) assert.True(t, verified)
assert.Nil(t, err) assert.Nil(t, err)
} }
func TestVoteMessageHandlerWrongGapNumber(t *testing.T) {
blockchain, _, currentBlock, signer, signFn, _ := PrepareXDCTestBlockChainForV2Engine(t, 905, params.TestXDPoSMockChainConfig, 0)
engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2
blockInfo := &utils.BlockInfo{
Hash: currentBlock.Hash(),
Round: utils.Round(5),
Number: big.NewInt(905),
}
voteForSign := &utils.VoteForSign{
ProposedBlockInfo: blockInfo,
GapNumber: 450,
}
voteSigningHash := utils.VoteSigHash(voteForSign)
// Set round to 5
engineV2.SetNewRoundFaker(blockchain, utils.Round(5), false)
// Create two vote messages which will not reach vote pool threshold
signedHash, _ := signFn(accounts.Account{Address: signer}, voteSigningHash.Bytes())
voteMsg := &utils.Vote{
ProposedBlockInfo: blockInfo,
Signature: signedHash,
GapNumber: 450,
}
engineV2.VoteHandler(blockchain, voteMsg)
signedHash = SignHashByPK(acc1Key, voteSigningHash.Bytes())
voteMsg = &utils.Vote{
ProposedBlockInfo: blockInfo,
Signature: signedHash,
GapNumber: 450,
}
engineV2.VoteHandler(blockchain, voteMsg)
// Create a vote message that has wrong gap number
voteForSign = &utils.VoteForSign{
ProposedBlockInfo: blockInfo,
GapNumber: 451,
}
voteSigningHash = utils.VoteSigHash(voteForSign)
signedHash = SignHashByPK(acc3Key, voteSigningHash.Bytes())
voteMsg = &utils.Vote{
ProposedBlockInfo: blockInfo,
Signature: signedHash,
GapNumber: 451,
}
err := engineV2.VoteHandler(blockchain, voteMsg)
assert.True(t, strings.Contains(err.Error(), "gap number mismatch"))
}

View file

@ -21,6 +21,7 @@ func makeVotes(n int) []utils.Vote {
votes = append(votes, utils.Vote{ votes = append(votes, utils.Vote{
ProposedBlockInfo: &utils.BlockInfo{}, ProposedBlockInfo: &utils.BlockInfo{},
Signature: []byte{byte(i)}, Signature: []byte{byte(i)},
GapNumber: 0,
}) })
} }
return votes return votes