Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion consensus/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ type PoSA interface {
IsLocalBlock(header *types.Header) bool
AllowLightProcess(chain ChainReader, currentHeader *types.Header) bool
GetJustifiedHeader(chain ChainHeaderReader, header *types.Header) *types.Header
GetFinalizedHeader(chain ChainHeaderReader, header *types.Header) *types.Header
GetFinalizedHeader(chain ChainHeaderReader, header *types.Header, backward uint64) *types.Header
VerifyVote(chain ChainHeaderReader, vote *types.VoteEnvelope) error
IsActiveValidatorAt(chain ChainHeaderReader, header *types.Header) bool
}
34 changes: 19 additions & 15 deletions consensus/parlia/parlia.go
Original file line number Diff line number Diff line change
Expand Up @@ -1685,38 +1685,42 @@ func (p *Parlia) GetJustifiedHeader(chain consensus.ChainHeaderReader, header *t
return nil
}

// There won't any attestation in first two blocks, return root.
if header.Number.Uint64() < 2 {
return chain.GetHeaderByNumber(0)
}

snap, err := p.snapshot(chain, header.Number.Uint64(), header.Hash(), nil)
if err != nil {
log.Error("Unexpected error when getting snapshot",
"error", err, "blockNumber", header.Number.Uint64(), "blockHash", header.Hash())
return nil
}

// If there is no vote justified block, then return root.
// If there is no vote justified block, then return root or naturally justified block.
if snap.Attestation == nil {
return chain.GetHeaderByNumber(0)
if header.Number.Uint64() <= naturallyJustifiedDist {
return chain.GetHeaderByNumber(0)
}
// Return naturally justified block.
return FindAncientHeader(header, naturallyJustifiedDist, chain, nil)
}
// Return naturally justified block.

// If the latest vote justified block is too far, return naturally justified block.
if snap.Number-snap.Attestation.TargetNumber > naturallyJustifiedDist {
return FindAncientHeader(header, naturallyJustifiedDist, chain, nil)
}
//Return latest vote justified block.
return chain.GetHeaderByHash(snap.Attestation.TargetHash)
}

