From 55cec52a1738f6d37b0e2e378e23f4bc47454798 Mon Sep 17 00:00:00 2001 From: buddh0 Date: Thu, 28 Dec 2023 15:30:05 +0800 Subject: [PATCH] parlia: fix verifyVoteAttestation when verify a batch of headers --- consensus/consensus.go | 2 +- consensus/parlia/parlia.go | 24 +++++++++++++++--------- core/blockchain.go | 2 +- core/blockchain_reader.go | 2 +- core/headerchain.go | 2 +- core/vote/vote_manager.go | 2 +- core/vote/vote_pool_test.go | 6 +++--- light/lightchain.go | 2 +- 8 files changed, 24 insertions(+), 18 deletions(-) diff --git a/consensus/consensus.go b/consensus/consensus.go index 709622ce34..855821c215 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -150,7 +150,7 @@ type PoSA interface { IsSystemContract(to *common.Address) bool EnoughDistance(chain ChainReader, 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 VerifyVote(chain ChainHeaderReader, vote *types.VoteEnvelope) error IsActiveValidatorAt(chain ChainHeaderReader, header *types.Header, checkVoteKeyFn func(bLSPublicKey *types.BLSPublicKey) bool) bool diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index f2ae2d86f1..23a3b4d6a9 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -447,7 +447,11 @@ func (p *Parlia) verifyVoteAttestation(chain consensus.ChainHeaderReader, header // The source block should be the highest justified block. sourceNumber := attestation.Data.SourceNumber 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 { 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 data - justifiedBlockNumber, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(chain, parent) + justifiedBlockNumber, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(chain, []*types.Header{parent}) if err != nil { 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") } - justifiedBlockNumber, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(chain, header) + justifiedBlockNumber, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(chain, []*types.Header{header}) if err != nil { 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") @@ -1751,20 +1755,22 @@ func (p *Parlia) applyTransaction( return nil } -// GetJustifiedNumberAndHash returns the highest justified block's number and hash on the branch including and before `header` -func (p *Parlia) GetJustifiedNumberAndHash(chain consensus.ChainHeaderReader, header *types.Header) (uint64, common.Hash, error) { - if chain == nil || header == nil { +// GetJustifiedNumberAndHash retrieves the number and hash of the highest justified block +// within the branch including `headers` and utilizing the latest element as the head. +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") } - 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 { 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 } 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") } return 0, chain.GetHeaderByNumber(0).Hash(), nil diff --git a/core/blockchain.go b/core/blockchain.go index e528c667c4..7a0288b92f 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -637,7 +637,7 @@ func (bc *BlockChain) empty() bool { // GetJustifiedNumber returns the highest justified blockNumber on the branch including and before `header`. func (bc *BlockChain) GetJustifiedNumber(header *types.Header) uint64 { 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 { return justifiedBlockNumber } diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go index 802b979a10..8123557861 100644 --- a/core/blockchain_reader.go +++ b/core/blockchain_reader.go @@ -71,7 +71,7 @@ func (bc *BlockChain) CurrentSafeBlock() *types.Header { if currentHeader == nil { return nil } - _, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(bc, currentHeader) + _, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(bc, []*types.Header{currentHeader}) if err == nil { return bc.GetHeaderByHash(justifiedBlockHash) } diff --git a/core/headerchain.go b/core/headerchain.go index def9d3dc54..bdf99c2e5b 100644 --- a/core/headerchain.go +++ b/core/headerchain.go @@ -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`. func (hc *HeaderChain) GetJustifiedNumber(header *types.Header) uint64 { 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 { return justifiedBlockNumber } diff --git a/core/vote/vote_manager.go b/core/vote/vote_manager.go index a253d57460..a7eaf10b09 100644 --- a/core/vote/vote_manager.go +++ b/core/vote/vote_manager.go @@ -218,7 +218,7 @@ func (voteManager *VoteManager) loop() { // A validator must not vote within the span of its other votes . (Rule 2) // Validators always vote for their canonical chain’s latest block. (Rule 3) 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 { 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{} diff --git a/core/vote/vote_pool_test.go b/core/vote/vote_pool_test.go index 0588c3fb92..0025db9900 100644 --- a/core/vote/vote_pool_test.go +++ b/core/vote/vote_pool_test.go @@ -78,15 +78,15 @@ func newTestBackend() *testBackend { func (b *testBackend) IsMining() bool { return true } func (b *testBackend) EventMux() *event.TypeMux { return b.eventMux } -func (p *mockPOSA) GetJustifiedNumberAndHash(chain consensus.ChainHeaderReader, header *types.Header) (uint64, common.Hash, error) { - parentHeader := chain.GetHeaderByHash(header.ParentHash) +func (p *mockPOSA) GetJustifiedNumberAndHash(chain consensus.ChainHeaderReader, headers []*types.Header) (uint64, common.Hash, error) { + parentHeader := chain.GetHeaderByHash(headers[len(headers)-1].ParentHash) if parentHeader == nil { return 0, common.Hash{}, fmt.Errorf("unexpected error") } 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") } diff --git a/light/lightchain.go b/light/lightchain.go index 129ebfe44c..69340eadb1 100644 --- a/light/lightchain.go +++ b/light/lightchain.go @@ -436,7 +436,7 @@ func (lc *LightChain) CurrentHeader() *types.Header { // GetJustifiedNumber returns the highest justified blockNumber on the branch including and before `header` func (lc *LightChain) GetJustifiedNumber(header *types.Header) uint64 { 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 { return justifiedBlockNumber }