parlia: fix verifyVoteAttestation when verify a batch of headers (#2121)

This commit is contained in:
buddho 2024-01-03 15:58:06 +08:00 committed by GitHub
parent 124939aaa4
commit de1a126ec5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 24 additions and 18 deletions

@ -150,7 +150,7 @@ type PoSA interface {
IsSystemContract(to *common.Address) bool IsSystemContract(to *common.Address) bool
EnoughDistance(chain ChainReader, header *types.Header) bool EnoughDistance(chain ChainReader, header *types.Header) bool
IsLocalBlock(header *types.Header) bool IsLocalBlock(header *types.Header) bool
GetJustifiedNumberAndHash(chain ChainHeaderReader, header *types.Header) (uint64, common.Hash, error) GetJustifiedNumberAndHash(chain ChainHeaderReader, headers []*types.Header) (uint64, common.Hash, error)
GetFinalizedHeader(chain ChainHeaderReader, header *types.Header) *types.Header GetFinalizedHeader(chain ChainHeaderReader, header *types.Header) *types.Header
VerifyVote(chain ChainHeaderReader, vote *types.VoteEnvelope) error VerifyVote(chain ChainHeaderReader, vote *types.VoteEnvelope) error
IsActiveValidatorAt(chain ChainHeaderReader, header *types.Header, checkVoteKeyFn func(bLSPublicKey *types.BLSPublicKey) bool) bool IsActiveValidatorAt(chain ChainHeaderReader, header *types.Header, checkVoteKeyFn func(bLSPublicKey *types.BLSPublicKey) bool) bool

@ -447,7 +447,11 @@ func (p *Parlia) verifyVoteAttestation(chain consensus.ChainHeaderReader, header
// The source block should be the highest justified block. // The source block should be the highest justified block.
sourceNumber := attestation.Data.SourceNumber sourceNumber := attestation.Data.SourceNumber
sourceHash := attestation.Data.SourceHash sourceHash := attestation.Data.SourceHash
justifiedBlockNumber, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(chain, parent) headers := []*types.Header{parent}
if len(parents) > 0 {
headers = parents
}
justifiedBlockNumber, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(chain, headers)
if err != nil { if err != nil {
return fmt.Errorf("unexpected error when getting the highest justified number and hash") return fmt.Errorf("unexpected error when getting the highest justified number and hash")
} }
@ -871,7 +875,7 @@ func (p *Parlia) assembleVoteAttestation(chain consensus.ChainHeaderReader, head
// Prepare vote attestation // Prepare vote attestation
// Prepare vote data // Prepare vote data
justifiedBlockNumber, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(chain, parent) justifiedBlockNumber, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(chain, []*types.Header{parent})
if err != nil { if err != nil {
return fmt.Errorf("unexpected error when getting the highest justified number and hash") return fmt.Errorf("unexpected error when getting the highest justified number and hash")
} }
@ -1266,7 +1270,7 @@ func (p *Parlia) VerifyVote(chain consensus.ChainHeaderReader, vote *types.VoteE
return fmt.Errorf("target number mismatch") return fmt.Errorf("target number mismatch")
} }
justifiedBlockNumber, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(chain, header) justifiedBlockNumber, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(chain, []*types.Header{header})
if err != nil { if err != nil {
log.Error("failed to get the highest justified number and hash", "headerNumber", header.Number, "headerHash", header.Hash()) log.Error("failed to get the highest justified number and hash", "headerNumber", header.Number, "headerHash", header.Hash())
return fmt.Errorf("unexpected error when getting the highest justified number and hash") return fmt.Errorf("unexpected error when getting the highest justified number and hash")
@ -1751,20 +1755,22 @@ func (p *Parlia) applyTransaction(
return nil return nil
} }
// GetJustifiedNumberAndHash returns the highest justified block's number and hash on the branch including and before `header` // GetJustifiedNumberAndHash retrieves the number and hash of the highest justified block
func (p *Parlia) GetJustifiedNumberAndHash(chain consensus.ChainHeaderReader, header *types.Header) (uint64, common.Hash, error) { // within the branch including `headers` and utilizing the latest element as the head.
if chain == nil || header == nil { func (p *Parlia) GetJustifiedNumberAndHash(chain consensus.ChainHeaderReader, headers []*types.Header) (uint64, common.Hash, error) {
if chain == nil || len(headers) == 0 || headers[len(headers)-1] == nil {
return 0, common.Hash{}, fmt.Errorf("illegal chain or header") return 0, common.Hash{}, fmt.Errorf("illegal chain or header")
} }
snap, err := p.snapshot(chain, header.Number.Uint64(), header.Hash(), nil) head := headers[len(headers)-1]
snap, err := p.snapshot(chain, head.Number.Uint64(), head.Hash(), headers)
if err != nil { if err != nil {
log.Error("Unexpected error when getting snapshot", log.Error("Unexpected error when getting snapshot",
"error", err, "blockNumber", header.Number.Uint64(), "blockHash", header.Hash()) "error", err, "blockNumber", head.Number.Uint64(), "blockHash", head.Hash())
return 0, common.Hash{}, err return 0, common.Hash{}, err
} }
if snap.Attestation == nil { if snap.Attestation == nil {
if p.chainConfig.IsLuban(header.Number) { if p.chainConfig.IsLuban(head.Number) {
log.Debug("once one attestation generated, attestation of snap would not be nil forever basically") log.Debug("once one attestation generated, attestation of snap would not be nil forever basically")
} }
return 0, chain.GetHeaderByNumber(0).Hash(), nil return 0, chain.GetHeaderByNumber(0).Hash(), nil

@ -637,7 +637,7 @@ func (bc *BlockChain) empty() bool {
// GetJustifiedNumber returns the highest justified blockNumber on the branch including and before `header`. // GetJustifiedNumber returns the highest justified blockNumber on the branch including and before `header`.
func (bc *BlockChain) GetJustifiedNumber(header *types.Header) uint64 { func (bc *BlockChain) GetJustifiedNumber(header *types.Header) uint64 {
if p, ok := bc.engine.(consensus.PoSA); ok { if p, ok := bc.engine.(consensus.PoSA); ok {
justifiedBlockNumber, _, err := p.GetJustifiedNumberAndHash(bc, header) justifiedBlockNumber, _, err := p.GetJustifiedNumberAndHash(bc, []*types.Header{header})
if err == nil { if err == nil {
return justifiedBlockNumber return justifiedBlockNumber
} }

@ -71,7 +71,7 @@ func (bc *BlockChain) CurrentSafeBlock() *types.Header {
if currentHeader == nil { if currentHeader == nil {
return nil return nil
} }
_, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(bc, currentHeader) _, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(bc, []*types.Header{currentHeader})
if err == nil { if err == nil {
return bc.GetHeaderByHash(justifiedBlockHash) return bc.GetHeaderByHash(justifiedBlockHash)
} }

@ -113,7 +113,7 @@ func NewHeaderChain(chainDb ethdb.Database, config *params.ChainConfig, engine c
// GetJustifiedNumber returns the highest justified blockNumber on the branch including and before `header`. // GetJustifiedNumber returns the highest justified blockNumber on the branch including and before `header`.
func (hc *HeaderChain) GetJustifiedNumber(header *types.Header) uint64 { func (hc *HeaderChain) GetJustifiedNumber(header *types.Header) uint64 {
if p, ok := hc.engine.(consensus.PoSA); ok { if p, ok := hc.engine.(consensus.PoSA); ok {
justifiedBlockNumber, _, err := p.GetJustifiedNumberAndHash(hc, header) justifiedBlockNumber, _, err := p.GetJustifiedNumberAndHash(hc, []*types.Header{header})
if err == nil { if err == nil {
return justifiedBlockNumber return justifiedBlockNumber
} }

@ -218,7 +218,7 @@ func (voteManager *VoteManager) loop() {
// A validator must not vote within the span of its other votes . (Rule 2) // A validator must not vote within the span of its other votes . (Rule 2)
// Validators always vote for their canonical chains latest block. (Rule 3) // Validators always vote for their canonical chains latest block. (Rule 3)
func (voteManager *VoteManager) UnderRules(header *types.Header) (bool, uint64, common.Hash) { func (voteManager *VoteManager) UnderRules(header *types.Header) (bool, uint64, common.Hash) {
sourceNumber, sourceHash, err := voteManager.engine.GetJustifiedNumberAndHash(voteManager.chain, header) sourceNumber, sourceHash, err := voteManager.engine.GetJustifiedNumberAndHash(voteManager.chain, []*types.Header{header})
if err != nil { if err != nil {
log.Error("failed to get the highest justified number and hash at cur header", "curHeader's BlockNumber", header.Number, "curHeader's BlockHash", header.Hash()) log.Error("failed to get the highest justified number and hash at cur header", "curHeader's BlockNumber", header.Number, "curHeader's BlockHash", header.Hash())
return false, 0, common.Hash{} return false, 0, common.Hash{}

@ -78,15 +78,15 @@ func newTestBackend() *testBackend {
func (b *testBackend) IsMining() bool { return true } func (b *testBackend) IsMining() bool { return true }
func (b *testBackend) EventMux() *event.TypeMux { return b.eventMux } func (b *testBackend) EventMux() *event.TypeMux { return b.eventMux }
func (p *mockPOSA) GetJustifiedNumberAndHash(chain consensus.ChainHeaderReader, header *types.Header) (uint64, common.Hash, error) { func (p *mockPOSA) GetJustifiedNumberAndHash(chain consensus.ChainHeaderReader, headers []*types.Header) (uint64, common.Hash, error) {
parentHeader := chain.GetHeaderByHash(header.ParentHash) parentHeader := chain.GetHeaderByHash(headers[len(headers)-1].ParentHash)
if parentHeader == nil { if parentHeader == nil {
return 0, common.Hash{}, fmt.Errorf("unexpected error") return 0, common.Hash{}, fmt.Errorf("unexpected error")
} }
return parentHeader.Number.Uint64(), parentHeader.Hash(), nil return parentHeader.Number.Uint64(), parentHeader.Hash(), nil
} }
func (p *mockInvalidPOSA) GetJustifiedNumberAndHash(chain consensus.ChainHeaderReader, header *types.Header) (uint64, common.Hash, error) { func (p *mockInvalidPOSA) GetJustifiedNumberAndHash(chain consensus.ChainHeaderReader, headers []*types.Header) (uint64, common.Hash, error) {
return 0, common.Hash{}, fmt.Errorf("not supported") return 0, common.Hash{}, fmt.Errorf("not supported")
} }

@ -436,7 +436,7 @@ func (lc *LightChain) CurrentHeader() *types.Header {
// GetJustifiedNumber returns the highest justified blockNumber on the branch including and before `header` // GetJustifiedNumber returns the highest justified blockNumber on the branch including and before `header`
func (lc *LightChain) GetJustifiedNumber(header *types.Header) uint64 { func (lc *LightChain) GetJustifiedNumber(header *types.Header) uint64 {
if p, ok := lc.engine.(consensus.PoSA); ok { if p, ok := lc.engine.(consensus.PoSA); ok {
justifiedBlockNumber, _, err := p.GetJustifiedNumberAndHash(lc.hc, header) justifiedBlockNumber, _, err := p.GetJustifiedNumberAndHash(lc.hc, []*types.Header{header})
if err == nil { if err == nil {
return justifiedBlockNumber return justifiedBlockNumber
} }