@@ -29,79 +29,104 @@ import (
2929type txJSON struct {
3030 Type hexutil.Uint64 `json:"type"`
3131
32- // Common transaction fields:
32+ ChainID * hexutil. Big `json:"chainId,omitempty"`
3333 Nonce * hexutil.Uint64 `json:"nonce"`
34+ To * common.Address `json:"to"`
35+ Gas * hexutil.Uint64 `json:"gas"`
3436 GasPrice * hexutil.Big `json:"gasPrice"`
3537 MaxPriorityFeePerGas * hexutil.Big `json:"maxPriorityFeePerGas"`
3638 MaxFeePerGas * hexutil.Big `json:"maxFeePerGas"`
37- Gas * hexutil.Uint64 `json:"gas"`
3839 Value * hexutil.Big `json:"value"`
3940 Data * hexutil.Bytes `json:"input"`
41+ AccessList * AccessList `json:"accessList,omitempty"`
4042 V * hexutil.Big `json:"v"`
4143 R * hexutil.Big `json:"r"`
4244 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"`
45+ YParity * hexutil.Uint64 `json:"yParity,omitempty"`
4846
4947 // Only used for encoding:
5048 Hash common.Hash `json:"hash"`
5149}
5250
51+ // yParityValue returns the YParity value from JSON. For backwards-compatibility reasons,
52+ // this can be given in the 'v' field or the 'yParity' field. If both exist, they must match.
53+ func (tx * txJSON ) yParityValue () (* big.Int , error ) {
54+ if tx .YParity != nil {
55+ val := uint64 (* tx .YParity )
56+ if val != 0 && val != 1 {
57+ return nil , errInvalidYParity
58+ }
59+ bigval := new (big.Int ).SetUint64 (val )
60+ if tx .V != nil && tx .V .ToInt ().Cmp (bigval ) != 0 {
61+ return nil , errVYParityMismatch
62+ }
63+ return bigval , nil
64+ }
65+ if tx .V != nil {
66+ return tx .V .ToInt (), nil
67+ }
68+ return nil , errVYParityMissing
69+ }
70+
5371// MarshalJSON marshals as JSON with a hash.
54- func (t * Transaction ) MarshalJSON () ([]byte , error ) {
72+ func (tx * Transaction ) MarshalJSON () ([]byte , error ) {
5573 var enc txJSON
5674 // These are set for all tx types.
57- enc .Hash = t .Hash ()
58- enc .Type = hexutil .Uint64 (t .Type ())
75+ enc .Hash = tx .Hash ()
76+ enc .Type = hexutil .Uint64 (tx .Type ())
5977
60- // Other fields are set conditionally depending on tx type.
61- switch tx := t .inner .(type ) {
78+ // Other fields are set conditionally depending on itx type.
79+ switch itx := tx .inner .(type ) {
6280 case * LegacyTx :
63- enc .Nonce = (* hexutil .Uint64 )(& tx .Nonce )
64- enc .Gas = (* hexutil .Uint64 )(& tx .Gas )
65- enc .GasPrice = (* hexutil .Big )(tx .GasPrice )
66- enc .Value = (* hexutil .Big )(tx .Value )
67- enc .Data = (* hexutil .Bytes )(& tx .Data )
68- enc .To = t .To ()
69- enc .V = (* hexutil .Big )(tx .V )
70- enc .R = (* hexutil .Big )(tx .R )
71- enc .S = (* hexutil .Big )(tx .S )
81+ enc .Nonce = (* hexutil .Uint64 )(& itx .Nonce )
82+ enc .To = tx .To ()
83+ enc .Gas = (* hexutil .Uint64 )(& itx .Gas )
84+ enc .GasPrice = (* hexutil .Big )(itx .GasPrice )
85+ enc .Value = (* hexutil .Big )(itx .Value )
86+ enc .Data = (* hexutil .Bytes )(& itx .Data )
87+ enc .V = (* hexutil .Big )(itx .V )
88+ enc .R = (* hexutil .Big )(itx .R )
89+ enc .S = (* hexutil .Big )(itx .S )
90+
7291 case * AccessListTx :
73- enc .ChainID = (* hexutil .Big )(tx .ChainID )
74- enc .AccessList = & tx .AccessList
75- enc .Nonce = (* hexutil .Uint64 )(& tx .Nonce )
76- enc .Gas = (* hexutil .Uint64 )(& tx .Gas )
77- enc .GasPrice = (* hexutil .Big )(tx .GasPrice )
78- enc .Value = (* hexutil .Big )(tx .Value )
79- enc .Data = (* hexutil .Bytes )(& tx .Data )
80- enc .To = t .To ()
81- enc .V = (* hexutil .Big )(tx .V )
82- enc .R = (* hexutil .Big )(tx .R )
83- enc .S = (* hexutil .Big )(tx .S )
92+ enc .ChainID = (* hexutil .Big )(itx .ChainID )
93+ enc .Nonce = (* hexutil .Uint64 )(& itx .Nonce )
94+ enc .To = tx .To ()
95+ enc .Gas = (* hexutil .Uint64 )(& itx .Gas )
96+ enc .GasPrice = (* hexutil .Big )(itx .GasPrice )
97+ enc .Value = (* hexutil .Big )(itx .Value )
98+ enc .Data = (* hexutil .Bytes )(& itx .Data )
99+ enc .AccessList = & itx .AccessList
100+ enc .V = (* hexutil .Big )(itx .V )
101+ enc .R = (* hexutil .Big )(itx .R )
102+ enc .S = (* hexutil .Big )(itx .S )
103+ yparity := itx .V .Uint64 ()
104+ enc .YParity = (* hexutil .Uint64 )(& yparity )
105+
84106 case * DynamicFeeTx :
85- enc .ChainID = (* hexutil .Big )(tx .ChainID )
86- enc .AccessList = & tx .AccessList
87- enc .Nonce = (* hexutil .Uint64 )(& tx .Nonce )
88- enc .Gas = (* hexutil .Uint64 )(& tx .Gas )
89- enc .MaxFeePerGas = (* hexutil .Big )(tx .GasFeeCap )
90- enc .MaxPriorityFeePerGas = (* hexutil .Big )(tx .GasTipCap )
91- enc .Value = (* hexutil .Big )(tx .Value )
92- enc .Data = (* hexutil .Bytes )(& tx .Data )
93- enc .To = t .To ()
94- enc .V = (* hexutil .Big )(tx .V )
95- enc .R = (* hexutil .Big )(tx .R )
96- enc .S = (* hexutil .Big )(tx .S )
107+ enc .ChainID = (* hexutil .Big )(itx .ChainID )
108+ enc .Nonce = (* hexutil .Uint64 )(& itx .Nonce )
109+ enc .To = tx .To ()
110+ enc .Gas = (* hexutil .Uint64 )(& itx .Gas )
111+ enc .MaxFeePerGas = (* hexutil .Big )(itx .GasFeeCap )
112+ enc .MaxPriorityFeePerGas = (* hexutil .Big )(itx .GasTipCap )
113+ enc .Value = (* hexutil .Big )(itx .Value )
114+ enc .Data = (* hexutil .Bytes )(& itx .Data )
115+ enc .AccessList = & itx .AccessList
116+ enc .V = (* hexutil .Big )(itx .V )
117+ enc .R = (* hexutil .Big )(itx .R )
118+ enc .S = (* hexutil .Big )(itx .S )
119+ yparity := itx .V .Uint64 ()
120+ enc .YParity = (* hexutil .Uint64 )(& yparity )
97121 }
98122 return json .Marshal (& enc )
99123}
100124
101125// UnmarshalJSON unmarshals from JSON.
102- func (t * Transaction ) UnmarshalJSON (input []byte ) error {
126+ func (tx * Transaction ) UnmarshalJSON (input []byte ) error {
103127 var dec txJSON
104- if err := json .Unmarshal (input , & dec ); err != nil {
128+ err := json .Unmarshal (input , & dec )
129+ if err != nil {
105130 return err
106131 }
107132
@@ -111,21 +136,21 @@ func (t *Transaction) UnmarshalJSON(input []byte) error {
111136 case LegacyTxType :
112137 var itx LegacyTx
113138 inner = & itx
114- if dec .To != nil {
115- itx .To = dec .To
116- }
117139 if dec .Nonce == nil {
118140 return errors .New ("missing required field 'nonce' in transaction" )
119141 }
120142 itx .Nonce = uint64 (* dec .Nonce )
121- if dec .GasPrice = = nil {
122- return errors . New ( "missing required field 'gasPrice' in transaction" )
143+ if dec .To ! = nil {
144+ itx . To = dec . To
123145 }
124- itx .GasPrice = (* big .Int )(dec .GasPrice )
125146 if dec .Gas == nil {
126147 return errors .New ("missing required field 'gas' in transaction" )
127148 }
128149 itx .Gas = uint64 (* dec .Gas )
150+ if dec .GasPrice == nil {
151+ return errors .New ("missing required field 'gasPrice' in transaction" )
152+ }
153+ itx .GasPrice = (* big .Int )(dec .GasPrice )
129154 if dec .Value == nil {
130155 return errors .New ("missing required field 'value' in transaction" )
131156 }
@@ -134,20 +159,23 @@ func (t *Transaction) UnmarshalJSON(input []byte) error {
134159 return errors .New ("missing required field 'input' in transaction" )
135160 }
136161 itx .Data = * dec .Data
137- if dec .V == nil {
138- return errors .New ("missing required field 'v' in transaction" )
139- }
140- itx .V = (* big .Int )(dec .V )
162+
163+ // signature R
141164 if dec .R == nil {
142165 return errors .New ("missing required field 'r' in transaction" )
143166 }
144167 itx .R = (* big .Int )(dec .R )
168+ // signature S
145169 if dec .S == nil {
146170 return errors .New ("missing required field 's' in transaction" )
147171 }
148172 itx .S = (* big .Int )(dec .S )
149- withSignature := itx .V .Sign () != 0 || itx .R .Sign () != 0 || itx .S .Sign () != 0
150- if withSignature {
173+ // signature V
174+ if dec .V == nil {
175+ return errors .New ("missing required field 'v' in transaction" )
176+ }
177+ itx .V = (* big .Int )(dec .V )
178+ if itx .V .Sign () != 0 || itx .R .Sign () != 0 || itx .S .Sign () != 0 {
151179 if err := sanityCheckSignature (itx .V , itx .R , itx .S , true ); err != nil {
152180 return err
153181 }
@@ -156,29 +184,25 @@ func (t *Transaction) UnmarshalJSON(input []byte) error {
156184 case AccessListTxType :
157185 var itx AccessListTx
158186 inner = & itx
159- // Access list is optional for now.
160- if dec .AccessList != nil {
161- itx .AccessList = * dec .AccessList
162- }
163187 if dec .ChainID == nil {
164188 return errors .New ("missing required field 'chainId' in transaction" )
165189 }
166190 itx .ChainID = (* big .Int )(dec .ChainID )
167- if dec .To != nil {
168- itx .To = dec .To
169- }
170191 if dec .Nonce == nil {
171192 return errors .New ("missing required field 'nonce' in transaction" )
172193 }
173194 itx .Nonce = uint64 (* dec .Nonce )
174- if dec .GasPrice = = nil {
175- return errors . New ( "missing required field 'gasPrice' in transaction" )
195+ if dec .To ! = nil {
196+ itx . To = dec . To
176197 }
177- itx .GasPrice = (* big .Int )(dec .GasPrice )
178198 if dec .Gas == nil {
179199 return errors .New ("missing required field 'gas' in transaction" )
180200 }
181201 itx .Gas = uint64 (* dec .Gas )
202+ if dec .GasPrice == nil {
203+ return errors .New ("missing required field 'gasPrice' in transaction" )
204+ }
205+ itx .GasPrice = (* big .Int )(dec .GasPrice )
182206 if dec .Value == nil {
183207 return errors .New ("missing required field 'value' in transaction" )
184208 }
@@ -187,20 +211,26 @@ func (t *Transaction) UnmarshalJSON(input []byte) error {
187211 return errors .New ("missing required field 'input' in transaction" )
188212 }
189213 itx .Data = * dec .Data
190- if dec .V = = nil {
191- return errors . New ( "missing required field 'v' in transaction" )
214+ if dec .AccessList ! = nil {
215+ itx . AccessList = * dec . AccessList
192216 }
193- itx .V = (* big .Int )(dec .V )
217+
218+ // signature R
194219 if dec .R == nil {
195220 return errors .New ("missing required field 'r' in transaction" )
196221 }
197222 itx .R = (* big .Int )(dec .R )
223+ // signature S
198224 if dec .S == nil {
199225 return errors .New ("missing required field 's' in transaction" )
200226 }
201227 itx .S = (* big .Int )(dec .S )
202- withSignature := itx .V .Sign () != 0 || itx .R .Sign () != 0 || itx .S .Sign () != 0
203- if withSignature {
228+ // signature V
229+ itx .V , err = dec .yParityValue ()
230+ if err != nil {
231+ return err
232+ }
233+ if itx .V .Sign () != 0 || itx .R .Sign () != 0 || itx .S .Sign () != 0 {
204234 if err := sanityCheckSignature (itx .V , itx .R , itx .S , false ); err != nil {
205235 return err
206236 }
@@ -209,21 +239,21 @@ func (t *Transaction) UnmarshalJSON(input []byte) error {
209239 case DynamicFeeTxType :
210240 var itx DynamicFeeTx
211241 inner = & itx
212- // Access list is optional for now.
213- if dec .AccessList != nil {
214- itx .AccessList = * dec .AccessList
215- }
216242 if dec .ChainID == nil {
217243 return errors .New ("missing required field 'chainId' in transaction" )
218244 }
219245 itx .ChainID = (* big .Int )(dec .ChainID )
220- if dec .To != nil {
221- itx .To = dec .To
222- }
223246 if dec .Nonce == nil {
224247 return errors .New ("missing required field 'nonce' in transaction" )
225248 }
226249 itx .Nonce = uint64 (* dec .Nonce )
250+ if dec .To != nil {
251+ itx .To = dec .To
252+ }
253+ if dec .Gas == nil {
254+ return errors .New ("missing required field 'gas' for txdata" )
255+ }
256+ itx .Gas = uint64 (* dec .Gas )
227257 if dec .MaxPriorityFeePerGas == nil {
228258 return errors .New ("missing required field 'maxPriorityFeePerGas' for txdata" )
229259 }
@@ -232,10 +262,6 @@ func (t *Transaction) UnmarshalJSON(input []byte) error {
232262 return errors .New ("missing required field 'maxFeePerGas' for txdata" )
233263 }
234264 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 )
239265 if dec .Value == nil {
240266 return errors .New ("missing required field 'value' in transaction" )
241267 }
@@ -244,20 +270,26 @@ func (t *Transaction) UnmarshalJSON(input []byte) error {
244270 return errors .New ("missing required field 'input' in transaction" )
245271 }
246272 itx .Data = * dec .Data
247- if dec .V = = nil {
248- return errors . New ( "missing required field 'v' in transaction" )
273+ if dec .AccessList ! = nil {
274+ itx . AccessList = * dec . AccessList
249275 }
250- itx .V = (* big .Int )(dec .V )
276+
277+ // signature R
251278 if dec .R == nil {
252279 return errors .New ("missing required field 'r' in transaction" )
253280 }
254281 itx .R = (* big .Int )(dec .R )
282+ // signature S
255283 if dec .S == nil {
256284 return errors .New ("missing required field 's' in transaction" )
257285 }
258286 itx .S = (* big .Int )(dec .S )
259- withSignature := itx .V .Sign () != 0 || itx .R .Sign () != 0 || itx .S .Sign () != 0
260- if withSignature {
287+ // signature V
288+ itx .V , err = dec .yParityValue ()
289+ if err != nil {
290+ return err
291+ }
292+ if itx .V .Sign () != 0 || itx .R .Sign () != 0 || itx .S .Sign () != 0 {
261293 if err := sanityCheckSignature (itx .V , itx .R , itx .S , false ); err != nil {
262294 return err
263295 }
@@ -268,7 +300,7 @@ func (t *Transaction) UnmarshalJSON(input []byte) error {
268300 }
269301
270302 // Now set the inner transaction.
271- t .setDecoded (inner , 0 )
303+ tx .setDecoded (inner , 0 )
272304
273305 // TODO: check hash here?
274306 return nil
0 commit comments