Skip to content

Commit

Permalink
core/rawdb: simple legacy receipt converter (24028)
Browse files Browse the repository at this point in the history
  • Loading branch information
JukLee0ira committed Sep 25, 2024
1 parent e2516dc commit a278696
Show file tree
Hide file tree
Showing 15 changed files with 106 additions and 297 deletions.
1 change: 1 addition & 0 deletions XDCxDAO/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ type XDCXDAO interface {
AppendAncient(number uint64, hash, header, body, receipt, td []byte) error
TruncateAncients(n uint64) error
Sync() error
MigrateTable(string, func([]byte) ([]byte, error)) error //type convertLegacyFn = func([]byte) ([]byte, error)
NewIterator(prefix []byte, start []byte) ethdb.Iterator

Stat(property string) (string, error)
Expand Down
6 changes: 6 additions & 0 deletions XDCxDAO/leveldb.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,12 @@ func (db *BatchDatabase) Sync() error {
return errNotSupported
}

// MigrateTable processes the entries in a given table in sequence
// converting them to a new format if they're of an old format.
func (db *BatchDatabase) MigrateTable(kind string, convert func([]byte) ([]byte, error)) error {
return errNotSupported
}

func (db *BatchDatabase) NewIterator(prefix []byte, start []byte) ethdb.Iterator {
panic("NewIterator from XDCxDAO leveldb is not supported")
}
Expand Down
6 changes: 6 additions & 0 deletions XDCxDAO/mongodb.go
Original file line number Diff line number Diff line change
Expand Up @@ -873,6 +873,12 @@ func (db *MongoDatabase) Sync() error {
return errNotSupported
}

// MigrateTable processes the entries in a given table in sequence
// converting them to a new format if they're of an old format.
func (db *MongoDatabase) MigrateTable(kind string, convert func([]byte) ([]byte, error)) error {
return errNotSupported
}

func (db *MongoDatabase) NewIterator(prefix []byte, start []byte) ethdb.Iterator {
panic("NewIterator from XDCxDAO mongodb is not supported")
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/XDC/chaincmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ func dump(ctx *cli.Context) error {
stack, _ := makeFullNode(ctx)
chain, chainDb := utils.MakeChain(ctx, stack)
defer chainDb.Close()

for _, arg := range ctx.Args() {
var block *types.Block
if hashish(arg) {
Expand Down
1 change: 0 additions & 1 deletion cmd/XDC/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,6 @@ func makeFullNode(ctx *cli.Context) (*node.Node, XDCConfig) {
// enable in default
utils.RegisterXDCXService(stack, &cfg.XDCX)
utils.RegisterEthService(stack, &cfg.Eth)

// Whisper must be explicitly enabled by specifying at least 1 whisper flag or in dev mode
shhEnabled := enableWhisper(ctx)
shhAutoEnabled := !ctx.GlobalIsSet(utils.WhisperEnabledFlag.Name) && ctx.GlobalIsSet(utils.DeveloperFlag.Name)
Expand Down
35 changes: 21 additions & 14 deletions cmd/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,36 @@ import (
)

// RegisterEthService adds an Ethereum client to the stack.
func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) {
func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) *eth.Ethereum {
var err error
if cfg.SyncMode == downloader.LightSync {
err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
return les.New(ctx, cfg)
})
} else {
err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
var XDCXServ *XDCx.XDCX
ctx.Service(&XDCXServ)
var lendingServ *XDCxlending.Lending
ctx.Service(&lendingServ)
fullNode, err := eth.New(ctx, cfg, XDCXServ, lendingServ)
if fullNode != nil && cfg.LightServ > 0 {
ls, _ := les.NewLesServer(fullNode, cfg)
fullNode.AddLesServer(ls)
}
return fullNode, err
})
if err != nil {
Fatalf("Failed to register the Ethereum service: %v", err)
}
return nil
}
var backend *eth.Ethereum
err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
var XDCXServ *XDCx.XDCX
ctx.Service(&XDCXServ)
var lendingServ *XDCxlending.Lending
ctx.Service(&lendingServ)
fullNode, err := eth.New(ctx, cfg, XDCXServ, lendingServ)
if fullNode != nil && cfg.LightServ > 0 {
ls, _ := les.NewLesServer(fullNode, cfg)
fullNode.AddLesServer(ls)
}
backend = fullNode
return fullNode, err
})

if err != nil {
Fatalf("Failed to register the Ethereum service: %v", err)
}
return backend
}

// RegisterShhService configures Whisper and adds it to the given node.
Expand Down
11 changes: 2 additions & 9 deletions core/rawdb/accessors_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,11 +258,7 @@ func DeleteReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
type storedReceiptRLP struct {
PostStateOrStatus []byte
CumulativeGasUsed uint64
Bloom types.Bloom
TxHash common.Hash
ContractAddress common.Address
Logs []*types.LogForStorage
GasUsed uint64
Logs []*types.Log
}

