|
|
|
@ -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 |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
// Get the chain's current head.
|
|
|
|
|
if headBlock, err = oracle.backend.HeaderByNumber(ctx, rpc.LatestBlockNumber); err != nil { |
|
|
|
|
return nil, nil, 0, 0, err |
|
|
|
|
} |
|
|
|
|
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 |
|
|
|
|
) |
|
|
|
|
// query either pending block or head header and set headBlock
|
|
|
|
|
if lastBlock == rpc.PendingBlockNumber { |
|
|
|
|
switch reqEnd { |
|
|
|
|
case rpc.PendingBlockNumber: |
|
|
|
|
if pendingBlock, pendingReceipts = oracle.backend.PendingBlockAndReceipts(); pendingBlock != nil { |
|
|
|
|
lastBlock = rpc.BlockNumber(pendingBlock.NumberU64()) |
|
|
|
|
headBlock = lastBlock - 1 |
|
|
|
|
resolved = pendingBlock.Header() |
|
|
|
|
} else { |
|
|
|
|
// pending block not supported by backend, process until latest block
|
|
|
|
|
lastBlock = rpc.LatestBlockNumber |
|
|
|
|
// Pending block not supported by backend, process only until latest block.
|
|
|
|
|
resolved = headBlock |
|
|
|
|
|
|
|
|
|
// Update total blocks to return to account for this.
|
|
|
|
|
blocks-- |
|
|
|
|
if blocks == 0 { |
|
|
|
|
return nil, nil, 0, 0, nil |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
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 { |
|
|
|
|
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.
|
|
|
|
|