forked from cerc-io/plugeth
eth/gasprice/feehistory: support finalized block (#25442)
This commit is contained in:
parent
1b34ed2ed6
commit
a0b88ce869
@ -137,44 +137,68 @@ func (oracle *Oracle) processBlock(bf *blockFees, percentiles []float64) {
|
||||
// also returned if requested and available.
|
||||
// Note: an error is only returned if retrieving the head header has failed. If there are no
|
||||
// retrievable blocks in the specified range then zero block count is returned with no error.
|
||||
func (oracle *Oracle) resolveBlockRange(ctx context.Context, lastBlock rpc.BlockNumber, blocks int) (*types.Block, []*types.Receipt, uint64, int, error) {
|
||||
func (oracle *Oracle) resolveBlockRange(ctx context.Context, reqEnd rpc.BlockNumber, blocks int) (*types.Block, []*types.Receipt, uint64, int, error) {
|
||||
var (
|
||||
headBlock rpc.BlockNumber
|
||||
headBlock *types.Header
|
||||
pendingBlock *types.Block
|
||||
pendingReceipts types.Receipts
|
||||
err error
|
||||
)
|
||||
// query either pending block or head header and set headBlock
|
||||
if lastBlock == rpc.PendingBlockNumber {
|
||||
if pendingBlock, pendingReceipts = oracle.backend.PendingBlockAndReceipts(); pendingBlock != nil {
|
||||
lastBlock = rpc.BlockNumber(pendingBlock.NumberU64())
|
||||
headBlock = lastBlock - 1
|
||||
} else {
|
||||
// pending block not supported by backend, process until latest block
|
||||
lastBlock = rpc.LatestBlockNumber
|
||||
blocks--
|
||||
if blocks == 0 {
|
||||
return nil, nil, 0, 0, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Get the chain's current head.
|
||||
if headBlock, err = oracle.backend.HeaderByNumber(ctx, rpc.LatestBlockNumber); err != nil {
|
||||
return nil, nil, 0, 0, err
|
||||
}
|
||||
if pendingBlock == nil {
|
||||
// if pending block is not fetched then we retrieve the head header to get the head block number
|
||||
if latestHeader, err := oracle.backend.HeaderByNumber(ctx, rpc.LatestBlockNumber); err == nil {
|
||||
headBlock = rpc.BlockNumber(latestHeader.Number.Uint64())
|
||||
} else {
|
||||
head := rpc.BlockNumber(headBlock.Number.Uint64())
|
||||
|
||||
// Fail if request block is beyond the chain's current head.
|
||||
if head < reqEnd {
|
||||
return nil, nil, 0, 0, fmt.Errorf("%w: requested %d, head %d", errRequestBeyondHead, reqEnd, head)
|
||||
}
|
||||
|
||||
// Resolve block tag.
|
||||
if reqEnd < 0 {
|
||||
var (
|
||||
resolved *types.Header
|
||||
err error
|
||||
)
|
||||
switch reqEnd {
|
||||
case rpc.PendingBlockNumber:
|
||||
if pendingBlock, pendingReceipts = oracle.backend.PendingBlockAndReceipts(); pendingBlock != nil {
|
||||
resolved = pendingBlock.Header()
|
||||
} else {
|
||||
// Pending block not supported by backend, process only until latest block.
|
||||
resolved = headBlock
|
||||
|
||||
// Update total blocks to return to account for this.
|
||||
blocks--
|
||||
}
|
||||
case rpc.LatestBlockNumber:
|
||||
// Retrieved above.
|
||||
resolved = headBlock
|
||||
case rpc.SafeBlockNumber:
|
||||
resolved, err = oracle.backend.HeaderByNumber(ctx, rpc.SafeBlockNumber)
|
||||
case rpc.FinalizedBlockNumber:
|
||||
resolved, err = oracle.backend.HeaderByNumber(ctx, rpc.FinalizedBlockNumber)
|
||||
case rpc.EarliestBlockNumber:
|
||||
resolved, err = oracle.backend.HeaderByNumber(ctx, rpc.EarliestBlockNumber)
|
||||
}
|
||||
if resolved == nil || err != nil {
|
||||
return nil, nil, 0, 0, err
|
||||
}
|
||||
// Absolute number resolved.
|
||||
reqEnd = rpc.BlockNumber(resolved.Number.Uint64())
|
||||
}
|
||||
if lastBlock == rpc.LatestBlockNumber {
|
||||
lastBlock = headBlock
|
||||
} else if pendingBlock == nil && lastBlock > headBlock {
|
||||
return nil, nil, 0, 0, fmt.Errorf("%w: requested %d, head %d", errRequestBeyondHead, lastBlock, headBlock)
|
||||
|
||||
// If there are no blocks to return, short circuit.
|
||||
if blocks == 0 {
|
||||
return nil, nil, 0, 0, nil
|
||||
}
|
||||
// ensure not trying to retrieve before genesis
|
||||
if rpc.BlockNumber(blocks) > lastBlock+1 {
|
||||
blocks = int(lastBlock + 1)
|
||||
// Ensure not trying to retrieve before genesis.
|
||||
if int(reqEnd+1) < blocks {
|
||||
blocks = int(reqEnd + 1)
|
||||
}
|
||||
return pendingBlock, pendingReceipts, uint64(lastBlock), blocks, nil
|
||||
return pendingBlock, pendingReceipts, uint64(reqEnd), blocks, nil
|
||||
}
|
||||
|
||||
// FeeHistory returns data relevant for fee estimation based on the specified range of blocks.
|
||||
|
@ -50,6 +50,8 @@ func TestFeeHistory(t *testing.T) {
|
||||
{false, 1000, 1000, 2, rpc.PendingBlockNumber, nil, 32, 1, nil},
|
||||
{true, 1000, 1000, 2, rpc.PendingBlockNumber, nil, 32, 2, nil},
|
||||
{true, 1000, 1000, 2, rpc.PendingBlockNumber, []float64{0, 10}, 32, 2, nil},
|
||||
{false, 1000, 1000, 2, rpc.FinalizedBlockNumber, []float64{0, 10}, 24, 2, nil},
|
||||
{false, 1000, 1000, 2, rpc.SafeBlockNumber, []float64{0, 10}, 24, 2, nil},
|
||||
}
|
||||
for i, c := range cases {
|
||||
config := Config{
|
||||
|
@ -45,6 +45,15 @@ func (b *testBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber
|
||||
if number > testHead {
|
||||
return nil, nil
|
||||
}
|
||||
if number == rpc.EarliestBlockNumber {
|
||||
number = 0
|
||||
}
|
||||
if number == rpc.FinalizedBlockNumber {
|
||||
return b.chain.CurrentFinalizedBlock().Header(), nil
|
||||
}
|
||||
if number == rpc.SafeBlockNumber {
|
||||
return b.chain.CurrentSafeBlock().Header(), nil
|
||||
}
|
||||
if number == rpc.LatestBlockNumber {
|
||||
number = testHead
|
||||
}
|
||||
@ -62,6 +71,15 @@ func (b *testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber)
|
||||
if number > testHead {
|
||||
return nil, nil
|
||||
}
|
||||
if number == rpc.EarliestBlockNumber {
|
||||
number = 0
|
||||
}
|
||||
if number == rpc.FinalizedBlockNumber {
|
||||
return b.chain.CurrentFinalizedBlock(), nil
|
||||
}
|
||||
if number == rpc.SafeBlockNumber {
|
||||
return b.chain.CurrentSafeBlock(), nil
|
||||
}
|
||||
if number == rpc.LatestBlockNumber {
|
||||
number = testHead
|
||||
}
|
||||
@ -109,6 +127,7 @@ func newTestBackend(t *testing.T, londonBlock *big.Int, pending bool) *testBacke
|
||||
config.LondonBlock = londonBlock
|
||||
config.ArrowGlacierBlock = londonBlock
|
||||
config.GrayGlacierBlock = londonBlock
|
||||
config.TerminalTotalDifficulty = common.Big0
|
||||
engine := ethash.NewFaker()
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
genesis, err := gspec.Commit(db)
|
||||
@ -150,6 +169,8 @@ func newTestBackend(t *testing.T, londonBlock *big.Int, pending bool) *testBacke
|
||||
t.Fatalf("Failed to create local chain, %v", err)
|
||||
}
|
||||
chain.InsertChain(blocks)
|
||||
chain.SetFinalized(chain.GetBlockByNumber(25))
|
||||
chain.SetSafe(chain.GetBlockByNumber(25))
|
||||
return &testBackend{chain: chain, pending: pending}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user