diff --git a/cmd/evm/runner.go b/cmd/evm/runner.go index b4de1651d6faa13d715a26637b08cd3453f4ef07..5efd30b65137ade7b469497e4855ecb88fcefc37 100644 --- a/cmd/evm/runner.go +++ b/cmd/evm/runner.go @@ -135,19 +135,22 @@ func runCmd(ctx *cli.Context) error { } else { debugLogger = vm.NewStructLogger(logconfig) } - db := kv.NewMemDatabase() + db := kv.NewMemKV() if ctx.GlobalString(GenesisFlag.Name) != "" { gen := readGenesis(ctx.GlobalString(GenesisFlag.Name)) - _, err := gen.Commit(db, false) - if err != nil { - return err - } + gen.MustCommit(db) genesisConfig = gen chainConfig = gen.Config } else { genesisConfig = new(core.Genesis) } - statedb = state.New(state.NewPlainStateReader(db)) + tx, err := db.BeginRw(context.Background()) + if err != nil { + return err + } + defer tx.Rollback() + + statedb = state.New(state.NewPlainStateReader(tx)) if ctx.GlobalString(SenderFlag.Name) != "" { sender = common.HexToAddress(ctx.GlobalString(SenderFlag.Name)) } @@ -281,11 +284,6 @@ func runCmd(ctx *cli.Context) error { fmt.Println("Could not commit state: ", err) os.Exit(1) } - tx, err1 := db.RwKV().BeginRo(context.Background()) - if err1 != nil { - return fmt.Errorf("transition cannot open tx: %v", err1) - } - defer tx.Rollback() fmt.Println(string(state.NewDumper(tx, 0).DefaultDump())) } diff --git a/cmd/rpctest/rpctest/account_range_verify.go b/cmd/rpctest/rpctest/account_range_verify.go index 476c1efe15fe8bbab0966ea8403bc23749eced25..c49c9a26a72b11bcdaf1b27120b67c5c3faef27e 100644 --- a/cmd/rpctest/rpctest/account_range_verify.go +++ b/cmd/rpctest/rpctest/account_range_verify.go @@ -33,8 +33,6 @@ func CompareAccountRange(erigonURL, gethURL, tmpDataDir, gethDataDir string, blo } resultsKV := kv.NewMDBX().Path(tmpDataDir).MustOpen() gethKV := kv.NewMDBX().Path(gethDataDir).MustOpen() - resultsDB := kv.NewObjectDatabase(resultsKV) - gethResultsDB := kv.NewObjectDatabase(gethKV) var client = &http.Client{ Timeout: time.Minute * 60, @@ -58,7 +56,7 @@ func CompareAccountRange(erigonURL, gethURL, tmpDataDir, gethDataDir string, blo Result state.IteratorDump `json:"result"` } - f := func(url string, db ethdb.Database) error { + f := func(url string, db ethdb.RwTx) error { i := uint64(0) reqGen := &RequestGenerator{ client: client, @@ -97,13 +95,17 @@ func CompareAccountRange(erigonURL, gethURL, tmpDataDir, gethDataDir string, blo next = ar.Result.Next } } - err = f(erigonURL, resultsDB) + err = resultsKV.Update(context.Background(), func(tx ethdb.RwTx) error { + return f(erigonURL, tx) + }) if err != nil { log.Fatal(err) } if !notRegenerateGethData { - err = f(gethURL, gethResultsDB) + err = gethKV.Update(context.Background(), func(tx ethdb.RwTx) error { + return f(erigonURL, tx) + }) if err != nil { log.Fatal(err) } diff --git a/common/etl/etl_test.go b/common/etl/etl_test.go index 55e786a52614771a18bff91b0dcdafe401a39106..2588501881dcdc1f11a5e84225c124c3e850edbd 100644 --- a/common/etl/etl_test.go +++ b/common/etl/etl_test.go @@ -2,7 +2,6 @@ package etl import ( "bytes" - "context" "fmt" "io" "os" @@ -132,19 +131,14 @@ func TestRAMDataProviders(t *testing.T) { func TestTransformRAMOnly(t *testing.T) { // test invariant when we only have one buffer and it fits into RAM (exactly 1 buffer) - db := kv.NewTestDB(t) - tx, err := db.Begin(context.Background(), ethdb.RW) - if err != nil { - t.Fatal(err) - } - defer tx.Rollback() + _, tx := kv.NewTestTx(t) sourceBucket := dbutils.Buckets[0] destBucket := dbutils.Buckets[1] generateTestData(t, tx, sourceBucket, 20) - err = Transform( + err := Transform( "logPrefix", - tx.(ethdb.HasTx).Tx().(ethdb.RwTx), + tx, sourceBucket, destBucket, "", // temp dir @@ -157,17 +151,12 @@ func TestTransformRAMOnly(t *testing.T) { } func TestEmptySourceBucket(t *testing.T) { - db := kv.NewTestDB(t) - tx, err := db.Begin(context.Background(), ethdb.RW) - if err != nil { - t.Fatal(err) - } - defer tx.Rollback() + _, tx := kv.NewTestTx(t) sourceBucket := dbutils.Buckets[0] destBucket := dbutils.Buckets[1] - err = Transform( + err := Transform( "logPrefix", - tx.(ethdb.HasTx).Tx().(ethdb.RwTx), + tx, sourceBucket, destBucket, "", // temp dir @@ -181,18 +170,13 @@ func TestEmptySourceBucket(t *testing.T) { func TestTransformExtractStartKey(t *testing.T) { // test invariant when we only have one buffer and it fits into RAM (exactly 1 buffer) - db := kv.NewTestDB(t) - tx, err := db.Begin(context.Background(), ethdb.RW) - if err != nil { - t.Fatal(err) - } - defer tx.Rollback() + _, tx := kv.NewTestTx(t) sourceBucket := dbutils.Buckets[0] destBucket := dbutils.Buckets[1] generateTestData(t, tx, sourceBucket, 10) - err = Transform( + err := Transform( "logPrefix", - tx.(ethdb.HasTx).Tx().(ethdb.RwTx), + tx, sourceBucket, destBucket, "", // temp dir @@ -206,18 +190,13 @@ func TestTransformExtractStartKey(t *testing.T) { func TestTransformThroughFiles(t *testing.T) { // test invariant when we go through files (> 1 buffer) - db := kv.NewTestDB(t) - tx, err := db.Begin(context.Background(), ethdb.RW) - if err != nil { - t.Fatal(err) - } - defer tx.Rollback() + _, tx := kv.NewTestTx(t) sourceBucket := dbutils.Buckets[0] destBucket := dbutils.Buckets[1] generateTestData(t, tx, sourceBucket, 10) - err = Transform( + err := Transform( "logPrefix", - tx.(ethdb.HasTx).Tx().(ethdb.RwTx), + tx, sourceBucket, destBucket, "", // temp dir @@ -233,18 +212,13 @@ func TestTransformThroughFiles(t *testing.T) { func TestTransformDoubleOnExtract(t *testing.T) { // test invariant when extractFunc multiplies the data 2x - db := kv.NewTestDB(t) - tx, err := db.Begin(context.Background(), ethdb.RW) - if err != nil { - t.Fatal(err) - } - defer tx.Rollback() + _, tx := kv.NewTestTx(t) sourceBucket := dbutils.Buckets[0] destBucket := dbutils.Buckets[1] generateTestData(t, tx, sourceBucket, 10) - err = Transform( + err := Transform( "logPrefix", - tx.(ethdb.HasTx).Tx().(ethdb.RwTx), + tx, sourceBucket, destBucket, "", // temp dir @@ -258,18 +232,13 @@ func TestTransformDoubleOnExtract(t *testing.T) { func TestTransformDoubleOnLoad(t *testing.T) { // test invariant when loadFunc multiplies the data 2x - db := kv.NewTestDB(t) - tx, err := db.Begin(context.Background(), ethdb.RW) - if err != nil { - t.Fatal(err) - } - defer tx.Rollback() + _, tx := kv.NewTestTx(t) sourceBucket := dbutils.Buckets[0] destBucket := dbutils.Buckets[1] generateTestData(t, tx, sourceBucket, 10) - err = Transform( + err := Transform( "logPrefix", - tx.(ethdb.HasTx).Tx().(ethdb.RwTx), + tx, sourceBucket, destBucket, "", // temp dir @@ -355,7 +324,7 @@ func testLoadFromMapDoubleFunc(k []byte, v []byte, _ CurrentTableReader, next Lo return next(k, append(k, 0xBB), append(realValue, 0xBB)) } -func compareBuckets(t *testing.T, db ethdb.Database, b1, b2 string, startKey []byte) { +func compareBuckets(t *testing.T, db ethdb.Tx, b1, b2 string, startKey []byte) { t.Helper() b1Map := make(map[string]string) err := db.ForEach(b1, startKey, func(k, v []byte) error { @@ -372,7 +341,7 @@ func compareBuckets(t *testing.T, db ethdb.Database, b1, b2 string, startKey []b assert.Equal(t, b1Map, b2Map) } -func compareBucketsDouble(t *testing.T, db ethdb.Database, b1, b2 string) { +func compareBucketsDouble(t *testing.T, db ethdb.Tx, b1, b2 string) { t.Helper() b1Map := make(map[string]string) err := db.ForEach(b1, nil, func(k, v []byte) error { diff --git a/core/state/database_test.go b/core/state/database_test.go index 913eb7c33c6d6cb82a3a4bbd5c624f0768296e3c..bf24e8349507b54f55768ee828a00427f585410d 100644 --- a/core/state/database_test.go +++ b/core/state/database_test.go @@ -20,11 +20,11 @@ import ( "bytes" "context" "errors" - "fmt" "math/big" "testing" "github.com/holiman/uint256" + "github.com/ledgerwatch/erigon/common/dbutils" "github.com/ledgerwatch/erigon/ethdb/kv" "github.com/ledgerwatch/erigon/turbo/stages" "github.com/ledgerwatch/erigon/turbo/trie" @@ -34,7 +34,6 @@ import ( "github.com/ledgerwatch/erigon/accounts/abi/bind" "github.com/ledgerwatch/erigon/accounts/abi/bind/backends" "github.com/ledgerwatch/erigon/common" - "github.com/ledgerwatch/erigon/common/dbutils" "github.com/ledgerwatch/erigon/core" "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/core/state" @@ -72,8 +71,6 @@ func TestCreate2Revive(t *testing.T) { ) m := stages.MockWithGenesis(t, gspec, key) - db := kv.NewObjectDatabase(m.DB) - defer db.Close() contractBackend := backends.NewSimulatedBackendWithConfig(gspec.Alloc, gspec.Config, gspec.GasLimit) defer contractBackend.Close() @@ -132,23 +129,31 @@ func TestCreate2Revive(t *testing.T) { t.Fatalf("generate blocks: %v", err) } - st := state.New(state.NewPlainStateReader(db)) - if !st.Exist(address) { - t.Error("expected account to exist") - } - if st.Exist(contractAddress) { - t.Error("expected contractAddress to not exist before block 0", contractAddress.String()) - } + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + st := state.New(state.NewPlainStateReader(tx)) + if !st.Exist(address) { + t.Error("expected account to exist") + } + if st.Exist(contractAddress) { + t.Error("expected contractAddress to not exist before block 0", contractAddress.String()) + } + return nil + }) + require.NoError(t, err) // BLOCK 1 if err = m.InsertChain(chain.Slice(0, 1)); err != nil { t.Fatal(err) } - st = state.New(state.NewPlainStateReader(db)) - if !st.Exist(contractAddress) { - t.Error("expected contractAddress to exist at the block 1", contractAddress.String()) - } + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + st := state.New(state.NewPlainStateReader(tx)) + if !st.Exist(contractAddress) { + t.Error("expected contractAddress to exist at the block 1", contractAddress.String()) + } + return nil + }) + require.NoError(t, err) // BLOCK 2 if err = m.InsertChain(chain.Slice(1, 2)); err != nil { @@ -165,26 +170,36 @@ func TestCreate2Revive(t *testing.T) { if it.Event.D != create2address { t.Errorf("Wrong create2address: %x, expected %x", it.Event.D, create2address) } - st = state.New(state.NewPlainStateReader(db)) - if !st.Exist(create2address) { - t.Error("expected create2address to exist at the block 2", create2address.String()) - } - // We expect number 0x42 in the position [2], because it is the block number 2 - key2 := common.BigToHash(big.NewInt(2)) + + var key2 common.Hash var check2 uint256.Int - st.GetState(create2address, &key2, &check2) - if check2.Uint64() != 0x42 { - t.Errorf("expected 0x42 in position 2, got: %x", check2.Uint64()) - } + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + st := state.New(state.NewPlainStateReader(tx)) + if !st.Exist(create2address) { + t.Error("expected create2address to exist at the block 2", create2address.String()) + } + // We expect number 0x42 in the position [2], because it is the block number 2 + key2 = common.BigToHash(big.NewInt(2)) + st.GetState(create2address, &key2, &check2) + if check2.Uint64() != 0x42 { + t.Errorf("expected 0x42 in position 2, got: %x", check2.Uint64()) + } + return nil + }) + require.NoError(t, err) // BLOCK 3 if err = m.InsertChain(chain.Slice(2, 3)); err != nil { t.Fatal(err) } - st = state.New(state.NewPlainStateReader(db)) - if st.Exist(create2address) { - t.Error("expected create2address to be self-destructed at the block 3", create2address.String()) - } + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + st := state.New(state.NewPlainStateReader(tx)) + if st.Exist(create2address) { + t.Error("expected create2address to be self-destructed at the block 3", create2address.String()) + } + return nil + }) + require.NoError(t, err) // BLOCK 4 if err = m.InsertChain(chain.Slice(3, 4)); err != nil { @@ -200,22 +215,27 @@ func TestCreate2Revive(t *testing.T) { if it.Event.D != create2address { t.Errorf("Wrong create2address: %x, expected %x", it.Event.D, create2address) } - st = state.New(state.NewPlainStateReader(db)) - if !st.Exist(create2address) { - t.Error("expected create2address to exist at the block 2", create2address.String()) - } - // We expect number 0x42 in the position [4], because it is the block number 4 - key4 := common.BigToHash(big.NewInt(4)) - var check4 uint256.Int - st.GetState(create2address, &key4, &check4) - if check4.Uint64() != 0x42 { - t.Errorf("expected 0x42 in position 4, got: %x", check4.Uint64()) - } - // We expect number 0x0 in the position [2], because it is the block number 4 - st.GetState(create2address, &key2, &check2) - if !check2.IsZero() { - t.Errorf("expected 0x0 in position 2, got: %x", check2) - } + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + st := state.New(state.NewPlainStateReader(tx)) + if !st.Exist(create2address) { + t.Error("expected create2address to exist at the block 2", create2address.String()) + } + // We expect number 0x42 in the position [4], because it is the block number 4 + key4 := common.BigToHash(big.NewInt(4)) + var check4 uint256.Int + st.GetState(create2address, &key4, &check4) + if check4.Uint64() != 0x42 { + t.Errorf("expected 0x42 in position 4, got: %x", check4.Uint64()) + } + // We expect number 0x0 in the position [2], because it is the block number 4 + st.GetState(create2address, &key2, &check2) + if !check2.IsZero() { + t.Errorf("expected 0x0 in position 2, got: %x", check2) + } + return nil + }) + require.NoError(t, err) + } // Polymorthic contracts via CREATE2 @@ -243,8 +263,6 @@ func TestCreate2Polymorth(t *testing.T) { signer = types.LatestSignerForChainID(nil) ) m := stages.MockWithGenesis(t, gspec, key) - db := kv.NewObjectDatabase(m.DB) - defer db.Close() contractBackend := backends.NewSimulatedBackendWithConfig(gspec.Alloc, gspec.Config, gspec.GasLimit) defer contractBackend.Close() @@ -337,23 +355,33 @@ func TestCreate2Polymorth(t *testing.T) { t.Fatalf("generate blocks: %v", err) } - st := state.New(state.NewPlainStateReader(db)) - if !st.Exist(address) { - t.Error("expected account to exist") - } - if st.Exist(contractAddress) { - t.Error("expected contractAddress to not exist before block 0", contractAddress.String()) - } + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + + st := state.New(state.NewPlainStateReader(tx)) + if !st.Exist(address) { + t.Error("expected account to exist") + } + if st.Exist(contractAddress) { + t.Error("expected contractAddress to not exist before block 0", contractAddress.String()) + } + return nil + }) + require.NoError(t, err) // BLOCK 1 if err = m.InsertChain(chain.Slice(0, 1)); err != nil { t.Fatal(err) } - st = state.New(state.NewPlainStateReader(db)) - if !st.Exist(contractAddress) { - t.Error("expected contractAddress to exist at the block 1", contractAddress.String()) - } + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + + st := state.New(state.NewPlainStateReader(tx)) + if !st.Exist(contractAddress) { + t.Error("expected contractAddress to exist at the block 1", contractAddress.String()) + } + return nil + }) + require.NoError(t, err) // BLOCK 2 if err = m.InsertChain(chain.Slice(1, 2)); err != nil { @@ -370,25 +398,33 @@ func TestCreate2Polymorth(t *testing.T) { if it.Event.D != create2address { t.Errorf("Wrong create2address: %x, expected %x", it.Event.D, create2address) } - st = state.New(state.NewPlainStateReader(db)) - if !st.Exist(create2address) { - t.Error("expected create2address to exist at the block 2", create2address.String()) - } - if !bytes.Equal(st.GetCode(create2address), common.FromHex("6002ff")) { - t.Errorf("Expected CREATE2 deployed code 6002ff, got %x", st.GetCode(create2address)) - } - if st.GetIncarnation(create2address) != 1 { - t.Errorf("expected incarnation 1, got %d", st.GetIncarnation(create2address)) - } + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + st := state.New(state.NewPlainStateReader(tx)) + if !st.Exist(create2address) { + t.Error("expected create2address to exist at the block 2", create2address.String()) + } + if !bytes.Equal(st.GetCode(create2address), common.FromHex("6002ff")) { + t.Errorf("Expected CREATE2 deployed code 6002ff, got %x", st.GetCode(create2address)) + } + if st.GetIncarnation(create2address) != 1 { + t.Errorf("expected incarnation 1, got %d", st.GetIncarnation(create2address)) + } + return nil + }) + require.NoError(t, err) // BLOCK 3 if err = m.InsertChain(chain.Slice(2, 3)); err != nil { t.Fatal(err) } - st = state.New(state.NewPlainStateReader(db)) - if st.Exist(create2address) { - t.Error("expected create2address to be self-destructed at the block 3", create2address.String()) - } + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + st := state.New(state.NewPlainStateReader(tx)) + if st.Exist(create2address) { + t.Error("expected create2address to be self-destructed at the block 3", create2address.String()) + } + return nil + }) + require.NoError(t, err) // BLOCK 4 if err = m.InsertChain(chain.Slice(3, 4)); err != nil { @@ -404,16 +440,21 @@ func TestCreate2Polymorth(t *testing.T) { if it.Event.D != create2address { t.Errorf("Wrong create2address: %x, expected %x", it.Event.D, create2address) } - st = state.New(state.NewPlainStateReader(db)) - if !st.Exist(create2address) { - t.Error("expected create2address to exist at the block 4", create2address.String()) - } - if !bytes.Equal(st.GetCode(create2address), common.FromHex("6004ff")) { - t.Errorf("Expected CREATE2 deployed code 6004ff, got %x", st.GetCode(create2address)) - } - if st.GetIncarnation(create2address) != 2 { - t.Errorf("expected incarnation 2, got %d", st.GetIncarnation(create2address)) - } + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + st := state.New(state.NewPlainStateReader(tx)) + if !st.Exist(create2address) { + t.Error("expected create2address to exist at the block 4", create2address.String()) + } + if !bytes.Equal(st.GetCode(create2address), common.FromHex("6004ff")) { + t.Errorf("Expected CREATE2 deployed code 6004ff, got %x", st.GetCode(create2address)) + } + if st.GetIncarnation(create2address) != 2 { + t.Errorf("expected incarnation 2, got %d", st.GetIncarnation(create2address)) + } + + return nil + }) + require.NoError(t, err) // BLOCK 5 if err = m.InsertChain(chain.Slice(4, 5)); err != nil { @@ -429,16 +470,21 @@ func TestCreate2Polymorth(t *testing.T) { if it.Event.D != create2address { t.Errorf("Wrong create2address: %x, expected %x", it.Event.D, create2address) } - st = state.New(state.NewPlainStateReader(db)) - if !st.Exist(create2address) { - t.Error("expected create2address to exist at the block 5", create2address.String()) - } - if !bytes.Equal(st.GetCode(create2address), common.FromHex("6005ff")) { - t.Errorf("Expected CREATE2 deployed code 6005ff, got %x", st.GetCode(create2address)) - } - if st.GetIncarnation(create2address) != 4 { - t.Errorf("expected incarnation 4 (two self-destructs and two-recreations within a block), got %d", st.GetIncarnation(create2address)) - } + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + st := state.New(state.NewPlainStateReader(tx)) + if !st.Exist(create2address) { + t.Error("expected create2address to exist at the block 5", create2address.String()) + } + if !bytes.Equal(st.GetCode(create2address), common.FromHex("6005ff")) { + t.Errorf("Expected CREATE2 deployed code 6005ff, got %x", st.GetCode(create2address)) + } + if st.GetIncarnation(create2address) != 4 { + t.Errorf("expected incarnation 4 (two self-destructs and two-recreations within a block), got %d", st.GetIncarnation(create2address)) + } + return nil + }) + require.NoError(t, err) + } func TestReorgOverSelfDestruct(t *testing.T) { @@ -464,8 +510,6 @@ func TestReorgOverSelfDestruct(t *testing.T) { ) m := stages.MockWithGenesis(t, gspec, key) - db := kv.NewObjectDatabase(m.DB) - defer db.Close() contractBackend := backends.NewSimulatedBackendWithConfig(gspec.Alloc, gspec.Config, gspec.GasLimit) defer contractBackend.Close() @@ -529,54 +573,68 @@ func TestReorgOverSelfDestruct(t *testing.T) { t.Fatalf("generate long blocks") } - st := state.New(state.NewPlainStateReader(db)) - if !st.Exist(address) { - t.Error("expected account to exist") - } - if st.Exist(contractAddress) { - t.Error("expected contractAddress to not exist before block 0", contractAddress.String()) - } + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + st := state.New(state.NewPlainStateReader(tx)) + if !st.Exist(address) { + t.Error("expected account to exist") + } + if st.Exist(contractAddress) { + t.Error("expected contractAddress to not exist before block 0", contractAddress.String()) + } + return nil + }) + require.NoError(t, err) // BLOCK 1 if err = m.InsertChain(chain.Slice(0, 1)); err != nil { t.Fatal(err) } - st = state.New(state.NewPlainStateReader(db)) - if !st.Exist(contractAddress) { - t.Error("expected contractAddress to exist at the block 1", contractAddress.String()) - } - - // Remember value of field "x" (storage item 0) after the first block, to check after rewinding var key0 common.Hash var correctValueX uint256.Int - st.GetState(contractAddress, &key0, &correctValueX) + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + st := state.New(state.NewPlainStateReader(tx)) + if !st.Exist(contractAddress) { + t.Error("expected contractAddress to exist at the block 1", contractAddress.String()) + } + + // Remember value of field "x" (storage item 0) after the first block, to check after rewinding + st.GetState(contractAddress, &key0, &correctValueX) + return nil + }) + require.NoError(t, err) // BLOCKS 2 + 3 if err = m.InsertChain(chain.Slice(1, chain.Length)); err != nil { t.Fatal(err) } - st = state.New(state.NewPlainStateReader(db)) - if st.Exist(contractAddress) { - t.Error("expected contractAddress to not exist at the block 3", contractAddress.String()) - } + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + st := state.New(state.NewPlainStateReader(tx)) + if st.Exist(contractAddress) { + t.Error("expected contractAddress to not exist at the block 3", contractAddress.String()) + } + return nil + }) + require.NoError(t, err) // REORG of block 2 and 3, and insert new (empty) BLOCK 2, 3, and 4 if err = m.InsertChain(longerChain.Slice(1, 4)); err != nil { t.Fatal(err) } - st = state.New(state.NewPlainStateReader(db)) - if !st.Exist(contractAddress) { - t.Error("expected contractAddress to exist at the block 4", contractAddress.String()) - } - - st = state.New(state.NewPlainStateReader(db)) - var valueX uint256.Int - st.GetState(contractAddress, &key0, &valueX) - if valueX != correctValueX { - t.Fatalf("storage value has changed after reorg: %x, expected %x", valueX, correctValueX) - } + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + st := state.New(state.NewPlainStateReader(tx)) + if !st.Exist(contractAddress) { + t.Error("expected contractAddress to exist at the block 4", contractAddress.String()) + } + var valueX uint256.Int + st.GetState(contractAddress, &key0, &valueX) + if valueX != correctValueX { + t.Fatalf("storage value has changed after reorg: %x, expected %x", valueX, correctValueX) + } + return nil + }) + require.NoError(t, err) } func TestReorgOverStateChange(t *testing.T) { @@ -602,8 +660,6 @@ func TestReorgOverStateChange(t *testing.T) { ) m := stages.MockWithGenesis(t, gspec, key) - db := kv.NewObjectDatabase(m.DB) - defer db.Close() contractBackend := backends.NewSimulatedBackendWithConfig(gspec.Alloc, gspec.Config, gspec.GasLimit) defer contractBackend.Close() @@ -660,28 +716,36 @@ func TestReorgOverStateChange(t *testing.T) { t.Fatalf("generate longer blocks: %v", err) } - st := state.New(state.NewPlainStateReader(db)) - if !st.Exist(address) { - t.Error("expected account to exist") - } - if st.Exist(contractAddress) { - t.Error("expected contractAddress to not exist before block 0", contractAddress.String()) - } + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + st := state.New(state.NewPlainStateReader(tx)) + if !st.Exist(address) { + t.Error("expected account to exist") + } + if st.Exist(contractAddress) { + t.Error("expected contractAddress to not exist before block 0", contractAddress.String()) + } + return nil + }) + require.NoError(t, err) // BLOCK 1 if err = m.InsertChain(chain.Slice(0, 1)); err != nil { t.Fatal(err) } - st = state.New(state.NewPlainStateReader(db)) - if !st.Exist(contractAddress) { - t.Error("expected contractAddress to exist at the block 1", contractAddress.String()) - } - - // Remember value of field "x" (storage item 0) after the first block, to check after rewinding var key0 common.Hash var correctValueX uint256.Int - st.GetState(contractAddress, &key0, &correctValueX) + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + st := state.New(state.NewPlainStateReader(tx)) + if !st.Exist(contractAddress) { + t.Error("expected contractAddress to exist at the block 1", contractAddress.String()) + } + + // Remember value of field "x" (storage item 0) after the first block, to check after rewinding + st.GetState(contractAddress, &key0, &correctValueX) + return nil + }) + require.NoError(t, err) // BLOCK 2 if err = m.InsertChain(chain.Slice(1, chain.Length)); err != nil { @@ -692,18 +756,22 @@ func TestReorgOverStateChange(t *testing.T) { if err = m.InsertChain(longerChain.Slice(1, 3)); err != nil { t.Fatal(err) } - st = state.New(state.NewPlainStateReader(db)) - if !st.Exist(contractAddress) { - t.Error("expected contractAddress to exist at the block 4", contractAddress.String()) - } + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + st := state.New(state.NewPlainStateReader(tx)) + if !st.Exist(contractAddress) { + t.Error("expected contractAddress to exist at the block 4", contractAddress.String()) + } + + // Reload blockchain from the database + var valueX uint256.Int + st.GetState(contractAddress, &key0, &valueX) + if valueX != correctValueX { + t.Fatalf("storage value has changed after reorg: %x, expected %x", valueX, correctValueX) + } + return nil + }) + require.NoError(t, err) - // Reload blockchain from the database - st = state.New(state.NewPlainStateReader(db)) - var valueX uint256.Int - st.GetState(contractAddress, &key0, &valueX) - if valueX != correctValueX { - t.Fatalf("storage value has changed after reorg: %x, expected %x", valueX, correctValueX) - } } type BucketsStats struct { @@ -746,8 +814,6 @@ func TestCreateOnExistingStorage(t *testing.T) { ) m := stages.MockWithGenesis(t, gspec, key) - db := kv.NewObjectDatabase(m.DB) - defer db.Close() var err error contractBackend := backends.NewSimulatedBackendWithConfig(gspec.Alloc, gspec.Config, gspec.GasLimit) @@ -760,6 +826,7 @@ func TestCreateOnExistingStorage(t *testing.T) { transactOpts.GasLimit = 1000000 var contractAddress common.Address + // There is one block, and it ends up deploying Revive contract (could be any other contract, it does not really matter) // On the address contractAddr, where there is a storage item in the genesis, but no contract code // We expect the pre-existing storage items to be removed by the deployment @@ -780,31 +847,38 @@ func TestCreateOnExistingStorage(t *testing.T) { t.Fatalf("generate blocks: %v", err) } - st := state.New(state.NewPlainStateReader(db)) - if !st.Exist(address) { - t.Error("expected account to exist") - } - if contractAddress != contractAddr { - t.Errorf("expected contract address to be %x, got: %x", contractAddr, contractAddress) - } + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + st := state.New(state.NewPlainStateReader(tx)) + if !st.Exist(address) { + t.Error("expected account to exist") + } + if contractAddress != contractAddr { + t.Errorf("expected contract address to be %x, got: %x", contractAddr, contractAddress) + } + return nil + }) + require.NoError(t, err) // BLOCK 1 if err = m.InsertChain(chain.Slice(0, 1)); err != nil { t.Fatal(err) } - st = state.New(state.NewPlainStateReader(db)) - if !st.Exist(contractAddress) { - t.Error("expected contractAddress to exist at the block 1", contractAddress.String()) - } - var key0 common.Hash var check0 uint256.Int - st.GetState(contractAddress, &key0, &check0) - fmt.Printf("c:%t,%x\n", check0.IsZero(), check0.Bytes()) - if !check0.IsZero() { - t.Errorf("expected 0x00 in position 0, got: %x", check0.Bytes()) - } + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + st := state.New(state.NewPlainStateReader(tx)) + if !st.Exist(contractAddress) { + t.Error("expected contractAddress to exist at the block 1", contractAddress.String()) + } + + st.GetState(contractAddress, &key0, &check0) + if !check0.IsZero() { + t.Errorf("expected 0x00 in position 0, got: %x", check0.Bytes()) + } + return nil + }) + require.NoError(t, err) } func TestReproduceCrash(t *testing.T) { @@ -821,9 +895,9 @@ func TestReproduceCrash(t *testing.T) { storageKey2 := common.HexToHash("0x0e4c0e7175f9d22279a4f63ff74f7fa28b7a954a6454debaa62ce43dd9132542") value2 := uint256.NewInt(0x58c00a51) - db := kv.NewTestDB(t) - tsw := state.NewPlainStateWriter(db, nil, 0) - intraBlockState := state.New(state.NewPlainStateReader(db)) + _, tx := kv.NewTestTx(t) + tsw := state.NewPlainStateWriter(tx, nil, 0) + intraBlockState := state.New(state.NewPlainKvState(tx, 0)) // Start the 1st transaction intraBlockState.CreateAccount(contract, true) if err := intraBlockState.FinalizeTx(params.Rules{}, tsw); err != nil { @@ -873,8 +947,6 @@ func TestEip2200Gas(t *testing.T) { ) m := stages.MockWithGenesis(t, gspec, key) - db := kv.NewObjectDatabase(m.DB) - defer db.Close() contractBackend := backends.NewSimulatedBackendWithConfig(gspec.Alloc, gspec.Config, gspec.GasLimit) defer contractBackend.Close() @@ -911,30 +983,39 @@ func TestEip2200Gas(t *testing.T) { t.Fatalf("generate blocks: %v", err) } - st := state.New(state.NewPlainStateReader(db)) - if !st.Exist(address) { - t.Error("expected account to exist") - } - if st.Exist(contractAddress) { - t.Error("expected contractAddress to not exist before block 0", contractAddress.String()) - } - balanceBefore := st.GetBalance(address) + var balanceBefore *uint256.Int + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + st := state.New(state.NewPlainStateReader(tx)) + if !st.Exist(address) { + t.Error("expected account to exist") + } + if st.Exist(contractAddress) { + t.Error("expected contractAddress to not exist before block 0", contractAddress.String()) + } + balanceBefore = st.GetBalance(address) + return nil + }) + require.NoError(t, err) // BLOCK 1 if err = m.InsertChain(chain.Slice(0, 1)); err != nil { t.Fatal(err) } - st = state.New(state.NewPlainStateReader(db)) - if !st.Exist(contractAddress) { - t.Error("expected contractAddress to exist at the block 1", contractAddress.String()) - } - balanceAfter := st.GetBalance(address) - gasSpent := big.NewInt(0).Sub(balanceBefore.ToBig(), balanceAfter.ToBig()) - expectedGasSpent := big.NewInt(190373) //(192245) // In the incorrect version, it is 179645 - if gasSpent.Cmp(expectedGasSpent) != 0 { - t.Errorf("Expected gas spent: %d, got %d", expectedGasSpent, gasSpent) - } + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + st := state.New(state.NewPlainStateReader(tx)) + if !st.Exist(contractAddress) { + t.Error("expected contractAddress to exist at the block 1", contractAddress.String()) + } + balanceAfter := st.GetBalance(address) + gasSpent := big.NewInt(0).Sub(balanceBefore.ToBig(), balanceAfter.ToBig()) + expectedGasSpent := big.NewInt(190373) //(192245) // In the incorrect version, it is 179645 + if gasSpent.Cmp(expectedGasSpent) != 0 { + t.Errorf("Expected gas spent: %d, got %d", expectedGasSpent, gasSpent) + } + return nil + }) + require.NoError(t, err) } //Create contract, drop trie, reload trie from disk and add block with contract call @@ -959,8 +1040,6 @@ func TestWrongIncarnation(t *testing.T) { ) m := stages.MockWithGenesis(t, gspec, key) - db := kv.NewObjectDatabase(m.DB) - defer db.Close() contractBackend := backends.NewSimulatedBackendWithConfig(gspec.Alloc, gspec.Config, gspec.GasLimit) defer contractBackend.Close() @@ -994,63 +1073,63 @@ func TestWrongIncarnation(t *testing.T) { t.Fatalf("generate blocks: %v", err) } - st := state.New(state.NewPlainStateReader(db)) - if !st.Exist(address) { - t.Error("expected account to exist") - } - if st.Exist(contractAddress) { - t.Error("expected contractAddress to not exist before block 0", contractAddress.String()) - } + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + st := state.New(state.NewPlainStateReader(tx)) + if !st.Exist(address) { + t.Error("expected account to exist") + } + if st.Exist(contractAddress) { + t.Error("expected contractAddress to not exist before block 0", contractAddress.String()) + } + return nil + }) + require.NoError(t, err) // BLOCK 1 if err = m.InsertChain(chain.Slice(0, 1)); err != nil { t.Fatal(err) } - addrHash := crypto.Keccak256(contractAddress[:]) var acc accounts.Account - ok, err := rawdb.ReadAccountDeprecated(db, common.BytesToHash(addrHash), &acc) - if err != nil { - t.Fatal(err) - } - if !ok { - t.Fatal(errors.New("acc not found")) - } + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + ok, err := rawdb.ReadAccount(tx, contractAddress, &acc) + if err != nil { + t.Fatal(err) + } + if !ok { + t.Fatal(errors.New("acc not found")) + } - if acc.Incarnation != state.FirstContractIncarnation { - t.Fatal("Incorrect incarnation", acc.Incarnation) - } + if acc.Incarnation != state.FirstContractIncarnation { + t.Fatal("Incorrect incarnation", acc.Incarnation) + } - st = state.New(state.NewPlainStateReader(db)) - if !st.Exist(contractAddress) { - t.Error("expected contractAddress to exist at the block 1", contractAddress.String()) - } + st := state.New(state.NewPlainStateReader(tx)) + if !st.Exist(contractAddress) { + t.Error("expected contractAddress to exist at the block 1", contractAddress.String()) + } + return nil + }) + require.NoError(t, err) // BLOCKS 2 if err = m.InsertChain(chain.Slice(1, 2)); err != nil { t.Fatal(err) } - addrHash = crypto.Keccak256(contractAddress[:]) - ok, err = rawdb.ReadAccountDeprecated(db, common.BytesToHash(addrHash), &acc) - if err != nil { - t.Fatal(err) - } - if !ok { - t.Fatal(errors.New("acc not found")) - } - if acc.Incarnation != state.FirstContractIncarnation { - t.Fatal("Incorrect incarnation", acc.Incarnation) - } - - var startKey [common.HashLength + 8 + common.HashLength]byte - copy(startKey[:], addrHash) - err = db.Walk(dbutils.HashedStorageBucket, startKey[:], 8*common.HashLength, func(k, v []byte) (bool, error) { - fmt.Printf("%x: %x\n", k, v) - return true, nil + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + ok, err := rawdb.ReadAccount(tx, contractAddress, &acc) + if err != nil { + t.Fatal(err) + } + if !ok { + t.Fatal(errors.New("acc not found")) + } + if acc.Incarnation != state.FirstContractIncarnation { + t.Fatal("Incorrect incarnation", acc.Incarnation) + } + return nil }) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) } //create acc, deploy to it contract, reorg to state without contract @@ -1078,8 +1157,6 @@ func TestWrongIncarnation2(t *testing.T) { knownContractAddress := common.HexToAddress("0xdb7d6ab1f17c6b31909ae466702703daef9269cf") m := stages.MockWithGenesis(t, gspec, key) - db := kv.NewObjectDatabase(m.DB) - defer db.Close() contractBackend := backends.NewSimulatedBackendWithConfig(gspec.Alloc, gspec.Config, gspec.GasLimit) defer contractBackend.Close() @@ -1145,10 +1222,14 @@ func TestWrongIncarnation2(t *testing.T) { t.Fatalf("generate longer blocks: %v", err) } - st := state.New(state.NewPlainStateReader(db)) - if !st.Exist(address) { - t.Error("expected account to exist") - } + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + st := state.New(state.NewPlainStateReader(tx)) + if !st.Exist(address) { + t.Error("expected account to exist") + } + return nil + }) + require.NoError(t, err) // BLOCK 1 if err = m.InsertChain(chain.Slice(0, 1)); err != nil { @@ -1160,38 +1241,45 @@ func TestWrongIncarnation2(t *testing.T) { t.Fatal(err) } - st = state.New(state.NewPlainStateReader(db)) - if !st.Exist(contractAddress) { - t.Error("expected contractAddress to exist at the block 1", contractAddress.String()) - } - - addrHash := crypto.Keccak256(contractAddress[:]) var acc accounts.Account - ok, err := rawdb.ReadAccountDeprecated(db, common.BytesToHash(addrHash), &acc) - if err != nil { - t.Fatal(err) - } - if !ok { - t.Fatal(errors.New("acc not found")) - } - if acc.Incarnation != state.FirstContractIncarnation { - t.Fatal("wrong incarnation") - } + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + st := state.New(state.NewPlainStateReader(tx)) + if !st.Exist(contractAddress) { + t.Error("expected contractAddress to exist at the block 1", contractAddress.String()) + } + + ok, err := rawdb.ReadAccount(tx, contractAddress, &acc) + if err != nil { + t.Fatal(err) + } + if !ok { + t.Fatal(errors.New("acc not found")) + } + if acc.Incarnation != state.FirstContractIncarnation { + t.Fatal("wrong incarnation") + } + return nil + }) + require.NoError(t, err) // REORG of block 2 and 3, and insert new (empty) BLOCK 2, 3, and 4 if err = m.InsertChain(longerChain.Slice(1, longerChain.Length)); err != nil { t.Fatal(err) } - ok, err = rawdb.ReadAccountDeprecated(db, common.BytesToHash(addrHash), &acc) - if err != nil { - t.Fatal(err) - } - if !ok { - t.Fatal(errors.New("acc not found")) - } - if acc.Incarnation != state.NonContractIncarnation { - t.Fatal("wrong incarnation", acc.Incarnation) - } + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + ok, err := rawdb.ReadAccount(tx, contractAddress, &acc) + if err != nil { + t.Fatal(err) + } + if !ok { + t.Fatal(errors.New("acc not found")) + } + if acc.Incarnation != state.NonContractIncarnation { + t.Fatal("wrong incarnation", acc.Incarnation) + } + return nil + }) + require.NoError(t, err) } @@ -1239,8 +1327,8 @@ func TestCacheCodeSizeSeparately(t *testing.T) { contract := common.HexToAddress("0x71dd1027069078091B3ca48093B00E4735B20624") //root := common.HexToHash("0xb939e5bcf5809adfb87ab07f0795b05b95a1d64a90f0eddd0c3123ac5b433854") - db := kv.NewTestDB(t) - r, w := state.NewPlainStateReader(db), state.NewPlainStateWriter(db, nil, 0) + _, tx := kv.NewTestTx(t) + r, w := state.NewPlainKvState(tx, 0), state.NewPlainStateWriter(tx, nil, 0) intraBlockState := state.New(r) // Start the 1st transaction intraBlockState.CreateAccount(contract, true) @@ -1272,10 +1360,9 @@ func TestCacheCodeSizeInTrie(t *testing.T) { contract := common.HexToAddress("0x71dd1027069078091B3ca48093B00E4735B20624") root := common.HexToHash("0xb939e5bcf5809adfb87ab07f0795b05b95a1d64a90f0eddd0c3123ac5b433854") - db := kv.NewTestDB(t) - r, w := state.NewPlainStateReader(db), state.NewPlainStateWriter(db, nil, 0) + _, tx := kv.NewTestTx(t) + r, w := state.NewPlainKvState(tx, 0), state.NewPlainStateWriter(tx, nil, 0) intraBlockState := state.New(r) - ctx := context.Background() // Start the 1st transaction intraBlockState.CreateAccount(contract, true) @@ -1290,32 +1377,24 @@ func TestCacheCodeSizeInTrie(t *testing.T) { t.Errorf("error committing block: %v", err) } - err := db.RwKV().View(ctx, func(tx ethdb.Tx) error { - r2, err := trie.CalcRoot("test", tx) - require.NoError(t, err) - require.Equal(t, root, r2) - return nil - }) + r2, err := trie.CalcRoot("test", tx) require.NoError(t, err) + require.Equal(t, root, r2) codeHash := common.BytesToHash(crypto.Keccak256(code)) codeSize, err := r.ReadAccountCodeSize(contract, 1, codeHash) assert.NoError(t, err, "you can receive the code size ") assert.Equal(t, len(code), codeSize, "you can receive the code size") - assert.NoError(t, db.Delete(dbutils.CodeBucket, codeHash[:], nil), nil) + assert.NoError(t, tx.Delete(dbutils.CodeBucket, codeHash[:], nil), nil) codeSize2, err := r.ReadAccountCodeSize(contract, 1, codeHash) assert.NoError(t, err, "you can still receive code size even with empty DB") assert.Equal(t, len(code), codeSize2, "code size should be received even with empty DB") - err = db.RwKV().View(ctx, func(tx ethdb.Tx) error { - r2, err := trie.CalcRoot("test", tx) - require.NoError(t, err) - require.Equal(t, root, r2) - return nil - }) + r2, err = trie.CalcRoot("test", tx) require.NoError(t, err) + require.Equal(t, root, r2) } func TestRecreateAndRewind(t *testing.T) { @@ -1333,8 +1412,6 @@ func TestRecreateAndRewind(t *testing.T) { ) m := stages.MockWithGenesis(t, gspec, key) - db := kv.NewObjectDatabase(m.DB) - defer db.Close() contractBackend := backends.NewSimulatedBackendWithConfig(gspec.Alloc, gspec.Config, gspec.GasLimit) defer contractBackend.Close() transactOpts := bind.NewKeyedTransactor(key) @@ -1466,45 +1543,57 @@ func TestRecreateAndRewind(t *testing.T) { t.Fatal(err) } - st := state.New(state.NewPlainStateReader(db)) - if !st.Exist(phoenixAddress) { - t.Errorf("expected phoenix %x to exist after first insert", phoenixAddress) - } - var key0 common.Hash var check0 uint256.Int - st.GetState(phoenixAddress, &key0, &check0) - if check0.Cmp(uint256.NewInt(2)) != 0 { - t.Errorf("expected 0x02 in position 0, got: 0x%x", check0.Bytes()) - } + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + st := state.New(state.NewPlainStateReader(tx)) + if !st.Exist(phoenixAddress) { + t.Errorf("expected phoenix %x to exist after first insert", phoenixAddress) + } + + st.GetState(phoenixAddress, &key0, &check0) + if check0.Cmp(uint256.NewInt(2)) != 0 { + t.Errorf("expected 0x02 in position 0, got: 0x%x", check0.Bytes()) + } + return nil + }) + require.NoError(t, err) // Block 3 and 4 if err = m.InsertChain(chain.Slice(2, chain.Length)); err != nil { t.Fatal(err) } + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { - st = state.New(state.NewPlainStateReader(db)) - if !st.Exist(phoenixAddress) { - t.Errorf("expected phoenix %x to exist after second insert", phoenixAddress) - } + st := state.New(state.NewPlainStateReader(tx)) + if !st.Exist(phoenixAddress) { + t.Errorf("expected phoenix %x to exist after second insert", phoenixAddress) + } - st.GetState(phoenixAddress, &key0, &check0) - if check0.Cmp(uint256.NewInt(1)) != 0 { - t.Errorf("expected 0x01 in position 0, got: 0x%x", check0.Bytes()) - } + st.GetState(phoenixAddress, &key0, &check0) + if check0.Cmp(uint256.NewInt(1)) != 0 { + t.Errorf("expected 0x01 in position 0, got: 0x%x", check0.Bytes()) + } + return nil + }) + require.NoError(t, err) // Reorg if err = m.InsertChain(longerChain); err != nil { t.Fatal(err) } + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + st := state.New(state.NewPlainStateReader(tx)) + if !st.Exist(phoenixAddress) { + t.Errorf("expected phoenix %x to exist after second insert", phoenixAddress) + } - st = state.New(state.NewPlainStateReader(db)) - if !st.Exist(phoenixAddress) { - t.Errorf("expected phoenix %x to exist after second insert", phoenixAddress) - } + st.GetState(phoenixAddress, &key0, &check0) + if check0.Cmp(uint256.NewInt(0)) != 0 { + t.Errorf("expected 0x00 in position 0, got: 0x%x", check0.Bytes()) + } + return nil + }) + require.NoError(t, err) - st.GetState(phoenixAddress, &key0, &check0) - if check0.Cmp(uint256.NewInt(0)) != 0 { - t.Errorf("expected 0x00 in position 0, got: 0x%x", check0.Bytes()) - } } diff --git a/core/state/intra_block_state_test.go b/core/state/intra_block_state_test.go index 0d3b859d370e5116b78efa061fbc80d8fbe33dcc..8d80affd3c11a96c41376298206e338fce03a100 100644 --- a/core/state/intra_block_state_test.go +++ b/core/state/intra_block_state_test.go @@ -18,6 +18,7 @@ package state import ( "bytes" + "context" "encoding/binary" "fmt" "math" @@ -225,10 +226,16 @@ func (test *snapshotTest) String() string { func (test *snapshotTest) run() bool { // Run all actions and create snapshots. - db := kv.NewMemDatabase() + db := kv.NewMemKV() defer db.Close() + tx, err := db.BeginRw(context.Background()) + if err != nil { + test.err = err + return false + } + defer tx.Rollback() var ( - ds = NewDbStateReader(db) + ds = NewPlainKvState(tx, 0) state = New(ds) snapshotRevs = make([]int, len(test.snapshots)) sindex = 0 @@ -243,7 +250,7 @@ func (test *snapshotTest) run() bool { // Revert all snapshots in reverse order. Each revert must yield a state // that is equivalent to fresh state with all actions up the snapshot applied. for sindex--; sindex >= 0; sindex-- { - checkds := NewDbStateReader(db) + checkds := NewPlainKvState(tx, 0) checkstate := New(checkds) for _, action := range test.actions[:test.snapshots[sindex]] { action.fn(action, checkstate) @@ -354,8 +361,8 @@ func TestAccessList(t *testing.T) { return common.HexToHash(a) } - db := kv.NewTestDB(t) - state := New(NewPlainStateReader(db)) + _, tx := kv.NewTestTx(t) + state := New(NewPlainKvState(tx, 0)) state.accessList = newAccessList() verifyAddrs := func(astrings ...string) { diff --git a/core/state/state_test.go b/core/state/state_test.go index 7a7df83f68d7f612e4f38d03c4579b2b99b75ea2..3c11e5b86112cdac1279ae29182831f6a0066642 100644 --- a/core/state/state_test.go +++ b/core/state/state_test.go @@ -35,8 +35,8 @@ import ( var toAddr = common.BytesToAddress type StateSuite struct { - db ethdb.Database - kv ethdb.RwKV // Same as db, but with a different interface + kv ethdb.RwKV + tx ethdb.RwTx state *IntraBlockState r StateReader w StateWriter @@ -102,14 +102,22 @@ func (s *StateSuite) TestDump(c *checker.C) { } func (s *StateSuite) SetUpTest(c *checker.C) { - db := kv.NewMemDatabase() - s.db = db - s.kv = db.RwKV() - s.r = NewDbStateReader(s.db) - s.w = NewDbStateWriter(s.db, 0) + s.kv = kv.NewMemKV() + tx, err := s.kv.BeginRw(context.Background()) + if err != nil { + panic(err) + } + s.tx = tx + s.r = NewPlainKvState(tx, 0) + s.w = NewPlainKvState(tx, 0) s.state = New(s.r) } +func (s *StateSuite) TearDownTest(c *checker.C) { + s.tx.Rollback() + s.kv.Close() +} + func (s *StateSuite) TestNull(c *checker.C) { address := common.HexToAddress("0x823140710bf13990e4500136726d8b55") s.state.CreateAccount(address, true) @@ -168,10 +176,9 @@ func (s *StateSuite) TestSnapshotEmpty(c *checker.C) { // use testing instead of checker because checker does not support // printing/logging in tests (-check.vv does not work) func TestSnapshot2(t *testing.T) { - - db := kv.NewMemDatabase() - w := NewDbStateWriter(db, 0) - state := New(NewDbStateReader(db)) + _, tx := kv.NewTestTx(t) + w := NewPlainKvState(tx, 0) + state := New(NewPlainKvState(tx, 0)) stateobjaddr0 := toAddr([]byte("so0")) stateobjaddr1 := toAddr([]byte("so1")) @@ -196,7 +203,7 @@ func TestSnapshot2(t *testing.T) { if err != nil { t.Fatal("error while finalizing transaction", err) } - w = NewDbStateWriter(db, 1) + w = NewPlainKvState(tx, 1) err = state.CommitBlock(params.Rules{}, w) if err != nil { diff --git a/core/vm/runtime/runtime_test.go b/core/vm/runtime/runtime_test.go index 627f2d7828ce57ebdfe18ddabd7b85519214b51c..375be3e84ca530d340b982cf15920af8f164c9b7 100644 --- a/core/vm/runtime/runtime_test.go +++ b/core/vm/runtime/runtime_test.go @@ -159,10 +159,9 @@ func BenchmarkCall(b *testing.B) { } } func benchmarkEVM_Create(bench *testing.B, code string) { - db := kv.NewMemDatabase() - defer db.Close() + _, tx := kv.NewTestTx(bench) var ( - statedb = state.New(state.NewPlainStateReader(db)) + statedb = state.New(state.NewPlainKvState(tx, 0)) sender = common.BytesToAddress([]byte("sender")) receiver = common.BytesToAddress([]byte("receiver")) ) @@ -330,9 +329,8 @@ func TestBlockhash(t *testing.T) { func benchmarkNonModifyingCode(gas uint64, code []byte, name string, b *testing.B) { //nolint:unparam cfg := new(Config) setDefaults(cfg) - db := kv.NewMemDatabase() - defer db.Close() - cfg.State = state.New(state.NewDbStateReader(db)) + _, tx := kv.NewTestTx(b) + cfg.State = state.New(state.NewPlainKvState(tx, 0)) cfg.GasLimit = gas var ( destination = common.BytesToAddress([]byte("contract")) diff --git a/eth/fetcher/block_fetcher_test.go b/eth/fetcher/block_fetcher_test.go index 13da00a43a3c9f5779a5245d199f6fe734ce4854..eb9d53f3b66d3ce0780f3bffdc56fc8f3739cd0f 100644 --- a/eth/fetcher/block_fetcher_test.go +++ b/eth/fetcher/block_fetcher_test.go @@ -36,10 +36,10 @@ import ( ) var ( - testdb = kv.NewMemDatabase() + testdb = kv.NewMemKV() testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") testAddress = crypto.PubkeyToAddress(testKey.PublicKey) - genesis = core.GenesisBlockForTesting(testdb.RwKV(), testAddress, big.NewInt(1000000000)) + genesis = core.GenesisBlockForTesting(testdb, testAddress, big.NewInt(1000000000)) unknownBlock = types.NewBlock(&types.Header{GasLimit: params.GenesisGasLimit}, nil, nil, nil) ) diff --git a/eth/stagedsync/stage_indexes_test.go b/eth/stagedsync/stage_indexes_test.go index bad6f56566ea189cbef2657bab996c65dd7041e4..e23e5ee1fb9feac1de3e10b205e1fa3bc33ed841 100644 --- a/eth/stagedsync/stage_indexes_test.go +++ b/eth/stagedsync/stage_indexes_test.go @@ -25,10 +25,8 @@ import ( func TestIndexGenerator_GenerateIndex_SimpleCase(t *testing.T) { log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) - db := kv2.NewMemDatabase() - defer db.Close() - kv := db.RwKV() - cfg := StageHistoryCfg(db.RwKV(), t.TempDir()) + kv := kv2.NewTestKV(t) + cfg := StageHistoryCfg(kv, t.TempDir()) test := func(blocksNum int, csBucket string) func(t *testing.T) { return func(t *testing.T) { tx, err := kv.BeginRw(context.Background()) diff --git a/ethdb/kv/kv_mdbx.go b/ethdb/kv/kv_mdbx.go index 08716a4b45541070894d2f1171e339862786c189..d2f43f09d665b0d4040d8a7639de7b51183dcf0f 100644 --- a/ethdb/kv/kv_mdbx.go +++ b/ethdb/kv/kv_mdbx.go @@ -24,8 +24,6 @@ import ( "github.com/torquem-ch/mdbx-go/mdbx" ) -var _ DbCopier = &MdbxKV{} - const expectMdbxVersionMajor = 0 const expectMdbxVersionMinor = 10 const pageSize = 4 * 1024 @@ -306,11 +304,6 @@ type MdbxKV struct { txSize uint64 } -func (db *MdbxKV) NewDbWithTheSameParameters() *ObjectDatabase { - opts := db.opts - return NewObjectDatabase(NewMDBX().Set(opts).MustOpen()) -} - // Close closes db // All transactions must be closed before closing the database. func (db *MdbxKV) Close() { diff --git a/ethdb/kv/mutation.go b/ethdb/kv/mutation.go index fafa3261a164ddc761dd2032252e77f909114069..48702e85832de016e634a320559e5afc620fad1a 100644 --- a/ethdb/kv/mutation.go +++ b/ethdb/kv/mutation.go @@ -356,11 +356,6 @@ func (m *mutation) panicOnEmptyDB() { } } -func (m *mutation) MemCopy() ethdb.Database { - m.panicOnEmptyDB() - return m.db -} - func (m *mutation) SetRwKV(kv ethdb.RwKV) { m.db.(ethdb.HasRwKV).SetRwKV(kv) } diff --git a/ethdb/kv/object_db.go b/ethdb/kv/object_db.go index 6287c08039f61afb8c0d3395b917f5f193bca413..1851cfc9ea27a58df82f5816fa4cecc6b0870dfa 100644 --- a/ethdb/kv/object_db.go +++ b/ethdb/kv/object_db.go @@ -24,16 +24,11 @@ import ( "github.com/google/btree" "github.com/ledgerwatch/erigon/common" - "github.com/ledgerwatch/erigon/common/dbutils" "github.com/ledgerwatch/erigon/ethdb" "github.com/ledgerwatch/erigon/log" "github.com/torquem-ch/mdbx-go/mdbx" ) -type DbCopier interface { - NewDbWithTheSameParameters() *ObjectDatabase -} - // ObjectDatabase - is an object-style interface of DB accessing type ObjectDatabase struct { kv ethdb.RwKV @@ -288,48 +283,6 @@ func (db *ObjectDatabase) SetRwKV(kv ethdb.RwKV) { db.kv = kv } -func (db *ObjectDatabase) MemCopy() *ObjectDatabase { - var mem *ObjectDatabase - // Open the db and recover any potential corruptions - switch t := db.kv.(type) { - case DbCopier: - mem = t.NewDbWithTheSameParameters() - default: - panic(fmt.Sprintf("MemCopy is not implemented for type %T", t)) - } - - if err := db.kv.View(context.Background(), func(readTx ethdb.Tx) error { - for _, name := range dbutils.Buckets { - name := name - if err := mem.kv.Update(context.Background(), func(writeTx ethdb.RwTx) error { - newBucketToWrite, err := writeTx.RwCursor(name) - if err != nil { - return err - } - defer newBucketToWrite.Close() - readC, err := readTx.Cursor(name) - if err != nil { - return err - } - defer readC.Close() - return ethdb.ForEach(readC, func(k, v []byte) (bool, error) { - if err := newBucketToWrite.Put(common.CopyBytes(k), common.CopyBytes(v)); err != nil { - return false, err - } - return true, nil - }) - }); err != nil { - return err - } - } - return nil - }); err != nil { - panic(err) - } - - return mem -} - func (db *ObjectDatabase) NewBatch() ethdb.DbWithPendingMutations { m := &mutation{ db: db, diff --git a/migrations/migrations.go b/migrations/migrations.go index e398479e8f7705206206812b24bfacf4019fe816..e8081e580a9000e3f1556ad4d544cdb1a76f1b0d 100644 --- a/migrations/migrations.go +++ b/migrations/migrations.go @@ -248,7 +248,7 @@ func (m *Migrator) Apply(kv ethdb.RwKV, datadir string) error { return nil } -func MarshalMigrationPayload(db ethdb.Getter) ([]byte, error) { +func MarshalMigrationPayload(db ethdb.KVGetter) ([]byte, error) { s := map[string][]byte{} buf := bytes.NewBuffer(nil) diff --git a/migrations/migrations_test.go b/migrations/migrations_test.go index c31027b6bee1a75ef10549eb32e32b4841a6060e..191a2919f77821fe1bdc6c92fdf26c8d051434f9 100644 --- a/migrations/migrations_test.go +++ b/migrations/migrations_test.go @@ -169,12 +169,13 @@ func TestWhenNonFirstMigrationAlreadyApplied(t *testing.T) { } func TestMarshalStages(t *testing.T) { - require, db := require.New(t), kv.NewTestDB(t) + require := require.New(t) + _, tx := kv.NewTestTx(t) - err := stages.SaveStageProgress(db, stages.Execution, 42) + err := stages.SaveStageProgress(tx, stages.Execution, 42) require.NoError(err) - data, err := MarshalMigrationPayload(db) + data, err := MarshalMigrationPayload(tx) require.NoError(err) res, err := UnmarshalMigrationPayload(data) diff --git a/turbo/stages/blockchain_test.go b/turbo/stages/blockchain_test.go index 4c7c48825088c50d22f646afc0391910ed26be0c..f08b93ea548bd1f1be09907af2ce27290ef75518 100644 --- a/turbo/stages/blockchain_test.go +++ b/turbo/stages/blockchain_test.go @@ -364,8 +364,6 @@ func testBadHashes(t *testing.T) { t.Skip("to support this error in Erigon") // Create a pristine chain and database m := newCanonical(t, 0) - db := kv.NewObjectDatabase(m.DB) - defer db.Close() var err error // Create a chain, ban a hash and try to import @@ -1271,8 +1269,6 @@ func TestDeleteRecreateSlots(t *testing.T) { }, } m := stages.MockWithGenesis(t, gspec, key) - db := kv.NewObjectDatabase(m.DB) - defer db.Close() chain, err := core.GenerateChain(m.ChainConfig, m.Genesis, m.Engine, m.DB, 1, func(i int, b *core.BlockGen) { b.SetCoinbase(common.Address{1}) // One transaction to AA, to kill it @@ -1291,31 +1287,35 @@ func TestDeleteRecreateSlots(t *testing.T) { if err := m.InsertChain(chain); err != nil { t.Fatalf("failed to insert into chain: %v", err) } - statedb := state.New(state.NewDbStateReader(db)) + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + statedb := state.New(state.NewPlainKvState(tx, 1)) - // If all is correct, then slot 1 and 2 are zero - key1 := common.HexToHash("01") - var got uint256.Int - statedb.GetState(aa, &key1, &got) - if !got.IsZero() { - t.Errorf("got %d exp %d", got.Uint64(), 0) - } - key2 := common.HexToHash("02") - statedb.GetState(aa, &key2, &got) - if !got.IsZero() { - t.Errorf("got %d exp %d", got.Uint64(), 0) - } - // Also, 3 and 4 should be set - key3 := common.HexToHash("03") - statedb.GetState(aa, &key3, &got) - if got.Uint64() != 3 { - t.Errorf("got %d exp %d", got.Uint64(), 3) - } - key4 := common.HexToHash("04") - statedb.GetState(aa, &key4, &got) - if got.Uint64() != 4 { - t.Errorf("got %d exp %d", got.Uint64(), 4) - } + // If all is correct, then slot 1 and 2 are zero + key1 := common.HexToHash("01") + var got uint256.Int + statedb.GetState(aa, &key1, &got) + if !got.IsZero() { + t.Errorf("got %d exp %d", got.Uint64(), 0) + } + key2 := common.HexToHash("02") + statedb.GetState(aa, &key2, &got) + if !got.IsZero() { + t.Errorf("got %d exp %d", got.Uint64(), 0) + } + // Also, 3 and 4 should be set + key3 := common.HexToHash("03") + statedb.GetState(aa, &key3, &got) + if got.Uint64() != 3 { + t.Errorf("got %d exp %d", got.Uint64(), 3) + } + key4 := common.HexToHash("04") + statedb.GetState(aa, &key4, &got) + if got.Uint64() != 4 { + t.Errorf("got %d exp %d", got.Uint64(), 4) + } + return nil + }) + require.NoError(t, err) } // TestDeleteRecreateAccount tests a state-transition that contains deletion of a @@ -1353,8 +1353,6 @@ func TestDeleteRecreateAccount(t *testing.T) { }, } m := stages.MockWithGenesis(t, gspec, key) - db := kv.NewObjectDatabase(m.DB) - defer db.Close() chain, err := core.GenerateChain(m.ChainConfig, m.Genesis, m.Engine, m.DB, 1, func(i int, b *core.BlockGen) { b.SetCoinbase(common.Address{1}) @@ -1374,20 +1372,24 @@ func TestDeleteRecreateAccount(t *testing.T) { if err := m.InsertChain(chain); err != nil { t.Fatalf("failed to insert into chain: %v", err) } - statedb := state.New(state.NewDbStateReader(db)) + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + statedb := state.New(state.NewPlainKvState(tx, 1)) - // If all is correct, then both slots are zero - key1 := common.HexToHash("01") - var got uint256.Int - statedb.GetState(aa, &key1, &got) - if !got.IsZero() { - t.Errorf("got %x exp %x", got, 0) - } - key2 := common.HexToHash("02") - statedb.GetState(aa, &key2, &got) - if !got.IsZero() { - t.Errorf("got %x exp %x", got, 0) - } + // If all is correct, then both slots are zero + key1 := common.HexToHash("01") + var got uint256.Int + statedb.GetState(aa, &key1, &got) + if !got.IsZero() { + t.Errorf("got %x exp %x", got, 0) + } + key2 := common.HexToHash("02") + statedb.GetState(aa, &key2, &got) + if !got.IsZero() { + t.Errorf("got %x exp %x", got, 0) + } + return nil + }) + require.NoError(t, err) } // TestDeleteRecreateSlotsAcrossManyBlocks tests multiple state-transition that contains both deletion @@ -1664,8 +1666,6 @@ func TestInitThenFailCreateContract(t *testing.T) { }, } m := stages.MockWithGenesis(t, gspec, key) - db := kv.NewObjectDatabase(m.DB) - defer db.Close() nonce := uint64(0) chain, err := core.GenerateChain(m.ChainConfig, m.Genesis, m.Engine, m.DB, 4, func(i int, b *core.BlockGen) { @@ -1680,28 +1680,33 @@ func TestInitThenFailCreateContract(t *testing.T) { t.Fatalf("generate blocks: %v", err) } - // Import the canonical chain - statedb := state.New(state.NewPlainStateReader(db)) - if got, exp := statedb.GetBalance(aa), uint64(100000); got.Uint64() != exp { - t.Fatalf("Genesis err, got %v exp %v", got, exp) - } - // First block tries to create, but fails - { - block := chain.Blocks[0] - if err := m.InsertChain(chain.Slice(0, 1)); err != nil { - t.Fatalf("block %d: failed to insert into chain: %v", block.NumberU64(), err) - } - statedb = state.New(state.NewPlainStateReader(db)) + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + + // Import the canonical chain + statedb := state.New(state.NewPlainKvState(tx, 1)) if got, exp := statedb.GetBalance(aa), uint64(100000); got.Uint64() != exp { - t.Fatalf("block %d: got %v exp %v", block.NumberU64(), got, exp) + t.Fatalf("Genesis err, got %v exp %v", got, exp) } - } - // Import the rest of the blocks - for i, block := range chain.Blocks[1:] { - if err := m.InsertChain(chain.Slice(1+i, 2+i)); err != nil { - t.Fatalf("block %d: failed to insert into chain: %v", block.NumberU64(), err) + // First block tries to create, but fails + { + block := chain.Blocks[0] + if err := m.InsertChain(chain.Slice(0, 1)); err != nil { + t.Fatalf("block %d: failed to insert into chain: %v", block.NumberU64(), err) + } + statedb = state.New(state.NewPlainKvState(tx, 0)) + if got, exp := statedb.GetBalance(aa), uint64(100000); got.Uint64() != exp { + t.Fatalf("block %d: got %v exp %v", block.NumberU64(), got, exp) + } } - } + // Import the rest of the blocks + for i, block := range chain.Blocks[1:] { + if err := m.InsertChain(chain.Slice(1+i, 2+i)); err != nil { + t.Fatalf("block %d: failed to insert into chain: %v", block.NumberU64(), err) + } + } + return nil + }) + require.NoError(t, err) } // TestEIP2718Transition tests that an EIP-2718 transaction will be accepted @@ -1738,8 +1743,6 @@ func TestEIP2718Transition(t *testing.T) { } ) m := stages.MockWithGenesis(t, gspec, key) - db := kv.NewObjectDatabase(m.DB) - defer db.Close() chain, err := core.GenerateChain(m.ChainConfig, m.Genesis, m.Engine, m.DB, 1, func(i int, b *core.BlockGen) { b.SetCoinbase(common.Address{1}) @@ -1835,8 +1838,6 @@ func TestEIP1559Transition(t *testing.T) { signer = types.LatestSigner(gspec.Config) ) m := stages.MockWithGenesis(t, gspec, key1) - db := kv.NewObjectDatabase(m.DB) - defer db.Close() chain, err := core.GenerateChain(m.ChainConfig, m.Genesis, m.Engine, m.DB, 501, func(i int, b *core.BlockGen) { if i == 500 { @@ -1887,24 +1888,29 @@ func TestEIP1559Transition(t *testing.T) { t.Fatalf("incorrect amount of gas spent: expected %d, got %d", expectedGas, block.GasUsed()) } - statedb := state.New(state.NewPlainStateReader(db)) + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + statedb := state.New(state.NewPlainKvState(tx, 0)) - // 3: Ensure that miner received only the tx's tip. - actual := statedb.GetBalance(block.Coinbase()) - expected := new(uint256.Int).Add( - new(uint256.Int).SetUint64(block.GasUsed()*block.Transactions()[0].GetPrice().Uint64()), - ethash.ConstantinopleBlockReward, - ) - if actual.Cmp(expected) != 0 { - t.Fatalf("miner balance incorrect: expected %d, got %d", expected, actual) - } + // 3: Ensure that miner received only the tx's tip. + actual := statedb.GetBalance(block.Coinbase()) + expected := new(uint256.Int).Add( + new(uint256.Int).SetUint64(block.GasUsed()*block.Transactions()[0].GetPrice().Uint64()), + ethash.ConstantinopleBlockReward, + ) + if actual.Cmp(expected) != 0 { + t.Fatalf("miner balance incorrect: expected %d, got %d", expected, actual) + } - // 4: Ensure the tx sender paid for the gasUsed * (tip + block baseFee). - actual = new(uint256.Int).Sub(funds, statedb.GetBalance(addr1)) - expected = new(uint256.Int).SetUint64(block.GasUsed() * (block.Transactions()[0].GetPrice().Uint64() + block.BaseFee().Uint64())) - if actual.Cmp(expected) != 0 { - t.Fatalf("sender expenditure incorrect: expected %d, got %d", expected, actual) - } + // 4: Ensure the tx sender paid for the gasUsed * (tip + block baseFee). + actual = new(uint256.Int).Sub(funds, statedb.GetBalance(addr1)) + expected = new(uint256.Int).SetUint64(block.GasUsed() * (block.Transactions()[0].GetPrice().Uint64() + block.BaseFee().Uint64())) + if actual.Cmp(expected) != 0 { + t.Fatalf("sender expenditure incorrect: expected %d, got %d", expected, actual) + } + + return nil + }) + require.NoError(t, err) chain, err = core.GenerateChain(m.ChainConfig, block, m.Engine, m.DB, 1, func(i int, b *core.BlockGen) { b.SetCoinbase(common.Address{2}) @@ -1923,25 +1929,29 @@ func TestEIP1559Transition(t *testing.T) { } block = chain.Blocks[0] - statedb = state.New(state.NewPlainStateReader(db)) - effectiveTip := block.Transactions()[0].GetPrice().Uint64() - block.BaseFee().Uint64() - - // 6+5: Ensure that miner received only the tx's effective tip. - actual = statedb.GetBalance(block.Coinbase()) - expected = new(uint256.Int).Add( - new(uint256.Int).SetUint64(block.GasUsed()*effectiveTip), - ethash.ConstantinopleBlockReward, - ) - if actual.Cmp(expected) != 0 { - t.Fatalf("miner balance incorrect: expected %d, got %d", expected, actual) - } + err = m.DB.View(context.Background(), func(tx ethdb.Tx) error { + statedb := state.New(state.NewPlainKvState(tx, 0)) + effectiveTip := block.Transactions()[0].GetPrice().Uint64() - block.BaseFee().Uint64() + + // 6+5: Ensure that miner received only the tx's effective tip. + actual := statedb.GetBalance(block.Coinbase()) + expected := new(uint256.Int).Add( + new(uint256.Int).SetUint64(block.GasUsed()*effectiveTip), + ethash.ConstantinopleBlockReward, + ) + if actual.Cmp(expected) != 0 { + t.Fatalf("miner balance incorrect: expected %d, got %d", expected, actual) + } - // 4: Ensure the tx sender paid for the gasUsed * (effectiveTip + block baseFee). - actual = new(uint256.Int).Sub(funds, statedb.GetBalance(addr2)) - expected = new(uint256.Int).SetUint64(block.GasUsed() * (effectiveTip + block.BaseFee().Uint64())) - if actual.Cmp(expected) != 0 { - t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual) - } + // 4: Ensure the tx sender paid for the gasUsed * (effectiveTip + block baseFee). + actual = new(uint256.Int).Sub(funds, statedb.GetBalance(addr2)) + expected = new(uint256.Int).SetUint64(block.GasUsed() * (effectiveTip + block.BaseFee().Uint64())) + if actual.Cmp(expected) != 0 { + t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual) + } + return nil + }) + require.NoError(t, err) } func current(kv ethdb.RwKV) *types.Block { diff --git a/turbo/trie/structural_branch_test.go b/turbo/trie/structural_branch_test.go index 6f65055b3f5d9fb0ae4f3050d539858348c77d1a..c1e28d41b8c1f88509748f3306c80e1b7efbf88f 100644 --- a/turbo/trie/structural_branch_test.go +++ b/turbo/trie/structural_branch_test.go @@ -17,7 +17,6 @@ package trie_test import ( - "context" "fmt" "testing" @@ -31,7 +30,8 @@ import ( ) func TestIHCursor(t *testing.T) { - db, require := kv.NewTestDB(t), require.New(t) + _, tx := kv.NewTestTx(t) + require := require.New(t) hash := common.HexToHash(fmt.Sprintf("%064d", 0)) newV := make([]byte, 0, 1024) @@ -39,7 +39,7 @@ func TestIHCursor(t *testing.T) { k := common.FromHex(ks) integrity.AssertSubset(k, hasTree, hasState) integrity.AssertSubset(k, hasHash, hasState) - _ = db.Put(dbutils.TrieOfAccountsBucket, k, common.CopyBytes(trie.MarshalTrieNodeTyped(hasState, hasTree, hasHash, hashes, newV))) + _ = tx.Put(dbutils.TrieOfAccountsBucket, k, common.CopyBytes(trie.MarshalTrieNodeTyped(hasState, hasTree, hasHash, hashes, newV))) } put("00", 0b0000000000000010, 0b0000000000000000, 0b0000000000000010, []common.Hash{hash}) @@ -56,10 +56,6 @@ func TestIHCursor(t *testing.T) { put("05000f", 0b0000000000000001, 0b0000000000000000, 0b0000000000000001, []common.Hash{hash}) put("06", 0b0000000000000001, 0b0000000000000000, 0b0000000000000001, []common.Hash{hash}) - tx, err := db.RwKV().BeginRw(context.Background()) - require.NoError(err) - defer tx.Rollback() - integrity.Trie(tx, false, nil) cursor, err := tx.Cursor(dbutils.TrieOfAccountsBucket)