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 local state index #541

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
d2b8c85
rename evm and remote
sideninja Sep 11, 2024
4554f46
move evm interface and rename file
sideninja Sep 11, 2024
e800a25
move validation and context inside the state
sideninja Sep 11, 2024
e039861
add local client
sideninja Sep 11, 2024
3ba5ba2
add support for calls and estimate
sideninja Sep 11, 2024
460cde6
implement call on state
sideninja Sep 11, 2024
584029f
add client handler
sideninja Sep 11, 2024
edf82ef
add client handler balancing remote and local
sideninja Sep 11, 2024
b2bb7b0
change local client creation
sideninja Sep 11, 2024
e3490c3
update local client syntax
sideninja Sep 11, 2024
f851e83
bootstrap client handler
sideninja Sep 11, 2024
8613437
update test apis
sideninja Sep 11, 2024
56e4bca
Merge branch 'gregor/local-state/main' into gregor/local-state/integrate
sideninja Sep 11, 2024
aded8e3
handle failed results
sideninja Sep 12, 2024
ec6d724
handle failed results
sideninja Sep 12, 2024
6cf64e4
check errors by value
sideninja Sep 12, 2024
cf9c41d
add state re-execution height
sideninja Sep 12, 2024
8ed258d
add evm height
sideninja Sep 12, 2024
2a73273
add pebble implementation for block state
sideninja Sep 12, 2024
d912624
update block mock
sideninja Sep 12, 2024
4a7ca08
fend for receipt status
sideninja Sep 12, 2024
0280909
update executed block height
sideninja Sep 12, 2024
80e698f
wip api changes executed height
sideninja Sep 12, 2024
550151c
rename block latest executed and indexed heights
sideninja Sep 13, 2024
7d2d5d1
use latest executed height
sideninja Sep 13, 2024
6829472
return data nil handle
sideninja Sep 13, 2024
a4e896f
add ms response time
sideninja Sep 13, 2024
0ddcaa6
use latest executed height on client init
sideninja Sep 13, 2024
dd9f945
handle estimate failures
sideninja Sep 13, 2024
832c39d
use specific height, don't use latest height since the local and remo…
sideninja Sep 13, 2024
e8ef351
fix tests
sideninja Sep 13, 2024
f4c0b83
Merge branch 'main' into gregor/local-state/main
sideninja Sep 13, 2024
2ca4b19
Merge branch 'gregor/local-state/main' into gregor/local-state/state
sideninja Sep 13, 2024
4e7aab7
change evm client height from int to uint
sideninja Sep 13, 2024
d1651c4
update block hash resolver change
sideninja Sep 13, 2024
935f68e
client handler api updates
sideninja Sep 13, 2024
8584fa7
update remote client changes
sideninja Sep 13, 2024
1aa026c
return remote values
sideninja Sep 13, 2024
f6c4f74
improve time output to ms
sideninja Sep 13, 2024
14ba53b
added cadence arch and environment tests
sideninja Sep 13, 2024
2150fb5
update flow-go with fixed replayer
sideninja Sep 13, 2024
675c7e5
update flow-go
sideninja Sep 14, 2024
cf582e6
add todo comments
sideninja Sep 14, 2024
a4e500c
extend storage contract to have logs emitted and improve the test
sideninja Sep 15, 2024
c20e766
fix test issues and add comment
sideninja Sep 15, 2024
d07b8ff
update comment
sideninja Sep 15, 2024
d0b5da8
update flow-go to specific version
sideninja Sep 15, 2024
ce4eb30
update test with changes
sideninja Sep 15, 2024
5e4201f
remove legacy decode done in flow-go
sideninja Sep 15, 2024
5fb3080
Update README.md
sideninja Sep 15, 2024
4960b86
Merge branch 'gregor/local-state/integrate' into gregor/local-state/main
sideninja Sep 15, 2024
8c319c2
Merge branch 'gregor/local-state/state' into gregor/local-state/main
sideninja Sep 15, 2024
2d6477c
comment out
sideninja Sep 15, 2024
fde99b6
comment out
sideninja Sep 15, 2024
0d6af5e
return errs
sideninja Sep 15, 2024
da2f408
Merge remote-tracking branch 'origin/gregor/local-state/state' into g…
sideninja Sep 15, 2024
05b4f64
fix test changes in contract storage.sol
sideninja Sep 15, 2024
846283c
fix test changes in contract storage.sol
sideninja Sep 15, 2024
24243a3
Merge branch 'gregor/local-state/state' into gregor/local-state/main
sideninja Sep 16, 2024
703e692
remove uneeded block fetch
sideninja Sep 16, 2024
b1d62e0
Merge branch 'gregor/local-state/integrate' into gregor/local-state/main
sideninja Sep 16, 2024
a0881de
Merge branch 'gregor/local-state/main' into feature/state
sideninja Sep 16, 2024
dc3a030
Merge branch 'main' into gregor/local-state/integrate
sideninja Sep 16, 2024
169c245
Merge branch 'main' into gregor/local-state/engine
sideninja Sep 16, 2024
2ba6449
Merge branch 'gregor/local-state/engine' into feature/state
sideninja Sep 16, 2024
d5874db
Merge branch 'gregor/local-state/historic' into feature/state
sideninja Sep 16, 2024
728923e
use remote client for height and add comment
sideninja Sep 16, 2024
61b9e0e
restrict calling latest evm height
sideninja Sep 16, 2024
f75c2c9
remove receipt match
sideninja Sep 16, 2024
73ea0a5
Merge branch 'gregor/local-state/integrate' into feature/state
sideninja Sep 16, 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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ EVM Gateway has public RPC endpoints available for the following environments:

| Name | Value |
|-----------------|----------------------------------------|
| Network Name | EVM on Flow Testnet |
| Network Name | Testnet |
| Description | The public RPC URL for Flow Testnet |
| RPC Endpoint | https://testnet.evm.nodes.onflow.org |
| Chain ID | 545 |
Expand All @@ -226,7 +226,7 @@ EVM Gateway has public RPC endpoints available for the following environments:

| Name | Value |
|-----------------|----------------------------------------|
| Network Name | EVM on Flow |
| Network Name | Mainnet |
| Description | The public RPC URL for Flow Mainnet |
| RPC Endpoint | https://mainnet.evm.nodes.onflow.org |
| Chain ID | 747 |
Expand Down
150 changes: 80 additions & 70 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func SupportedAPIs(
type BlockChainAPI struct {
logger zerolog.Logger
config *config.Config
evm requester.Requester
evm requester.EVMClient
blocks storage.BlockIndexer
transactions storage.TransactionIndexer
receipts storage.ReceiptIndexer
Expand All @@ -96,7 +96,7 @@ type BlockChainAPI struct {
func NewBlockChainAPI(
logger zerolog.Logger,
config *config.Config,
evm requester.Requester,
evm requester.EVMClient,
blocks storage.BlockIndexer,
transactions storage.TransactionIndexer,
receipts storage.ReceiptIndexer,
Expand All @@ -105,7 +105,7 @@ func NewBlockChainAPI(
collector metrics.Collector,
) (*BlockChainAPI, error) {
// get the height from which the indexing resumed since the last restart, this is needed for syncing status.
indexingResumedHeight, err := blocks.LatestEVMHeight()
indexingResumedHeight, err := blocks.LatestIndexedHeight()
if err != nil {
return nil, fmt.Errorf("failed to retrieve the indexing resumed height: %w", err)
}
Expand All @@ -130,12 +130,12 @@ func (b *BlockChainAPI) BlockNumber(ctx context.Context) (hexutil.Uint64, error)
return 0, err
}

latestBlockHeight, err := b.blocks.LatestEVMHeight()
latest, err := b.blocks.LatestExecutedHeight()
if err != nil {
return handleError[hexutil.Uint64](err, b.logger, b.collector)
return hexutil.Uint64(0), err
}

return hexutil.Uint64(latestBlockHeight), nil
return hexutil.Uint64(latest), nil
}

// Syncing returns false in case the node is currently not syncing with the network.
Expand All @@ -149,7 +149,7 @@ func (b *BlockChainAPI) Syncing(ctx context.Context) (interface{}, error) {
return nil, err
}

currentBlock, err := b.blocks.LatestEVMHeight()
currentBlock, err := b.blocks.LatestExecutedHeight()
if err != nil {
return handleError[any](err, b.logger, b.collector)
}
Expand Down Expand Up @@ -214,7 +214,7 @@ func (b *BlockChainAPI) GetBalance(
return nil, err
}

evmHeight, err := b.getBlockNumber(&blockNumberOrHash)
evmHeight, err := b.resolveBlockNumberOrHash(&blockNumberOrHash)
if err != nil {
return handleError[*hexutil.Big](err, l, b.collector)
}
Expand Down Expand Up @@ -246,6 +246,7 @@ func (b *BlockChainAPI) GetTransactionByHash(
return handleError[*Transaction](err, l, b.collector)
}

// todo what if there's no receipt yet? but tx exists
rcp, err := b.receipts.GetByTransactionID(hash)
if err != nil {
return handleError[*Transaction](err, l, b.collector)
Expand Down Expand Up @@ -305,15 +306,12 @@ func (b *BlockChainAPI) GetTransactionByBlockNumberAndIndex(
return nil, err
}

if blockNumber < rpc.EarliestBlockNumber {
latestBlockNumber, err := b.blocks.LatestEVMHeight()
if err != nil {
return handleError[*Transaction](err, l, b.collector)
}
blockNumber = rpc.BlockNumber(latestBlockNumber)
height, err := b.resolveBlockNumber(blockNumber)
if err != nil {
return nil, err
}

block, err := b.blocks.GetByHeight(uint64(blockNumber))
block, err := b.blocks.GetByHeight(uint64(height))
if err != nil {
return handleError[*Transaction](err, l, b.collector)
}
Expand All @@ -335,7 +333,7 @@ func (b *BlockChainAPI) GetTransactionByBlockNumberAndIndex(
func (b *BlockChainAPI) GetTransactionReceipt(
ctx context.Context,
hash common.Hash,
) (map[string]interface{}, error) {
) (map[string]any, error) {
l := b.logger.With().
Str("endpoint", "getTransactionReceipt").
Str("hash", hash.String()).
Expand All @@ -347,17 +345,27 @@ func (b *BlockChainAPI) GetTransactionReceipt(

tx, err := b.transactions.Get(hash)
if err != nil {
return handleError[map[string]interface{}](err, l, b.collector)
return handleError[map[string]any](err, l, b.collector)
}

receipt, err := b.receipts.GetByTransactionID(hash)
if err != nil {
return handleError[map[string]interface{}](err, l, b.collector)
return handleError[map[string]any](err, l, b.collector)
}

// we don't return receipts until local state index
// recreated the state by executing the transaction
latestExecutedHeight, err := b.blocks.LatestExecutedHeight()
if err != nil {
return handleError[map[string]any](err, l, b.collector)
}
if receipt.BlockNumber.Uint64() > latestExecutedHeight {
return nil, nil
}

txReceipt, err := MarshalReceipt(receipt, tx)
if err != nil {
return handleError[map[string]interface{}](err, l, b.collector)
return handleError[map[string]any](err, l, b.collector)
}

return txReceipt, nil
Expand Down Expand Up @@ -413,17 +421,12 @@ func (b *BlockChainAPI) GetBlockByNumber(
return nil, err
}

height := uint64(blockNumber)
var err error
if blockNumber < 0 {
height, err = b.blocks.LatestEVMHeight()
if err != nil {
return handleError[*Block](err, l, b.collector)
}
height, err := b.resolveBlockNumber(blockNumber)
if err != nil {
return handleError[*Block](err, l, b.collector)
}

block, err := b.blocks.GetByHeight(height)

block, err := b.blocks.GetByHeight(uint64(height))
if err != nil {
return handleError[*Block](err, l, b.collector)
}
Expand All @@ -439,51 +442,42 @@ func (b *BlockChainAPI) GetBlockByNumber(
// GetBlockReceipts returns the block receipts for the given block hash or number or tag.
func (b *BlockChainAPI) GetBlockReceipts(
ctx context.Context,
blockNumberOrHash rpc.BlockNumberOrHash,
) ([]map[string]interface{}, error) {
numHash rpc.BlockNumberOrHash,
) ([]map[string]any, error) {
l := b.logger.With().
Str("endpoint", "getBlockReceipts").
Str("hash", blockNumberOrHash.String()).
Str("hash", numHash.String()).
Logger()

if err := rateLimit(ctx, b.limiter, l); err != nil {
return nil, err
}

var (
block *models.Block
err error
)
if blockNumberOrHash.BlockHash != nil {
block, err = b.blocks.GetByID(*blockNumberOrHash.BlockHash)
} else if blockNumberOrHash.BlockNumber != nil {
block, err = b.blocks.GetByHeight(uint64(blockNumberOrHash.BlockNumber.Int64()))
} else {
return handleError[[]map[string]interface{}](
fmt.Errorf("%w: block number or hash not provided", errs.ErrInvalid),
l,
b.collector,
)
height, err := b.resolveBlockNumberOrHash(&numHash)
if err != nil {
return handleError[[]map[string]any](err, l, b.collector)
}

block, err := b.blocks.GetByHeight(uint64(height))
if err != nil {
return handleError[[]map[string]interface{}](err, l, b.collector)
return handleError[[]map[string]any](err, l, b.collector)
}

receipts := make([]map[string]interface{}, len(block.TransactionHashes))
for i, hash := range block.TransactionHashes {
tx, err := b.transactions.Get(hash)
if err != nil {
return handleError[[]map[string]interface{}](err, l, b.collector)
return handleError[[]map[string]any](err, l, b.collector)
}

receipt, err := b.receipts.GetByTransactionID(hash)
if err != nil {
return handleError[[]map[string]interface{}](err, l, b.collector)
return handleError[[]map[string]any](err, l, b.collector)
}

receipts[i], err = MarshalReceipt(receipt, tx)
if err != nil {
return handleError[[]map[string]interface{}](err, l, b.collector)
return handleError[[]map[string]any](err, l, b.collector)
}
}

Expand Down Expand Up @@ -529,15 +523,12 @@ func (b *BlockChainAPI) GetBlockTransactionCountByNumber(
return nil, err
}

if blockNumber < rpc.EarliestBlockNumber {
latestBlockNumber, err := b.blocks.LatestEVMHeight()
if err != nil {
return handleError[*hexutil.Uint](err, l, b.collector)
}
blockNumber = rpc.BlockNumber(latestBlockNumber)
height, err := b.resolveBlockNumber(blockNumber)
if err != nil {
return handleError[*hexutil.Uint](err, l, b.collector)
}

block, err := b.blocks.GetByHeight(uint64(blockNumber))
block, err := b.blocks.GetByHeight(uint64(height))
if err != nil {
return handleError[*hexutil.Uint](err, l, b.collector)
}
Expand Down Expand Up @@ -576,7 +567,7 @@ func (b *BlockChainAPI) Call(
blockNumberOrHash = &latestBlockNumberOrHash
}

evmHeight, err := b.getBlockNumber(blockNumberOrHash)
evmHeight, err := b.resolveBlockNumberOrHash(blockNumberOrHash)
if err != nil {
return handleError[hexutil.Bytes](err, l, b.collector)
}
Expand Down Expand Up @@ -637,6 +628,7 @@ func (b *BlockChainAPI) GetLogs(
// otherwise we use the block range as the filter

// assign default values to latest block number, unless provided
// todo should we resolve latest to specific height
from := models.LatestBlockNumber
if criteria.FromBlock != nil {
from = criteria.FromBlock
Expand All @@ -646,7 +638,7 @@ func (b *BlockChainAPI) GetLogs(
to = criteria.ToBlock
}

h, err := b.blocks.LatestEVMHeight()
h, err := b.blocks.LatestIndexedHeight()
if err != nil {
return handleError[[]*types.Log](err, l, b.collector)
}
Expand Down Expand Up @@ -694,7 +686,7 @@ func (b *BlockChainAPI) GetTransactionCount(
return nil, err
}

evmHeight, err := b.getBlockNumber(&blockNumberOrHash)
evmHeight, err := b.resolveBlockNumberOrHash(&blockNumberOrHash)
if err != nil {
return handleError[*hexutil.Uint64](err, l, b.collector)
}
Expand Down Expand Up @@ -760,7 +752,7 @@ func (b *BlockChainAPI) EstimateGas(
blockNumberOrHash = &latestBlockNumberOrHash
}

evmHeight, err := b.getBlockNumber(blockNumberOrHash)
evmHeight, err := b.resolveBlockNumberOrHash(blockNumberOrHash)
if err != nil {
return handleError[hexutil.Uint64](err, l, b.collector)
}
Expand Down Expand Up @@ -789,7 +781,7 @@ func (b *BlockChainAPI) GetCode(
return nil, err
}

evmHeight, err := b.getBlockNumber(&blockNumberOrHash)
evmHeight, err := b.resolveBlockNumberOrHash(&blockNumberOrHash)
if err != nil {
return handleError[hexutil.Bytes](err, l, b.collector)
}
Expand Down Expand Up @@ -834,7 +826,7 @@ func (b *BlockChainAPI) FeeHistory(
var err error
if lastBlock < 0 {
// From the special block tags, we only support "latest".
lastBlockNumber, err = b.blocks.LatestEVMHeight()
lastBlockNumber, err = b.blocks.LatestIndexedHeight()
if err != nil {
return handleError[*FeeHistoryResult](err, l, b.collector)
}
Expand Down Expand Up @@ -914,7 +906,7 @@ func (b *BlockChainAPI) GetStorageAt(
)
}

evmHeight, err := b.getBlockNumber(&blockNumberOrHash)
evmHeight, err := b.resolveBlockNumberOrHash(&blockNumberOrHash)
if err != nil {
return handleError[hexutil.Bytes](err, l, b.collector)
}
Expand Down Expand Up @@ -1029,27 +1021,45 @@ func (b *BlockChainAPI) prepareBlockResponse(
return blockResponse, nil
}

func (b *BlockChainAPI) getBlockNumber(blockNumberOrHash *rpc.BlockNumberOrHash) (int64, error) {
// resolveBlockNumberOrHash resolves the block number or hash into the evm block number.
// If block number is negative we resolve to latest executed height.
func (b *BlockChainAPI) resolveBlockNumberOrHash(block *rpc.BlockNumberOrHash) (uint64, error) {
err := fmt.Errorf("%w: neither block number nor hash specified", errs.ErrInvalid)
if blockNumberOrHash == nil {
if block == nil {
return 0, err
}
if number, ok := blockNumberOrHash.Number(); ok {
return number.Int64(), nil
if number, ok := block.Number(); ok {
return b.resolveBlockNumber(number)
}

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

return 0, err
}

// resolveBlockNumber resolves the block number into the evm block number.
// If block number is negative we resolve to latest executed height.
func (b *BlockChainAPI) resolveBlockNumber(number rpc.BlockNumber) (uint64, error) {
height := number.Int64()

// if special values (latest) we return latest executed height
if height < 0 {
executed, err := b.blocks.LatestExecutedHeight()
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
Expand Down
Loading
Loading