// GetFinalizedHeader returns highest finalized block header before the specific block,
// the attestation within the specific block will be taken into account.
func (p *Parlia) GetFinalizedHeader(chain consensus.ChainHeaderReader, header *types.Header) *types.Header {
// GetFinalizedHeader returns highest finalized block header before the specific block.
// It will first to find vote finalized block within the specific backward blocks, the suggested backward blocks is 21.
// If the vote finalized block not found, return its previous backward block.
func (p *Parlia) GetFinalizedHeader(chain consensus.ChainHeaderReader, header *types.Header, backward uint64) *types.Header {
if chain == nil || header == nil {
return nil
}
if !chain.Config().IsLynn(header.Number) {
return chain.GetHeaderByNumber(0)
}
if chain == nil || header == nil || header.Number.Uint64() < 2 {
return chain.GetHeaderByNumber(0)
if header.Number.Uint64() < backward {
Comment thread
realuncle marked this conversation as resolved.
backward = header.Number.Uint64()
Comment thread
realuncle marked this conversation as resolved.
}

snap, err := p.snapshot(chain, header.Number.Uint64(), header.Hash(), nil)
Expand All @@ -1726,7 +1730,7 @@ func (p *Parlia) GetFinalizedHeader(chain consensus.ChainHeaderReader, header *t
return nil
}

for snap.Attestation != nil {
for snap.Attestation != nil && snap.Attestation.SourceNumber >= header.Number.Uint64()-backward {
if snap.Attestation.TargetNumber == snap.Attestation.SourceNumber+1 {
return chain.GetHeaderByHash(snap.Attestation.SourceHash)
}
Expand All @@ -1739,7 +1743,7 @@ func (p *Parlia) GetFinalizedHeader(chain consensus.ChainHeaderReader, header *t
}
}

return chain.GetHeaderByNumber(0)
return FindAncientHeader(header, backward, chain, nil)
}

// =========================== utility function ==========================
Expand Down
29 changes: 25 additions & 4 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -545,14 +545,35 @@ func (bc *BlockChain) getJustifiedNumber(header *types.Header) uint64 {
// getFinalizedNumber returns the highest finalized number before the specific block.
func (bc *BlockChain) getFinalizedNumber(header *types.Header) uint64 {
if p, ok := bc.engine.(consensus.PoSA); ok {
if finalizedHeader := p.GetFinalizedHeader(bc, header); finalizedHeader != nil {
if finalizedHeader := p.GetFinalizedHeader(bc, header, types.NaturallyFinalizedDist); finalizedHeader != nil {
return finalizedHeader.Number.Uint64()
}
}

return 0
}

// isFinalizedBlockHigher returns true when the new block's finalized block is higher than current block.
func (bc *BlockChain) isFinalizedBlockHigher(header *types.Header, curHeader *types.Header) bool {
p, ok := bc.engine.(consensus.PoSA)
if !ok {
return false
}

ancestor := rawdb.FindCommonAncestor(bc.db, header, curHeader)
if ancestor == nil {
return false
}

finalized := p.GetFinalizedHeader(bc, header, header.Number.Uint64()-ancestor.Number.Uint64())
curFinalized := p.GetFinalizedHeader(bc, curHeader, curHeader.Number.Uint64()-ancestor.Number.Uint64())
if finalized == nil || curFinalized == nil {
return false
}

return finalized.Number.Uint64() > curFinalized.Number.Uint64()
}

// loadLastState loads the last known chain state from the database. This method
// assumes that the chain manager mutex is held.
func (bc *BlockChain) loadLastState() error {
Expand Down Expand Up @@ -1842,7 +1863,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
// Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf
reorg := externTd.Cmp(localTd) > 0
currentBlock = bc.CurrentBlock()
if bc.getFinalizedNumber(block.Header()) > bc.getFinalizedNumber(currentBlock.Header()) {
if bc.isFinalizedBlockHigher(block.Header(), currentBlock.Header()) {
reorg = true
}
if !reorg && externTd.Cmp(localTd) == 0 {
Expand Down Expand Up @@ -1890,7 +1911,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
if emitHeadEvent {
bc.chainHeadFeed.Send(ChainHeadEvent{Block: block})
if posa, ok := bc.Engine().(consensus.PoSA); ok {
if finalizedHeader := posa.GetFinalizedHeader(bc, block.Header()); finalizedHeader != nil {
if finalizedHeader := posa.GetFinalizedHeader(bc, block.Header(), types.NaturallyFinalizedDist); finalizedHeader != nil {
bc.finalizedHeaderFeed.Send(FinalizedHeaderEvent{finalizedHeader})
}
}
Expand Down Expand Up @@ -1997,7 +2018,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, er
if lastCanon != nil && bc.CurrentBlock().Hash() == lastCanon.Hash() {
bc.chainHeadFeed.Send(ChainHeadEvent{lastCanon})
if posa, ok := bc.Engine().(consensus.PoSA); ok {
if finalizedHeader := posa.GetFinalizedHeader(bc, lastCanon.Header()); finalizedHeader != nil {
if finalizedHeader := posa.GetFinalizedHeader(bc, lastCanon.Header(), types.NaturallyFinalizedDist); finalizedHeader != nil {
bc.finalizedHeaderFeed.Send(FinalizedHeaderEvent{finalizedHeader})
}
}
Expand Down
25 changes: 23 additions & 2 deletions core/headerchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,14 +133,35 @@ func (hc *HeaderChain) getJustifiedNumber(header *types.Header) uint64 {
// getFinalizedNumber returns the highest finalized number before the specific block.
func (hc *HeaderChain) getFinalizedNumber(header *types.Header) uint64 {
if p, ok := hc.engine.(consensus.PoSA); ok {
if finalizedHeader := p.GetFinalizedHeader(hc, header); finalizedHeader != nil {
if finalizedHeader := p.GetFinalizedHeader(hc, header, types.NaturallyFinalizedDist); finalizedHeader != nil {
return finalizedHeader.Number.Uint64()
}
}

return 0
}

// isFinalizedBlockHigher returns true when the new block's finalized block is higher than current block.
func (hc *HeaderChain) isFinalizedBlockHigher(header *types.Header, curHeader *types.Header) bool {
p, ok := hc.engine.(consensus.PoSA)
if !ok {
return false
}

ancestor := rawdb.FindCommonAncestor(hc.chainDb, header, curHeader)
if ancestor == nil {
return false
}

finalized := p.GetFinalizedHeader(hc, header, header.Number.Uint64()-ancestor.Number.Uint64())
curFinalized := p.GetFinalizedHeader(hc, curHeader, curHeader.Number.Uint64()-ancestor.Number.Uint64())
if finalized == nil || curFinalized == nil {
return false
}

return finalized.Number.Uint64() > curFinalized.Number.Uint64()
}

// GetBlockNumber retrieves the block number belonging to the given hash
// from the cache or database
func (hc *HeaderChain) GetBlockNumber(hash common.Hash) *uint64 {
Expand Down Expand Up @@ -241,7 +262,7 @@ func (hc *HeaderChain) writeHeaders(headers []*types.Header) (result *headerWrit
// Second clause in the if statement reduces the vulnerability to selfish mining.
// Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf
reorg := newTD.Cmp(localTD) > 0
if hc.getFinalizedNumber(lastHeader) > hc.getFinalizedNumber(hc.CurrentHeader()) {
if hc.isFinalizedBlockHigher(lastHeader, hc.CurrentHeader()) {
reorg = true
}
if !reorg && newTD.Cmp(localTD) == 0 {
Expand Down
3 changes: 2 additions & 1 deletion core/types/vote.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@ const (
BLSSignatureLength = 96

MaxAttestationExtraLength = 256
NaturallyFinalizedDist = 21 // The distance to naturally finalized a block
)

type BLSPublicKey [BLSPublicKeyLength]byte
type BLSSignature [BLSSignatureLength]byte
type ValidatorsBitSet uint64

// VoteData represents the vote data that validator voted for fast finality.
// VoteData represents the vote range that validator voted for fast finality.
type VoteData struct {
SourceNumber uint64 // The source block number should be the latest justified block number.
SourceHash common.Hash // The block hash of the source block.
Expand Down
2 changes: 1 addition & 1 deletion internal/ethapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -1328,7 +1328,7 @@ func (s *PublicBlockChainAPI) GetFinalizedHeader(ctx context.Context, blockNrOrH
}

if posa, ok := s.b.Engine().(consensus.PoSA); ok {
return posa.GetFinalizedHeader(s.b.Chain(), header), nil
return posa.GetFinalizedHeader(s.b.Chain(), header, types.NaturallyFinalizedDist), nil
}

// Not support.
Expand Down
2 changes: 1 addition & 1 deletion light/lightchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ func (lc *LightChain) InsertHeaderChain(chain []*types.Header, checkFreq int) (i
case core.CanonStatTy:
events = append(events, core.ChainEvent{Block: block, Hash: block.Hash()})
if posa, ok := lc.Engine().(consensus.PoSA); ok {
events = append(events, core.FinalizedHeaderEvent{Header: posa.GetFinalizedHeader(lc, block.Header())})
events = append(events, core.FinalizedHeaderEvent{Header: posa.GetFinalizedHeader(lc, block.Header(), types.NaturallyFinalizedDist)})
}
case core.SideStatTy:
events = append(events, core.ChainSideEvent{Block: block})
Expand Down