Skip to content

Commit 9334e94

Browse files
authored
rpc: fix in API with request Hash and state processing add check Canonical (#19356)
APIs performing state lookups via Hash must implement a canonicality check. Failure to do so may allow access to stale or invalid state data from side-chains/reorgs, compromising the accuracy of the API response API that was OK: - eth_getStorageAt() - eth_call () - eth_estimateGas() - eth_getWitness() - eth_getProof() - eth_createAccessList() - debug_traceBlockByHash (( - debug_accountAt() API Fixed with this PR: - eth_getBalance() - eth_getTransactionCount() - eth_getCode() - eth_getStorageAt() - debug_storageRangeAt() - otterscan_hasCode() - erigon_getBalanceChangesInBlock() - debug_traceCall() - trace_replayBlockTransactions() - debug_accountRange()
1 parent 84a5aad commit 9334e94

File tree

7 files changed

+29
-26
lines changed

7 files changed

+29
-26
lines changed

rpc/jsonrpc/debug_api.go

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -98,20 +98,21 @@ func (api *DebugAPIImpl) StorageRangeAt(ctx context.Context, blockHash common.Ha
9898
}
9999
defer tx.Rollback()
100100

101-
number, err := api._blockReader.HeaderNumber(ctx, tx, blockHash)
101+
blockNrOrHash := rpc.BlockNumberOrHashWithHash(blockHash, true)
102+
blockNumber, _, _, err := rpchelper.GetCanonicalBlockNumber(ctx, blockNrOrHash, tx, api._blockReader, api.filters)
102103
if err != nil {
104+
if errors.As(err, &rpc.BlockNotFoundErr{}) {
105+
return StorageRangeResult{}, nil
106+
}
103107
return StorageRangeResult{}, err
104108
}
105-
if number == nil {
106-
return StorageRangeResult{}, nil
107-
}
108109

109-
err = api.BaseAPI.checkPruneHistory(ctx, tx, *number)
110+
err = api.BaseAPI.checkPruneHistory(ctx, tx, blockNumber)
110111
if err != nil {
111112
return StorageRangeResult{}, err
112113
}
113114

114-
minTxNum, err := api._txNumReader.Min(ctx, tx, *number)
115+
minTxNum, err := api._txNumReader.Min(ctx, tx, blockNumber)
115116
if err != nil {
116117
return StorageRangeResult{}, err
117118
}
@@ -188,15 +189,12 @@ func (api *DebugAPIImpl) AccountRange(ctx context.Context, blockNrOrHash rpc.Blo
188189
blockNumber = uint64(number)
189190
}
190191

191-
} else if hash, ok := blockNrOrHash.Hash(); ok {
192-
header, err1 := api.headerByHash(ctx, hash, tx)
193-
if err1 != nil {
194-
return state.IteratorDump{}, err1
195-
}
196-
if header == nil {
197-
return state.IteratorDump{}, fmt.Errorf("header %s not found", hash.Hex())
192+
} else if _, ok := blockNrOrHash.Hash(); ok {
193+
bn, _, _, err2 := rpchelper.GetCanonicalBlockNumber(ctx, blockNrOrHash, tx, api._blockReader, api.filters)
194+
if err2 != nil {
195+
return state.IteratorDump{}, err2
198196
}
199-
blockNumber = header.Number.Uint64()
197+
blockNumber = bn
200198
}
201199

202200
err = api.BaseAPI.checkPruneHistory(ctx, tx, blockNumber)

rpc/jsonrpc/erigon_block.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ func (api *ErigonImpl) GetBalanceChangesInBlock(ctx context.Context, blockNrOrHa
217217

218218
balancesMapping := make(map[common.Address]*hexutil.Big)
219219

220-
blockNumber, _, latest, err := rpchelper.GetBlockNumber(ctx, blockNrOrHash, tx, api._blockReader, api.filters)
220+
blockNumber, _, latest, err := rpchelper.GetCanonicalBlockNumber(ctx, blockNrOrHash, tx, api._blockReader, api.filters)
221221
if err != nil {
222222
return nil, err
223223
}

rpc/jsonrpc/eth_accounts.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func (api *APIImpl) GetBalance(ctx context.Context, address common.Address, bloc
4444
}
4545
defer tx.Rollback()
4646

47-
blockNumber, _, latest, err := rpchelper.GetBlockNumber(ctx, blockNrOrHash, tx, api._blockReader, api.filters)
47+
blockNumber, _, latest, err := rpchelper.GetCanonicalBlockNumber(ctx, blockNrOrHash, tx, api._blockReader, api.filters)
4848
if err != nil {
4949
return nil, err
5050
}
@@ -96,7 +96,7 @@ func (api *APIImpl) GetTransactionCount(ctx context.Context, address common.Addr
9696
}
9797
defer tx.Rollback()
9898

99-
blockNumber, _, latest, err := rpchelper.GetBlockNumber(ctx, blockNrOrHash, tx, api._blockReader, api.filters)
99+
blockNumber, _, latest, err := rpchelper.GetCanonicalBlockNumber(ctx, blockNrOrHash, tx, api._blockReader, api.filters)
100100
if err != nil {
101101
return nil, err
102102
}
@@ -129,7 +129,7 @@ func (api *APIImpl) GetCode(ctx context.Context, address common.Address, blockNr
129129
return nil, fmt.Errorf("getCode cannot open tx: %w", err1)
130130
}
131131
defer tx.Rollback()
132-
blockNumber, _, latest, err := rpchelper.GetBlockNumber(ctx, blockNrOrHash, tx, api._blockReader, api.filters)
132+
blockNumber, _, latest, err := rpchelper.GetCanonicalBlockNumber(ctx, blockNrOrHash, tx, api._blockReader, api.filters)
133133
if err != nil {
134134
return nil, err
135135
}
@@ -240,8 +240,7 @@ func (api *APIImpl) GetStorageAt(ctx context.Context, address common.Address, in
240240
}
241241
defer tx.Rollback()
242242

243-
blockNrOrHash.RequireCanonical = true
244-
blockNumber, _, latest, err := rpchelper.GetBlockNumber(ctx, blockNrOrHash, tx, api._blockReader, api.filters)
243+
blockNumber, _, latest, err := rpchelper.GetCanonicalBlockNumber(ctx, blockNrOrHash, tx, api._blockReader, api.filters)
245244
if err != nil {
246245
return hexutil.Encode(common.LeftPadBytes(empty, 32)), err
247246
}
@@ -283,7 +282,7 @@ func (api *APIImpl) Exist(ctx context.Context, address common.Address, blockNrOr
283282
}
284283
defer tx.Rollback()
285284

286-
blockNumber, _, latest, err := rpchelper.GetBlockNumber(ctx, blockNrOrHash, tx, api._blockReader, api.filters)
285+
blockNumber, _, latest, err := rpchelper.GetCanonicalBlockNumber(ctx, blockNrOrHash, tx, api._blockReader, api.filters)
287286
if err != nil {
288287
return false, err
289288
}

rpc/jsonrpc/otterscan_has_code.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func (api *OtterscanAPIImpl) HasCode(ctx context.Context, address common.Address
3333
}
3434
defer tx.Rollback()
3535

36-
blockNumber, _, _, err := rpchelper.GetBlockNumber(ctx, blockNrOrHash, tx, api._blockReader, api.filters)
36+
blockNumber, _, _, err := rpchelper.GetCanonicalBlockNumber(ctx, blockNrOrHash, tx, api._blockReader, api.filters)
3737
if err != nil {
3838
return false, err
3939
}

rpc/jsonrpc/trace_adhoc.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -989,7 +989,7 @@ func (api *TraceAPIImpl) ReplayBlockTransactions(ctx context.Context, blockNrOrH
989989
return nil, err
990990
}
991991

992-
blockNumber, blockHash, _, err := rpchelper.GetBlockNumber(ctx, blockNrOrHash, tx, api._blockReader, api.filters)
992+
blockNumber, blockHash, _, err := rpchelper.GetCanonicalBlockNumber(ctx, blockNrOrHash, tx, api._blockReader, api.filters)
993993
if err != nil {
994994
return nil, err
995995
}

rpc/jsonrpc/tracing.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ func (api *DebugAPIImpl) TraceCall(ctx context.Context, args ethapi.CallArgs, bl
365365
}
366366
engine := api.engine()
367367

368-
blockNumber, hash, isLatest, err := rpchelper.GetBlockNumber(ctx, blockNrOrHash, dbtx, api._blockReader, api.filters)
368+
blockNumber, hash, isLatest, err := rpchelper.GetCanonicalBlockNumber(ctx, blockNrOrHash, dbtx, api._blockReader, api.filters)
369369
if err != nil {
370370
return fmt.Errorf("get block number: %v", err)
371371
}

rpc/rpchelper/helper.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,14 @@ func GetBlockNumber(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash, tx
7777
}
7878

7979
func GetCanonicalBlockNumber(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash, tx kv.Tx, br services.FullBlockReader, filters *Filters) (uint64, common.Hash, bool, error) {
80-
bn, bh, latest, _, err := _GetBlockNumber(ctx, true, blockNrOrHash, tx, br, filters)
81-
return bn, bh, latest, err
80+
bn, bh, latest, found, err := _GetBlockNumber(ctx, true, blockNrOrHash, tx, br, filters)
81+
if err != nil {
82+
return 0, common.Hash{}, false, err
83+
}
84+
if !found {
85+
return bn, bh, latest, rpc.BlockNotFoundErr{BlockId: blockNrOrHash.String()}
86+
}
87+
return bn, bh, latest, nil
8288
}
8389

8490
func _GetBlockNumber(ctx context.Context, requireCanonical bool, blockNrOrHash rpc.BlockNumberOrHash, tx kv.Tx, br services.FullBlockReader, filters *Filters) (blockNumber uint64, hash common.Hash, latest bool, found bool, err error) {

0 commit comments

Comments
 (0)