@@ -45,11 +45,32 @@ type txJSON struct {
45
45
V * hexutil.Big `json:"v"`
46
46
R * hexutil.Big `json:"r"`
47
47
S * hexutil.Big `json:"s"`
48
+ YParity * hexutil.Uint64 `json:"yParity,omitempty"`
48
49
49
50
// Only used for encoding:
50
51
Hash common.Hash `json:"hash"`
51
52
}
52
53
54
+ // yParityValue returns the YParity value from JSON. For backwards-compatibility reasons,
55
+ // this can be given in the 'v' field or the 'yParity' field. If both exist, they must match.
56
+ func (tx * txJSON ) yParityValue () (* big.Int , error ) {
57
+ if tx .YParity != nil {
58
+ val := uint64 (* tx .YParity )
59
+ if val != 0 && val != 1 {
60
+ return nil , errors .New ("'yParity' field must be 0 or 1" )
61
+ }
62
+ bigval := new (big.Int ).SetUint64 (val )
63
+ if tx .V != nil && tx .V .ToInt ().Cmp (bigval ) != 0 {
64
+ return nil , errors .New ("'v' and 'yParity' fields do not match" )
65
+ }
66
+ return bigval , nil
67
+ }
68
+ if tx .V != nil {
69
+ return tx .V .ToInt (), nil
70
+ }
71
+ return nil , errors .New ("missing 'yParity' or 'v' field in transaction" )
72
+ }
73
+
53
74
// MarshalJSON marshals as JSON with a hash.
54
75
func (tx * Transaction ) MarshalJSON () ([]byte , error ) {
55
76
var enc txJSON
@@ -85,6 +106,8 @@ func (tx *Transaction) MarshalJSON() ([]byte, error) {
85
106
enc .V = (* hexutil .Big )(itx .V )
86
107
enc .R = (* hexutil .Big )(itx .R )
87
108
enc .S = (* hexutil .Big )(itx .S )
109
+ yparity := itx .V .Uint64 ()
110
+ enc .YParity = (* hexutil .Uint64 )(& yparity )
88
111
89
112
case * DynamicFeeTx :
90
113
enc .ChainID = (* hexutil .Big )(itx .ChainID )
@@ -99,6 +122,8 @@ func (tx *Transaction) MarshalJSON() ([]byte, error) {
99
122
enc .V = (* hexutil .Big )(itx .V )
100
123
enc .R = (* hexutil .Big )(itx .R )
101
124
enc .S = (* hexutil .Big )(itx .S )
125
+ yparity := itx .V .Uint64 ()
126
+ enc .YParity = (* hexutil .Uint64 )(& yparity )
102
127
103
128
case * BlobTx :
104
129
enc .ChainID = (* hexutil .Big )(itx .ChainID .ToBig ())
@@ -115,14 +140,17 @@ func (tx *Transaction) MarshalJSON() ([]byte, error) {
115
140
enc .V = (* hexutil .Big )(itx .V .ToBig ())
116
141
enc .R = (* hexutil .Big )(itx .R .ToBig ())
117
142
enc .S = (* hexutil .Big )(itx .S .ToBig ())
143
+ yparity := itx .V .Uint64 ()
144
+ enc .YParity = (* hexutil .Uint64 )(& yparity )
118
145
}
119
146
return json .Marshal (& enc )
120
147
}
121
148
122
149
// UnmarshalJSON unmarshals from JSON.
123
150
func (tx * Transaction ) UnmarshalJSON (input []byte ) error {
124
151
var dec txJSON
125
- if err := json .Unmarshal (input , & dec ); err != nil {
152
+ err := json .Unmarshal (input , & dec )
153
+ if err != nil {
126
154
return err
127
155
}
128
156
@@ -155,20 +183,23 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
155
183
return errors .New ("missing required field 'input' in transaction" )
156
184
}
157
185
itx .Data = * dec .Input
158
- if dec .V == nil {
159
- return errors .New ("missing required field 'v' in transaction" )
160
- }
161
- itx .V = (* big .Int )(dec .V )
186
+
187
+ // signature R
162
188
if dec .R == nil {
163
189
return errors .New ("missing required field 'r' in transaction" )
164
190
}
165
191
itx .R = (* big .Int )(dec .R )
192
+ // signature S
166
193
if dec .S == nil {
167
194
return errors .New ("missing required field 's' in transaction" )
168
195
}
169
196
itx .S = (* big .Int )(dec .S )
170
- withSignature := itx .V .Sign () != 0 || itx .R .Sign () != 0 || itx .S .Sign () != 0
171
- if withSignature {
197
+ // signature V
198
+ if dec .V == nil {
199
+ return errors .New ("missing required field 'v' in transaction" )
200
+ }
201
+ itx .V = (* big .Int )(dec .V )
202
+ if itx .V .Sign () != 0 || itx .R .Sign () != 0 || itx .S .Sign () != 0 {
172
203
if err := sanityCheckSignature (itx .V , itx .R , itx .S , true ); err != nil {
173
204
return err
174
205
}
@@ -204,23 +235,26 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
204
235
return errors .New ("missing required field 'input' in transaction" )
205
236
}
206
237
itx .Data = * dec .Input
207
- if dec .V == nil {
208
- return errors .New ("missing required field 'v' in transaction" )
209
- }
210
238
if dec .AccessList != nil {
211
239
itx .AccessList = * dec .AccessList
212
240
}
213
- itx .V = (* big .Int )(dec .V )
241
+
242
+ // signature R
214
243
if dec .R == nil {
215
244
return errors .New ("missing required field 'r' in transaction" )
216
245
}
217
246
itx .R = (* big .Int )(dec .R )
247
+ // signature S
218
248
if dec .S == nil {
219
249
return errors .New ("missing required field 's' in transaction" )
220
250
}
221
251
itx .S = (* big .Int )(dec .S )
222
- withSignature := itx .V .Sign () != 0 || itx .R .Sign () != 0 || itx .S .Sign () != 0
223
- if withSignature {
252
+ // signature V
253
+ itx .V , err = dec .yParityValue ()
254
+ if err != nil {
255
+ return err
256
+ }
257
+ if itx .V .Sign () != 0 || itx .R .Sign () != 0 || itx .S .Sign () != 0 {
224
258
if err := sanityCheckSignature (itx .V , itx .R , itx .S , false ); err != nil {
225
259
return err
226
260
}
@@ -266,17 +300,23 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
266
300
if dec .AccessList != nil {
267
301
itx .AccessList = * dec .AccessList
268
302
}
269
- itx .V = (* big .Int )(dec .V )
303
+
304
+ // signature R
270
305
if dec .R == nil {
271
306
return errors .New ("missing required field 'r' in transaction" )
272
307
}
273
308
itx .R = (* big .Int )(dec .R )
309
+ // signature S
274
310
if dec .S == nil {
275
311
return errors .New ("missing required field 's' in transaction" )
276
312
}
277
313
itx .S = (* big .Int )(dec .S )
278
- withSignature := itx .V .Sign () != 0 || itx .R .Sign () != 0 || itx .S .Sign () != 0
279
- if withSignature {
314
+ // signature V
315
+ itx .V , err = dec .yParityValue ()
316
+ if err != nil {
317
+ return err
318
+ }
319
+ if itx .V .Sign () != 0 || itx .R .Sign () != 0 || itx .S .Sign () != 0 {
280
320
if err := sanityCheckSignature (itx .V , itx .R , itx .S , false ); err != nil {
281
321
return err
282
322
}
@@ -331,18 +371,35 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
331
371
return errors .New ("missing required field 'blobVersionedHashes' in transaction" )
332
372
}
333
373
itx .BlobHashes = dec .BlobVersionedHashes
334
- itx .V = uint256 .MustFromBig ((* big .Int )(dec .V ))
374
+
375
+ // signature R
376
+ var ok bool
335
377
if dec .R == nil {
336
378
return errors .New ("missing required field 'r' in transaction" )
337
379
}
338
- itx .R = uint256 .MustFromBig ((* big .Int )(dec .R ))
380
+ itx .R , ok = uint256 .FromBig ((* big .Int )(dec .R ))
381
+ if ! ok {
382
+ return errors .New ("'r' value overflows uint256" )
383
+ }
384
+ // signature S
339
385
if dec .S == nil {
340
386
return errors .New ("missing required field 's' in transaction" )
341
387
}
342
- itx .S = uint256 .MustFromBig ((* big .Int )(dec .S ))
343
- withSignature := itx .V .Sign () != 0 || itx .R .Sign () != 0 || itx .S .Sign () != 0
344
- if withSignature {
345
- if err := sanityCheckSignature (itx .V .ToBig (), itx .R .ToBig (), itx .S .ToBig (), false ); err != nil {
388
+ itx .S , ok = uint256 .FromBig ((* big .Int )(dec .S ))
389
+ if ! ok {
390
+ return errors .New ("'s' value overflows uint256" )
391
+ }
392
+ // signature V
393
+ vbig , err := dec .yParityValue ()
394
+ if err != nil {
395
+ return err
396
+ }
397
+ itx .V , ok = uint256 .FromBig (vbig )
398
+ if ! ok {
399
+ return errors .New ("'v' value overflows uint256" )
400
+ }
401
+ if itx .V .Sign () != 0 || itx .R .Sign () != 0 || itx .S .Sign () != 0 {
402
+ if err := sanityCheckSignature (vbig , itx .R .ToBig (), itx .S .ToBig (), false ); err != nil {
346
403
return err
347
404
}
348
405
}
0 commit comments