@@ -94,7 +94,28 @@ type receiptRLP struct {
94
94
type storedReceiptRLP struct {
95
95
PostStateOrStatus []byte
96
96
CumulativeGasUsed uint64
97
- Logs []* Log
97
+ Logs []* LogForStorage
98
+ }
99
+
100
+ // v4StoredReceiptRLP is the storage encoding of a receipt used in database version 4.
101
+ type v4StoredReceiptRLP struct {
102
+ PostStateOrStatus []byte
103
+ CumulativeGasUsed uint64
104
+ TxHash common.Hash
105
+ ContractAddress common.Address
106
+ Logs []* LogForStorage
107
+ GasUsed uint64
108
+ }
109
+
110
+ // v3StoredReceiptRLP is the original storage encoding of a receipt including some unnecessary fields.
111
+ type v3StoredReceiptRLP struct {
112
+ PostStateOrStatus []byte
113
+ CumulativeGasUsed uint64
114
+ Bloom Bloom
115
+ TxHash common.Hash
116
+ ContractAddress common.Address
117
+ Logs []* LogForStorage
118
+ GasUsed uint64
98
119
}
99
120
100
121
// NewReceipt creates a barebone transaction receipt, copying the init fields.
@@ -212,28 +233,96 @@ func (r *Receipt) Size() common.StorageSize {
212
233
// entire content of a receipt, as opposed to only the consensus fields originally.
213
234
type ReceiptForStorage Receipt
214
235
215
- // EncodeRLP implements rlp.Encoder.
236
+ // EncodeRLP implements rlp.Encoder, and flattens all content fields of a receipt
237
+ // into an RLP stream.
216
238
func (r * ReceiptForStorage ) EncodeRLP (w io.Writer ) error {
217
239
enc := & storedReceiptRLP {
218
240
PostStateOrStatus : (* Receipt )(r ).statusEncoding (),
219
241
CumulativeGasUsed : r .CumulativeGasUsed ,
220
- Logs : r .Logs ,
242
+ Logs : make ([]* LogForStorage , len (r .Logs )),
243
+ }
244
+ for i , log := range r .Logs {
245
+ enc .Logs [i ] = (* LogForStorage )(log )
221
246
}
222
247
return rlp .Encode (w , enc )
223
248
}
224
249
225
- // DecodeRLP implements rlp.Decoder.
250
+ // DecodeRLP implements rlp.Decoder, and loads both consensus and implementation
251
+ // fields of a receipt from an RLP stream.
226
252
func (r * ReceiptForStorage ) DecodeRLP (s * rlp.Stream ) error {
253
+ // Retrieve the entire receipt blob as we need to try multiple decoders
254
+ blob , err := s .Raw ()
255
+ if err != nil {
256
+ return err
257
+ }
258
+ // Try decoding from the newest format for future proofness, then the older one
259
+ // for old nodes that just upgraded. V4 was an intermediate unreleased format so
260
+ // we do need to decode it, but it's not common (try last).
261
+ if err := decodeStoredReceiptRLP (r , blob ); err == nil {
262
+ return nil
263
+ }
264
+ if err := decodeV3StoredReceiptRLP (r , blob ); err == nil {
265
+ return nil
266
+ }
267
+ return decodeV4StoredReceiptRLP (r , blob )
268
+ }
269
+
270
+ func decodeStoredReceiptRLP (r * ReceiptForStorage , blob []byte ) error {
227
271
var stored storedReceiptRLP
228
- if err := s . Decode ( & stored ); err != nil {
272
+ if err := rlp . DecodeBytes ( blob , & stored ); err != nil {
229
273
return err
230
274
}
231
275
if err := (* Receipt )(r ).setStatus (stored .PostStateOrStatus ); err != nil {
232
276
return err
233
277
}
234
278
r .CumulativeGasUsed = stored .CumulativeGasUsed
235
- r .Logs = stored .Logs
279
+ r .Logs = make ([]* Log , len (stored .Logs ))
280
+ for i , log := range stored .Logs {
281
+ r .Logs [i ] = (* Log )(log )
282
+ }
236
283
r .Bloom = CreateBloom (Receipts {(* Receipt )(r )})
284
+
285
+ return nil
286
+ }
287
+
288
+ func decodeV4StoredReceiptRLP (r * ReceiptForStorage , blob []byte ) error {
289
+ var stored v4StoredReceiptRLP
290
+ if err := rlp .DecodeBytes (blob , & stored ); err != nil {
291
+ return err
292
+ }
293
+ if err := (* Receipt )(r ).setStatus (stored .PostStateOrStatus ); err != nil {
294
+ return err
295
+ }
296
+ r .CumulativeGasUsed = stored .CumulativeGasUsed
297
+ r .TxHash = stored .TxHash
298
+ r .ContractAddress = stored .ContractAddress
299
+ r .GasUsed = stored .GasUsed
300
+ r .Logs = make ([]* Log , len (stored .Logs ))
301
+ for i , log := range stored .Logs {
302
+ r .Logs [i ] = (* Log )(log )
303
+ }
304
+ r .Bloom = CreateBloom (Receipts {(* Receipt )(r )})
305
+
306
+ return nil
307
+ }
308
+
309
+ func decodeV3StoredReceiptRLP (r * ReceiptForStorage , blob []byte ) error {
310
+ var stored v3StoredReceiptRLP
311
+ if err := rlp .DecodeBytes (blob , & stored ); err != nil {
312
+ return err
313
+ }
314
+ if err := (* Receipt )(r ).setStatus (stored .PostStateOrStatus ); err != nil {
315
+ return err
316
+ }
317
+ r .CumulativeGasUsed = stored .CumulativeGasUsed
318
+ r .Bloom = stored .Bloom
319
+ r .TxHash = stored .TxHash
320
+ r .ContractAddress = stored .ContractAddress
321
+ r .GasUsed = stored .GasUsed
322
+ r .Logs = make ([]* Log , len (stored .Logs ))
323
+ for i , log := range stored .Logs {
324
+ r .Logs [i ] = (* Log )(log )
325
+ }
237
326
return nil
238
327
}
239
328
0 commit comments