/
block.go
187 lines (157 loc) · 4.79 KB
/
block.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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
package ethrpc
import (
"encoding/json"
"errors"
"fmt"
"math/big"
"github.com/0xsequence/ethkit/go-ethereum"
"github.com/0xsequence/ethkit/go-ethereum/common"
"github.com/0xsequence/ethkit/go-ethereum/common/hexutil"
"github.com/0xsequence/ethkit/go-ethereum/core/types"
)
type rpcTransaction struct {
tx *types.Transaction
txExtraInfo
}
type txExtraInfo struct {
BlockNumber *string `json:"blockNumber,omitempty"`
BlockHash *common.Hash `json:"blockHash,omitempty"`
From *common.Address `json:"from,omitempty"`
TxType string `json:"type,omitempty"`
}
type rpcBlock struct {
Hash common.Hash `json:"hash"`
Transactions []rpcTransaction `json:"transactions"`
UncleHashes []common.Hash `json:"uncles"`
Withdrawals types.Withdrawals `json:"withdrawals"`
}
func (tx *rpcTransaction) UnmarshalJSON(msg []byte) error {
if err := json.Unmarshal(msg, &tx.tx); err != nil {
// for unsupported txn types, we don't completely fail,
// ie. some chains like arbitrum nova will return a non-standard type
if err != types.ErrTxTypeNotSupported {
return err
}
}
return json.Unmarshal(msg, &tx.txExtraInfo)
}
func IntoJSONRawMessage(raw json.RawMessage, ret *json.RawMessage) error {
*ret = raw
return nil
}
func IntoBlock(raw json.RawMessage, ret **types.Block) error {
if len(raw) == 0 {
return ethereum.NotFound
}
// Decode header and transactions
var (
head *types.Header
body rpcBlock
)
if err := json.Unmarshal(raw, &head); err != nil {
return err
}
if head == nil {
return ethereum.NotFound
}
if err := json.Unmarshal(raw, &body); err != nil {
return err
}
// Fill the sender cache of transactions in the block.
txs := make([]*types.Transaction, 0, len(body.Transactions))
for _, tx := range body.Transactions {
if tx.From != nil {
setSenderFromServer(tx.tx, *tx.From, body.Hash)
}
if tx.txExtraInfo.TxType != "" {
txType, err := hexutil.DecodeUint64(tx.txExtraInfo.TxType)
if err != nil {
return err
}
if txType > types.DynamicFeeTxType {
// skip the txn, its a non-standard type we don't care about
continue
}
}
txs = append(txs, tx.tx)
}
// return types.NewBlockWithHeader(head).WithBody(txs, uncles), nil
block := types.NewBlockWithHeader(head).WithBody(txs, nil).WithWithdrawals(body.Withdrawals)
// TODO: Remove this, we shouldn't need to use the block cache
// in order for it to contain the correct block hash
block.SetHash(body.Hash)
*ret = block
return nil
}
// unused
/*func intoBlocks(raw json.RawMessage, ret *[]*types.Block) error {
var list []json.RawMessage
err := json.Unmarshal(raw, &list)
if err != nil {
return err
}
blocks := make([]*types.Block, len(list))
for i := range list {
err = intoBlock(list[i], &blocks[i])
if err != nil {
return err
}
}
*ret = blocks
return nil
}*/
func IntoTransaction(raw json.RawMessage, tx **types.Transaction) error {
return IntoTransactionWithPending(raw, tx, nil)
}
func IntoTransactionWithPending(raw json.RawMessage, tx **types.Transaction, pending *bool) error {
var body *rpcTransaction
if err := json.Unmarshal(raw, &body); err != nil {
return err
} else if body == nil {
return ethereum.NotFound
} else if _, r, _ := body.tx.RawSignatureValues(); r == nil {
return fmt.Errorf("server returned transaction without signature")
}
if body.From != nil && body.BlockHash != nil {
setSenderFromServer(body.tx, *body.From, *body.BlockHash)
}
*tx = body.tx
if pending != nil {
*pending = body.BlockNumber == nil
}
return nil
}
// senderFromServer is a types.Signer that remembers the sender address returned by the RPC
// server. It is stored in the transaction's sender address cache to avoid an additional
// request in TransactionSender.
type senderFromServer struct {
addr common.Address
blockhash common.Hash
}
var errNotCached = errors.New("ethrpc: sender not cached")
func setSenderFromServer(tx *types.Transaction, addr common.Address, block common.Hash) {
// Use types.Sender for side-effect to store our signer into the cache.
if tx == nil {
panic("tx is nil")
}
types.Sender(&senderFromServer{addr, block}, tx)
}
func (s *senderFromServer) Equal(other types.Signer) bool {
os, ok := other.(*senderFromServer)
return ok && os.blockhash == s.blockhash
}
func (s *senderFromServer) Sender(tx *types.Transaction) (common.Address, error) {
if s.blockhash == (common.Hash{}) {
return common.Address{}, errNotCached
}
return s.addr, nil
}
func (s *senderFromServer) ChainID() *big.Int {
panic("can't sign with senderFromServer")
}
func (s *senderFromServer) Hash(tx *types.Transaction) common.Hash {
panic("can't sign with senderFromServer")
}
func (s *senderFromServer) SignatureValues(tx *types.Transaction, sig []byte) (R, S, V *big.Int, err error) {
panic("can't sign with senderFromServer")
}