@@ -128,12 +128,29 @@ func (r *Receipt) EncodeRLP(w io.Writer) error {
128
128
defer encodeBufferPool .Put (buf )
129
129
buf .Reset ()
130
130
buf .WriteByte (r .Type )
131
- if err := rlp . Encode ( buf , data ); err != nil {
131
+ if err := r . encodeTyped ( data , buf ); err != nil {
132
132
return err
133
133
}
134
134
return rlp .Encode (w , buf .Bytes ())
135
135
}
136
136
137
+ // encodeTyped writes the canonical encoding of a typed receipt to w.
138
+ func (r * Receipt ) encodeTyped (data * receiptRLP , w * bytes.Buffer ) error {
139
+ w .WriteByte (r .Type )
140
+ return rlp .Encode (w , data )
141
+ }
142
+
143
+ // MarshalBinary returns the consensus encoding of the receipt.
144
+ func (r * Receipt ) MarshalBinary () ([]byte , error ) {
145
+ if r .Type == LegacyTxType {
146
+ return rlp .EncodeToBytes (r )
147
+ }
148
+ data := & receiptRLP {r .statusEncoding (), r .CumulativeGasUsed , r .Bloom , r .Logs }
149
+ var buf bytes.Buffer
150
+ err := r .encodeTyped (data , & buf )
151
+ return buf .Bytes (), err
152
+ }
153
+
137
154
// DecodeRLP implements rlp.Decoder, and loads the consensus fields of a receipt
138
155
// from an RLP stream.
139
156
func (r * Receipt ) DecodeRLP (s * rlp.Stream ) error {
@@ -172,6 +189,42 @@ func (r *Receipt) DecodeRLP(s *rlp.Stream) error {
172
189
}
173
190
}
174
191
192
+ // UnmarshalBinary decodes the consensus encoding of receipts.
193
+ // It supports legacy RLP receipts and EIP-2718 typed receipts.
194
+ func (r * Receipt ) UnmarshalBinary (b []byte ) error {
195
+ if len (b ) > 0 && b [0 ] > 0x7f {
196
+ // It's a legacy receipt decode the RLP
197
+ var data receiptRLP
198
+ err := rlp .DecodeBytes (b , & data )
199
+ if err != nil {
200
+ return err
201
+ }
202
+ r .Type = LegacyTxType
203
+ return r .setFromRLP (data )
204
+ }
205
+ // It's an EIP2718 typed transaction envelope.
206
+ return r .decodeTyped (b )
207
+ }
208
+
209
+ // decodeTyped decodes a typed receipt from the canonical format.
210
+ func (r * Receipt ) decodeTyped (b []byte ) error {
211
+ if len (b ) == 0 {
212
+ return errEmptyTypedReceipt
213
+ }
214
+ switch b [0 ] {
215
+ case DynamicFeeTxType , AccessListTxType :
216
+ var data receiptRLP
217
+ err := rlp .DecodeBytes (b [1 :], & data )
218
+ if err != nil {
219
+ return err
220
+ }
221
+ r .Type = b [0 ]
222
+ return r .setFromRLP (data )
223
+ default :
224
+ return ErrTxTypeNotSupported
225
+ }
226
+ }
227
+
175
228
func (r * Receipt ) setFromRLP (data receiptRLP ) error {
176
229
r .CumulativeGasUsed , r .Bloom , r .Logs = data .CumulativeGasUsed , data .Bloom , data .Logs
177
230
return r .setStatus (data .PostStateOrStatus )
@@ -279,11 +332,11 @@ func decodeStoredReceiptRLP(r *ReceiptForStorage, blob []byte) error {
279
332
type Receipts []* Receipt
280
333
281
334
// Len returns the number of receipts in this list.
282
- func (r Receipts ) Len () int { return len (r ) }
335
+ func (rs Receipts ) Len () int { return len (rs ) }
283
336
284
337
// GetRlp returns the RLP encoding of one receipt from the list.
285
- func (r Receipts ) GetRlp (i int ) []byte {
286
- bytes , err := rlp .EncodeToBytes (r [i ])
338
+ func (rs Receipts ) GetRlp (i int ) []byte {
339
+ bytes , err := rlp .EncodeToBytes (rs [i ])
287
340
if err != nil {
288
341
panic (err )
289
342
}
@@ -292,42 +345,42 @@ func (r Receipts) GetRlp(i int) []byte {
292
345
293
346
// DeriveFields fills the receipts with their computed fields based on consensus
294
347
// data and contextual infos like containing block and transactions.
295
- func (r Receipts ) DeriveFields (config * params.ChainConfig , hash common.Hash , number uint64 , txs Transactions ) error {
348
+ func (rs Receipts ) DeriveFields (config * params.ChainConfig , hash common.Hash , number uint64 , txs Transactions ) error {
296
349
signer := MakeSigner (config , new (big.Int ).SetUint64 (number ))
297
350
298
351
logIndex := uint (0 )
299
- if len (txs ) != len (r ) {
352
+ if len (txs ) != len (rs ) {
300
353
return errors .New ("transaction and receipt count mismatch" )
301
354
}
302
- for i := 0 ; i < len (r ); i ++ {
355
+ for i := 0 ; i < len (rs ); i ++ {
303
356
// The transaction type and hash can be retrieved from the transaction itself
304
- r [i ].Type = txs [i ].Type ()
305
- r [i ].TxHash = txs [i ].Hash ()
357
+ rs [i ].Type = txs [i ].Type ()
358
+ rs [i ].TxHash = txs [i ].Hash ()
306
359
307
360
// block location fields
308
- r [i ].BlockHash = hash
309
- r [i ].BlockNumber = new (big.Int ).SetUint64 (number )
310
- r [i ].TransactionIndex = uint (i )
361
+ rs [i ].BlockHash = hash
362
+ rs [i ].BlockNumber = new (big.Int ).SetUint64 (number )
363
+ rs [i ].TransactionIndex = uint (i )
311
364
312
365
// The contract address can be derived from the transaction itself
313
366
if txs [i ].To () == nil {
314
367
// Deriving the signer is expensive, only do if it's actually needed
315
368
from , _ := Sender (signer , txs [i ])
316
- r [i ].ContractAddress = crypto .CreateAddress (from , txs [i ].Nonce ())
369
+ rs [i ].ContractAddress = crypto .CreateAddress (from , txs [i ].Nonce ())
317
370
}
318
371
// The used gas can be calculated based on previous r
319
372
if i == 0 {
320
- r [i ].GasUsed = r [i ].CumulativeGasUsed
373
+ rs [i ].GasUsed = rs [i ].CumulativeGasUsed
321
374
} else {
322
- r [i ].GasUsed = r [i ].CumulativeGasUsed - r [i - 1 ].CumulativeGasUsed
375
+ rs [i ].GasUsed = rs [i ].CumulativeGasUsed - rs [i - 1 ].CumulativeGasUsed
323
376
}
324
377
// The derived log fields can simply be set from the block and transaction
325
- for j := 0 ; j < len (r [i ].Logs ); j ++ {
326
- r [i ].Logs [j ].BlockNumber = number
327
- r [i ].Logs [j ].BlockHash = hash
328
- r [i ].Logs [j ].TxHash = r [i ].TxHash
329
- r [i ].Logs [j ].TxIndex = uint (i )
330
- r [i ].Logs [j ].Index = logIndex
378
+ for j := 0 ; j < len (rs [i ].Logs ); j ++ {
379
+ rs [i ].Logs [j ].BlockNumber = number
380
+ rs [i ].Logs [j ].BlockHash = hash
381
+ rs [i ].Logs [j ].TxHash = rs [i ].TxHash
382
+ rs [i ].Logs [j ].TxIndex = uint (i )
383
+ rs [i ].Logs [j ].Index = logIndex
331
384
logIndex ++
332
385
}
333
386
}
0 commit comments