Skip to content

Commit 370680a

Browse files
authored
core/types: revert removal of legacy receipt support (ethereum#23247)
* Revert "core/types: go generate (ethereum#23177)" This reverts commit 00b922f. * Revert "core/types: remove LogForStorage type (ethereum#23173)" This reverts commit 7522642. * Revert "core/types: remove support for legacy receipt/log storage encoding (ethereum#22852)" This reverts commit 643fd0e.
1 parent 97aacd9 commit 370680a

File tree

4 files changed

+319
-24
lines changed

4 files changed

+319
-24
lines changed

core/types/gen_log_json.go

+12-12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/types/log.go

+89-6
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@
1717
package types
1818

1919
import (
20+
"io"
21+
2022
"github.com/ethereum/go-ethereum/common"
2123
"github.com/ethereum/go-ethereum/common/hexutil"
24+
"github.com/ethereum/go-ethereum/rlp"
2225
)
2326

2427
//go:generate gencodec -type Log -field-override logMarshaling -out gen_log_json.go
@@ -37,19 +40,19 @@ type Log struct {
3740
// Derived fields. These fields are filled in by the node
3841
// but not secured by consensus.
3942
// block in which the transaction was included
40-
BlockNumber uint64 `json:"blockNumber" rlp:"-"`
43+
BlockNumber uint64 `json:"blockNumber"`
4144
// hash of the transaction
42-
TxHash common.Hash `json:"transactionHash" gencodec:"required" rlp:"-"`
45+
TxHash common.Hash `json:"transactionHash" gencodec:"required"`
4346
// index of the transaction in the block
44-
TxIndex uint `json:"transactionIndex" rlp:"-"`
47+
TxIndex uint `json:"transactionIndex"`
4548
// hash of the block in which the transaction was included
46-
BlockHash common.Hash `json:"blockHash" rlp:"-"`
49+
BlockHash common.Hash `json:"blockHash"`
4750
// index of the log in the block
48-
Index uint `json:"logIndex" rlp:"-"`
51+
Index uint `json:"logIndex"`
4952

5053
// The Removed field is true if this log was reverted due to a chain reorganisation.
5154
// You must pay attention to this field if you receive logs through a filter query.
52-
Removed bool `json:"removed" rlp:"-"`
55+
Removed bool `json:"removed"`
5356
}
5457

5558
type logMarshaling struct {
@@ -58,3 +61,83 @@ type logMarshaling struct {
5861
TxIndex hexutil.Uint
5962
Index hexutil.Uint
6063
}
64+
65+
type rlpLog struct {
66+
Address common.Address
67+
Topics []common.Hash
68+
Data []byte
69+
}
70+
71+
// rlpStorageLog is the storage encoding of a log.
72+
type rlpStorageLog rlpLog
73+
74+
// legacyRlpStorageLog is the previous storage encoding of a log including some redundant fields.
75+
type legacyRlpStorageLog struct {
76+
Address common.Address
77+
Topics []common.Hash
78+
Data []byte
79+
BlockNumber uint64
80+
TxHash common.Hash
81+
TxIndex uint
82+
BlockHash common.Hash
83+
Index uint
84+
}
85+
86+
// EncodeRLP implements rlp.Encoder.
87+
func (l *Log) EncodeRLP(w io.Writer) error {
88+
return rlp.Encode(w, rlpLog{Address: l.Address, Topics: l.Topics, Data: l.Data})
89+
}
90+
91+
// DecodeRLP implements rlp.Decoder.
92+
func (l *Log) DecodeRLP(s *rlp.Stream) error {
93+
var dec rlpLog
94+
err := s.Decode(&dec)
95+
if err == nil {
96+
l.Address, l.Topics, l.Data = dec.Address, dec.Topics, dec.Data
97+
}
98+
return err
99+
}
100+
101+
// LogForStorage is a wrapper around a Log that flattens and parses the entire content of
102+
// a log including non-consensus fields.
103+
type LogForStorage Log
104+
105+
// EncodeRLP implements rlp.Encoder.
106+
func (l *LogForStorage) EncodeRLP(w io.Writer) error {
107+
return rlp.Encode(w, rlpStorageLog{
108+
Address: l.Address,
109+
Topics: l.Topics,
110+
Data: l.Data,
111+
})
112+
}
113+
114+
// DecodeRLP implements rlp.Decoder.
115+
//
116+
// Note some redundant fields(e.g. block number, tx hash etc) will be assembled later.
117+
func (l *LogForStorage) DecodeRLP(s *rlp.Stream) error {
118+
blob, err := s.Raw()
119+
if err != nil {
120+
return err
121+
}
122+
var dec rlpStorageLog
123+
err = rlp.DecodeBytes(blob, &dec)
124+
if err == nil {
125+
*l = LogForStorage{
126+
Address: dec.Address,
127+
Topics: dec.Topics,
128+
Data: dec.Data,
129+
}
130+
} else {
131+
// Try to decode log with previous definition.
132+
var dec legacyRlpStorageLog
133+
err = rlp.DecodeBytes(blob, &dec)
134+
if err == nil {
135+
*l = LogForStorage{
136+
Address: dec.Address,
137+
Topics: dec.Topics,
138+
Data: dec.Data,
139+
}
140+
}
141+
}
142+
return err
143+
}

core/types/receipt.go

+95-6
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,28 @@ type receiptRLP struct {
9494
type storedReceiptRLP struct {
9595
PostStateOrStatus []byte
9696
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
98119
}
99120

100121
// NewReceipt creates a barebone transaction receipt, copying the init fields.
@@ -212,28 +233,96 @@ func (r *Receipt) Size() common.StorageSize {
212233
// entire content of a receipt, as opposed to only the consensus fields originally.
213234
type ReceiptForStorage Receipt
214235

215-
// EncodeRLP implements rlp.Encoder.
236+
// EncodeRLP implements rlp.Encoder, and flattens all content fields of a receipt
237+
// into an RLP stream.
216238
func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error {
217239
enc := &storedReceiptRLP{
218240
PostStateOrStatus: (*Receipt)(r).statusEncoding(),
219241
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)
221246
}
222247
return rlp.Encode(w, enc)
223248
}
224249

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.
226252
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 {
227271
var stored storedReceiptRLP
228-
if err := s.Decode(&stored); err != nil {
272+
if err := rlp.DecodeBytes(blob, &stored); err != nil {
229273
return err
230274
}
231275
if err := (*Receipt)(r).setStatus(stored.PostStateOrStatus); err != nil {
232276
return err
233277
}
234278
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+
}
236283
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+
}
237326
return nil
238327
}
239328

0 commit comments

Comments
 (0)