Skip to content

Commit 1982437

Browse files
authored
core/types: un-ssz blob txs, add json marshalling and tweaks (#27256)
1 parent dffd804 commit 1982437

File tree

5 files changed

+138
-62
lines changed

5 files changed

+138
-62
lines changed

core/types/gen_access_tuple.go

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/types/transaction.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ func (tx *Transaction) decodeTyped(b []byte) (TxData, error) {
198198
return &inner, err
199199
case BlobTxType:
200200
var inner BlobTx
201-
err := rlp.DecodeBytes(b[1:], &inner) // TODO(karalabe): This needs to be ssz
201+
err := rlp.DecodeBytes(b[1:], &inner)
202202
return &inner, err
203203
default:
204204
return nil, ErrTxTypeNotSupported
@@ -417,11 +417,7 @@ func (tx *Transaction) Size() uint64 {
417417
return size.(uint64)
418418
}
419419
c := writeCounter(0)
420-
if tx.Type() == BlobTxType {
421-
rlp.Encode(&c, &tx.inner) // TODO(karalabe): Replace with SSZ encoding
422-
} else {
423-
rlp.Encode(&c, &tx.inner)
424-
}
420+
rlp.Encode(&c, &tx.inner)
425421

426422
size := uint64(c)
427423
if tx.Type() != LegacyTxType {

core/types/transaction_marshalling.go

Lines changed: 129 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -23,28 +23,28 @@ import (
2323

2424
"github.com/ethereum/go-ethereum/common"
2525
"github.com/ethereum/go-ethereum/common/hexutil"
26+
"github.com/holiman/uint256"
2627
)
2728

2829
// txJSON is the JSON representation of transactions.
2930
type txJSON struct {
3031
Type hexutil.Uint64 `json:"type"`
3132

32-
// Common transaction fields:
33+
ChainID *hexutil.Big `json:"chainId,omitempty"`
3334
Nonce *hexutil.Uint64 `json:"nonce"`
35+
To *common.Address `json:"to"`
36+
Gas *hexutil.Uint64 `json:"gas"`
3437
GasPrice *hexutil.Big `json:"gasPrice"`
3538
MaxPriorityFeePerGas *hexutil.Big `json:"maxPriorityFeePerGas"`
3639
MaxFeePerGas *hexutil.Big `json:"maxFeePerGas"`
37-
Gas *hexutil.Uint64 `json:"gas"`
40+
MaxFeePerDataGas *hexutil.Big `json:"maxFeePerDataGas,omitempty"`
3841
Value *hexutil.Big `json:"value"`
39-
Data *hexutil.Bytes `json:"input"`
42+
Input *hexutil.Bytes `json:"input"`
43+
AccessList *AccessList `json:"accessList,omitempty"`
44+
BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"`
4045
V *hexutil.Big `json:"v"`
4146
R *hexutil.Big `json:"r"`
4247
S *hexutil.Big `json:"s"`
43-
To *common.Address `json:"to"`
44-
45-
// Access list transaction fields:
46-
ChainID *hexutil.Big `json:"chainId,omitempty"`
47-
AccessList *AccessList `json:"accessList,omitempty"`
4848

4949
// Only used for encoding:
5050
Hash common.Hash `json:"hash"`
@@ -61,39 +61,57 @@ func (tx *Transaction) MarshalJSON() ([]byte, error) {
6161
switch itx := tx.inner.(type) {
6262
case *LegacyTx:
6363
enc.Nonce = (*hexutil.Uint64)(&itx.Nonce)
64+
enc.To = tx.To()
6465
enc.Gas = (*hexutil.Uint64)(&itx.Gas)
6566
enc.GasPrice = (*hexutil.Big)(itx.GasPrice)
6667
enc.Value = (*hexutil.Big)(itx.Value)
67-
enc.Data = (*hexutil.Bytes)(&itx.Data)
68-
enc.To = tx.To()
68+
enc.Input = (*hexutil.Bytes)(&itx.Data)
6969
enc.V = (*hexutil.Big)(itx.V)
7070
enc.R = (*hexutil.Big)(itx.R)
7171
enc.S = (*hexutil.Big)(itx.S)
72+
7273
case *AccessListTx:
7374
enc.ChainID = (*hexutil.Big)(itx.ChainID)
74-
enc.AccessList = &itx.AccessList
7575
enc.Nonce = (*hexutil.Uint64)(&itx.Nonce)
76+
enc.To = tx.To()
7677
enc.Gas = (*hexutil.Uint64)(&itx.Gas)
7778
enc.GasPrice = (*hexutil.Big)(itx.GasPrice)
7879
enc.Value = (*hexutil.Big)(itx.Value)
79-
enc.Data = (*hexutil.Bytes)(&itx.Data)
80-
enc.To = tx.To()
80+
enc.Input = (*hexutil.Bytes)(&itx.Data)
81+
enc.AccessList = &itx.AccessList
8182
enc.V = (*hexutil.Big)(itx.V)
8283
enc.R = (*hexutil.Big)(itx.R)
8384
enc.S = (*hexutil.Big)(itx.S)
85+
8486
case *DynamicFeeTx:
8587
enc.ChainID = (*hexutil.Big)(itx.ChainID)
86-
enc.AccessList = &itx.AccessList
8788
enc.Nonce = (*hexutil.Uint64)(&itx.Nonce)
89+
enc.To = tx.To()
8890
enc.Gas = (*hexutil.Uint64)(&itx.Gas)
8991
enc.MaxFeePerGas = (*hexutil.Big)(itx.GasFeeCap)
9092
enc.MaxPriorityFeePerGas = (*hexutil.Big)(itx.GasTipCap)
9193
enc.Value = (*hexutil.Big)(itx.Value)
92-
enc.Data = (*hexutil.Bytes)(&itx.Data)
93-
enc.To = tx.To()
94+
enc.Input = (*hexutil.Bytes)(&itx.Data)
95+
enc.AccessList = &itx.AccessList
9496
enc.V = (*hexutil.Big)(itx.V)
9597
enc.R = (*hexutil.Big)(itx.R)
9698
enc.S = (*hexutil.Big)(itx.S)
99+
100+
case *BlobTx:
101+
enc.ChainID = (*hexutil.Big)(itx.ChainID.ToBig())
102+
enc.Nonce = (*hexutil.Uint64)(&itx.Nonce)
103+
enc.Gas = (*hexutil.Uint64)(&itx.Gas)
104+
enc.MaxFeePerGas = (*hexutil.Big)(itx.GasFeeCap.ToBig())
105+
enc.MaxPriorityFeePerGas = (*hexutil.Big)(itx.GasTipCap.ToBig())
106+
enc.MaxFeePerDataGas = (*hexutil.Big)(itx.BlobFeeCap.ToBig())
107+
enc.Value = (*hexutil.Big)(itx.Value.ToBig())
108+
enc.Input = (*hexutil.Bytes)(&itx.Data)
109+
enc.AccessList = &itx.AccessList
110+
enc.BlobVersionedHashes = itx.BlobHashes
111+
enc.To = tx.To()
112+
enc.V = (*hexutil.Big)(itx.V.ToBig())
113+
enc.R = (*hexutil.Big)(itx.R.ToBig())
114+
enc.S = (*hexutil.Big)(itx.S.ToBig())
97115
}
98116
return json.Marshal(&enc)
99117
}
@@ -111,29 +129,29 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
111129
case LegacyTxType:
112130
var itx LegacyTx
113131
inner = &itx
114-
if dec.To != nil {
115-
itx.To = dec.To
116-
}
117132
if dec.Nonce == nil {
118133
return errors.New("missing required field 'nonce' in transaction")
119134
}
120135
itx.Nonce = uint64(*dec.Nonce)
121-
if dec.GasPrice == nil {
122-
return errors.New("missing required field 'gasPrice' in transaction")
136+
if dec.To != nil {
137+
itx.To = dec.To
123138
}
124-
itx.GasPrice = (*big.Int)(dec.GasPrice)
125139
if dec.Gas == nil {
126140
return errors.New("missing required field 'gas' in transaction")
127141
}
128142
itx.Gas = uint64(*dec.Gas)
143+
if dec.GasPrice == nil {
144+
return errors.New("missing required field 'gasPrice' in transaction")
145+
}
146+
itx.GasPrice = (*big.Int)(dec.GasPrice)
129147
if dec.Value == nil {
130148
return errors.New("missing required field 'value' in transaction")
131149
}
132150
itx.Value = (*big.Int)(dec.Value)
133-
if dec.Data == nil {
151+
if dec.Input == nil {
134152
return errors.New("missing required field 'input' in transaction")
135153
}
136-
itx.Data = *dec.Data
154+
itx.Data = *dec.Input
137155
if dec.V == nil {
138156
return errors.New("missing required field 'v' in transaction")
139157
}
@@ -156,40 +174,39 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
156174
case AccessListTxType:
157175
var itx AccessListTx
158176
inner = &itx
159-
// Access list is optional for now.
160-
if dec.AccessList != nil {
161-
itx.AccessList = *dec.AccessList
162-
}
163177
if dec.ChainID == nil {
164178
return errors.New("missing required field 'chainId' in transaction")
165179
}
166180
itx.ChainID = (*big.Int)(dec.ChainID)
167-
if dec.To != nil {
168-
itx.To = dec.To
169-
}
170181
if dec.Nonce == nil {
171182
return errors.New("missing required field 'nonce' in transaction")
172183
}
173184
itx.Nonce = uint64(*dec.Nonce)
174-
if dec.GasPrice == nil {
175-
return errors.New("missing required field 'gasPrice' in transaction")
185+
if dec.To != nil {
186+
itx.To = dec.To
176187
}
177-
itx.GasPrice = (*big.Int)(dec.GasPrice)
178188
if dec.Gas == nil {
179189
return errors.New("missing required field 'gas' in transaction")
180190
}
181191
itx.Gas = uint64(*dec.Gas)
192+
if dec.GasPrice == nil {
193+
return errors.New("missing required field 'gasPrice' in transaction")
194+
}
195+
itx.GasPrice = (*big.Int)(dec.GasPrice)
182196
if dec.Value == nil {
183197
return errors.New("missing required field 'value' in transaction")
184198
}
185199
itx.Value = (*big.Int)(dec.Value)
186-
if dec.Data == nil {
200+
if dec.Input == nil {
187201
return errors.New("missing required field 'input' in transaction")
188202
}
189-
itx.Data = *dec.Data
203+
itx.Data = *dec.Input
190204
if dec.V == nil {
191205
return errors.New("missing required field 'v' in transaction")
192206
}
207+
if dec.AccessList != nil {
208+
itx.AccessList = *dec.AccessList
209+
}
193210
itx.V = (*big.Int)(dec.V)
194211
if dec.R == nil {
195212
return errors.New("missing required field 'r' in transaction")
@@ -209,21 +226,21 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
209226
case DynamicFeeTxType:
210227
var itx DynamicFeeTx
211228
inner = &itx
212-
// Access list is optional for now.
213-
if dec.AccessList != nil {
214-
itx.AccessList = *dec.AccessList
215-
}
216229
if dec.ChainID == nil {
217230
return errors.New("missing required field 'chainId' in transaction")
218231
}
219232
itx.ChainID = (*big.Int)(dec.ChainID)
220-
if dec.To != nil {
221-
itx.To = dec.To
222-
}
223233
if dec.Nonce == nil {
224234
return errors.New("missing required field 'nonce' in transaction")
225235
}
226236
itx.Nonce = uint64(*dec.Nonce)
237+
if dec.To != nil {
238+
itx.To = dec.To
239+
}
240+
if dec.Gas == nil {
241+
return errors.New("missing required field 'gas' for txdata")
242+
}
243+
itx.Gas = uint64(*dec.Gas)
227244
if dec.MaxPriorityFeePerGas == nil {
228245
return errors.New("missing required field 'maxPriorityFeePerGas' for txdata")
229246
}
@@ -232,21 +249,20 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
232249
return errors.New("missing required field 'maxFeePerGas' for txdata")
233250
}
234251
itx.GasFeeCap = (*big.Int)(dec.MaxFeePerGas)
235-
if dec.Gas == nil {
236-
return errors.New("missing required field 'gas' for txdata")
237-
}
238-
itx.Gas = uint64(*dec.Gas)
239252
if dec.Value == nil {
240253
return errors.New("missing required field 'value' in transaction")
241254
}
242255
itx.Value = (*big.Int)(dec.Value)
243-
if dec.Data == nil {
256+
if dec.Input == nil {
244257
return errors.New("missing required field 'input' in transaction")
245258
}
246-
itx.Data = *dec.Data
259+
itx.Data = *dec.Input
247260
if dec.V == nil {
248261
return errors.New("missing required field 'v' in transaction")
249262
}
263+
if dec.AccessList != nil {
264+
itx.AccessList = *dec.AccessList
265+
}
250266
itx.V = (*big.Int)(dec.V)
251267
if dec.R == nil {
252268
return errors.New("missing required field 'r' in transaction")
@@ -263,6 +279,70 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
263279
}
264280
}
265281

282+
case BlobTxType:
283+
var itx BlobTx
284+
inner = &itx
285+
if dec.ChainID == nil {
286+
return errors.New("missing required field 'chainId' in transaction")
287+
}
288+
itx.ChainID = uint256.MustFromBig((*big.Int)(dec.ChainID))
289+
if dec.Nonce == nil {
290+
return errors.New("missing required field 'nonce' in transaction")
291+
}
292+
itx.Nonce = uint64(*dec.Nonce)
293+
if dec.To != nil {
294+
itx.To = dec.To
295+
}
296+
if dec.Gas == nil {
297+
return errors.New("missing required field 'gas' for txdata")
298+
}
299+
itx.Gas = uint64(*dec.Gas)
300+
if dec.MaxPriorityFeePerGas == nil {
301+
return errors.New("missing required field 'maxPriorityFeePerGas' for txdata")
302+
}
303+
itx.GasTipCap = uint256.MustFromBig((*big.Int)(dec.MaxPriorityFeePerGas))
304+
if dec.MaxFeePerGas == nil {
305+
return errors.New("missing required field 'maxFeePerGas' for txdata")
306+
}
307+
itx.GasFeeCap = uint256.MustFromBig((*big.Int)(dec.MaxFeePerGas))
308+
if dec.MaxFeePerDataGas == nil {
309+
return errors.New("missing required field 'maxFeePerDataGas' for txdata")
310+
}
311+
itx.BlobFeeCap = uint256.MustFromBig((*big.Int)(dec.MaxFeePerDataGas))
312+
if dec.Value == nil {
313+
return errors.New("missing required field 'value' in transaction")
314+
}
315+
itx.Value = uint256.MustFromBig((*big.Int)(dec.Value))
316+
if dec.Input == nil {
317+
return errors.New("missing required field 'input' in transaction")
318+
}
319+
itx.Data = *dec.Input
320+
if dec.V == nil {
321+
return errors.New("missing required field 'v' in transaction")
322+
}
323+
if dec.AccessList != nil {
324+
itx.AccessList = *dec.AccessList
325+
}
326+
if dec.BlobVersionedHashes == nil {
327+
return errors.New("missing required field 'blobVersionedHashes' in transaction")
328+
}
329+
itx.BlobHashes = dec.BlobVersionedHashes
330+
itx.V = uint256.MustFromBig((*big.Int)(dec.V))
331+
if dec.R == nil {
332+
return errors.New("missing required field 'r' in transaction")
333+
}
334+
itx.R = uint256.MustFromBig((*big.Int)(dec.R))
335+
if dec.S == nil {
336+
return errors.New("missing required field 's' in transaction")
337+
}
338+
itx.S = uint256.MustFromBig((*big.Int)(dec.S))
339+
withSignature := itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0
340+
if withSignature {
341+
if err := sanityCheckSignature(itx.V.ToBig(), itx.R.ToBig(), itx.S.ToBig(), false); err != nil {
342+
return err
343+
}
344+
}
345+
266346
default:
267347
return ErrTxTypeNotSupported
268348
}

core/types/tx_access_list.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ type AccessList []AccessTuple
2929

3030
// AccessTuple is the element type of an access list.
3131
type AccessTuple struct {
32-
Address common.Address `json:"address" gencodec:"required"`
33-
StorageKeys []common.Hash `json:"storageKeys" gencodec:"required"`
32+
Address common.Address `json:"address" gencodec:"required"`
33+
StorageKeys []common.Hash `json:"storageKeys" gencodec:"required"`
3434
}
3535

3636
// StorageKeys returns the total number of storage keys in the access list.

core/types/tx_blob.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ type BlobTx struct {
3131
GasTipCap *uint256.Int // a.k.a. maxPriorityFeePerGas
3232
GasFeeCap *uint256.Int // a.k.a. maxFeePerGas
3333
Gas uint64
34-
To *common.Address // `rlp:"nil"` // nil means contract creation
34+
To *common.Address `rlp:"nil"` // nil means contract creation
3535
Value *uint256.Int
3636
Data []byte
3737
AccessList AccessList

0 commit comments

Comments
 (0)