// ReceiptLogs is a barebone version of ReceiptForStorage which only keeps
Expand All @@ -278,10 +274,7 @@ func (r *receiptLogs) DecodeRLP(s *rlp.Stream) error {
if err := s.Decode(&stored); err != nil {
return err
}
r.Logs = make([]*types.Log, len(stored.Logs))
for i, log := range stored.Logs {
r.Logs[i] = (*types.Log)(log)
}
r.Logs = stored.Logs
return nil
}

Expand Down
6 changes: 6 additions & 0 deletions core/rawdb/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ func (db *nofreezedb) Sync() error {
return errNotSupported
}

// MigrateTable processes the entries in a given table in sequence
// converting them to a new format if they're of an old format.
func (db *nofreezedb) MigrateTable(kind string, convert convertLegacyFn) error {
return errNotSupported
}

// NewDatabase creates a high level database on top of a given key-value data
// store without a freezer moving immutable chain segments into cold storage.
func NewDatabase(db ethdb.KeyValueStore) ethdb.Database {
Expand Down
21 changes: 21 additions & 0 deletions core/rawdb/freezer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2019 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package rawdb

// convertLegacyFn takes a raw freezer entry in an older format and
// returns it in the new format.
type convertLegacyFn = func([]byte) ([]byte, error)
6 changes: 6 additions & 0 deletions core/rawdb/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ func (t *table) Sync() error {
return t.db.Sync()
}

// MigrateTable processes the entries in a given table in sequence
// converting them to a new format if they're of an old format.
func (t *table) MigrateTable(kind string, convert convertLegacyFn) error {
return t.db.MigrateTable(kind, convert)
}

// Put inserts the given value into the database at a prefixed version of the
// provided key.
func (t *table) Put(key []byte, value []byte) error {
Expand Down
59 changes: 0 additions & 59 deletions core/types/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,21 +69,6 @@ type rlpLog struct {
Data []byte
}

// rlpStorageLog is the storage encoding of a log.
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.
func (l *Log) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, rlpLog{Address: l.Address, Topics: l.Topics, Data: l.Data})
Expand All @@ -102,47 +87,3 @@ func (l *Log) DecodeRLP(s *rlp.Stream) error {
func (l *Log) String() string {
return fmt.Sprintf(`log: %x %x %x %x %d %x %d`, l.Address, l.Topics, l.Data, l.TxHash, l.TxIndex, l.BlockHash, l.Index)
}

// LogForStorage is a wrapper around a Log that flattens and parses the entire content of
// a log including non-consensus fields.
type LogForStorage Log

// EncodeRLP implements rlp.Encoder.
func (l *LogForStorage) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, rlpStorageLog{
Address: l.Address,
Topics: l.Topics,
Data: l.Data,
})
}

// DecodeRLP implements rlp.Decoder.
//
// Note some redundant fields(e.g. block number, tx hash etc) will be assembled later.
func (l *LogForStorage) DecodeRLP(s *rlp.Stream) error {
blob, err := s.Raw()
if err != nil {
return err
}
var dec rlpStorageLog
err = rlp.DecodeBytes(blob, &dec)
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
}
102 changes: 8 additions & 94 deletions core/types/receipt.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,28 +94,7 @@ type receiptRLP struct {
type storedReceiptRLP struct {
PostStateOrStatus []byte
CumulativeGasUsed uint64
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
Logs []*Log
}

// receiptStorageRLP is the storage encoding of a receipt.
Expand All @@ -124,7 +103,7 @@ type receiptStorageRLP struct {
CumulativeGasUsed uint64
TxHash common.Hash
ContractAddress common.Address
Logs []*LogForStorage
Logs []*Log
GasUsed uint64
}

Expand All @@ -135,7 +114,7 @@ type receiptSwollenStorageRLP struct {
Bloom Bloom
TxHash common.Hash
ContractAddress common.Address
Logs []*LogForStorage
Logs []*Log
GasUsed uint64
}

Expand Down Expand Up @@ -269,99 +248,34 @@ type ReceiptForStorage Receipt
// EncodeRLP implements rlp.Encoder, and flattens all content fields of a receipt
// into an RLP stream.
func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error {
enc := &v3StoredReceiptRLP{
enc := &storedReceiptRLP{
PostStateOrStatus: (*Receipt)(r).statusEncoding(),
CumulativeGasUsed: r.CumulativeGasUsed,
Bloom: r.Bloom,
TxHash: r.TxHash,
ContractAddress: r.ContractAddress,
Logs: make([]*LogForStorage, len(r.Logs)),
Logs: make([]*Log, len(r.Logs)),
}
for i, log := range r.Logs {
enc.Logs[i] = (*LogForStorage)(log)
enc.Logs[i] = (*Log)(log)
}
return rlp.Encode(w, enc)
}

// DecodeRLP implements rlp.Decoder, and loads both consensus and implementation
// fields of a receipt from an RLP stream.
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
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.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 decodeV4StoredReceiptRLP(r *ReceiptForStorage, blob []byte) error {
var stored v4StoredReceiptRLP
if err := rlp.DecodeBytes(blob, &stored); err != nil {
if err := s.Decode(&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.Logs = stored.Logs
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
}

// Receipts implements DerivableList for receipts.
type Receipts []*Receipt

Expand Down
Loading

0 comments on commit a278696

Please sign in to comment.