Skip to content

Commit b158011

Browse files
committed
use finalizer instead of returning state release function
1 parent 8d5951a commit b158011

File tree

9 files changed

+86
-89
lines changed

9 files changed

+86
-89
lines changed

arbitrum/apibackend.go

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"errors"
66
"fmt"
77
"math/big"
8+
"runtime"
89
"strconv"
910
"strings"
1011
"time"
@@ -229,11 +230,10 @@ func (a *APIBackend) FeeHistory(
229230

230231
// use the most recent average compute rate for all blocks
231232
// note: while we could query this value for each block, it'd be prohibitively expensive
232-
state, _, release, err := a.StateAndHeaderByNumber(ctx, newestBlock)
233+
state, _, err := a.StateAndHeaderByNumber(ctx, newestBlock)
233234
if err != nil {
234235
return common.Big0, nil, nil, nil, err
235236
}
236-
defer release()
237237
speedLimit, err := core.GetArbOSSpeedLimitPerSecond(state)
238238
if err != nil {
239239
return common.Big0, nil, nil, nil, err
@@ -434,59 +434,77 @@ func (a *APIBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.
434434
return nil, errors.New("invalid arguments; neither block nor hash specified")
435435
}
436436

437-
func (a *APIBackend) stateAndHeaderFromHeader(ctx context.Context, header *types.Header, err error) (*state.StateDB, *types.Header, ethapi.StateReleaseFunc, error) {
437+
func (a *APIBackend) stateAndHeaderFromHeader(ctx context.Context, header *types.Header, err error) (*state.StateDB, *types.Header, error) {
438438
if err != nil {
439-
return nil, header, nil, err
439+
return nil, header, err
440440
}
441441
if header == nil {
442-
return nil, nil, nil, errors.New("header not found")
442+
return nil, nil, errors.New("header not found")
443443
}
444444
if !a.BlockChain().Config().IsArbitrumNitro(header.Number) {
445-
return nil, header, nil, types.ErrUseFallback
445+
return nil, header, types.ErrUseFallback
446446
}
447447
bc := a.BlockChain()
448448
stateFor := func(header *types.Header) (*state.StateDB, error) {
449449
if header.Root != (common.Hash{}) {
450450
// Try referencing the root, if it isn't in dirties cache then Reference will have no effect
451451
bc.StateCache().TrieDB().Reference(header.Root, common.Hash{})
452452
}
453-
state, err := bc.StateAt(header.Root)
454-
return state, err
453+
statedb, err := state.New(header.Root, bc.StateCache(), bc.Snapshots())
454+
if err != nil {
455+
return nil, err
456+
}
457+
if header.Root != (common.Hash{}) {
458+
// we are setting finalizer instead of returning a StateReleaseFunc to avoid changing ethapi.Backend interface to minimize diff to upstream
459+
headerRoot := header.Root
460+
runtime.SetFinalizer(statedb, func(_ *state.StateDB) {
461+
bc.StateCache().TrieDB().Dereference(headerRoot)
462+
})
463+
}
464+
return statedb, err
455465
}
456466
lastState, lastHeader, err := FindLastAvailableState(ctx, bc, stateFor, header, nil, a.b.config.MaxRecreateStateDepth)
457467
if err != nil {
458-
return nil, nil, nil, err
459-
}
460-
release := func() {
461-
if lastHeader.Root != (common.Hash{}) {
462-
bc.StateCache().TrieDB().Dereference(lastHeader.Root)
463-
}
468+
return nil, nil, err
464469
}
465470
if lastHeader == header {
466-
return lastState, header, release, nil
471+
return lastState, header, nil
472+
}
473+
if lastHeader.Root != (common.Hash{}) {
474+
defer bc.StateCache().TrieDB().Dereference(lastHeader.Root)
467475
}
468-
defer release()
469476
targetBlock := bc.GetBlockByNumber(header.Number.Uint64())
470477
if targetBlock == nil {
471-
return nil, nil, nil, errors.New("target block not found")
478+
return nil, nil, errors.New("target block not found")
472479
}
473480
lastBlock := bc.GetBlockByNumber(lastHeader.Number.Uint64())
474481
if lastBlock == nil {
475-
return nil, nil, nil, errors.New("last block not found")
482+
return nil, nil, errors.New("last block not found")
476483
}
477484
reexec := uint64(0)
478485
checkLive := false
479486
preferDisk := true
480-
state, release, err := eth.NewArbEthereum(a.b.arb.BlockChain(), a.ChainDb()).StateAtBlock(ctx, targetBlock, reexec, lastState, lastBlock, checkLive, preferDisk)
481-
return state, header, release, err
487+
statedb, release, err := eth.NewArbEthereum(a.b.arb.BlockChain(), a.ChainDb()).StateAtBlock(ctx, targetBlock, reexec, lastState, lastBlock, checkLive, preferDisk)
488+
if err != nil {
489+
return nil, nil, err
490+
}
491+
// we are setting finalizer instead of returning a StateReleaseFunc to avoid changing ethapi.Backend interface to minimize diff to upstream
492+
// to set a finalizer we need to allocated the obj in current block
493+
statedb, err = state.New(header.Root, statedb.Database(), nil)
494+
if header.Root != (common.Hash{}) {
495+
runtime.SetFinalizer(statedb, func(_ *state.StateDB) {
496+
release()
497+
})
498+
}
499+
return statedb, header, err
482500
}
483501

484-
func (a *APIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, ethapi.StateReleaseFunc, error) {
502+
func (a *APIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) {
485503
header, err := a.HeaderByNumber(ctx, number)
486504
return a.stateAndHeaderFromHeader(ctx, header, err)
487505
}
488506

489-
func (a *APIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, ethapi.StateReleaseFunc, error) {
507+
func (a *APIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) {
490508
header, err := a.HeaderByNumberOrHash(ctx, blockNrOrHash)
491509
return a.stateAndHeaderFromHeader(ctx, header, err)
492510
}

eth/api_backend.go

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ import (
3737
"github.com/ethereum/go-ethereum/eth/tracers"
3838
"github.com/ethereum/go-ethereum/ethdb"
3939
"github.com/ethereum/go-ethereum/event"
40-
"github.com/ethereum/go-ethereum/internal/ethapi"
4140
"github.com/ethereum/go-ethereum/miner"
4241
"github.com/ethereum/go-ethereum/params"
4342
"github.com/ethereum/go-ethereum/rpc"
@@ -199,46 +198,46 @@ func (b *EthAPIBackend) PendingBlockAndReceipts() (*types.Block, types.Receipts)
199198
return b.eth.miner.PendingBlockAndReceipts()
200199
}
201200

202-
func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, ethapi.StateReleaseFunc, error) {
201+
func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) {
203202
// Pending state is only known by the miner
204203
if number == rpc.PendingBlockNumber {
205204
block, state := b.eth.miner.Pending()
206205
if block == nil || state == nil {
207-
return nil, nil, nil, errors.New("pending state is not available")
206+
return nil, nil, errors.New("pending state is not available")
208207
}
209-
return state, block.Header(), ethapi.NoOpStateRelease, nil
208+
return state, block.Header(), nil
210209
}
211210
// Otherwise resolve the block number and return its state
212211
header, err := b.HeaderByNumber(ctx, number)
213212
if err != nil {
214-
return nil, nil, nil, err
213+
return nil, nil, err
215214
}
216215
if header == nil {
217-
return nil, nil, nil, errors.New("header not found")
216+
return nil, nil, errors.New("header not found")
218217
}
219218
stateDb, err := b.eth.BlockChain().StateAt(header.Root)
220-
return stateDb, header, ethapi.NoOpStateRelease, err
219+
return stateDb, header, err
221220
}
222221

223-
func (b *EthAPIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, ethapi.StateReleaseFunc, error) {
222+
func (b *EthAPIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) {
224223
if blockNr, ok := blockNrOrHash.Number(); ok {
225224
return b.StateAndHeaderByNumber(ctx, blockNr)
226225
}
227226
if hash, ok := blockNrOrHash.Hash(); ok {
228227
header, err := b.HeaderByHash(ctx, hash)
229228
if err != nil {
230-
return nil, nil, nil, err
229+
return nil, nil, err
231230
}
232231
if header == nil {
233-
return nil, nil, nil, errors.New("header for hash not found")
232+
return nil, nil, errors.New("header for hash not found")
234233
}
235234
if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash {
236-
return nil, nil, nil, errors.New("hash is not currently canonical")
235+
return nil, nil, errors.New("hash is not currently canonical")
237236
}
238237
stateDb, err := b.eth.BlockChain().StateAt(header.Root)
239-
return stateDb, header, ethapi.NoOpStateRelease, err
238+
return stateDb, header, err
240239
}
241-
return nil, nil, nil, errors.New("invalid arguments; neither block nor hash specified")
240+
return nil, nil, errors.New("invalid arguments; neither block nor hash specified")
242241
}
243242

244243
func (b *EthAPIBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {

eth/catalyst/api_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1143,11 +1143,10 @@ func TestWithdrawals(t *testing.T) {
11431143
}
11441144

11451145
// 11: verify withdrawals were processed.
1146-
db, _, release, err := ethservice.APIBackend.StateAndHeaderByNumber(context.Background(), rpc.BlockNumber(execData.ExecutionPayload.Number))
1146+
db, _, err := ethservice.APIBackend.StateAndHeaderByNumber(context.Background(), rpc.BlockNumber(execData.ExecutionPayload.Number))
11471147
if err != nil {
11481148
t.Fatalf("unable to load db: %v", err)
11491149
}
1150-
defer release()
11511150
for i, w := range blockParams.Withdrawals {
11521151
// w.Amount is in gwei, balance in wei
11531152
if db.GetBalance(w.Address).Uint64() != w.Amount*params.GWei {

graphql/graphql.go

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -86,21 +86,20 @@ type Account struct {
8686
}
8787

8888
// getState fetches the StateDB object for an account.
89-
func (a *Account) getState(ctx context.Context) (*state.StateDB, ethapi.StateReleaseFunc, error) {
90-
state, _, release, err := a.r.backend.StateAndHeaderByNumberOrHash(ctx, a.blockNrOrHash)
91-
return state, release, err
89+
func (a *Account) getState(ctx context.Context) (*state.StateDB, error) {
90+
state, _, err := a.r.backend.StateAndHeaderByNumberOrHash(ctx, a.blockNrOrHash)
91+
return state, err
9292
}
9393

9494
func (a *Account) Address(ctx context.Context) (common.Address, error) {
9595
return a.address, nil
9696
}
9797

9898
func (a *Account) Balance(ctx context.Context) (hexutil.Big, error) {
99-
state, release, err := a.getState(ctx)
99+
state, err := a.getState(ctx)
100100
if err != nil {
101101
return hexutil.Big{}, err
102102
}
103-
defer release()
104103
balance := state.GetBalance(a.address)
105104
if balance == nil {
106105
return hexutil.Big{}, fmt.Errorf("failed to load balance %x", a.address)
@@ -117,29 +116,26 @@ func (a *Account) TransactionCount(ctx context.Context) (hexutil.Uint64, error)
117116
}
118117
return hexutil.Uint64(nonce), nil
119118
}
120-
state, release, err := a.getState(ctx)
119+
state, err := a.getState(ctx)
121120
if err != nil {
122121
return 0, err
123122
}
124-
defer release()
125123
return hexutil.Uint64(state.GetNonce(a.address)), nil
126124
}
127125

128126
func (a *Account) Code(ctx context.Context) (hexutil.Bytes, error) {
129-
state, release, err := a.getState(ctx)
127+
state, err := a.getState(ctx)
130128
if err != nil {
131129
return hexutil.Bytes{}, err
132130
}
133-
defer release()
134131
return state.GetCode(a.address), nil
135132
}
136133

137134
func (a *Account) Storage(ctx context.Context, args struct{ Slot common.Hash }) (common.Hash, error) {
138-
state, release, err := a.getState(ctx)
135+
state, err := a.getState(ctx)
139136
if err != nil {
140137
return common.Hash{}, err
141138
}
142-
defer release()
143139
return state.GetState(a.address, args.Slot), nil
144140
}
145141

0 commit comments

Comments
 (0)