forked from erigontech/erigon
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhelper.go
134 lines (123 loc) · 4.38 KB
/
helper.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package rpchelper
import (
"context"
"fmt"
"github.com/ledgerwatch/erigon-lib/kv"
"github.com/ledgerwatch/erigon-lib/kv/kvcache"
state2 "github.com/ledgerwatch/erigon-lib/state"
"github.com/ledgerwatch/erigon/common"
"github.com/ledgerwatch/erigon/core/rawdb"
"github.com/ledgerwatch/erigon/core/state"
"github.com/ledgerwatch/erigon/core/types/accounts"
"github.com/ledgerwatch/erigon/eth/stagedsync/stages"
"github.com/ledgerwatch/erigon/rpc"
"github.com/ledgerwatch/erigon/turbo/adapter"
"github.com/ledgerwatch/log/v3"
)
// unable to decode supplied params, or an invalid number of parameters
type nonCanonocalHashError struct{ hash common.Hash }
func (e nonCanonocalHashError) ErrorCode() int { return -32603 }
func (e nonCanonocalHashError) Error() string {
return fmt.Sprintf("hash %x is not currently canonical", e.hash)
}
func GetBlockNumber(blockNrOrHash rpc.BlockNumberOrHash, tx kv.Tx, filters *Filters) (uint64, common.Hash, bool, error) {
return _GetBlockNumber(blockNrOrHash.RequireCanonical, blockNrOrHash, tx, filters)
}
func GetCanonicalBlockNumber(blockNrOrHash rpc.BlockNumberOrHash, tx kv.Tx, filters *Filters) (uint64, common.Hash, bool, error) {
return _GetBlockNumber(true, blockNrOrHash, tx, filters)
}
func _GetBlockNumber(requireCanonical bool, blockNrOrHash rpc.BlockNumberOrHash, tx kv.Tx, filters *Filters) (blockNumber uint64, hash common.Hash, latest bool, err error) {
// Due to changed semantics of `lastest` block in RPC request, it is now distinct
// from the block block number corresponding to the plain state
var plainStateBlockNumber uint64
if plainStateBlockNumber, err = stages.GetStageProgress(tx, stages.Execution); err != nil {
return 0, common.Hash{}, false, fmt.Errorf("getting plain state block number: %w", err)
}
var ok bool
hash, ok = blockNrOrHash.Hash()
if !ok {
number := *blockNrOrHash.BlockNumber
switch number {
case rpc.LatestBlockNumber:
if blockNumber, err = GetLatestBlockNumber(tx); err != nil {
return 0, common.Hash{}, false, err
}
case rpc.EarliestBlockNumber:
blockNumber = 0
case rpc.FinalizedBlockNumber:
blockNumber, err = GetFinalizedBlockNumber(tx)
if err != nil {
return 0, common.Hash{}, false, err
}
case rpc.SafeBlockNumber:
blockNumber, err = GetSafeBlockNumber(tx)
if err != nil {
return 0, common.Hash{}, false, err
}
case rpc.PendingBlockNumber:
pendingBlock := filters.LastPendingBlock()
if pendingBlock == nil {
log.Warn("no pending block found returning latest executed block")
blockNumber = plainStateBlockNumber
} else {
return pendingBlock.NumberU64(), pendingBlock.Hash(), false, nil
}
case rpc.LatestExecutedBlockNumber:
blockNumber = plainStateBlockNumber
default:
blockNumber = uint64(number.Int64())
}
hash, err = rawdb.ReadCanonicalHash(tx, blockNumber)
if err != nil {
return 0, common.Hash{}, false, err
}
} else {
number := rawdb.ReadHeaderNumber(tx, hash)
if number == nil {
return 0, common.Hash{}, false, fmt.Errorf("block %x not found", hash)
}
blockNumber = *number
ch, err := rawdb.ReadCanonicalHash(tx, blockNumber)
if err != nil {
return 0, common.Hash{}, false, err
}
if requireCanonical && ch != hash {
return 0, common.Hash{}, false, nonCanonocalHashError{hash}
}
}
return blockNumber, hash, blockNumber == plainStateBlockNumber, nil
}
func GetAccount(tx kv.Tx, blockNumber uint64, address common.Address) (*accounts.Account, error) {
reader := adapter.NewStateReader(tx, blockNumber)
return reader.ReadAccountData(address)
}
func CreateStateReader(ctx context.Context, tx kv.Tx, blockNrOrHash rpc.BlockNumberOrHash, filters *Filters, stateCache kvcache.Cache, historyV3 bool, agg *state2.Aggregator22) (state.StateReader, error) {
blockNumber, _, latest, err := _GetBlockNumber(true, blockNrOrHash, tx, filters)
if err != nil {
return nil, err
}
var stateReader state.StateReader
if latest {
cacheView, err := stateCache.View(ctx, tx)
if err != nil {
return nil, err
}
stateReader = state.NewCachedReader2(cacheView, tx)
} else {
if historyV3 {
aggCtx := agg.MakeContext()
aggCtx.SetTx(tx)
r := state.NewHistoryReader22(aggCtx)
r.SetTx(tx)
minTxNum, err := rawdb.TxNums.Min(tx, blockNumber+1)
if err != nil {
return nil, err
}
r.SetTxNum(minTxNum)
stateReader = r
} else {
stateReader = state.NewPlainState(tx, blockNumber+1)
}
}
return stateReader, nil
}