Skip to content

Commit

Permalink
stop using olddb in simulated backend (erigontech#7219)
Browse files Browse the repository at this point in the history
  • Loading branch information
AskAlexSharov authored and calmbeing committed Apr 24, 2023
1 parent 76a564b commit 281a3a5
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 61 deletions.
23 changes: 15 additions & 8 deletions accounts/abi/bind/backends/simulated.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ import (
"github.com/ledgerwatch/erigon/core/state"
"github.com/ledgerwatch/erigon/core/types"
"github.com/ledgerwatch/erigon/core/vm"
"github.com/ledgerwatch/erigon/ethdb/olddb"
"github.com/ledgerwatch/erigon/event"
"github.com/ledgerwatch/erigon/params"
"github.com/ledgerwatch/erigon/turbo/snapshotsync"
Expand Down Expand Up @@ -79,6 +78,7 @@ type SimulatedBackend struct {
gasPool *core.GasPool
pendingBlock *types.Block // Currently pending block that will be imported on request
pendingReader *state.PlainStateReader
pendingReaderTx kv.Tx
pendingState *state.IntraBlockState // Currently pending state that will be the active on request

rmLogsFeed event.Feed
Expand Down Expand Up @@ -112,9 +112,7 @@ func NewSimulatedBackendWithConfig(alloc types.GenesisAlloc, config *chain.Confi
// A simulated backend always uses chainID 1337.
func NewSimulatedBackend(t *testing.T, alloc types.GenesisAlloc, gasLimit uint64) *SimulatedBackend {
b := NewSimulatedBackendWithConfig(alloc, params.TestChainConfig, gasLimit)
t.Cleanup(func() {
b.Close()
})
t.Cleanup(b.Close)
//if b.m.HistoryV3 {
// t.Skip("TODO: Fixme")
//}
Expand All @@ -123,9 +121,7 @@ func NewSimulatedBackend(t *testing.T, alloc types.GenesisAlloc, gasLimit uint64

func NewTestSimulatedBackendWithConfig(t *testing.T, alloc types.GenesisAlloc, config *chain.Config, gasLimit uint64) *SimulatedBackend {
b := NewSimulatedBackendWithConfig(alloc, config, gasLimit)
t.Cleanup(func() {
b.Close()
})
t.Cleanup(b.Close)
//if b.m.HistoryV3 {
// t.Skip("TODO: Fixme")
//}
Expand All @@ -141,6 +137,9 @@ func (b *SimulatedBackend) Engine() consensus.Engine { return b.m.Engine }

// Close terminates the underlying blockchain's update loop.
func (b *SimulatedBackend) Close() {
if b.pendingReaderTx != nil {
b.pendingReaderTx.Rollback()
}
b.m.Close()
}

Expand Down Expand Up @@ -194,7 +193,15 @@ func (b *SimulatedBackend) emptyPendingBlock() {
defer agg.StartUnbufferedWrites().FinishWrites()
*/
}
b.pendingReader = state.NewPlainStateReader(olddb.NewObjectDatabase(b.m.DB))
if b.pendingReaderTx != nil {
b.pendingReaderTx.Rollback()
}
tx, err := b.m.DB.BeginRo(context.Background())
if err != nil {
panic(err)
}
b.pendingReaderTx = tx
b.pendingReader = state.NewPlainStateReader(b.pendingReaderTx)
b.pendingState = state.New(b.pendingReader)
}

Expand Down
13 changes: 10 additions & 3 deletions consensus/clique/snapshot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,21 @@ package clique_test

import (
"bytes"
"context"
"crypto/ecdsa"
"sort"
"testing"

"github.com/ledgerwatch/erigon-lib/chain"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon-lib/common/length"
"github.com/ledgerwatch/erigon-lib/kv"
"github.com/ledgerwatch/erigon-lib/kv/memdb"
"github.com/ledgerwatch/erigon/consensus/clique"
"github.com/ledgerwatch/erigon/core"
"github.com/ledgerwatch/erigon/core/types"
"github.com/ledgerwatch/erigon/crypto"
"github.com/ledgerwatch/erigon/eth/stagedsync"
"github.com/ledgerwatch/erigon/ethdb/olddb"
"github.com/ledgerwatch/erigon/params"
"github.com/ledgerwatch/erigon/turbo/stages"
)
Expand Down Expand Up @@ -504,8 +505,14 @@ func TestClique(t *testing.T) {
// No failure was produced or requested, generate the final voting snapshot
head := chain.Blocks[len(chain.Blocks)-1]

snap, err := engine.Snapshot(stagedsync.ChainReader{Cfg: config, Db: olddb.NewObjectDatabase(m.DB)}, head.NumberU64(), head.Hash(), nil)
if err != nil {
var snap *clique.Snapshot
if err := m.DB.View(context.Background(), func(tx kv.Tx) error {
snap, err = engine.Snapshot(stagedsync.ChainReader{Cfg: config, Db: tx}, head.NumberU64(), head.Hash(), nil)
if err != nil {
return err
}
return nil
}); err != nil {
t.Errorf("test %d: failed to retrieve voting snapshot %d(%s): %v",
i, head.NumberU64(), head.Hash().Hex(), err)
engine.Close()
Expand Down
55 changes: 32 additions & 23 deletions core/block_validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@
package core_test

import (
"context"
"testing"

"github.com/ledgerwatch/erigon-lib/kv"
"github.com/ledgerwatch/erigon/consensus/ethash"
"github.com/ledgerwatch/erigon/core"
"github.com/ledgerwatch/erigon/core/types"
"github.com/ledgerwatch/erigon/eth/stagedsync"
"github.com/ledgerwatch/erigon/ethdb/olddb"
"github.com/ledgerwatch/erigon/params"
"github.com/ledgerwatch/erigon/turbo/stages"
)
Expand All @@ -44,19 +45,23 @@ func TestHeaderVerification(t *testing.T) {

// Run the header checker for blocks one-by-one, checking for both valid and invalid nonces
for i := 0; i < chain.Length(); i++ {
for j, valid := range []bool{true, false} {
if valid {
engine := ethash.NewFaker()
err = engine.VerifyHeader(stagedsync.ChainReader{Cfg: *params.TestChainConfig, Db: olddb.NewObjectDatabase(m.DB)}, chain.Headers[i], true)
} else {
engine := ethash.NewFakeFailer(chain.Headers[i].Number.Uint64())
err = engine.VerifyHeader(stagedsync.ChainReader{Cfg: *params.TestChainConfig, Db: olddb.NewObjectDatabase(m.DB)}, chain.Headers[i], true)
}
if (err == nil) != valid {
t.Errorf("test %d.%d: validity mismatch: have %v, want %v", i, j, err, valid)
if err := m.DB.View(context.Background(), func(tx kv.Tx) error {
for j, valid := range []bool{true, false} {
if valid {
engine := ethash.NewFaker()
err = engine.VerifyHeader(stagedsync.ChainReader{Cfg: *params.TestChainConfig, Db: tx}, chain.Headers[i], true)
} else {
engine := ethash.NewFakeFailer(chain.Headers[i].Number.Uint64())
err = engine.VerifyHeader(stagedsync.ChainReader{Cfg: *params.TestChainConfig, Db: tx}, chain.Headers[i], true)
}
if (err == nil) != valid {
t.Errorf("test %d.%d: validity mismatch: have %v, want %v", i, j, err, valid)
}
}
return nil
}); err != nil {
panic(err)
}

if err = m.InsertChain(chain.Slice(i, i+1)); err != nil {
t.Fatalf("test %d: error inserting the block: %v", i, err)
}
Expand All @@ -81,19 +86,23 @@ func TestHeaderWithSealVerification(t *testing.T) {

// Run the header checker for blocks one-by-one, checking for both valid and invalid nonces
for i := 0; i < chain.Length(); i++ {
for j, valid := range []bool{true, false} {
if valid {
engine := ethash.NewFaker()
err = engine.VerifyHeader(stagedsync.ChainReader{Cfg: *params.TestChainAuraConfig, Db: olddb.NewObjectDatabase(m.DB)}, chain.Headers[i], true)
} else {
engine := ethash.NewFakeFailer(chain.Headers[i].Number.Uint64())
err = engine.VerifyHeader(stagedsync.ChainReader{Cfg: *params.TestChainAuraConfig, Db: olddb.NewObjectDatabase(m.DB)}, chain.Headers[i], true)
}
if (err == nil) != valid {
t.Errorf("test %d.%d: validity mismatch: have %v, want %v", i, j, err, valid)
if err := m.DB.View(context.Background(), func(tx kv.Tx) error {
for j, valid := range []bool{true, false} {
if valid {
engine := ethash.NewFaker()
err = engine.VerifyHeader(stagedsync.ChainReader{Cfg: *params.TestChainAuraConfig, Db: tx}, chain.Headers[i], true)
} else {
engine := ethash.NewFakeFailer(chain.Headers[i].Number.Uint64())
err = engine.VerifyHeader(stagedsync.ChainReader{Cfg: *params.TestChainAuraConfig, Db: tx}, chain.Headers[i], true)
}
if (err == nil) != valid {
t.Errorf("test %d.%d: validity mismatch: have %v, want %v", i, j, err, valid)
}
}
return nil
}); err != nil {
panic(err)
}

if err = m.InsertChain(chain.Slice(i, i+1)); err != nil {
t.Fatalf("test %d: error inserting the block: %v", i, err)
}
Expand Down
35 changes: 26 additions & 9 deletions core/vm/runtime/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,19 @@
package runtime

import (
"context"
"math"
"math/big"
"time"

"github.com/holiman/uint256"
"github.com/ledgerwatch/erigon-lib/chain"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon-lib/kv"
"github.com/ledgerwatch/erigon-lib/kv/memdb"
"github.com/ledgerwatch/erigon/core/state"
"github.com/ledgerwatch/erigon/core/vm"
"github.com/ledgerwatch/erigon/crypto"
"github.com/ledgerwatch/erigon/ethdb/olddb"
)

// Config is a basic type specifying certain configuration flags for running
Expand Down Expand Up @@ -112,11 +113,19 @@ func Execute(code, input []byte, cfg *Config, bn uint64) ([]byte, *state.IntraBl
}
setDefaults(cfg)

if cfg.State == nil {
db := olddb.NewObjectDatabase(memdb.New(""))
externalState := cfg.State != nil
var tx kv.RwTx
var err error
if !externalState {
db := memdb.New("")
defer db.Close()
cfg.r = state.NewDbStateReader(db)
cfg.w = state.NewDbStateWriter(db, 0)
tx, err = db.BeginRw(context.Background())
if err != nil {
return nil, nil, err
}
defer tx.Rollback()
cfg.r = state.NewPlainStateReader(tx)
cfg.w = state.NewPlainStateWriter(tx, tx, 0)
cfg.State = state.New(cfg.r)
}
var (
Expand Down Expand Up @@ -150,11 +159,19 @@ func Create(input []byte, cfg *Config, blockNr uint64) ([]byte, libcommon.Addres
}
setDefaults(cfg)

if cfg.State == nil {
db := olddb.NewObjectDatabase(memdb.New(""))
externalState := cfg.State != nil
var tx kv.RwTx
var err error
if !externalState {
db := memdb.New("")
defer db.Close()
cfg.r = state.NewDbStateReader(db)
cfg.w = state.NewDbStateWriter(db, 0)
tx, err = db.BeginRw(context.Background())
if err != nil {
return nil, [20]byte{}, 0, err
}
defer tx.Rollback()
cfg.r = state.NewPlainStateReader(tx)
cfg.w = state.NewPlainStateWriter(tx, tx, 0)
cfg.State = state.New(cfg.r)
}
var (
Expand Down
14 changes: 9 additions & 5 deletions core/vm/runtime/runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package runtime

import (
"context"
"fmt"
"math/big"
"os"
Expand All @@ -35,7 +36,6 @@ import (
"github.com/ledgerwatch/erigon/core/types"
"github.com/ledgerwatch/erigon/core/vm"
"github.com/ledgerwatch/erigon/eth/tracers/logger"
"github.com/ledgerwatch/erigon/ethdb/olddb"
)

func TestDefaults(t *testing.T) {
Expand Down Expand Up @@ -152,13 +152,17 @@ func BenchmarkCall(b *testing.B) {
b.Fatal(err)
}
cfg := &Config{}
db := olddb.NewObjectDatabase(memdb.New(""))
db := memdb.New("")
defer db.Close()
cfg.r = state.NewDbStateReader(db)
cfg.w = state.NewDbStateWriter(db, 0)
tx, err := db.BeginRw(context.Background())
if err != nil {
panic(err)
}
defer tx.Rollback()
cfg.r = state.NewPlainStateReader(tx)
cfg.w = state.NewPlainStateWriter(tx, tx, 0)
cfg.State = state.New(cfg.r)

cfg.State = state.New(cfg.r)
cfg.Debug = true
b.ResetTimer()
for i := 0; i < b.N; i++ {
Expand Down
34 changes: 21 additions & 13 deletions tests/statedb_chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package tests

import (
"context"
"math/big"
"testing"

Expand All @@ -25,8 +26,6 @@ import (
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/stretchr/testify/require"

"github.com/ledgerwatch/erigon/ethdb/olddb"

"github.com/ledgerwatch/erigon/accounts/abi/bind"
"github.com/ledgerwatch/erigon/accounts/abi/bind/backends"
"github.com/ledgerwatch/erigon/core"
Expand Down Expand Up @@ -61,8 +60,6 @@ func TestSelfDestructReceive(t *testing.T) {
)

m := stages.MockWithGenesis(t, gspec, key, false)
db := olddb.NewObjectDatabase(m.DB)
defer db.Close()

contractBackend := backends.NewTestSimulatedBackendWithConfig(t, gspec.Alloc, gspec.Config, gspec.GasLimit)
transactOpts, err := bind.NewKeyedTransactorWithChainID(key, m.ChainConfig.ChainID)
Expand All @@ -77,31 +74,37 @@ func TestSelfDestructReceive(t *testing.T) {
// The second block is empty and is only used to force the newly created blockchain object to reload the trie
// from the database.
chain, err := core.GenerateChain(m.ChainConfig, m.Genesis, m.Engine, m.DB, 2, func(i int, block *core.BlockGen) {
var tx types.Transaction
var txn types.Transaction

switch i {
case 0:
contractAddress, tx, selfDestructorContract, err = contracts.DeploySelfDestructor(transactOpts, contractBackend)
contractAddress, txn, selfDestructorContract, err = contracts.DeploySelfDestructor(transactOpts, contractBackend)
if err != nil {
t.Fatal(err)
}
block.AddTx(tx)
tx, err = selfDestructorContract.SelfDestruct(transactOpts)
block.AddTx(txn)
txn, err = selfDestructorContract.SelfDestruct(transactOpts)
if err != nil {
t.Fatal(err)
}
block.AddTx(tx)
block.AddTx(txn)
// Send 1 wei to contract after self-destruction
tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), contractAddress, uint256.NewInt(1000), 21000, uint256.NewInt(1), nil), *signer, key)
block.AddTx(tx)
txn, err = types.SignTx(types.NewTransaction(block.TxNonce(address), contractAddress, uint256.NewInt(1000), 21000, uint256.NewInt(1), nil), *signer, key)
block.AddTx(txn)
}
contractBackend.Commit()
}, false /* intermediateHashes */)
if err != nil {
t.Fatalf("generate blocks: %v", err)
}

st := state.New(state.NewPlainStateReader(db))
tx, err := m.DB.BeginRo(context.Background())
if err != nil {
panic(err)
}
defer tx.Rollback()

st := state.New(state.NewPlainStateReader(tx))
if !st.Exist(address) {
t.Error("expected account to exist")
}
Expand All @@ -122,7 +125,12 @@ func TestSelfDestructReceive(t *testing.T) {
// and that means that the state of the accounts written in the first block was correct.
// This test checks that the storage root of the account is properly set to the root of the empty tree

st = state.New(state.NewPlainStateReader(db))
tx, err = m.DB.BeginRo(context.Background())
if err != nil {
panic(err)
}
defer tx.Rollback()
st = state.New(state.NewPlainStateReader(tx))
if !st.Exist(address) {
t.Error("expected account to exist")
}
Expand Down

0 comments on commit 281a3a5

Please sign in to comment.