Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion cmd/opera/launcher/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package launcher

import (
"compress/gzip"
"errors"
"io"
"os"
"strconv"
Expand Down Expand Up @@ -138,7 +139,11 @@ func exportEvmKeys(ctx *cli.Context) error {
keysDB := batched.Wrap(keysDB_)
defer keysDB.Close()

it := gdb.EvmStore().EvmDb.NewIterator(nil, nil)
evmDb := gdb.EvmStore().EvmDb
if evmDb == nil {
return errors.New("only legacy MPT EVM keys export makes sense")
}
it := evmDb.NewIterator(nil, nil)
// iterate only over MPT data
it = mptAndPreimageIterator{it}
defer it.Release()
Expand Down
7 changes: 6 additions & 1 deletion cmd/opera/launcher/genesiscmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,12 @@ func exportGenesis(ctx *cli.Context) error {
if err != nil {
return err
}
it := gdb.EvmStore().EvmDb.NewIterator(nil, nil)

evmDb := gdb.EvmStore().EvmDb
if evmDb == nil {
return errors.New("genesis should include legacy MPT EVM data only")
}
it := evmDb.NewIterator(nil, nil)
if mode == "mpt" {
// iterate only over MPT data
it = mptIterator{it}
Expand Down
14 changes: 13 additions & 1 deletion cmd/opera/launcher/snapshotcmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,13 @@ func pruneState(ctx *cli.Context) error {
return err
}
}
pruner, err := evmpruner.NewPruner(gdb.EvmStore().EvmDb, genesisRoot, root, tmpDir, bloom)

evmDb := gdb.EvmStore().EvmDb
if evmDb == nil {
return errors.New("only legacy MPT EVM pruning makes sense")
}

pruner, err := evmpruner.NewPruner(evmDb, genesisRoot, root, tmpDir, bloom)
if err != nil {
log.Error("Failed to open snapshot tree", "err", err)
return err
Expand Down Expand Up @@ -269,6 +275,9 @@ func traverseState(ctx *cli.Context) error {
return errors.New("failed to open snapshot tree: genesis is not written")
}
chaindb := gdb.EvmStore().EvmDb
if chaindb == nil {
return errors.New("only legacy MPT EVM nodes traversing makes sense")
}

if ctx.NArg() > 1 {
log.Error("Too many arguments given")
Expand Down Expand Up @@ -359,6 +368,9 @@ func traverseRawState(ctx *cli.Context) error {
return errors.New("failed to open snapshot tree: genesis is not written")
}
chaindb := gdb.EvmStore().EvmDb
if chaindb == nil {
return errors.New("only legacy MPT EVM nodes traversing makes sense")
}

if ctx.NArg() > 1 {
log.Error("Too many arguments given")
Expand Down
13 changes: 9 additions & 4 deletions ethapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
Expand Down Expand Up @@ -710,8 +709,14 @@ type StorageResult struct {

// GetProof returns the Merkle-proof for a given account and optionally some storage keys.
func (s *PublicBlockChainAPI) GetProof(ctx context.Context, address common.Address, storageKeys []string, blockNrOrHash rpc.BlockNumberOrHash) (*AccountResult, error) {
state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
if state == nil || err != nil {
statedb, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
if statedb == nil || err != nil {
return nil, err
}

state, ok := evmcore.IsMptStateDB(statedb)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for asking, was just looking into the code and the consensus and found PRs.
How do you think, does it worth it to use generics+interfaces here to get rid of type assertion and have more strict type checks?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will be an over-engineering for now. All we need is check here does the proofs complies with the legacy format.
We should not return others kind of proofs because clients understand the legacy (MPT) only.

if !ok {
err = errors.New("Proofs are not provided by current state db impl")
return nil, err
}

Expand Down Expand Up @@ -912,7 +917,7 @@ type OverrideAccount struct {
type StateOverride map[common.Address]OverrideAccount

// Apply overrides the fields of specified accounts into the given state.
func (diff *StateOverride) Apply(state *state.StateDB) error {
func (diff *StateOverride) Apply(state evmcore.StateDB) error {
if diff == nil {
return nil
}
Expand Down
5 changes: 2 additions & 3 deletions ethapi/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import (
"github.com/Fantom-foundation/lachesis-base/inter/idx"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb"
Expand Down Expand Up @@ -69,12 +68,12 @@ type Backend interface {
HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*evmcore.EvmHeader, error)
HeaderByHash(ctx context.Context, hash common.Hash) (*evmcore.EvmHeader, error)
BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*evmcore.EvmBlock, error)
StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *evmcore.EvmHeader, error)
StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (evmcore.StateDB, *evmcore.EvmHeader, error)
ResolveRpcBlockNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (idx.Block, error)
BlockByHash(ctx context.Context, hash common.Hash) (*evmcore.EvmBlock, error)
GetReceiptsByNumber(ctx context.Context, number rpc.BlockNumber) (types.Receipts, error)
GetTd(hash common.Hash) *big.Int
GetEVM(ctx context.Context, msg evmcore.Message, state *state.StateDB, header *evmcore.EvmHeader, vmConfig *vm.Config) (*vm.EVM, func() error, error)
GetEVM(ctx context.Context, msg evmcore.Message, state evmcore.StateDB, header *evmcore.EvmHeader, vmConfig *vm.Config) (*vm.EVM, func() error, error)
MinGasPrice() *big.Int
MaxGasLimit() uint64

Expand Down
7 changes: 3 additions & 4 deletions evmcore/apply_fake_genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
Expand All @@ -35,7 +34,7 @@ import (
var FakeGenesisTime = inter.Timestamp(1608600000 * time.Second)

// ApplyFakeGenesis writes or updates the genesis block in db.
func ApplyFakeGenesis(statedb *state.StateDB, time inter.Timestamp, balances map[common.Address]*big.Int) (*EvmBlock, error) {
func ApplyFakeGenesis(statedb StateDB, time inter.Timestamp, balances map[common.Address]*big.Int) (*EvmBlock, error) {
for acc, balance := range balances {
statedb.SetBalance(acc, balance)
}
Expand All @@ -50,7 +49,7 @@ func ApplyFakeGenesis(statedb *state.StateDB, time inter.Timestamp, balances map
return block, nil
}

func flush(statedb *state.StateDB, clean bool) (root common.Hash, err error) {
func flush(statedb StateDB, clean bool) (root common.Hash, err error) {
root, err = statedb.Commit(clean)
if err != nil {
return
Expand Down Expand Up @@ -83,7 +82,7 @@ func genesisBlock(time inter.Timestamp, root common.Hash) *EvmBlock {
}

// MustApplyFakeGenesis writes the genesis block and state to db, panicking on error.
func MustApplyFakeGenesis(statedb *state.StateDB, time inter.Timestamp, balances map[common.Address]*big.Int) *EvmBlock {
func MustApplyFakeGenesis(statedb StateDB, time inter.Timestamp, balances map[common.Address]*big.Int) *EvmBlock {
block, err := ApplyFakeGenesis(statedb, time, balances)
if err != nil {
log.Crit("ApplyFakeGenesis", "err", err)
Expand Down
19 changes: 13 additions & 6 deletions evmcore/bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@ import (
"os"
"testing"

"github.com/ethereum/go-ethereum/core/state"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
Expand Down Expand Up @@ -145,13 +146,19 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
defer db.Close()
}

stateAt := func(root common.Hash) StateDB {
st, err := state.New(root, state.NewDatabase(db), nil)
if err != nil {
panic(err)
}

return ToStateDB(st)
}

// Generate a chain of b.N blocks using the supplied block
// generator function.
// state
statedb, err := state.New(common.Hash{}, state.NewDatabase(db), nil)
if err != nil {
b.Fatalf("cannot create statedb: %v", err)
}
statedb := newMemoryStateDB()
genesisBlock := MustApplyFakeGenesis(statedb, FakeGenesisTime, map[common.Address]*big.Int{
benchRootAddr: benchRootFunds,
})
Expand All @@ -162,5 +169,5 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
b.ReportAllocs()
b.ResetTimer()

_, _, _ = GenerateChain(nil, genesisBlock, db, b.N, gen)
_, _, _ = GenerateChain(nil, genesisBlock, b.N, stateAt, gen)
}
44 changes: 12 additions & 32 deletions evmcore/chain_makers.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,8 @@ import (
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"

"github.com/Fantom-foundation/go-opera/inter"
Expand All @@ -39,7 +37,7 @@ type BlockGen struct {
parent *EvmBlock
chain []*EvmBlock
header *EvmHeader
statedb *state.StateDB
statedb StateDB

gasPool *GasPool
txs []*types.Transaction
Expand Down Expand Up @@ -100,7 +98,7 @@ func (b *BlockGen) AddTxWithChain(bc DummyChain, tx *types.Transaction) {
b.statedb.Prepare(tx.Hash(), len(b.txs))
blockContext := NewEVMBlockContext(b.header, bc, nil)
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, b.statedb, b.config, opera.DefaultVMConfig)
receipt, _, _, err := applyTransaction(msg, b.config, b.gasPool, b.statedb, b.header.Number, b.header.Hash, tx, &b.header.GasUsed, vmenv, func(log *types.Log, db *state.StateDB) {})
receipt, _, _, err := applyTransaction(msg, b.config, b.gasPool, b.statedb, b.header.Number, b.header.Hash, tx, &b.header.GasUsed, vmenv, func(log *types.Log, db StateDB) {})
if err != nil {
panic(err)
}
Expand Down Expand Up @@ -185,7 +183,11 @@ func (b *BlockGen) OffsetTime(seconds int64) {
// Blocks created by GenerateChain do not contain valid proof of work
// values. Inserting them into BlockChain requires use of FakePow or
// a similar non-validating proof of work implementation.
func GenerateChain(config *params.ChainConfig, parent *EvmBlock, db ethdb.Database, n int, gen func(int, *BlockGen)) ([]*EvmBlock, []types.Receipts, DummyChain) {
func GenerateChain(
config *params.ChainConfig, parent *EvmBlock, n int, stateAt func(common.Hash) StateDB, gen func(int, *BlockGen),
) (
[]*EvmBlock, []types.Receipts, DummyChain,
) {
if config == nil {
config = params.AllEthashProtocolChanges
}
Expand All @@ -195,7 +197,7 @@ func GenerateChain(config *params.ChainConfig, parent *EvmBlock, db ethdb.Databa
}

blocks, receipts := make([]*EvmBlock, n), make([]types.Receipts, n)
genblock := func(i int, parent *EvmBlock, statedb *state.StateDB) (*EvmBlock, types.Receipts) {
genblock := func(i int, parent *EvmBlock, statedb StateDB) (*EvmBlock, types.Receipts) {
b := &BlockGen{i: i, chain: blocks, parent: parent, statedb: statedb, config: config}
b.header = makeHeader(parent, statedb)

Expand All @@ -219,11 +221,10 @@ func GenerateChain(config *params.ChainConfig, parent *EvmBlock, db ethdb.Databa

return block, b.receipts
}

for i := 0; i < n; i++ {
statedb, err := state.New(parent.Root, state.NewDatabase(db), nil)
if err != nil {
panic(err)
}
statedb := stateAt(parent.Root)

block, receipt := genblock(i, parent, statedb)
blocks[i] = block
receipts[i] = receipt
Expand All @@ -234,7 +235,7 @@ func GenerateChain(config *params.ChainConfig, parent *EvmBlock, db ethdb.Databa
return blocks, receipts, chain
}

func makeHeader(parent *EvmBlock, state *state.StateDB) *EvmHeader {
func makeHeader(parent *EvmBlock, state StateDB) *EvmHeader {
var t inter.Timestamp
if parent.Time == 0 {
t = 10
Expand All @@ -252,27 +253,6 @@ func makeHeader(parent *EvmBlock, state *state.StateDB) *EvmHeader {
return header
}

// makeHeaderChain creates a deterministic chain of headers rooted at parent.
func makeHeaderChain(parent *EvmHeader, n int, db ethdb.Database, seed int) []*EvmHeader {
block := &EvmBlock{}
block.EvmHeader = *parent

blocks := makeBlockChain(block, n, db, seed)
headers := make([]*EvmHeader, len(blocks))
for i, block := range blocks {
headers[i] = block.Header()
}
return headers
}

// makeBlockChain creates a deterministic chain of blocks rooted at parent.
func makeBlockChain(parent *EvmBlock, n int, db ethdb.Database, seed int) []*EvmBlock {
blocks, _, _ := GenerateChain(params.TestChainConfig, parent, db, n, func(i int, b *BlockGen) {
b.SetCoinbase(common.Address{0: byte(seed), 19: byte(i)})
})
return blocks
}

type fakeChainReader struct {
config *params.ChainConfig
genesis *EvmBlock
Expand Down
5 changes: 2 additions & 3 deletions evmcore/state_prefetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package evmcore
import (
"sync/atomic"

"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
Expand All @@ -46,7 +45,7 @@ func newStatePrefetcher(config *params.ChainConfig, bc DummyChain) *statePrefetc
// Prefetch processes the state changes according to the Ethereum rules by running
// the transaction messages using the statedb, but any changes are discarded. The
// only goal is to pre-cache transaction signatures and state trie nodes.
func (p *statePrefetcher) Prefetch(block *EvmBlock, statedb *state.StateDB, cfg vm.Config, interrupt *uint32) {
func (p *statePrefetcher) Prefetch(block *EvmBlock, statedb StateDB, cfg vm.Config, interrupt *uint32) {
var (
header = block.Header()
gaspool = new(GasPool).AddGas(block.GasLimit)
Expand Down Expand Up @@ -84,7 +83,7 @@ func (p *statePrefetcher) Prefetch(block *EvmBlock, statedb *state.StateDB, cfg
// precacheTransaction attempts to apply a transaction to the given state database
// and uses the input parameters for its environment. The goal is not to execute
// the transaction successfully, rather to warm up touched data slots.
func precacheTransaction(msg types.Message, config *params.ChainConfig, gaspool *GasPool, statedb *state.StateDB, header *EvmHeader, evm *vm.EVM) error {
func precacheTransaction(msg types.Message, config *params.ChainConfig, gaspool *GasPool, statedb StateDB, header *EvmHeader, evm *vm.EVM) error {
// Update the evm with the new transaction context.
evm.Reset(NewEVMTxContext(msg), statedb)
// Add addresses to access list if applicable
Expand Down
7 changes: 3 additions & 4 deletions evmcore/state_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"math/big"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
Expand Down Expand Up @@ -56,7 +55,7 @@ func NewStateProcessor(config *params.ChainConfig, bc DummyChain) *StateProcesso
// returns the amount of gas that was used in the process. If any of the
// transactions failed to execute due to insufficient gas it will return an error.
func (p *StateProcessor) Process(
block *EvmBlock, statedb *state.StateDB, cfg vm.Config, usedGas *uint64, onNewLog func(*types.Log, *state.StateDB),
block *EvmBlock, statedb StateDB, cfg vm.Config, usedGas *uint64, onNewLog func(*types.Log, StateDB),
) (
receipts types.Receipts, allLogs []*types.Log, skipped []uint32, err error,
) {
Expand Down Expand Up @@ -99,13 +98,13 @@ func applyTransaction(
msg types.Message,
config *params.ChainConfig,
gp *GasPool,
statedb *state.StateDB,
statedb StateDB,
blockNumber *big.Int,
blockHash common.Hash,
tx *types.Transaction,
usedGas *uint64,
evm *vm.EVM,
onNewLog func(*types.Log, *state.StateDB),
onNewLog func(*types.Log, StateDB),
) (
*types.Receipt,
uint64,
Expand Down
Loading