-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
helper.go
160 lines (146 loc) · 5.59 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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package rpchelper
import (
"context"
"errors"
"fmt"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon-lib/config3"
"github.com/ledgerwatch/erigon-lib/kv"
"github.com/ledgerwatch/erigon-lib/kv/kvcache"
"github.com/ledgerwatch/erigon-lib/kv/rawdbv3"
"github.com/ledgerwatch/erigon/core/rawdb"
"github.com/ledgerwatch/erigon/core/state"
"github.com/ledgerwatch/erigon/core/systemcontracts"
"github.com/ledgerwatch/erigon/eth/stagedsync/stages"
borfinality "github.com/ledgerwatch/erigon/polygon/bor/finality"
"github.com/ledgerwatch/erigon/polygon/bor/finality/whitelist"
"github.com/ledgerwatch/erigon/rpc"
)
// unable to decode supplied params, or an invalid number of parameters
type nonCanonocalHashError struct{ hash libcommon.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, libcommon.Hash, bool, error) {
return _GetBlockNumber(blockNrOrHash.RequireCanonical, blockNrOrHash, tx, filters)
}
func GetCanonicalBlockNumber(blockNrOrHash rpc.BlockNumberOrHash, tx kv.Tx, filters *Filters) (uint64, libcommon.Hash, bool, error) {
return _GetBlockNumber(true, blockNrOrHash, tx, filters)
}
func _GetBlockNumber(requireCanonical bool, blockNrOrHash rpc.BlockNumberOrHash, tx kv.Tx, filters *Filters) (blockNumber uint64, hash libcommon.Hash, latest bool, err error) {
// Due to changed semantics of `lastest` block in RPC request, it is now distinct
// from the block number corresponding to the plain state
var plainStateBlockNumber uint64
if plainStateBlockNumber, err = stages.GetStageProgress(tx, stages.Execution); err != nil {
return 0, libcommon.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, libcommon.Hash{}, false, err
}
case rpc.EarliestBlockNumber:
blockNumber = 0
case rpc.FinalizedBlockNumber:
if whitelist.GetWhitelistingService() != nil {
num := borfinality.GetFinalizedBlockNumber(tx)
if num == 0 {
// nolint
return 0, libcommon.Hash{}, false, errors.New("No finalized block")
}
blockNum := borfinality.CurrentFinalizedBlock(tx, num).NumberU64()
blockHash := rawdb.ReadHeaderByNumber(tx, blockNum).Hash()
return blockNum, blockHash, false, nil
}
blockNumber, err = GetFinalizedBlockNumber(tx)
if err != nil {
return 0, libcommon.Hash{}, false, err
}
case rpc.SafeBlockNumber:
blockNumber, err = GetSafeBlockNumber(tx)
if err != nil {
return 0, libcommon.Hash{}, false, err
}
case rpc.PendingBlockNumber:
pendingBlock := filters.LastPendingBlock()
if pendingBlock == nil {
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, libcommon.Hash{}, false, err
}
} else {
number := rawdb.ReadHeaderNumber(tx, hash)
if number == nil {
return 0, libcommon.Hash{}, false, fmt.Errorf("block %x not found", hash)
}
blockNumber = *number
ch, err := rawdb.ReadCanonicalHash(tx, blockNumber)
if err != nil {
return 0, libcommon.Hash{}, false, err
}
if requireCanonical && ch != hash {
return 0, libcommon.Hash{}, false, nonCanonocalHashError{hash}
}
}
return blockNumber, hash, blockNumber == plainStateBlockNumber, nil
}
func CreateStateReader(ctx context.Context, tx kv.Tx, blockNrOrHash rpc.BlockNumberOrHash, txnIndex int, filters *Filters, stateCache kvcache.Cache, historyV3 bool, chainName string) (state.StateReader, error) {
blockNumber, _, latest, err := _GetBlockNumber(true, blockNrOrHash, tx, filters)
if err != nil {
return nil, err
}
return CreateStateReaderFromBlockNumber(ctx, tx, blockNumber, latest, txnIndex, stateCache, historyV3, chainName)
}
func CreateStateReaderFromBlockNumber(ctx context.Context, tx kv.Tx, blockNumber uint64, latest bool, txnIndex int, stateCache kvcache.Cache, historyV3 bool, chainName string) (state.StateReader, error) {
if latest {
cacheView, err := stateCache.View(ctx, tx)
if err != nil {
return nil, err
}
return state.NewCachedReader2(cacheView, tx), nil
}
return CreateHistoryStateReader(tx, blockNumber+1, txnIndex, historyV3, chainName)
}
func CreateHistoryStateReader(tx kv.Tx, blockNumber uint64, txnIndex int, historyV3 bool, chainName string) (state.StateReader, error) {
if !historyV3 {
r := state.NewPlainState(tx, blockNumber, systemcontracts.SystemContractCodeLookup[chainName])
//r.SetTrace(true)
return r, nil
}
r := state.NewHistoryReaderV3()
r.SetTx(tx)
//r.SetTrace(true)
minTxNum, err := rawdbv3.TxNums.Min(tx, blockNumber)
if err != nil {
return nil, err
}
r.SetTxNum(uint64(int(minTxNum) + txnIndex + 1))
return r, nil
}
func NewLatestStateReader(tx kv.Getter) state.StateReader {
if config3.EnableHistoryV4InTest {
panic("implement me")
//b.pendingReader = state.NewReaderV4(b.pendingReaderTx.(kv.TemporalTx))
}
return state.NewPlainStateReader(tx)
}
func NewLatestStateWriter(tx kv.RwTx, blockNum uint64) state.StateWriter {
if config3.EnableHistoryV4InTest {
panic("implement me")
}
return state.NewPlainStateWriter(tx, tx, blockNum)
}