update adaptor for verify headers and fix vote handler to include +1 distance when checking rounds (#48)

This commit is contained in:
Jerome 2022-01-30 14:26:05 +11:00 committed by GitHub
parent 328d555b9b
commit 7cc2bef2d3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 60 additions and 15 deletions

View file

@ -149,8 +149,30 @@ func (x *XDPoS) VerifyHeader(chain consensus.ChainReader, header *types.Header,
// method returns a quit channel to abort the operations and a results channel to
// retrieve the async verifications (the order is that of the input slice).
func (x *XDPoS) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, fullVerifies []bool) (chan<- struct{}, <-chan error) {
// TODO: (Hashlab) This funciton is a special case
return x.EngineV1.VerifyHeaders(chain, headers, fullVerifies)
abort := make(chan struct{})
results := make(chan error, len(headers))
// Split the headers list into v1 and v2 buckets
var v1headers []*types.Header
var v2headers []*types.Header
for _, header := range headers {
switch x.config.BlockConsensusVersion(header.Number) {
case params.ConsensusEngineVersion2:
v2headers = append(v2headers, header)
default: // Default "v1"
v1headers = append(v1headers, header)
}
}
if v1headers != nil {
x.EngineV1.VerifyHeaders(chain, headers, fullVerifies, abort, results)
}
if v2headers != nil {
x.EngineV2.VerifyHeaders(chain, headers, fullVerifies, abort, results)
}
return abort, results
}
// VerifyUncles implements consensus.Engine, always returning an error for any

View file

@ -116,10 +116,7 @@ func (x *XDPoS_v1) VerifyHeader(chain consensus.ChainReader, header *types.Heade
// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers. The
// method returns a quit channel to abort the operations and a results channel to
// retrieve the async verifications (the order is that of the input slice).
func (x *XDPoS_v1) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, fullVerifies []bool) (chan<- struct{}, <-chan error) {
abort := make(chan struct{})
results := make(chan error, len(headers))
func (x *XDPoS_v1) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, fullVerifies []bool, abort <-chan struct{}, results chan<- error) {
go func() {
for i, header := range headers {
err := x.verifyHeaderWithCache(chain, header, headers[:i], fullVerifies[i])
@ -131,7 +128,6 @@ func (x *XDPoS_v1) VerifyHeaders(chain consensus.ChainReader, headers []*types.H
}
}
}()
return abort, results
}
func (x *XDPoS_v1) verifyHeaderWithCache(chain consensus.ChainReader, header *types.Header, parents []*types.Header, fullVerify bool) error {

View file

@ -478,6 +478,19 @@ func (x *XDPoS_v2) VerifyHeader(chain consensus.ChainReader, header *types.Heade
return nil
}
// TODO: Yet to be implemented XIN-135
func (x *XDPoS_v2) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, fullVerifies []bool, abort <-chan struct{}, results chan<- error) {
go func() {
for range headers {
select {
case <-abort:
return
case results <- nil:
}
}
}()
}
// Utils for test to get current Pool size
func (x *XDPoS_v2) GetVotePoolSize(vote *utils.Vote) int {
return x.votePool.Size(vote)
@ -556,8 +569,8 @@ func (x *XDPoS_v2) VoteHandler(chain consensus.ChainReader, voteMsg *utils.Vote)
func (x *XDPoS_v2) voteHandler(chain consensus.ChainReader, voteMsg *utils.Vote) error {
// 1. checkRoundNumber
if voteMsg.ProposedBlockInfo.Round != x.currentRound {
return &utils.ErrIncomingMessageRoundNotEqualCurrentRound{
if (voteMsg.ProposedBlockInfo.Round != x.currentRound) && (voteMsg.ProposedBlockInfo.Round != x.currentRound+1) {
return &utils.ErrIncomingMessageRoundTooFarFromCurrentRound{
Type: "vote",
IncomingRound: voteMsg.ProposedBlockInfo.Round,
CurrentRound: x.currentRound,

View file

@ -88,3 +88,13 @@ type ErrIncomingMessageRoundNotEqualCurrentRound struct {
func (e *ErrIncomingMessageRoundNotEqualCurrentRound) Error() string {
return fmt.Sprintf("%s message round number: %v does not match currentRound: %v", e.Type, e.IncomingRound, e.CurrentRound)
}
type ErrIncomingMessageRoundTooFarFromCurrentRound struct {
Type string
IncomingRound Round
CurrentRound Round
}
func (e *ErrIncomingMessageRoundTooFarFromCurrentRound) Error() string {
return fmt.Sprintf("%s message round number: %v is too far away from currentRound: %v", e.Type, e.IncomingRound, e.CurrentRound)
}

View file

@ -126,7 +126,7 @@ func TestVoteMessageHandlerSuccessfullyGeneratedAndProcessQC(t *testing.T) {
assert.Equal(t, big.NewInt(13), highestCommitBlock.Number)
}
func TestThrowErrorIfVoteMsgRoundNotEqualToCurrentRound(t *testing.T) {
func TestThrowErrorIfVoteMsgRoundIsMoreThanOneRoundAwayFromCurrentRound(t *testing.T) {
blockchain, _, _, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 15, params.TestXDPoSMockChainConfigWithV2Engine, 0)
engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2
@ -146,14 +146,18 @@ func TestThrowErrorIfVoteMsgRoundNotEqualToCurrentRound(t *testing.T) {
// voteRound > currentRound
err := engineV2.VoteHandler(blockchain, voteMsg)
assert.NotNil(t, err)
assert.Equal(t, "vote message round number: 6 does not match currentRound: 7", err.Error())
assert.Equal(t, "vote message round number: 6 is too far away from currentRound: 7", err.Error())
// Set round to 5
// Set round to 5, it's 1 round away, should not trigger failure
engineV2.SetNewRoundFaker(utils.Round(5), false)
err = engineV2.VoteHandler(blockchain, voteMsg)
assert.Nil(t, err)
engineV2.SetNewRoundFaker(utils.Round(4), false)
err = engineV2.VoteHandler(blockchain, voteMsg)
assert.NotNil(t, err)
// voteRound < currentRound
assert.Equal(t, "vote message round number: 6 does not match currentRound: 5", err.Error())
assert.Equal(t, "vote message round number: 6 is too far away from currentRound: 4", err.Error())
}
func TestProcessVoteMsgThenTimeoutMsg(t *testing.T) {

View file

@ -94,7 +94,7 @@ func (b *Bfter) Vote(vote *utils.Vote) error {
err = b.consensus.voteHandler(b.blockChainReader, vote)
if err != nil {
if _, ok := err.(*utils.ErrIncomingMessageRoundNotEqualCurrentRound); ok {
if _, ok := err.(*utils.ErrIncomingMessageRoundTooFarFromCurrentRound); ok {
log.Warn("vote round not equal", "error", err, "vote", vote.Hash())
return err
}