mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-06 21:14:27 +00:00
update adaptor for verify headers and fix vote handler to include +1 distance when checking rounds (#48)
This commit is contained in:
parent
328d555b9b
commit
7cc2bef2d3
6 changed files with 60 additions and 15 deletions
|
|
@ -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
|
// 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).
|
// 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) {
|
func (x *XDPoS) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, fullVerifies []bool) (chan<- struct{}, <-chan error) {
|
||||||
// TODO: (Hashlab) This funciton is a special case
|
abort := make(chan struct{})
|
||||||
return x.EngineV1.VerifyHeaders(chain, headers, fullVerifies)
|
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
|
// VerifyUncles implements consensus.Engine, always returning an error for any
|
||||||
|
|
|
||||||
|
|
@ -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
|
// 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
|
// 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).
|
// 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) {
|
func (x *XDPoS_v1) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, fullVerifies []bool, abort <-chan struct{}, results chan<- error) {
|
||||||
abort := make(chan struct{})
|
|
||||||
results := make(chan error, len(headers))
|
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for i, header := range headers {
|
for i, header := range headers {
|
||||||
err := x.verifyHeaderWithCache(chain, header, headers[:i], fullVerifies[i])
|
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 {
|
func (x *XDPoS_v1) verifyHeaderWithCache(chain consensus.ChainReader, header *types.Header, parents []*types.Header, fullVerify bool) error {
|
||||||
|
|
|
||||||
|
|
@ -478,6 +478,19 @@ func (x *XDPoS_v2) VerifyHeader(chain consensus.ChainReader, header *types.Heade
|
||||||
return nil
|
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
|
// Utils for test to get current Pool size
|
||||||
func (x *XDPoS_v2) GetVotePoolSize(vote *utils.Vote) int {
|
func (x *XDPoS_v2) GetVotePoolSize(vote *utils.Vote) int {
|
||||||
return x.votePool.Size(vote)
|
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 {
|
func (x *XDPoS_v2) voteHandler(chain consensus.ChainReader, voteMsg *utils.Vote) error {
|
||||||
|
|
||||||
// 1. checkRoundNumber
|
// 1. checkRoundNumber
|
||||||
if voteMsg.ProposedBlockInfo.Round != x.currentRound {
|
if (voteMsg.ProposedBlockInfo.Round != x.currentRound) && (voteMsg.ProposedBlockInfo.Round != x.currentRound+1) {
|
||||||
return &utils.ErrIncomingMessageRoundNotEqualCurrentRound{
|
return &utils.ErrIncomingMessageRoundTooFarFromCurrentRound{
|
||||||
Type: "vote",
|
Type: "vote",
|
||||||
IncomingRound: voteMsg.ProposedBlockInfo.Round,
|
IncomingRound: voteMsg.ProposedBlockInfo.Round,
|
||||||
CurrentRound: x.currentRound,
|
CurrentRound: x.currentRound,
|
||||||
|
|
|
||||||
|
|
@ -88,3 +88,13 @@ type ErrIncomingMessageRoundNotEqualCurrentRound struct {
|
||||||
func (e *ErrIncomingMessageRoundNotEqualCurrentRound) Error() string {
|
func (e *ErrIncomingMessageRoundNotEqualCurrentRound) Error() string {
|
||||||
return fmt.Sprintf("%s message round number: %v does not match currentRound: %v", e.Type, e.IncomingRound, e.CurrentRound)
|
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)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@ func TestVoteMessageHandlerSuccessfullyGeneratedAndProcessQC(t *testing.T) {
|
||||||
assert.Equal(t, big.NewInt(13), highestCommitBlock.Number)
|
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)
|
blockchain, _, _, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 15, params.TestXDPoSMockChainConfigWithV2Engine, 0)
|
||||||
engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2
|
engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2
|
||||||
|
|
||||||
|
|
@ -146,14 +146,18 @@ func TestThrowErrorIfVoteMsgRoundNotEqualToCurrentRound(t *testing.T) {
|
||||||
// voteRound > currentRound
|
// voteRound > currentRound
|
||||||
err := engineV2.VoteHandler(blockchain, voteMsg)
|
err := engineV2.VoteHandler(blockchain, voteMsg)
|
||||||
assert.NotNil(t, err)
|
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)
|
engineV2.SetNewRoundFaker(utils.Round(5), false)
|
||||||
err = engineV2.VoteHandler(blockchain, voteMsg)
|
err = engineV2.VoteHandler(blockchain, voteMsg)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
engineV2.SetNewRoundFaker(utils.Round(4), false)
|
||||||
|
err = engineV2.VoteHandler(blockchain, voteMsg)
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
// voteRound < currentRound
|
assert.Equal(t, "vote message round number: 6 is too far away from currentRound: 4", err.Error())
|
||||||
assert.Equal(t, "vote message round number: 6 does not match currentRound: 5", err.Error())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestProcessVoteMsgThenTimeoutMsg(t *testing.T) {
|
func TestProcessVoteMsgThenTimeoutMsg(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ func (b *Bfter) Vote(vote *utils.Vote) error {
|
||||||
|
|
||||||
err = b.consensus.voteHandler(b.blockChainReader, vote)
|
err = b.consensus.voteHandler(b.blockChainReader, vote)
|
||||||
if err != nil {
|
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())
|
log.Warn("vote round not equal", "error", err, "vote", vote.Hash())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue