Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate & incorporate flow-go's onchain package #635

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
17080cb
Integrate & incorporate flow-go's onchain package
m-Peter Nov 4, 2024
27993d0
Implement RemoteCadenceArch type for fetching precompiled calls in co…
m-Peter Nov 4, 2024
14b1b08
swap storage
janezpodhostnik Nov 6, 2024
e415543
Add no-op implementation for RegisterDelta.AllocateSlabIndex
m-Peter Nov 7, 2024
127dd90
Extract method for detecting whether the tracer config is equal to th…
m-Peter Nov 7, 2024
de02ed2
Remove StateDB from BlockExecutor
m-Peter Nov 7, 2024
8f89c77
Remove out-dated comment regarding precompiles
m-Peter Nov 7, 2024
8e8b7a1
Move tracer assignment in blockContext method
m-Peter Nov 7, 2024
246e5d2
Remove receipt return value from BlockExecutor.Run
m-Peter Nov 7, 2024
a5199e9
Check that txTracer is not nil before getting the result
m-Peter Nov 7, 2024
6cd78c4
use batch to init blocks
janezpodhostnik Nov 7, 2024
885f427
fix db init issue in tests
janezpodhostnik Nov 7, 2024
6edf1bf
Simplify condition in TraceBlockByNumber
m-Peter Nov 7, 2024
c93fa57
Extract common methods for resolving RPC block tags into a utils file
m-Peter Nov 8, 2024
4f9cfff
Move down creation of tracers.Context object
m-Peter Nov 8, 2024
0b287e7
Move caching of returned data from precompiled call to runCall method
m-Peter Nov 8, 2024
8f2a551
Change evm height in requester to uint64
m-Peter Nov 8, 2024
50cb975
Simplify Requester API interface
m-Peter Nov 11, 2024
9c34a24
Remove dead code from Requester
m-Peter Nov 11, 2024
e5e1dd3
Remove unused const
m-Peter Nov 11, 2024
a26733d
Move dryRunScript var to RemoteCadenceArch and bump the gas limit
m-Peter Nov 11, 2024
6432af1
Extract replaceAddresses helper function to its own file for re-usabi…
m-Peter Nov 11, 2024
6569787
Minor improvements for resolveBlockTag function
m-Peter Nov 11, 2024
50ce14e
Simplify Requester initialization from bootstrap
m-Peter Nov 11, 2024
04d7c10
Simplify DebugAPI initialization from bootstrap
m-Peter Nov 11, 2024
dc8b8aa
Move hard-coded values to constants
m-Peter Nov 11, 2024
21953e0
Minor improvements for DebugAPI
m-Peter Nov 11, 2024
221b63c
Remove redundant error return value from BlockExecutor constructor
m-Peter Nov 11, 2024
2575969
Minor improvements for event ingestion engine
m-Peter Nov 11, 2024
71971e4
Minor improvements for CallTracerCollector
m-Peter Nov 11, 2024
3f6d97e
Remove Cadence script caching from Requester
m-Peter Nov 11, 2024
bc549e7
Properly initialize trace call config in debug_traceCall
m-Peter Nov 11, 2024
40488cc
Add test case for debug_traceTransaction with Cadence arch call
m-Peter Nov 11, 2024
a928435
Enable Cadence Arch calls for debug_traceCall
m-Peter Nov 11, 2024
1118c44
Remove unused embed import
m-Peter Nov 12, 2024
8e96ac7
Move gas limit for Cadence Arch call to a named constant
m-Peter Nov 12, 2024
9b09e88
Better handling of errors for stored default call traces
m-Peter Nov 12, 2024
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
148 changes: 21 additions & 127 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,8 @@ package api

import (
"context"
_ "embed"
"encoding/hex"
"errors"
"fmt"
"math/big"
"strings"

"github.com/onflow/go-ethereum/common"
"github.com/onflow/go-ethereum/common/hexutil"
Expand All @@ -30,6 +26,8 @@ import (
"github.com/onflow/flow-evm-gateway/storage"
)

const BlockGasLimit uint64 = 120_000_000

const maxFeeHistoryBlockCount = 1024

var baseFeesPerGas = big.NewInt(1)
Expand Down Expand Up @@ -76,6 +74,7 @@ var validMethods = map[string]struct{}{
"debug_traceTransaction": {},
"debug_traceBlockByNumber": {},
"debug_traceBlockByHash": {},
"debug_traceCall": {},

// web3 namespace
"web3_clientVersion": {},
Expand Down Expand Up @@ -282,12 +281,12 @@ func (b *BlockChainAPI) GetBalance(
return nil, err
}

evmHeight, err := b.getBlockNumber(&blockNumberOrHash)
height, err := resolveBlockTag(&blockNumberOrHash, b.blocks, b.logger)
if err != nil {
return handleError[*hexutil.Big](err, l, b.collector)
}

balance, err := b.evm.GetBalance(ctx, address, int64(evmHeight))
balance, err := b.evm.GetBalance(address, height)
if err != nil {
return handleError[*hexutil.Big](err, l, b.collector)
}
Expand Down Expand Up @@ -518,12 +517,12 @@ func (b *BlockChainAPI) GetBlockReceipts(
return nil, err
}

evmHeight, err := b.getBlockNumber(&blockNumberOrHash)
height, err := resolveBlockTag(&blockNumberOrHash, b.blocks, b.logger)
if err != nil {
return handleError[[]map[string]interface{}](err, l, b.collector)
}

block, err := b.blocks.GetByHeight(evmHeight)
block, err := b.blocks.GetByHeight(height)
if err != nil {
return handleError[[]map[string]interface{}](err, l, b.collector)
}
Expand Down Expand Up @@ -635,7 +634,7 @@ func (b *BlockChainAPI) Call(
blockNumberOrHash = &latestBlockNumberOrHash
}

evmHeight, err := b.getBlockNumber(blockNumberOrHash)
height, err := resolveBlockTag(blockNumberOrHash, b.blocks, b.logger)
if err != nil {
return handleError[hexutil.Bytes](err, l, b.collector)
}
Expand All @@ -651,7 +650,7 @@ func (b *BlockChainAPI) Call(
from = *args.From
}

res, err := b.evm.Call(ctx, tx, from, int64(evmHeight))
res, err := b.evm.Call(tx, from, height)
if err != nil {
return handleError[hexutil.Bytes](err, l, b.collector)
}
Expand Down Expand Up @@ -753,12 +752,12 @@ func (b *BlockChainAPI) GetTransactionCount(
return nil, err
}

evmHeight, err := b.getBlockNumber(&blockNumberOrHash)
height, err := resolveBlockTag(&blockNumberOrHash, b.blocks, b.logger)
if err != nil {
return handleError[*hexutil.Uint64](err, l, b.collector)
}

networkNonce, err := b.evm.GetNonce(ctx, address, int64(evmHeight))
networkNonce, err := b.evm.GetNonce(address, height)
if err != nil {
return handleError[*hexutil.Uint64](err, l, b.collector)
}
Expand Down Expand Up @@ -806,7 +805,7 @@ func (b *BlockChainAPI) EstimateGas(

tx, err := encodeTxFromArgs(args)
if err != nil {
return hexutil.Uint64(blockGasLimit), nil // return block gas limit
return hexutil.Uint64(BlockGasLimit), nil // return block gas limit
}

// Default address in case user does not provide one
Expand All @@ -819,12 +818,12 @@ func (b *BlockChainAPI) EstimateGas(
blockNumberOrHash = &latestBlockNumberOrHash
}

evmHeight, err := b.getBlockNumber(blockNumberOrHash)
height, err := resolveBlockTag(blockNumberOrHash, b.blocks, b.logger)
if err != nil {
return handleError[hexutil.Uint64](err, l, b.collector)
}

estimatedGas, err := b.evm.EstimateGas(ctx, tx, from, int64(evmHeight))
estimatedGas, err := b.evm.EstimateGas(tx, from, height)
if err != nil {
return handleError[hexutil.Uint64](err, l, b.collector)
}
Expand All @@ -848,12 +847,12 @@ func (b *BlockChainAPI) GetCode(
return nil, err
}

evmHeight, err := b.getBlockNumber(&blockNumberOrHash)
height, err := resolveBlockTag(&blockNumberOrHash, b.blocks, b.logger)
if err != nil {
return handleError[hexutil.Bytes](err, l, b.collector)
}

code, err := b.evm.GetCode(ctx, address, int64(evmHeight))
code, err := b.evm.GetCode(address, height)
if err != nil {
return handleError[hexutil.Bytes](err, l, b.collector)
}
Expand Down Expand Up @@ -934,7 +933,7 @@ func (b *BlockChainAPI) FeeHistory(

rewards = append(rewards, blockRewards)

gasUsedRatio := float64(block.TotalGasUsed) / float64(blockGasLimit)
gasUsedRatio := float64(block.TotalGasUsed) / float64(BlockGasLimit)
gasUsedRatios = append(gasUsedRatios, gasUsedRatio)
}

Expand Down Expand Up @@ -964,7 +963,7 @@ func (b *BlockChainAPI) GetStorageAt(
return nil, err
}

key, _, err := decodeHash(storageSlot)
key, err := decodeHash(storageSlot)
if err != nil {
return handleError[hexutil.Bytes](
fmt.Errorf("%w: %w", errs.ErrInvalid, err),
Expand All @@ -973,12 +972,12 @@ func (b *BlockChainAPI) GetStorageAt(
)
}

evmHeight, err := b.getBlockNumber(&blockNumberOrHash)
height, err := resolveBlockTag(&blockNumberOrHash, b.blocks, b.logger)
if err != nil {
return handleError[hexutil.Bytes](err, l, b.collector)
}

result, err := b.evm.GetStorageAt(ctx, address, key, int64(evmHeight))
result, err := b.evm.GetStorageAt(address, key, height)
if err != nil {
return handleError[hexutil.Bytes](err, l, b.collector)
}
Expand Down Expand Up @@ -1043,7 +1042,7 @@ func (b *BlockChainAPI) prepareBlockResponse(
TransactionsRoot: block.TransactionHashRoot,
Transactions: block.TransactionHashes,
Uncles: []common.Hash{},
GasLimit: hexutil.Uint64(blockGasLimit),
GasLimit: hexutil.Uint64(BlockGasLimit),
Nonce: types.BlockNonce{0x1},
Timestamp: hexutil.Uint64(block.Timestamp),
BaseFeePerGas: hexutil.Big(*baseFeesPerGas),
Expand Down Expand Up @@ -1088,111 +1087,6 @@ func (b *BlockChainAPI) prepareBlockResponse(
return blockResponse, nil
}

func (b *BlockChainAPI) getBlockNumber(blockNumberOrHash *rpc.BlockNumberOrHash) (uint64, error) {
err := fmt.Errorf("%w: neither block number nor hash specified", errs.ErrInvalid)
if blockNumberOrHash == nil {
return 0, err
}
if number, ok := blockNumberOrHash.Number(); ok {
height, err := resolveBlockNumber(number, b.blocks)
if err != nil {
b.logger.Error().Err(err).
Stringer("block_number", number).
Msg("failed to resolve block by hash")
return 0, err
}
return height, nil
}

if hash, ok := blockNumberOrHash.Hash(); ok {
evmHeight, err := b.blocks.GetHeightByID(hash)
if err != nil {
b.logger.Error().Err(err).
Stringer("block_hash", hash).
Msg("failed to get block by hash")
return 0, err
}
return evmHeight, nil
}

return 0, err
}

func resolveBlockNumber(
number rpc.BlockNumber,
blocksDB storage.BlockIndexer,
) (uint64, error) {
height := number.Int64()

// if special values (latest) we return latest executed height
//
// all the special values are:
// SafeBlockNumber = BlockNumber(-4)
// FinalizedBlockNumber = BlockNumber(-3)
// LatestBlockNumber = BlockNumber(-2)
// PendingBlockNumber = BlockNumber(-1)
//
// EVM on Flow does not have these concepts, but the latest block is the closest fit
if height < 0 {
executed, err := blocksDB.LatestEVMHeight()
if err != nil {
return 0, err
}
height = int64(executed)
}

return uint64(height), nil
}

// handleError takes in an error and in case the error is of type ErrEntityNotFound
// it returns nil instead of an error since that is according to the API spec,
// if the error is not of type ErrEntityNotFound it will return the error and the generic
// empty type.
func handleError[T any](err error, log zerolog.Logger, collector metrics.Collector) (T, error) {
var (
zero T
revertedErr *errs.RevertError
)

switch {
// as per specification returning nil and nil for not found resources
case errors.Is(err, errs.ErrEntityNotFound):
return zero, nil
case errors.Is(err, errs.ErrInvalid):
return zero, err
case errors.Is(err, errs.ErrFailedTransaction):
return zero, err
case errors.As(err, &revertedErr):
return zero, revertedErr
default:
collector.ApiErrorOccurred()
log.Error().Err(err).Msg("api error")
return zero, errs.ErrInternal
}
}

// decodeHash parses a hex-encoded 32-byte hash. The input may optionally
// be prefixed by 0x and can have a byte length up to 32.
func decodeHash(s string) (h common.Hash, inputLength int, err error) {
if strings.HasPrefix(s, "0x") || strings.HasPrefix(s, "0X") {
s = s[2:]
}
if (len(s) & 1) > 0 {
s = "0" + s
}
b, err := hex.DecodeString(s)
if err != nil {
return common.Hash{}, 0, fmt.Errorf("invalid hex string: %s", s)
}
if len(b) > common.HashLength {
return common.Hash{}, len(b), fmt.Errorf(
"hex string too long, want at most 32 bytes, have %d bytes",
len(b),
)
}
return common.BytesToHash(b), len(b), nil
}

/*
Static responses section

Expand Down
Loading
Loading