mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 13:21:37 +00:00
consensus: verify timeout from epochInfo instead of snap.NextEpochCandidates, close XFN-62 (#1628)
This commit is contained in:
parent
fac866138b
commit
e617598d1d
6 changed files with 33 additions and 55 deletions
|
|
@ -78,6 +78,10 @@ func (x *XDPoS_v2) getEpochSwitchInfo(chain consensus.ChainReader, header *types
|
|||
log.Error("[getEpochSwitchInfo] get extra field", "err", err, "number", h.Number.Uint64())
|
||||
return nil, err
|
||||
}
|
||||
if len(masternodes) == 0 {
|
||||
return nil, fmt.Errorf("masternodes list is empty at epoch switch block %v", h.Number.Uint64())
|
||||
}
|
||||
|
||||
snap, err := x.getSnapshot(chain, h.Number.Uint64(), false)
|
||||
if err != nil {
|
||||
log.Error("[getEpochSwitchInfo] Adaptor v2 getSnapshot has error", "err", err)
|
||||
|
|
@ -110,11 +114,13 @@ func (x *XDPoS_v2) getEpochSwitchInfo(chain consensus.ChainReader, header *types
|
|||
x.epochSwitches.Add(hash, epochSwitchInfo)
|
||||
return epochSwitchInfo, nil
|
||||
}
|
||||
|
||||
epochSwitchInfo, err = x.getEpochSwitchInfo(chain, nil, h.ParentHash)
|
||||
if err != nil {
|
||||
log.Error("[getEpochSwitchInfo] recursive error", "err", err, "hash", hash.Hex(), "number", h.Number.Uint64())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Debug("[getEpochSwitchInfo] get epoch switch info recursively", "hash", hash.Hex(), "number", h.Number.Uint64())
|
||||
x.epochSwitches.Add(hash, epochSwitchInfo)
|
||||
return epochSwitchInfo, nil
|
||||
|
|
|
|||
|
|
@ -31,9 +31,9 @@ func (x *XDPoS_v2) VerifySyncInfoMessage(chain consensus.ChainReader, syncInfo *
|
|||
return false, nil
|
||||
}
|
||||
|
||||
snapshot, err := x.getSnapshot(chain, qc.GapNumber, true)
|
||||
epochInfo, err := x.getEpochSwitchInfo(chain, nil, qc.ProposedBlockInfo.Hash)
|
||||
if err != nil {
|
||||
log.Error("[VerifySyncInfoMessage] fail to get snapshot for a syncInfo message", "blockNum", qc.ProposedBlockInfo.Number, "blockHash", qc.ProposedBlockInfo.Hash, "error", err)
|
||||
log.Error("[VerifySyncInfoMessage] fail to get epochInfo for qc syncInfo message", "blockNum", qc.ProposedBlockInfo.Number, "blockHash", qc.ProposedBlockInfo.Hash, "error", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
|
|
@ -42,16 +42,16 @@ func (x *XDPoS_v2) VerifySyncInfoMessage(chain consensus.ChainReader, syncInfo *
|
|||
GapNumber: qc.GapNumber,
|
||||
})
|
||||
|
||||
if err := x.verifySignatures(voteSigHash, qc.Signatures, snapshot.NextEpochCandidates); err != nil {
|
||||
if err := x.verifySignatures(voteSigHash, qc.Signatures, epochInfo.Masternodes); err != nil {
|
||||
log.Warn("[VerifySyncInfoMessage] SyncInfo message verification failed due to QC", "blockNum", qc.ProposedBlockInfo.Number, "gapNum", qc.GapNumber, "round", qc.ProposedBlockInfo.Round, "error", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
if tc != nil { // tc is optional, when the node is starting up there is no TC at the memory
|
||||
snapshot, err = x.getSnapshot(chain, tc.GapNumber, true)
|
||||
epochInfo, err := x.getTCEpochInfo(chain, tc.Round)
|
||||
if err != nil {
|
||||
log.Error("[VerifySyncInfoMessage] Fail to get snapshot when verifying TC!", "tcGapNumber", tc.GapNumber)
|
||||
return false, fmt.Errorf("[VerifySyncInfoMessage] Unable to get snapshot, %s", err)
|
||||
log.Error("[VerifySyncInfoMessage] Fail to get epochInfo for tc syncInfo message", "tcRound", tc.Round, "error", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
signedTimeoutObj := types.TimeoutSigHash(&types.TimeoutForSign{
|
||||
|
|
@ -59,7 +59,7 @@ func (x *XDPoS_v2) VerifySyncInfoMessage(chain consensus.ChainReader, syncInfo *
|
|||
GapNumber: tc.GapNumber,
|
||||
})
|
||||
|
||||
if err := x.verifySignatures(signedTimeoutObj, tc.Signatures, snapshot.NextEpochCandidates); err != nil {
|
||||
if err := x.verifySignatures(signedTimeoutObj, tc.Signatures, epochInfo.Masternodes); err != nil {
|
||||
log.Warn("[VerifySyncInfoMessage] SyncInfo message verification failed due to TC", "gapNum", tc.GapNumber, "round", tc.Round, "error", err)
|
||||
return false, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,20 +22,17 @@ func (x *XDPoS_v2) VerifyTimeoutMessage(chain consensus.ChainReader, timeoutMsg
|
|||
log.Debug("[VerifyTimeoutMessage] Disqualified timeout message as the proposed round does not match currentRound", "timeoutHash", timeoutMsg.Hash(), "timeoutRound", timeoutMsg.Round, "currentRound", x.currentRound)
|
||||
return false, nil
|
||||
}
|
||||
snap, err := x.getSnapshot(chain, timeoutMsg.GapNumber, true)
|
||||
if err != nil || snap == nil {
|
||||
log.Error("[VerifyTimeoutMessage] Fail to get snapshot when verifying timeout message!", "messageGapNumber", timeoutMsg.GapNumber, "err", err)
|
||||
|
||||
epochInfo, err := x.getTCEpochInfo(chain, timeoutMsg.Round)
|
||||
if err != nil {
|
||||
log.Error("[VerifyTimeoutMessage] Fail to get epochInfo for timeout message", "tcGapNumber", timeoutMsg.GapNumber, "tcRound", timeoutMsg.Round, "error", err)
|
||||
return false, err
|
||||
}
|
||||
if len(snap.NextEpochCandidates) == 0 {
|
||||
log.Error("[VerifyTimeoutMessage] cannot find NextEpochCandidates from snapshot", "messageGapNumber", timeoutMsg.GapNumber)
|
||||
return false, errors.New("empty master node lists from snapshot")
|
||||
}
|
||||
|
||||
verified, signer, err := x.verifyMsgSignature(types.TimeoutSigHash(&types.TimeoutForSign{
|
||||
Round: timeoutMsg.Round,
|
||||
GapNumber: timeoutMsg.GapNumber,
|
||||
}), timeoutMsg.Signature, snap.NextEpochCandidates)
|
||||
}), timeoutMsg.Signature, epochInfo.Masternodes)
|
||||
|
||||
if err != nil {
|
||||
log.Warn("[VerifyTimeoutMessage] cannot verify timeout signature", "err", err)
|
||||
|
|
@ -116,7 +113,7 @@ func (x *XDPoS_v2) onTimeoutPoolThresholdReached(blockChainReader consensus.Chai
|
|||
return nil
|
||||
}
|
||||
|
||||
func (x *XDPoS_v2) getTCEpochInfo(chain consensus.ChainReader, timeoutCert *types.TimeoutCert) (*types.EpochSwitchInfo, error) {
|
||||
func (x *XDPoS_v2) getTCEpochInfo(chain consensus.ChainReader, timeoutRound types.Round) (*types.EpochSwitchInfo, error) {
|
||||
epochSwitchInfo, err := x.getEpochSwitchInfo(chain, (chain.CurrentHeader()), (chain.CurrentHeader()).Hash())
|
||||
if err != nil {
|
||||
log.Error("[getTCEpochInfo] Error when getting epoch switch info", "error", err)
|
||||
|
|
@ -131,18 +128,18 @@ func (x *XDPoS_v2) getTCEpochInfo(chain consensus.ChainReader, timeoutCert *type
|
|||
Round: epochRound,
|
||||
Number: epochSwitchInfo.EpochSwitchBlockInfo.Number,
|
||||
}
|
||||
log.Info("[getTCEpochInfo] Init epochInfo", "number", epochBlockInfo.Number, "round", epochRound, "tcRound", timeoutCert.Round, "tcEpoch", tempTCEpoch)
|
||||
for epochBlockInfo.Round > timeoutCert.Round {
|
||||
log.Info("[getTCEpochInfo] Init epochInfo", "number", epochBlockInfo.Number, "round", epochRound, "tcRound", timeoutRound, "tcEpoch", tempTCEpoch)
|
||||
for epochBlockInfo.Round > timeoutRound {
|
||||
tempTCEpoch--
|
||||
epochBlockInfo, err = x.GetBlockByEpochNumber(chain, tempTCEpoch)
|
||||
if err != nil {
|
||||
log.Error("[getTCEpochInfo] Error when getting epoch block info by tc round", "error", err)
|
||||
return nil, fmt.Errorf("fail on getTCEpochInfo due to failure in getting epoch block info tc round, %s", err)
|
||||
}
|
||||
log.Debug("[getTCEpochInfo] Loop to get right epochInfo", "number", epochBlockInfo.Number, "round", epochBlockInfo.Round, "tcRound", timeoutCert.Round, "tcEpoch", tempTCEpoch)
|
||||
log.Debug("[getTCEpochInfo] Loop to get right epochInfo", "number", epochBlockInfo.Number, "round", epochBlockInfo.Round, "tcRound", timeoutRound, "tcEpoch", tempTCEpoch)
|
||||
}
|
||||
tcEpoch := tempTCEpoch
|
||||
log.Info("[getTCEpochInfo] Final TC epochInfo", "number", epochBlockInfo.Number, "round", epochBlockInfo.Round, "tcRound", timeoutCert.Round, "tcEpoch", tcEpoch)
|
||||
log.Info("[getTCEpochInfo] Final TC epochInfo", "number", epochBlockInfo.Number, "round", epochBlockInfo.Round, "tcRound", timeoutRound, "tcEpoch", tcEpoch)
|
||||
|
||||
epochInfo, err := x.getEpochSwitchInfo(chain, nil, epochBlockInfo.Hash)
|
||||
if err != nil {
|
||||
|
|
@ -175,7 +172,7 @@ func (x *XDPoS_v2) verifyTC(chain consensus.ChainReader, timeoutCert *types.Time
|
|||
}
|
||||
}
|
||||
|
||||
epochInfo, err := x.getTCEpochInfo(chain, timeoutCert)
|
||||
epochInfo, err := x.getTCEpochInfo(chain, timeoutCert.Round)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,17 +22,18 @@ func (x *XDPoS_v2) VerifyVoteMessage(chain consensus.ChainReader, vote *types.Vo
|
|||
return false, nil
|
||||
}
|
||||
|
||||
snapshot, err := x.getSnapshot(chain, vote.GapNumber, true)
|
||||
epochInfo, err := x.getEpochSwitchInfo(chain, chain.CurrentHeader(), chain.CurrentHeader().Hash())
|
||||
if err != nil {
|
||||
log.Error("[VerifyVoteMessage] fail to get snapshot for a vote message", "blockNum", vote.ProposedBlockInfo.Number, "blockHash", vote.ProposedBlockInfo.Hash, "voteHash", vote.Hash(), "error", err.Error())
|
||||
log.Error("[VerifyVoteMessage] Fail to get epochInfo when verifying vote message!", "blockNum", vote.ProposedBlockInfo.Number, "blockHash", vote.ProposedBlockInfo.Hash, "voteHash", vote.Hash(), "voteGapNumber", vote.GapNumber, "err", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
verified, signer, err := x.verifyMsgSignature(types.VoteSigHash(&types.VoteForSign{
|
||||
ProposedBlockInfo: vote.ProposedBlockInfo,
|
||||
GapNumber: vote.GapNumber,
|
||||
}), vote.Signature, snapshot.NextEpochCandidates)
|
||||
}), vote.Signature, epochInfo.Masternodes)
|
||||
if err != nil {
|
||||
for i, mn := range snapshot.NextEpochCandidates {
|
||||
for i, mn := range epochInfo.Masternodes {
|
||||
log.Warn("[VerifyVoteMessage] Master node list item", "index", i, "Master node", mn.Hex())
|
||||
}
|
||||
log.Warn("[VerifyVoteMessage] Error while verifying vote message", "votedBlockNum", vote.ProposedBlockInfo.Number.Uint64(), "votedBlockHash", vote.ProposedBlockInfo.Hash.Hex(), "voteHash", vote.Hash(), "error", err.Error())
|
||||
|
|
|
|||
|
|
@ -172,11 +172,11 @@ func TestGetBlockByEpochNumber(t *testing.T) {
|
|||
blockchain, _, currentBlock, signer, signFn := PrepareXDCTestBlockChainWithPenaltyForV2Engine(t, 1802, params.TestXDPoSMockChainConfig)
|
||||
|
||||
blockCoinBase := "0x111000000000000000000000000000000123"
|
||||
largeRound := int64(1802)
|
||||
largeRound := int64(1800)
|
||||
newBlock := CreateBlock(blockchain, params.TestXDPoSMockChainConfig, currentBlock, int(currentBlock.NumberU64())+1, largeRound, blockCoinBase, signer, signFn, nil, nil, currentBlock.Header().Root.Hex())
|
||||
err := blockchain.InsertBlock(newBlock)
|
||||
assert.Nil(t, err)
|
||||
largeRound2 := int64(3603)
|
||||
largeRound2 := int64(3600)
|
||||
newBlock2 := CreateBlock(blockchain, params.TestXDPoSMockChainConfig, newBlock, int(newBlock.NumberU64())+1, largeRound2, blockCoinBase, signer, signFn, nil, nil, newBlock.Header().Root.Hex())
|
||||
err = blockchain.InsertBlock(newBlock2)
|
||||
assert.Nil(t, err)
|
||||
|
|
@ -189,9 +189,9 @@ func TestGetBlockByEpochNumber(t *testing.T) {
|
|||
// 1800,900,2 (2nd epoch switch block)
|
||||
// 1801,901,2
|
||||
// 1802,902,2
|
||||
// 1803,1802,3 (epoch switch)
|
||||
// 1803,1800,3 (epoch switch)
|
||||
// epoch 4 has no block
|
||||
// 1804,3603,5 (epoch switch)
|
||||
// 1804,3600,5 (epoch switch)
|
||||
engine := blockchain.Engine().(*XDPoS.XDPoS)
|
||||
|
||||
// init the snapshot, otherwise getEpochSwitchInfo would return error
|
||||
|
|
|
|||
|
|
@ -537,32 +537,6 @@ func TestVerifyVoteMsg(t *testing.T) {
|
|||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestVoteMsgMissingSnapshot(t *testing.T) {
|
||||
blockchain, _, currentBlock, signer, signFn, _ := PrepareXDCTestBlockChainForV2Engine(t, 915, params.TestXDPoSMockChainConfig, nil)
|
||||
engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2
|
||||
|
||||
blockInfo := &types.BlockInfo{
|
||||
Hash: currentBlock.Hash(),
|
||||
Round: types.Round(14),
|
||||
Number: big.NewInt(915),
|
||||
}
|
||||
voteForSign := &types.VoteForSign{
|
||||
ProposedBlockInfo: blockInfo,
|
||||
GapNumber: 450,
|
||||
}
|
||||
|
||||
signHash, _ := signFn(accounts.Account{Address: signer}, types.VoteSigHash(voteForSign).Bytes())
|
||||
voteMsg := &types.Vote{
|
||||
ProposedBlockInfo: blockInfo,
|
||||
Signature: signHash,
|
||||
GapNumber: 1350, // missing 1350 snapshot
|
||||
}
|
||||
engineV2.SetNewRoundFaker(blockchain, types.Round(14), false)
|
||||
verified, err := engineV2.VerifyVoteMessage(blockchain, voteMsg)
|
||||
assert.False(t, verified)
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestVoteMessageHandlerWrongGapNumber(t *testing.T) {
|
||||
blockchain, _, currentBlock, signer, signFn, _ := PrepareXDCTestBlockChainForV2Engine(t, 905, params.TestXDPoSMockChainConfig, nil)
|
||||
engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2
|
||||
|
|
|
|||
Loading…
Reference in a new issue