From 4c677fc0aba24703df4ab656acf98b9eea738c33 Mon Sep 17 00:00:00 2001 From: NathanBSC Date: Mon, 31 Jul 2023 18:08:09 +0800 Subject: [PATCH] rpc: add GetFinalizedHeader/Block to simplify using the fast finality --- consensus/parlia/parlia.go | 8 +++--- internal/ethapi/api.go | 54 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index 7522f555ac..c79eccb91d 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -1758,10 +1758,12 @@ func (p *Parlia) GetFinalizedHeader(chain consensus.ChainHeaderReader, header *t return nil } - if snap.Attestation != nil { - return chain.GetHeader(snap.Attestation.SourceHash, snap.Attestation.SourceNumber) + // snap.Attestation is nil after plato upgrade, only can happen in local testnet + if snap.Attestation == nil { + return chain.GetHeaderByNumber(0) // keep consistent with GetJustifiedNumberAndHash } - return nil + + return chain.GetHeader(snap.Attestation.SourceHash, snap.Attestation.SourceNumber) } // =========================== utility function ========================== diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index fc903d3602..177ab97c18 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -54,6 +54,14 @@ import ( const UnHealthyTimeout = 5 * time.Second +// max is a helper function which returns the larger of the two given integers. +func max(a, b int64) int64 { + if a > b { + return a + } + return b +} + // PublicEthereumAPI provides an API to access Ethereum related information. // It offers only methods that operate on public data that is freely available to anyone. type PublicEthereumAPI struct { @@ -773,6 +781,52 @@ func (s *PublicBlockChainAPI) Health() bool { return true } +// GetFinalizedHeader returns the requested finalized block header. +// - probabilisticFinalized should be in range [2,21], +// then the block header with number `max(fastFinalized, latest-probabilisticFinalized)` is returned +func (s *PublicBlockChainAPI) GetFinalizedHeader(ctx context.Context, probabilisticFinalized int64) (map[string]interface{}, error) { + if probabilisticFinalized < 2 || probabilisticFinalized > 21 { + return nil, fmt.Errorf("%d out of range [2,21]", probabilisticFinalized) + } + + var err error + fastFinalizedHeader, err := s.b.HeaderByNumber(ctx, rpc.FinalizedBlockNumber) + if err != nil { // impossible + return nil, err + } + latestHeader, err := s.b.HeaderByNumber(ctx, rpc.LatestBlockNumber) + if err != nil { // impossible + return nil, err + } + finalizedBlockNumber := max(fastFinalizedHeader.Number.Int64(), latestHeader.Number.Int64()-probabilisticFinalized) + + return s.GetHeaderByNumber(ctx, rpc.BlockNumber(finalizedBlockNumber)) +} + +// GetFinalizedBlock returns the requested finalized block. +// - probabilisticFinalized should be in range [2,21], +// then the block with number `max(fastFinalized, latest-probabilisticFinalized)` is returned +// - When fullTx is true all transactions in the block are returned, otherwise +// only the transaction hash is returned. +func (s *PublicBlockChainAPI) GetFinalizedBlock(ctx context.Context, probabilisticFinalized int64, fullTx bool) (map[string]interface{}, error) { + if probabilisticFinalized < 2 || probabilisticFinalized > 21 { + return nil, fmt.Errorf("%d out of range [2,21]", probabilisticFinalized) + } + + var err error + fastFinalizedHeader, err := s.b.HeaderByNumber(ctx, rpc.FinalizedBlockNumber) + if err != nil { // impossible + return nil, err + } + latestHeader, err := s.b.HeaderByNumber(ctx, rpc.LatestBlockNumber) + if err != nil { // impossible + return nil, err + } + finalizedBlockNumber := max(fastFinalizedHeader.Number.Int64(), latestHeader.Number.Int64()-probabilisticFinalized) + + return s.GetBlockByNumber(ctx, rpc.BlockNumber(finalizedBlockNumber), fullTx) +} + // GetUncleByBlockNumberAndIndex returns the uncle block for the given block hash and index. func (s *PublicBlockChainAPI) GetUncleByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) (map[string]interface{}, error) { block, err := s.b.BlockByNumber(ctx, blockNr)