core/types: remove support for legacy receipt/log storage encoding (#22852)
* core/types: remove support for legacy receipt storage encoding * core/types: remove support for legacy log storage encoding
This commit is contained in:
parent
e536bb52ff
commit
643fd0efc6
@ -71,18 +71,6 @@ type rlpLog struct {
|
|||||||
// rlpStorageLog is the storage encoding of a log.
|
// rlpStorageLog is the storage encoding of a log.
|
||||||
type rlpStorageLog rlpLog
|
type rlpStorageLog rlpLog
|
||||||
|
|
||||||
// legacyRlpStorageLog is the previous storage encoding of a log including some redundant fields.
|
|
||||||
type legacyRlpStorageLog struct {
|
|
||||||
Address common.Address
|
|
||||||
Topics []common.Hash
|
|
||||||
Data []byte
|
|
||||||
BlockNumber uint64
|
|
||||||
TxHash common.Hash
|
|
||||||
TxIndex uint
|
|
||||||
BlockHash common.Hash
|
|
||||||
Index uint
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeRLP implements rlp.Encoder.
|
// EncodeRLP implements rlp.Encoder.
|
||||||
func (l *Log) EncodeRLP(w io.Writer) error {
|
func (l *Log) EncodeRLP(w io.Writer) error {
|
||||||
return rlp.Encode(w, rlpLog{Address: l.Address, Topics: l.Topics, Data: l.Data})
|
return rlp.Encode(w, rlpLog{Address: l.Address, Topics: l.Topics, Data: l.Data})
|
||||||
@ -115,29 +103,10 @@ func (l *LogForStorage) EncodeRLP(w io.Writer) error {
|
|||||||
//
|
//
|
||||||
// Note some redundant fields(e.g. block number, tx hash etc) will be assembled later.
|
// Note some redundant fields(e.g. block number, tx hash etc) will be assembled later.
|
||||||
func (l *LogForStorage) DecodeRLP(s *rlp.Stream) error {
|
func (l *LogForStorage) DecodeRLP(s *rlp.Stream) error {
|
||||||
blob, err := s.Raw()
|
var dec rlpStorageLog
|
||||||
if err != nil {
|
if err := s.Decode(&dec); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var dec rlpStorageLog
|
*l = LogForStorage{Address: dec.Address, Topics: dec.Topics, Data: dec.Data}
|
||||||
err = rlp.DecodeBytes(blob, &dec)
|
return nil
|
||||||
if err == nil {
|
|
||||||
*l = LogForStorage{
|
|
||||||
Address: dec.Address,
|
|
||||||
Topics: dec.Topics,
|
|
||||||
Data: dec.Data,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Try to decode log with previous definition.
|
|
||||||
var dec legacyRlpStorageLog
|
|
||||||
err = rlp.DecodeBytes(blob, &dec)
|
|
||||||
if err == nil {
|
|
||||||
*l = LogForStorage{
|
|
||||||
Address: dec.Address,
|
|
||||||
Topics: dec.Topics,
|
|
||||||
Data: dec.Data,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
@ -97,27 +97,6 @@ type storedReceiptRLP struct {
|
|||||||
Logs []*LogForStorage
|
Logs []*LogForStorage
|
||||||
}
|
}
|
||||||
|
|
||||||
// v4StoredReceiptRLP is the storage encoding of a receipt used in database version 4.
|
|
||||||
type v4StoredReceiptRLP struct {
|
|
||||||
PostStateOrStatus []byte
|
|
||||||
CumulativeGasUsed uint64
|
|
||||||
TxHash common.Hash
|
|
||||||
ContractAddress common.Address
|
|
||||||
Logs []*LogForStorage
|
|
||||||
GasUsed uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
// v3StoredReceiptRLP is the original storage encoding of a receipt including some unnecessary fields.
|
|
||||||
type v3StoredReceiptRLP struct {
|
|
||||||
PostStateOrStatus []byte
|
|
||||||
CumulativeGasUsed uint64
|
|
||||||
Bloom Bloom
|
|
||||||
TxHash common.Hash
|
|
||||||
ContractAddress common.Address
|
|
||||||
Logs []*LogForStorage
|
|
||||||
GasUsed uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewReceipt creates a barebone transaction receipt, copying the init fields.
|
// NewReceipt creates a barebone transaction receipt, copying the init fields.
|
||||||
// Deprecated: create receipts using a struct literal instead.
|
// Deprecated: create receipts using a struct literal instead.
|
||||||
func NewReceipt(root []byte, failed bool, cumulativeGasUsed uint64) *Receipt {
|
func NewReceipt(root []byte, failed bool, cumulativeGasUsed uint64) *Receipt {
|
||||||
@ -237,8 +216,7 @@ func (r *Receipt) Size() common.StorageSize {
|
|||||||
// entire content of a receipt, as opposed to only the consensus fields originally.
|
// entire content of a receipt, as opposed to only the consensus fields originally.
|
||||||
type ReceiptForStorage Receipt
|
type ReceiptForStorage Receipt
|
||||||
|
|
||||||
// EncodeRLP implements rlp.Encoder, and flattens all content fields of a receipt
|
// EncodeRLP implements rlp.Encoder.
|
||||||
// into an RLP stream.
|
|
||||||
func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error {
|
func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error {
|
||||||
enc := &storedReceiptRLP{
|
enc := &storedReceiptRLP{
|
||||||
PostStateOrStatus: (*Receipt)(r).statusEncoding(),
|
PostStateOrStatus: (*Receipt)(r).statusEncoding(),
|
||||||
@ -251,29 +229,10 @@ func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error {
|
|||||||
return rlp.Encode(w, enc)
|
return rlp.Encode(w, enc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeRLP implements rlp.Decoder, and loads both consensus and implementation
|
// DecodeRLP implements rlp.Decoder.
|
||||||
// fields of a receipt from an RLP stream.
|
|
||||||
func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error {
|
func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error {
|
||||||
// Retrieve the entire receipt blob as we need to try multiple decoders
|
|
||||||
blob, err := s.Raw()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Try decoding from the newest format for future proofness, then the older one
|
|
||||||
// for old nodes that just upgraded. V4 was an intermediate unreleased format so
|
|
||||||
// we do need to decode it, but it's not common (try last).
|
|
||||||
if err := decodeStoredReceiptRLP(r, blob); err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if err := decodeV3StoredReceiptRLP(r, blob); err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return decodeV4StoredReceiptRLP(r, blob)
|
|
||||||
}
|
|
||||||
|
|
||||||
func decodeStoredReceiptRLP(r *ReceiptForStorage, blob []byte) error {
|
|
||||||
var stored storedReceiptRLP
|
var stored storedReceiptRLP
|
||||||
if err := rlp.DecodeBytes(blob, &stored); err != nil {
|
if err := s.Decode(&stored); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := (*Receipt)(r).setStatus(stored.PostStateOrStatus); err != nil {
|
if err := (*Receipt)(r).setStatus(stored.PostStateOrStatus); err != nil {
|
||||||
@ -285,48 +244,6 @@ func decodeStoredReceiptRLP(r *ReceiptForStorage, blob []byte) error {
|
|||||||
r.Logs[i] = (*Log)(log)
|
r.Logs[i] = (*Log)(log)
|
||||||
}
|
}
|
||||||
r.Bloom = CreateBloom(Receipts{(*Receipt)(r)})
|
r.Bloom = CreateBloom(Receipts{(*Receipt)(r)})
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func decodeV4StoredReceiptRLP(r *ReceiptForStorage, blob []byte) error {
|
|
||||||
var stored v4StoredReceiptRLP
|
|
||||||
if err := rlp.DecodeBytes(blob, &stored); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := (*Receipt)(r).setStatus(stored.PostStateOrStatus); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
r.CumulativeGasUsed = stored.CumulativeGasUsed
|
|
||||||
r.TxHash = stored.TxHash
|
|
||||||
r.ContractAddress = stored.ContractAddress
|
|
||||||
r.GasUsed = stored.GasUsed
|
|
||||||
r.Logs = make([]*Log, len(stored.Logs))
|
|
||||||
for i, log := range stored.Logs {
|
|
||||||
r.Logs[i] = (*Log)(log)
|
|
||||||
}
|
|
||||||
r.Bloom = CreateBloom(Receipts{(*Receipt)(r)})
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func decodeV3StoredReceiptRLP(r *ReceiptForStorage, blob []byte) error {
|
|
||||||
var stored v3StoredReceiptRLP
|
|
||||||
if err := rlp.DecodeBytes(blob, &stored); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := (*Receipt)(r).setStatus(stored.PostStateOrStatus); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
r.CumulativeGasUsed = stored.CumulativeGasUsed
|
|
||||||
r.Bloom = stored.Bloom
|
|
||||||
r.TxHash = stored.TxHash
|
|
||||||
r.ContractAddress = stored.ContractAddress
|
|
||||||
r.GasUsed = stored.GasUsed
|
|
||||||
r.Logs = make([]*Log, len(stored.Logs))
|
|
||||||
for i, log := range stored.Logs {
|
|
||||||
r.Logs[i] = (*Log)(log)
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"math"
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
"reflect"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
@ -38,128 +37,6 @@ func TestDecodeEmptyTypedReceipt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLegacyReceiptDecoding(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
encode func(*Receipt) ([]byte, error)
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
"StoredReceiptRLP",
|
|
||||||
encodeAsStoredReceiptRLP,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"V4StoredReceiptRLP",
|
|
||||||
encodeAsV4StoredReceiptRLP,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"V3StoredReceiptRLP",
|
|
||||||
encodeAsV3StoredReceiptRLP,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
tx := NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), 1, big.NewInt(1), nil)
|
|
||||||
receipt := &Receipt{
|
|
||||||
Status: ReceiptStatusFailed,
|
|
||||||
CumulativeGasUsed: 1,
|
|
||||||
Logs: []*Log{
|
|
||||||
{
|
|
||||||
Address: common.BytesToAddress([]byte{0x11}),
|
|
||||||
Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")},
|
|
||||||
Data: []byte{0x01, 0x00, 0xff},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Address: common.BytesToAddress([]byte{0x01, 0x11}),
|
|
||||||
Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")},
|
|
||||||
Data: []byte{0x01, 0x00, 0xff},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
TxHash: tx.Hash(),
|
|
||||||
ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}),
|
|
||||||
GasUsed: 111111,
|
|
||||||
}
|
|
||||||
receipt.Bloom = CreateBloom(Receipts{receipt})
|
|
||||||
|
|
||||||
for _, tc := range tests {
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
enc, err := tc.encode(receipt)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error encoding receipt: %v", err)
|
|
||||||
}
|
|
||||||
var dec ReceiptForStorage
|
|
||||||
if err := rlp.DecodeBytes(enc, &dec); err != nil {
|
|
||||||
t.Fatalf("Error decoding RLP receipt: %v", err)
|
|
||||||
}
|
|
||||||
// Check whether all consensus fields are correct.
|
|
||||||
if dec.Status != receipt.Status {
|
|
||||||
t.Fatalf("Receipt status mismatch, want %v, have %v", receipt.Status, dec.Status)
|
|
||||||
}
|
|
||||||
if dec.CumulativeGasUsed != receipt.CumulativeGasUsed {
|
|
||||||
t.Fatalf("Receipt CumulativeGasUsed mismatch, want %v, have %v", receipt.CumulativeGasUsed, dec.CumulativeGasUsed)
|
|
||||||
}
|
|
||||||
if dec.Bloom != receipt.Bloom {
|
|
||||||
t.Fatalf("Bloom data mismatch, want %v, have %v", receipt.Bloom, dec.Bloom)
|
|
||||||
}
|
|
||||||
if len(dec.Logs) != len(receipt.Logs) {
|
|
||||||
t.Fatalf("Receipt log number mismatch, want %v, have %v", len(receipt.Logs), len(dec.Logs))
|
|
||||||
}
|
|
||||||
for i := 0; i < len(dec.Logs); i++ {
|
|
||||||
if dec.Logs[i].Address != receipt.Logs[i].Address {
|
|
||||||
t.Fatalf("Receipt log %d address mismatch, want %v, have %v", i, receipt.Logs[i].Address, dec.Logs[i].Address)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(dec.Logs[i].Topics, receipt.Logs[i].Topics) {
|
|
||||||
t.Fatalf("Receipt log %d topics mismatch, want %v, have %v", i, receipt.Logs[i].Topics, dec.Logs[i].Topics)
|
|
||||||
}
|
|
||||||
if !bytes.Equal(dec.Logs[i].Data, receipt.Logs[i].Data) {
|
|
||||||
t.Fatalf("Receipt log %d data mismatch, want %v, have %v", i, receipt.Logs[i].Data, dec.Logs[i].Data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func encodeAsStoredReceiptRLP(want *Receipt) ([]byte, error) {
|
|
||||||
stored := &storedReceiptRLP{
|
|
||||||
PostStateOrStatus: want.statusEncoding(),
|
|
||||||
CumulativeGasUsed: want.CumulativeGasUsed,
|
|
||||||
Logs: make([]*LogForStorage, len(want.Logs)),
|
|
||||||
}
|
|
||||||
for i, log := range want.Logs {
|
|
||||||
stored.Logs[i] = (*LogForStorage)(log)
|
|
||||||
}
|
|
||||||
return rlp.EncodeToBytes(stored)
|
|
||||||
}
|
|
||||||
|
|
||||||
func encodeAsV4StoredReceiptRLP(want *Receipt) ([]byte, error) {
|
|
||||||
stored := &v4StoredReceiptRLP{
|
|
||||||
PostStateOrStatus: want.statusEncoding(),
|
|
||||||
CumulativeGasUsed: want.CumulativeGasUsed,
|
|
||||||
TxHash: want.TxHash,
|
|
||||||
ContractAddress: want.ContractAddress,
|
|
||||||
Logs: make([]*LogForStorage, len(want.Logs)),
|
|
||||||
GasUsed: want.GasUsed,
|
|
||||||
}
|
|
||||||
for i, log := range want.Logs {
|
|
||||||
stored.Logs[i] = (*LogForStorage)(log)
|
|
||||||
}
|
|
||||||
return rlp.EncodeToBytes(stored)
|
|
||||||
}
|
|
||||||
|
|
||||||
func encodeAsV3StoredReceiptRLP(want *Receipt) ([]byte, error) {
|
|
||||||
stored := &v3StoredReceiptRLP{
|
|
||||||
PostStateOrStatus: want.statusEncoding(),
|
|
||||||
CumulativeGasUsed: want.CumulativeGasUsed,
|
|
||||||
Bloom: want.Bloom,
|
|
||||||
TxHash: want.TxHash,
|
|
||||||
ContractAddress: want.ContractAddress,
|
|
||||||
Logs: make([]*LogForStorage, len(want.Logs)),
|
|
||||||
GasUsed: want.GasUsed,
|
|
||||||
}
|
|
||||||
for i, log := range want.Logs {
|
|
||||||
stored.Logs[i] = (*LogForStorage)(log)
|
|
||||||
}
|
|
||||||
return rlp.EncodeToBytes(stored)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tests that receipt data can be correctly derived from the contextual infos
|
// Tests that receipt data can be correctly derived from the contextual infos
|
||||||
func TestDeriveFields(t *testing.T) {
|
func TestDeriveFields(t *testing.T) {
|
||||||
// Create a few transactions to have receipts for
|
// Create a few transactions to have receipts for
|
||||||
|
Loading…
Reference in New Issue
Block a user