From f1f235fec31eab6f977230eaa9245ada90e1d361 Mon Sep 17 00:00:00 2001 From: Ilya Mikheev <54912776+JkLondon@users.noreply.github.com> Date: Sat, 1 Feb 2025 11:36:24 +0100 Subject: [PATCH] Serializing and Deserializing to V3 (#13390) closes #12480 --------- Co-authored-by: JkLondon Co-authored-by: alex.sharov --- core/state/rw_v3.go | 3 +- core/test/domains_restart_test.go | 9 +- erigon-lib/commitment/commitment.go | 28 ++-- erigon-lib/kv/kvcache/cache_test.go | 16 +- erigon-lib/state/aggregator_fuzz_test.go | 20 ++- erigon-lib/state/aggregator_test.go | 96 +++++++++--- erigon-lib/state/domain_shared.go | 16 +- erigon-lib/state/domain_shared_test.go | 19 ++- erigon-lib/state/domain_test.go | 18 ++- erigon-lib/state/squeeze_test.go | 11 +- erigon-lib/types/account.go | 126 --------------- erigon-lib/types/accounts/account.go | 36 +++++ .../types/accounts/account_benchmark_test.go | 25 ++- erigon-lib/types/accounts/account_test.go | 146 +++++++----------- txnprovider/txpool/pool_test.go | 117 +++++++++++--- txnprovider/txpool/senders.go | 51 +----- 16 files changed, 384 insertions(+), 353 deletions(-) delete mode 100644 erigon-lib/types/account.go diff --git a/core/state/rw_v3.go b/core/state/rw_v3.go index 80e8694ec3a..ef5c3f9af12 100644 --- a/core/state/rw_v3.go +++ b/core/state/rw_v3.go @@ -258,8 +258,7 @@ func (rs *StateV3) Unwind(ctx context.Context, tx kv.RwTx, blockUnwindTo, txUnwi var address common.Address copy(address[:], k) - newV := make([]byte, acc.EncodingLengthForStorage()) - acc.EncodeForStorage(newV) + newV := accounts.SerialiseV3(&acc) if accumulator != nil { accumulator.ChangeAccount(address, acc.Incarnation, newV) } diff --git a/core/test/domains_restart_test.go b/core/test/domains_restart_test.go index d5ae4a7f3dd..cb542d46b18 100644 --- a/core/test/domains_restart_test.go +++ b/core/test/domains_restart_test.go @@ -43,7 +43,6 @@ import ( "github.com/erigontech/erigon-lib/kv/temporal" "github.com/erigontech/erigon-lib/log/v3" "github.com/erigontech/erigon-lib/state" - types2 "github.com/erigontech/erigon-lib/types" "github.com/erigontech/erigon-lib/types/accounts" "github.com/erigontech/erigon/core" reset2 "github.com/erigontech/erigon/core/rawdb/rawdbreset" @@ -491,7 +490,13 @@ func TestCommit(t *testing.T) { require.NoError(t, err) defer domains.Close() - buf := types2.EncodeAccountBytesV3(0, uint256.NewInt(7), nil, 1) + acc := accounts.Account{ + Nonce: 0, + Balance: *uint256.NewInt(7), + CodeHash: libcommon.Hash{}, + Incarnation: 1, + } + buf := accounts.SerialiseV3(&acc) addr := libcommon.Hex2Bytes("8e5476fc5990638a4fb0b5fd3f61bb4b5c5f395e") loc := libcommon.Hex2Bytes("24f3a02dc65eda502dbf75919e795458413d3c45b38bb35b51235432707900ed") diff --git a/erigon-lib/commitment/commitment.go b/erigon-lib/commitment/commitment.go index ad6a5d183dd..a6a6d61d2af 100644 --- a/erigon-lib/commitment/commitment.go +++ b/erigon-lib/commitment/commitment.go @@ -22,6 +22,7 @@ import ( "encoding/binary" "errors" "fmt" + "github.com/erigontech/erigon-lib/types/accounts" "math/bits" "sort" "strings" @@ -34,12 +35,10 @@ import ( "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon-lib/common/cryptozerocopy" - "github.com/erigontech/erigon-lib/log/v3" - "github.com/erigontech/erigon-lib/metrics" - "github.com/erigontech/erigon-lib/types" - "github.com/erigontech/erigon-lib/common/length" "github.com/erigontech/erigon-lib/etl" + "github.com/erigontech/erigon-lib/log/v3" + "github.com/erigontech/erigon-lib/metrics" ) var ( @@ -1060,21 +1059,26 @@ func (t *Updates) TouchAccount(c *KeyUpdate, val []byte) { if c.update.Flags&DeleteUpdate != 0 { c.update.Flags = 0 // also could invert with ^ but 0 is just a reset } - nonce, balance, chash := types.DecodeAccountBytesV3(val) - if c.update.Nonce != nonce { - c.update.Nonce = nonce + + acc := accounts.Account{} + err := accounts.DeserialiseV3(&acc, val) + if err != nil { + panic(err) + } + if c.update.Nonce != acc.Nonce { + c.update.Nonce = acc.Nonce c.update.Flags |= NonceUpdate } - if !c.update.Balance.Eq(balance) { - c.update.Balance.Set(balance) + if !c.update.Balance.Eq(&acc.Balance) { + c.update.Balance.Set(&acc.Balance) c.update.Flags |= BalanceUpdate } - if !bytes.Equal(chash, c.update.CodeHash[:]) { - if len(chash) == 0 { + if !bytes.Equal(acc.CodeHash.Bytes(), c.update.CodeHash[:]) { + if len(acc.CodeHash.Bytes()) == 0 { copy(c.update.CodeHash[:], EmptyCodeHash) } else { c.update.Flags |= CodeUpdate - copy(c.update.CodeHash[:], chash) + copy(c.update.CodeHash[:], acc.CodeHash.Bytes()) } } } diff --git a/erigon-lib/kv/kvcache/cache_test.go b/erigon-lib/kv/kvcache/cache_test.go index 5915d95ca81..eb0cc41bb05 100644 --- a/erigon-lib/kv/kvcache/cache_test.go +++ b/erigon-lib/kv/kvcache/cache_test.go @@ -20,6 +20,7 @@ import ( "context" "encoding/binary" "fmt" + "github.com/erigontech/erigon-lib/types/accounts" "runtime" "sync" "sync/atomic" @@ -37,7 +38,6 @@ import ( "github.com/erigontech/erigon-lib/kv/temporal/temporaltest" "github.com/erigontech/erigon-lib/log/v3" "github.com/erigontech/erigon-lib/state" - "github.com/erigontech/erigon-lib/types" ) func TestEvictionInUnexpectedOrder(t *testing.T) { @@ -179,9 +179,17 @@ func TestAPI(t *testing.T) { c := New(DefaultCoherentConfig) k1, k2 := [20]byte{1}, [20]byte{2} db, _ := temporaltest.NewTestDB(t, datadir.New(t.TempDir())) - account1Enc := types.EncodeAccountBytesV3(1, uint256.NewInt(11), make([]byte, 32), 2) - account2Enc := types.EncodeAccountBytesV3(1, uint256.NewInt(11), make([]byte, 32), 3) - account4Enc := types.EncodeAccountBytesV3(1, uint256.NewInt(11), make([]byte, 32), 5) + acc := accounts.Account{ + Nonce: 1, + Balance: *uint256.NewInt(11), + CodeHash: common.Hash{}, + Incarnation: 2, + } + account1Enc := accounts.SerialiseV3(&acc) + acc.Incarnation = 3 + account2Enc := accounts.SerialiseV3(&acc) + acc.Incarnation = 5 + account4Enc := accounts.SerialiseV3(&acc) get := func(key [20]byte, expectTxnID uint64) (res [1]chan []byte) { diff --git a/erigon-lib/state/aggregator_fuzz_test.go b/erigon-lib/state/aggregator_fuzz_test.go index 659dbed084d..470aa21fe23 100644 --- a/erigon-lib/state/aggregator_fuzz_test.go +++ b/erigon-lib/state/aggregator_fuzz_test.go @@ -21,6 +21,7 @@ package state import ( "context" "encoding/binary" + "github.com/erigontech/erigon-lib/types/accounts" "testing" "time" @@ -31,7 +32,6 @@ import ( "github.com/erigontech/erigon-lib/kv" "github.com/erigontech/erigon-lib/kv/mdbx" "github.com/erigontech/erigon-lib/log/v3" - "github.com/erigontech/erigon-lib/types" "github.com/holiman/uint256" "github.com/stretchr/testify/require" @@ -96,8 +96,13 @@ func Fuzz_AggregatorV3_Merge(f *testing.F) { } for txNum := uint64(1); txNum <= txs; txNum++ { domains.SetTxNum(txNum) - - buf := types.EncodeAccountBytesV3(1, uint256.NewInt(0), nil, 0) + acc := accounts.Account{ + Nonce: 1, + Balance: *uint256.NewInt(0), + CodeHash: common.Hash{}, + Incarnation: 0, + } + buf := accounts.SerialiseV3(&acc) err = domains.DomainPut(kv.AccountsDomain, addrs[txNum].Bytes(), nil, buf, nil, 0) require.NoError(t, err) @@ -215,8 +220,13 @@ func Fuzz_AggregatorV3_MergeValTransform(f *testing.F) { } for txNum := uint64(1); txNum <= txs; txNum++ { domains.SetTxNum(txNum) - - buf := types.EncodeAccountBytesV3(1, uint256.NewInt(txNum*1e6), nil, 0) + acc := accounts.Account{ + Nonce: 1, + Balance: *uint256.NewInt(txNum * 1e6), + CodeHash: common.Hash{}, + Incarnation: 0, + } + buf := accounts.SerialiseV3(&acc) err = domains.DomainPut(kv.AccountsDomain, addrs[txNum].Bytes(), nil, buf, nil, 0) require.NoError(t, err) diff --git a/erigon-lib/state/aggregator_test.go b/erigon-lib/state/aggregator_test.go index 273d6a70fa5..f120961bad7 100644 --- a/erigon-lib/state/aggregator_test.go +++ b/erigon-lib/state/aggregator_test.go @@ -22,6 +22,7 @@ import ( "encoding/binary" "encoding/hex" "fmt" + "github.com/erigontech/erigon-lib/types/accounts" "math" "math/rand" "os" @@ -48,7 +49,6 @@ import ( "github.com/erigontech/erigon-lib/kv/stream" "github.com/erigontech/erigon-lib/log/v3" "github.com/erigontech/erigon-lib/seg" - "github.com/erigontech/erigon-lib/types" "github.com/holiman/uint256" "github.com/stretchr/testify/require" ) @@ -93,8 +93,13 @@ func TestAggregatorV3_Merge(t *testing.T) { n, err = rnd.Read(loc) require.NoError(t, err) require.EqualValues(t, length.Hash, n) - - buf := types.EncodeAccountBytesV3(1, uint256.NewInt(0), nil, 0) + acc := accounts.Account{ + Nonce: 1, + Balance: *uint256.NewInt(0), + CodeHash: common.Hash{}, + Incarnation: 0, + } + buf := accounts.SerialiseV3(&acc) err = domains.DomainPut(kv.AccountsDomain, addr, nil, buf, nil, 0) require.NoError(t, err) @@ -208,8 +213,13 @@ func TestAggregatorV3_MergeValTransform(t *testing.T) { n, err = rnd.Read(loc) require.NoError(t, err) require.EqualValues(t, length.Hash, n) - - buf := types.EncodeAccountBytesV3(1, uint256.NewInt(txNum*1e6), nil, 0) + acc := accounts.Account{ + Nonce: 1, + Balance: *uint256.NewInt(txNum * 1e6), + CodeHash: common.Hash{}, + Incarnation: 0, + } + buf := accounts.SerialiseV3(&acc) err = domains.DomainPut(kv.AccountsDomain, addr, nil, buf, nil, 0) require.NoError(t, err) @@ -335,8 +345,13 @@ func aggregatorV3_RestartOnDatadir(t *testing.T, rc runCfg) { require.NoError(t, err) require.EqualValues(t, length.Hash, n) //keys[txNum-1] = append(addr, loc...) - - buf := types.EncodeAccountBytesV3(1, uint256.NewInt(rnd.Uint64()), nil, 0) + acc := accounts.Account{ + Nonce: 1, + Balance: *uint256.NewInt(rnd.Uint64()), + CodeHash: common.Hash{}, + Incarnation: 0, + } + buf := accounts.SerialiseV3(&acc) err = domains.DomainPut(kv.AccountsDomain, addr, nil, buf, nil, 0) require.NoError(t, err) @@ -678,7 +693,13 @@ func generateSharedDomainsUpdatesForTx(t *testing.T, domains *SharedDomains, txN r := rnd.IntN(101) switch { case r <= 33: - buf := types.EncodeAccountBytesV3(txNum, uint256.NewInt(txNum*100_000), nil, 0) + acc := accounts.Account{ + Nonce: txNum, + Balance: *uint256.NewInt(txNum * 100_000), + CodeHash: common.Hash{}, + Incarnation: 0, + } + buf := accounts.SerialiseV3(&acc) prev, step, err := domains.GetLatest(kv.AccountsDomain, key) require.NoError(t, err) @@ -723,7 +744,13 @@ func generateSharedDomainsUpdatesForTx(t *testing.T, domains *SharedDomains, txN require.NoError(t, err) if prev == nil { usedKeys[string(key)] = struct{}{} - buf := types.EncodeAccountBytesV3(txNum, uint256.NewInt(txNum*100_000), nil, 0) + acc := accounts.Account{ + Nonce: txNum, + Balance: *uint256.NewInt(txNum * 100_000), + CodeHash: common.Hash{}, + Incarnation: 0, + } + buf := accounts.SerialiseV3(&acc) err = domains.DomainPut(kv.AccountsDomain, key, nil, buf, prev, step) require.NoError(t, err) } @@ -788,7 +815,13 @@ func TestAggregatorV3_RestartOnFiles(t *testing.T) { require.NoError(t, err) require.EqualValues(t, length.Hash, n) - buf := types.EncodeAccountBytesV3(txNum, uint256.NewInt(1000000000000), nil, 0) + acc := accounts.Account{ + Nonce: txNum, + Balance: *uint256.NewInt(1000000000000), + CodeHash: common.Hash{}, + Incarnation: 0, + } + buf := accounts.SerialiseV3(&acc) err = domains.DomainPut(kv.AccountsDomain, addr, nil, buf[:], nil, 0) require.NoError(t, err) @@ -853,9 +886,11 @@ func TestAggregatorV3_RestartOnFiles(t *testing.T) { //fmt.Printf("%x [%d/%d]", key, miss, i+1) // txnum starts from 1 continue } - nonce, _, _ := types.DecodeAccountBytesV3(stored) + acc := accounts.Account{} + err = accounts.DeserialiseV3(&acc, stored) + require.NoError(t, err) - require.EqualValues(t, i+1, int(nonce)) + require.EqualValues(t, i+1, int(acc.Nonce)) storedV, _, found, err := ac.GetLatest(kv.StorageDomain, key, newTx) require.NoError(t, err) @@ -929,7 +964,13 @@ func TestAggregatorV3_ReplaceCommittedKeys(t *testing.T) { require.EqualValues(t, length.Hash, n) keys[txNum-1] = append(addr, loc...) - buf := types.EncodeAccountBytesV3(1, uint256.NewInt(0), nil, 0) + acc := accounts.Account{ + Nonce: 1, + Balance: *uint256.NewInt(0), + CodeHash: common.Hash{}, + Incarnation: 0, + } + buf := accounts.SerialiseV3(&acc) err = domains.DomainPut(kv.AccountsDomain, addr, nil, buf, prev1, 0) require.NoError(t, err) @@ -1161,7 +1202,13 @@ func TestAggregatorV3_SharedDomains(t *testing.T) { } for j := 0; j < len(keys); j++ { - buf := types.EncodeAccountBytesV3(uint64(i), uint256.NewInt(uint64(i*100_000)), nil, 0) + acc := accounts.Account{ + Nonce: uint64(i), + Balance: *uint256.NewInt(uint64(i * 100_000)), + CodeHash: common.Hash{}, + Incarnation: 0, + } + buf := accounts.SerialiseV3(&acc) prev, step, err := domains.GetLatest(kv.AccountsDomain, keys[j]) require.NoError(t, err) @@ -1196,7 +1243,13 @@ func TestAggregatorV3_SharedDomains(t *testing.T) { domains.SetTxNum(uint64(i)) for j := 0; j < len(keys); j++ { - buf := types.EncodeAccountBytesV3(uint64(i), uint256.NewInt(uint64(i*100_000)), nil, 0) + acc := accounts.Account{ + Nonce: uint64(i), + Balance: *uint256.NewInt(uint64(i * 100_000)), + CodeHash: common.Hash{}, + Incarnation: 0, + } + buf := accounts.SerialiseV3(&acc) prev, step, _, err := mc.GetLatest(kv.AccountsDomain, keys[j], rwTx) require.NoError(t, err) @@ -1233,7 +1286,13 @@ func TestAggregatorV3_SharedDomains(t *testing.T) { domains.SetTxNum(uint64(i)) for j := 0; j < len(keys); j++ { - buf := types.EncodeAccountBytesV3(uint64(i), uint256.NewInt(uint64(i*100_000)), nil, 0) + acc := accounts.Account{ + Nonce: uint64(i), + Balance: *uint256.NewInt(uint64(i * 100_000)), + CodeHash: common.Hash{}, + Incarnation: 0, + } + buf := accounts.SerialiseV3(&acc) prev, step, _, err := mc.GetLatest(kv.AccountsDomain, keys[j], rwTx) require.NoError(t, err) @@ -1256,8 +1315,9 @@ func Test_helper_decodeAccountv3Bytes(t *testing.T) { input, err := hex.DecodeString("000114000101") require.NoError(t, err) - n, b, ch := types.DecodeAccountBytesV3(input) - fmt.Printf("input %x nonce %d balance %d codeHash %d\n", input, n, b.Uint64(), ch) + acc := accounts.Account{} + _ = accounts.DeserialiseV3(&acc, input) + fmt.Printf("input %x nonce %d balance %d codeHash %d\n", input, acc.Nonce, acc.Balance.Uint64(), acc.CodeHash.Bytes()) } func TestAggregator_RebuildCommitmentBasedOnFiles(t *testing.T) { diff --git a/erigon-lib/state/domain_shared.go b/erigon-lib/state/domain_shared.go index 6fece4d4b8b..b0578ab0290 100644 --- a/erigon-lib/state/domain_shared.go +++ b/erigon-lib/state/domain_shared.go @@ -23,6 +23,7 @@ import ( "encoding/binary" "encoding/hex" "fmt" + "github.com/erigontech/erigon-lib/types/accounts" "math" "path/filepath" "runtime" @@ -48,7 +49,6 @@ import ( "github.com/erigontech/erigon-lib/kv" "github.com/erigontech/erigon-lib/kv/order" "github.com/erigontech/erigon-lib/kv/rawdbv3" - "github.com/erigontech/erigon-lib/types" ) var ErrBehindCommitment = errors.New("behind commitment") @@ -1226,14 +1226,18 @@ func (sdc *SharedDomainsCommitmentContext) Account(plainKey []byte) (u *commitme u = &commitment.Update{CodeHash: commitment.EmptyCodeHashArray} if len(encAccount) > 0 { - nonce, balance, chash := types.DecodeAccountBytesV3(encAccount) + acc := accounts.Account{} + err = accounts.DeserialiseV3(&acc, encAccount) + if err != nil { + return nil, err + } u.Flags |= commitment.NonceUpdate - u.Nonce = nonce + u.Nonce = acc.Nonce u.Flags |= commitment.BalanceUpdate - u.Balance.Set(balance) - if len(chash) > 0 { + u.Balance.Set(&acc.Balance) + if len(acc.CodeHash.Bytes()) > 0 { u.Flags |= commitment.CodeUpdate - copy(u.CodeHash[:], chash) + copy(u.CodeHash[:], acc.CodeHash.Bytes()) } } if u.CodeHash == commitment.EmptyCodeHashArray { diff --git a/erigon-lib/state/domain_shared_test.go b/erigon-lib/state/domain_shared_test.go index 29018977b48..7fa9ea86e3a 100644 --- a/erigon-lib/state/domain_shared_test.go +++ b/erigon-lib/state/domain_shared_test.go @@ -20,6 +20,8 @@ import ( "context" "encoding/binary" "fmt" + "github.com/erigontech/erigon-lib/common" + accounts3 "github.com/erigontech/erigon-lib/types/accounts" "testing" "time" @@ -30,7 +32,6 @@ import ( "github.com/erigontech/erigon-lib/kv" "github.com/erigontech/erigon-lib/kv/rawdbv3" "github.com/erigontech/erigon-lib/log/v3" - "github.com/erigontech/erigon-lib/types" ) func TestSharedDomain_CommitmentKeyReplacement(t *testing.T) { @@ -155,7 +156,13 @@ Loop: for ; i < int(maxTx); i++ { domains.SetTxNum(uint64(i)) for accs := 0; accs < 256; accs++ { - v := types.EncodeAccountBytesV3(uint64(i), uint256.NewInt(uint64(i*10e6)+uint64(accs*10e2)), nil, 0) + acc := accounts3.Account{ + Nonce: uint64(i), + Balance: *uint256.NewInt(uint64(i*10e6) + uint64(accs*10e2)), + CodeHash: common.Hash{}, + Incarnation: 0, + } + v := accounts3.SerialiseV3(&acc) k0[0] = byte(accs) pv, step, err := domains.GetLatest(kv.AccountsDomain, k0) require.NoError(t, err) @@ -416,7 +423,13 @@ func TestSharedDomain_StorageIter(t *testing.T) { for ; i < int(maxTx); i++ { domains.SetTxNum(uint64(i)) for accs := 0; accs < accounts; accs++ { - v := types.EncodeAccountBytesV3(uint64(i), uint256.NewInt(uint64(i*10e6)+uint64(accs*10e2)), nil, 0) + acc := accounts3.Account{ + Nonce: uint64(i), + Balance: *uint256.NewInt(uint64(i*10e6) + uint64(accs*10e2)), + CodeHash: common.Hash{}, + Incarnation: 0, + } + v := accounts3.SerialiseV3(&acc) k0[0] = byte(accs) pv, step, err := domains.GetLatest(kv.AccountsDomain, k0) diff --git a/erigon-lib/state/domain_test.go b/erigon-lib/state/domain_test.go index aa3c4e4d1c3..aae504cdaef 100644 --- a/erigon-lib/state/domain_test.go +++ b/erigon-lib/state/domain_test.go @@ -22,6 +22,7 @@ import ( "encoding/binary" "encoding/hex" "fmt" + accounts3 "github.com/erigontech/erigon-lib/types/accounts" "io/fs" "math" randOld "math/rand" @@ -46,7 +47,6 @@ import ( "github.com/erigontech/erigon-lib/kv/stream" "github.com/erigontech/erigon-lib/log/v3" "github.com/erigontech/erigon-lib/seg" - "github.com/erigontech/erigon-lib/types" "github.com/holiman/uint256" "github.com/stretchr/testify/require" ) @@ -1184,7 +1184,13 @@ func TestDomainContext_getFromFiles(t *testing.T) { writer.SetTxNum(uint64(i)) for j := 0; j < len(keys); j++ { - buf := types.EncodeAccountBytesV3(uint64(i), uint256.NewInt(uint64(i*100_000)), nil, 0) + acc := accounts3.Account{ + Nonce: uint64(i), + Balance: *uint256.NewInt(uint64(i * 100_000)), + CodeHash: common.Hash{}, + Incarnation: 0, + } + buf := accounts3.SerialiseV3(&acc) err = writer.PutWithPrev(keys[j], nil, buf, prev, 0) require.NoError(t, err) @@ -1395,7 +1401,13 @@ func generateAccountUpdates(r *rndGen, totalTx, keyTxsLimit uint64) []upd { for i := uint64(0); i < keyTxsLimit; i++ { txNum := generateRandomTxNum(r, totalTx, usedTxNums) jitter := r.IntN(10e7) - value := types.EncodeAccountBytesV3(i, uint256.NewInt(i*10e4+uint64(jitter)), nil, 0) + acc := accounts3.Account{ + Nonce: i, + Balance: *uint256.NewInt(i*10e4 + uint64(jitter)), + CodeHash: common.Hash{}, + Incarnation: 0, + } + value := accounts3.SerialiseV3(&acc) updates = append(updates, upd{txNum: txNum, value: value}) usedTxNums[txNum] = true diff --git a/erigon-lib/state/squeeze_test.go b/erigon-lib/state/squeeze_test.go index c95dc881414..e5529f378d4 100644 --- a/erigon-lib/state/squeeze_test.go +++ b/erigon-lib/state/squeeze_test.go @@ -2,6 +2,8 @@ package state import ( "context" + "github.com/erigontech/erigon-lib/common" + accounts3 "github.com/erigontech/erigon-lib/types/accounts" "math" "testing" @@ -9,7 +11,6 @@ import ( "github.com/erigontech/erigon-lib/common/length" "github.com/erigontech/erigon-lib/kv" "github.com/erigontech/erigon-lib/log/v3" - "github.com/erigontech/erigon-lib/types" "github.com/holiman/uint256" "github.com/stretchr/testify/require" ) @@ -49,7 +50,13 @@ func testDbAggregatorWithFiles(tb testing.TB, cfg *testAggConfig) (kv.RwDB, *Agg domains.SetTxNum(uint64(i)) for j := 0; j < len(keys); j++ { - buf := types.EncodeAccountBytesV3(uint64(i), uint256.NewInt(uint64(i*100_000)), nil, 0) + acc := accounts3.Account{ + Nonce: uint64(i), + Balance: *uint256.NewInt(uint64(i * 100_000)), + CodeHash: common.Hash{}, + Incarnation: 0, + } + buf := accounts3.SerialiseV3(&acc) prev, step, err := domains.GetLatest(kv.AccountsDomain, keys[j]) require.NoError(tb, err) diff --git a/erigon-lib/types/account.go b/erigon-lib/types/account.go deleted file mode 100644 index cc194845d45..00000000000 --- a/erigon-lib/types/account.go +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2021 The Erigon Authors -// This file is part of Erigon. -// -// Erigon is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Erigon is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Erigon. If not, see . - -package types - -import ( - "fmt" - "math/bits" - - "github.com/holiman/uint256" - - "github.com/erigontech/erigon-lib/common" - "github.com/erigontech/erigon-lib/common/length" -) - -// TODO move to erigon/core/types/accounts once erigon-lib is further unpacked into erigon/ -func DecodeAccountBytesV3(enc []byte) (nonce uint64, balance *uint256.Int, hash []byte) { - if len(enc) == 0 { - return - } - pos := 0 - nonceBytes := int(enc[pos]) - balance = &uint256.Int{} - pos++ - if nonceBytes > 0 { - nonce = common.BytesToUint64(enc[pos : pos+nonceBytes]) - pos += nonceBytes - } - balanceBytes := int(enc[pos]) - pos++ - if balanceBytes > 0 { - balance.SetBytes(enc[pos : pos+balanceBytes]) - pos += balanceBytes - } - codeHashBytes := int(enc[pos]) - pos++ - if codeHashBytes == length.Hash { - hash = make([]byte, codeHashBytes) - copy(hash, enc[pos:pos+codeHashBytes]) - pos += codeHashBytes - } - if pos >= len(enc) { - panic(fmt.Errorf("deserialse2: %d >= %d ", pos, len(enc))) - } - return -} - -// TODO move to erigon/core/types/accounts once erigon-lib is further unpacked into erigon/ -func EncodeAccountBytesV3(nonce uint64, balance *uint256.Int, hash []byte, incarnation uint64) []byte { - l := 1 - if nonce > 0 { - l += common.BitLenToByteLen(bits.Len64(nonce)) - } - l++ - if !balance.IsZero() { - l += balance.ByteLen() - } - l++ - if len(hash) == length.Hash { - l += 32 - } - l++ - if incarnation > 0 { - l += common.BitLenToByteLen(bits.Len64(incarnation)) - } - value := make([]byte, l) - pos := 0 - - if nonce == 0 { - value[pos] = 0 - pos++ - } else { - nonceBytes := common.BitLenToByteLen(bits.Len64(nonce)) - value[pos] = byte(nonceBytes) - var nonce = nonce - for i := nonceBytes; i > 0; i-- { - value[pos+i] = byte(nonce) - nonce >>= 8 - } - pos += nonceBytes + 1 - } - if balance.IsZero() { - value[pos] = 0 - pos++ - } else { - balanceBytes := balance.ByteLen() - value[pos] = byte(balanceBytes) - pos++ - balance.WriteToSlice(value[pos : pos+balanceBytes]) - pos += balanceBytes - } - if len(hash) == 0 { - value[pos] = 0 - pos++ - } else { - value[pos] = 32 - pos++ - copy(value[pos:pos+32], hash) - pos += 32 - } - if incarnation == 0 { - value[pos] = 0 - } else { - incBytes := common.BitLenToByteLen(bits.Len64(incarnation)) - value[pos] = byte(incBytes) - var inc = incarnation - for i := incBytes; i > 0; i-- { - value[pos+i] = byte(inc) - inc >>= 8 - } - } - return value -} diff --git a/erigon-lib/types/accounts/account.go b/erigon-lib/types/accounts/account.go index 3ce4ec02023..61f4da233f6 100644 --- a/erigon-lib/types/accounts/account.go +++ b/erigon-lib/types/accounts/account.go @@ -791,3 +791,39 @@ func SerialiseV3To(a *Account, value []byte) { } } } + +// Decode the sender's balance and nonce from encoded byte-slice +func DecodeSender(enc []byte) (nonce uint64, balance uint256.Int, err error) { + if len(enc) == 0 { + return + } + + var fieldSet = enc[0] + var pos = 1 + + if fieldSet&1 > 0 { + decodeLength := int(enc[pos]) + + if len(enc) < pos+decodeLength+1 { + return nonce, balance, fmt.Errorf( + "malformed CBOR for Account.Nonce: %s, Length %d", + enc[pos+1:], decodeLength) + } + + nonce = libcommon.BytesToUint64(enc[pos+1 : pos+decodeLength+1]) + pos += decodeLength + 1 + } + + if fieldSet&2 > 0 { + decodeLength := int(enc[pos]) + + if len(enc) < pos+decodeLength+1 { + return nonce, balance, fmt.Errorf( + "malformed CBOR for Account.Nonce: %s, Length %d", + enc[pos+1:], decodeLength) + } + + (&balance).SetBytes(enc[pos+1 : pos+decodeLength+1]) + } + return +} diff --git a/erigon-lib/types/accounts/account_benchmark_test.go b/erigon-lib/types/accounts/account_benchmark_test.go index e749e7b84bb..4ed43cd9a71 100644 --- a/erigon-lib/types/accounts/account_benchmark_test.go +++ b/erigon-lib/types/accounts/account_benchmark_test.go @@ -175,10 +175,11 @@ func BenchmarkEncodingAccountForStorage(b *testing.B) { for _, test := range accountCases { test := test - buf := make([]byte, test.acc.EncodingLengthForStorage()) + //buf := make([]byte, test.acc.EncodingLengthForStorage()) b.Run(fmt.Sprint(test.name), func(b *testing.B) { for i := 0; i < b.N; i++ { - test.acc.EncodeForStorage(buf) + SerialiseV3(test.acc) + //test.acc.EncodeForStorage(buf) performance has degraded a bit because we are not using the same buf now } }) } @@ -286,17 +287,16 @@ func BenchmarkDecodingAccount(b *testing.B) { test := test b.Run(fmt.Sprint(test.name), func(b *testing.B) { for i := 0; i < b.N; i++ { + println(test.name, i, b.N) //TODO: it just stucks w/o that print b.StopTimer() test.acc.Nonce = uint64(i) test.acc.Balance.SetUint64(uint64(i)) - encodedAccount := make([]byte, test.acc.EncodingLengthForStorage()) - - test.acc.EncodeForStorage(encodedAccount) + encodedAccount := SerialiseV3(test.acc) b.StartTimer() var decodedAccount Account - if err := decodedAccount.DecodeForStorage(encodedAccount); err != nil { + if err := DeserialiseV3(&decodedAccount, encodedAccount); err != nil { b.Fatal("cant decode the account", err, encodedAccount) } @@ -314,7 +314,7 @@ func BenchmarkDecodingAccount(b *testing.B) { } } -func BenchmarkDecodingIncarnation(b *testing.B) { +func BenchmarkDecodingIncarnation(b *testing.B) { // V2 version of bench was a panic one accountCases := []struct { name string acc *Account @@ -354,25 +354,24 @@ func BenchmarkDecodingIncarnation(b *testing.B) { b.ResetTimer() for _, test := range accountCases { test := test - encodedAccount := make([]byte, test.acc.EncodingLengthForStorage()) b.Run(fmt.Sprint(test.name), func(b *testing.B) { for i := 0; i < b.N; i++ { + println(test.name, i, b.N) //TODO: it just stucks w/o that print b.StopTimer() test.acc.Nonce = uint64(i) test.acc.Balance.SetUint64(uint64(i)) - test.acc.EncodeForStorage(encodedAccount) + encodedAccount := SerialiseV3(test.acc) b.StartTimer() - if _, err := DecodeIncarnationFromStorage(encodedAccount); err != nil { + decodedAcc := Account{} + if err := DeserialiseV3(&decodedAcc, encodedAccount); err != nil { b.Fatal("can't decode the incarnation", err, encodedAccount) } - decodedIncarnation, _ := DecodeIncarnationFromStorage(encodedAccount) - b.StopTimer() - decodedIncarnations = append(decodedIncarnations, decodedIncarnation) + decodedIncarnations = append(decodedIncarnations, decodedAcc.Incarnation) b.StartTimer() } diff --git a/erigon-lib/types/accounts/account_test.go b/erigon-lib/types/accounts/account_test.go index 4f8d5087583..c039e8ea5f9 100644 --- a/erigon-lib/types/accounts/account_test.go +++ b/erigon-lib/types/accounts/account_test.go @@ -36,28 +36,28 @@ func TestEmptyAccount(t *testing.T) { Incarnation: 5, } - encodedAccount := make([]byte, a.EncodingLengthForStorage()) - a.EncodeForStorage(encodedAccount) + encodedAccount := SerialiseV3(&a) - var decodedAccount Account - if err := decodedAccount.DecodeForStorage(encodedAccount); err != nil { - t.Fatal("cant decode the account", err, encodedAccount) + decodedAcc := Account{} + if err := DeserialiseV3(&decodedAcc, encodedAccount); err != nil { + t.Fatal("Can't decode the incarnation", err, encodedAccount) } - isAccountsEqual(t, a, decodedAccount) + isIncarnationEqual(t, a.Incarnation, decodedAcc.Incarnation) } func TestEmptyAccount2(t *testing.T) { t.Parallel() - encodedAccount := Account{} + emptyAcc := Account{} - b := make([]byte, encodedAccount.EncodingLengthForStorage()) - encodedAccount.EncodeForStorage(b) + encodedAccount := SerialiseV3(&emptyAcc) - var decodedAccount Account - if err := decodedAccount.DecodeForStorage(b); err != nil { - t.Fatal("cant decode the account", err, encodedAccount) + decodedAcc := Account{} + if err := DeserialiseV3(&decodedAcc, encodedAccount); err != nil { + t.Fatal("Can't decode the incarnation", err, encodedAccount) } + + isIncarnationEqual(t, emptyAcc.Incarnation, decodedAcc.Incarnation) } // fails if run package tests @@ -66,13 +66,14 @@ func TestEmptyAccount_BufferStrangeBehaviour(t *testing.T) { t.Parallel() a := Account{} - encodedAccount := make([]byte, a.EncodingLengthForStorage()) - a.EncodeForStorage(encodedAccount) + encodedAccount := SerialiseV3(&a) - var decodedAccount Account - if err := decodedAccount.DecodeForStorage(encodedAccount); err != nil { - t.Fatal("cant decode the account", err, encodedAccount) + decodedAcc := Account{} + if err := DeserialiseV3(&decodedAcc, encodedAccount); err != nil { + t.Fatal("Can't decode the incarnation", err, encodedAccount) } + + isIncarnationEqual(t, a.Incarnation, decodedAcc.Incarnation) } func TestAccountEncodeWithCode(t *testing.T) { @@ -86,16 +87,14 @@ func TestAccountEncodeWithCode(t *testing.T) { Incarnation: 4, } - encodedLen := a.EncodingLengthForStorage() - encodedAccount := make([]byte, encodedLen) - a.EncodeForStorage(encodedAccount) + encodedAccount := SerialiseV3(&a) - var decodedAccount Account - if err := decodedAccount.DecodeForStorage(encodedAccount); err != nil { - t.Fatal("cant decode the account", err, encodedAccount) + decodedAcc := Account{} + if err := DeserialiseV3(&decodedAcc, encodedAccount); err != nil { + t.Fatal("Can't decode the incarnation", err, encodedAccount) } - isAccountsEqual(t, a, decodedAccount) + isIncarnationEqual(t, a.Incarnation, decodedAcc.Incarnation) } func TestAccountEncodeWithCodeWithStorageSizeHack(t *testing.T) { @@ -109,16 +108,14 @@ func TestAccountEncodeWithCodeWithStorageSizeHack(t *testing.T) { Incarnation: 5, } - encodedLen := a.EncodingLengthForStorage() - encodedAccount := make([]byte, encodedLen) - a.EncodeForStorage(encodedAccount) + encodedAccount := SerialiseV3(&a) - var decodedAccount Account - if err := decodedAccount.DecodeForStorage(encodedAccount); err != nil { - t.Fatal("cant decode the account", err, encodedAccount) + decodedAcc := Account{} + if err := DeserialiseV3(&decodedAcc, encodedAccount); err != nil { + t.Fatal("Can't decode the incarnation", err, encodedAccount) } - isAccountsEqual(t, a, decodedAccount) + isIncarnationEqual(t, a.Incarnation, decodedAcc.Incarnation) } func TestAccountEncodeWithoutCode(t *testing.T) { @@ -132,16 +129,14 @@ func TestAccountEncodeWithoutCode(t *testing.T) { Incarnation: 5, } - encodedLen := a.EncodingLengthForStorage() - encodedAccount := make([]byte, encodedLen) - a.EncodeForStorage(encodedAccount) + encodedAccount := SerialiseV3(&a) - var decodedAccount Account - if err := decodedAccount.DecodeForStorage(encodedAccount); err != nil { - t.Fatal("cant decode the account", err, encodedAccount) + decodedAcc := Account{} + if err := DeserialiseV3(&decodedAcc, encodedAccount); err != nil { + t.Fatal("Can't decode the incarnation", err, encodedAccount) } - isAccountsEqual(t, a, decodedAccount) + isIncarnationEqual(t, a.Incarnation, decodedAcc.Incarnation) } func TestEncodeAccountWithEmptyBalanceNonNilContractAndNotZeroIncarnation(t *testing.T) { @@ -154,16 +149,14 @@ func TestEncodeAccountWithEmptyBalanceNonNilContractAndNotZeroIncarnation(t *tes CodeHash: libcommon.HexToHash("123"), Incarnation: 1, } - encodedLen := a.EncodingLengthForStorage() - encodedAccount := make([]byte, encodedLen) - a.EncodeForStorage(encodedAccount) + encodedAccount := SerialiseV3(&a) - var decodedAccount Account - if err := decodedAccount.DecodeForStorage(encodedAccount); err != nil { - t.Fatal("cant decode the account", err, encodedAccount) + decodedAcc := Account{} + if err := DeserialiseV3(&decodedAcc, encodedAccount); err != nil { + t.Fatal("Can't decode the incarnation", err, encodedAccount) } - isAccountsEqual(t, a, decodedAccount) + isIncarnationEqual(t, a.Incarnation, decodedAcc.Incarnation) } func TestEncodeAccountWithEmptyBalanceAndNotZeroIncarnation(t *testing.T) { t.Parallel() @@ -173,13 +166,11 @@ func TestEncodeAccountWithEmptyBalanceAndNotZeroIncarnation(t *testing.T) { Balance: *uint256.NewInt(0), Incarnation: 1, } - encodedLen := a.EncodingLengthForStorage() - encodedAccount := make([]byte, encodedLen) - a.EncodeForStorage(encodedAccount) + encodedAccount := SerialiseV3(&a) - var decodedAccount Account - if err := decodedAccount.DecodeForStorage(encodedAccount); err != nil { - t.Fatal("cant decode the account", err, encodedAccount) + decodedAccount := Account{} + if err := DeserialiseV3(&decodedAccount, encodedAccount); err != nil { + t.Fatal("Can't decode the incarnation", err, encodedAccount) } if a.Incarnation != decodedAccount.Incarnation { @@ -226,38 +217,28 @@ func TestIncarnationForEmptyAccount(t *testing.T) { Incarnation: 4, } - encodedAccount := make([]byte, a.EncodingLengthForStorage()) - a.EncodeForStorage(encodedAccount) + encodedAccount := SerialiseV3(&a) - if _, err := DecodeIncarnationFromStorage(encodedAccount); err != nil { + decodedAcc := Account{} + if err := DeserialiseV3(&decodedAcc, encodedAccount); err != nil { t.Fatal("Can't decode the incarnation", err, encodedAccount) } - decodedIncarnation, err := DecodeIncarnationFromStorage(encodedAccount) - if err != nil { - t.Fatal("Can't decode the incarnation", err, encodedAccount) - } - - isIncarnationEqual(t, a.Incarnation, decodedIncarnation) + isIncarnationEqual(t, a.Incarnation, decodedAcc.Incarnation) } func TestEmptyIncarnationForEmptyAccount2(t *testing.T) { t.Parallel() a := Account{} - encodedAccount := make([]byte, a.EncodingLengthForStorage()) - a.EncodeForStorage(encodedAccount) - - if _, err := DecodeIncarnationFromStorage(encodedAccount); err != nil { - t.Fatal("Can't decode the incarnation", err, encodedAccount) - } + encodedAccount := SerialiseV3(&a) - decodedIncarnation, err := DecodeIncarnationFromStorage(encodedAccount) - if err != nil { + decodedAcc := Account{} + if err := DeserialiseV3(&decodedAcc, encodedAccount); err != nil { t.Fatal("Can't decode the incarnation", err, encodedAccount) } - isIncarnationEqual(t, a.Incarnation, decodedIncarnation) + isIncarnationEqual(t, a.Incarnation, decodedAcc.Incarnation) } @@ -272,20 +253,14 @@ func TestIncarnationWithNonEmptyAccount(t *testing.T) { Incarnation: 4, } - encodedAccount := make([]byte, a.EncodingLengthForStorage()) - a.EncodeForStorage(encodedAccount) + encodedAccount := SerialiseV3(&a) - if _, err := DecodeIncarnationFromStorage(encodedAccount); err != nil { + decodedAcc := Account{} + if err := DeserialiseV3(&decodedAcc, encodedAccount); err != nil { t.Fatal("Can't decode the incarnation", err, encodedAccount) } - decodedIncarnation, err := DecodeIncarnationFromStorage(encodedAccount) - if err != nil { - t.Fatal("Can't decode the incarnation", err, encodedAccount) - } - - isIncarnationEqual(t, a.Incarnation, decodedIncarnation) - + isIncarnationEqual(t, a.Incarnation, decodedAcc.Incarnation) } func TestIncarnationWithNoIncarnation(t *testing.T) { @@ -299,19 +274,14 @@ func TestIncarnationWithNoIncarnation(t *testing.T) { Incarnation: 0, } - encodedAccount := make([]byte, a.EncodingLengthForStorage()) - a.EncodeForStorage(encodedAccount) - - if _, err := DecodeIncarnationFromStorage(encodedAccount); err != nil { - t.Fatal("Can't decode the incarnation", err, encodedAccount) - } + encodedAccount := SerialiseV3(&a) - decodedIncarnation, err := DecodeIncarnationFromStorage(encodedAccount) - if err != nil { + decodedAcc := Account{} + if err := DeserialiseV3(&decodedAcc, encodedAccount); err != nil { t.Fatal("Can't decode the incarnation", err, encodedAccount) } - isIncarnationEqual(t, a.Incarnation, decodedIncarnation) + isIncarnationEqual(t, a.Incarnation, decodedAcc.Incarnation) } diff --git a/txnprovider/txpool/pool_test.go b/txnprovider/txpool/pool_test.go index b5c659cd53f..456e2da0b4c 100644 --- a/txnprovider/txpool/pool_test.go +++ b/txnprovider/txpool/pool_test.go @@ -20,6 +20,8 @@ import ( "bytes" "context" "fmt" + "github.com/erigontech/erigon-lib/state" + accounts3 "github.com/erigontech/erigon-lib/types/accounts" "math" "math/big" "testing" @@ -43,7 +45,6 @@ import ( "github.com/erigontech/erigon-lib/kv/temporal/temporaltest" "github.com/erigontech/erigon-lib/log/v3" "github.com/erigontech/erigon-lib/rlp" - types2 "github.com/erigontech/erigon-lib/types" "github.com/erigontech/erigon/core/types" "github.com/erigontech/erigon/core/types/typestest" "github.com/erigontech/erigon/params" @@ -76,7 +77,13 @@ func TestNonceFromAddress(t *testing.T) { } var addr [20]byte addr[0] = 1 - v := types2.EncodeAccountBytesV3(2, uint256.NewInt(1*common.Ether), make([]byte, 32), 1) + acc := accounts3.Account{ + Nonce: 2, + Balance: *uint256.NewInt(1 * common.Ether), + CodeHash: common.Hash{}, + Incarnation: 1, + } + v := accounts3.SerialiseV3(&acc) change.ChangeBatch[0].Changes = append(change.ChangeBatch[0].Changes, &remote.AccountChange{ Action: remote.Action_UPSERT, Address: gointerfaces.ConvertAddressToH160(addr), @@ -203,7 +210,13 @@ func TestMultipleAuthorizations(t *testing.T) { var addr1, addr2 [20]byte addr2[0] = 1 - v := types2.EncodeAccountBytesV3(0, uint256.NewInt(1*common.Ether), make([]byte, 32), 1) + acc := accounts3.Account{ + Nonce: 0, + Balance: *uint256.NewInt(1 * common.Ether), + CodeHash: common.Hash{}, + Incarnation: 1, + } + v := accounts3.SerialiseV3(&acc) change.ChangeBatch[0].Changes = append(change.ChangeBatch[0].Changes, &remote.AccountChange{ Action: remote.Action_UPSERT, Address: gointerfaces.ConvertAddressToH160(addr1), @@ -448,7 +461,13 @@ func TestReplaceWithHigherFee(t *testing.T) { } var addr [20]byte addr[0] = 1 - v := types2.EncodeAccountBytesV3(2, uint256.NewInt(1*common.Ether), make([]byte, 32), 1) + acc := accounts3.Account{ + Nonce: 2, + Balance: *uint256.NewInt(1 * common.Ether), + CodeHash: common.Hash{}, + Incarnation: 1, + } + v := accounts3.SerialiseV3(&acc) change.ChangeBatch[0].Changes = append(change.ChangeBatch[0].Changes, &remote.AccountChange{ Action: remote.Action_UPSERT, Address: gointerfaces.ConvertAddressToH160(addr), @@ -565,7 +584,13 @@ func TestReverseNonces(t *testing.T) { } var addr [20]byte addr[0] = 1 - v := types2.EncodeAccountBytesV3(2, uint256.NewInt(1*common.Ether), make([]byte, 32), 1) + acc := accounts3.Account{ + Nonce: 2, + Balance: *uint256.NewInt(1 * common.Ether), + CodeHash: common.Hash{}, + Incarnation: 1, + } + v := accounts3.SerialiseV3(&acc) change.ChangeBatch[0].Changes = append(change.ChangeBatch[0].Changes, &remote.AccountChange{ Action: remote.Action_UPSERT, Address: gointerfaces.ConvertAddressToH160(addr), @@ -689,7 +714,13 @@ func TestTxnPoke(t *testing.T) { } var addr [20]byte addr[0] = 1 - v := types2.EncodeAccountBytesV3(2, uint256.NewInt(1*common.Ether), make([]byte, 32), 1) + acc := accounts3.Account{ + Nonce: 2, + Balance: *uint256.NewInt(1 * common.Ether), + CodeHash: common.Hash{}, + Incarnation: 1, + } + v := accounts3.SerialiseV3(&acc) change.ChangeBatch[0].Changes = append(change.ChangeBatch[0].Changes, &remote.AccountChange{ Action: remote.Action_UPSERT, Address: gointerfaces.ConvertAddressToH160(addr), @@ -896,17 +927,22 @@ func TestShanghaiValidateTxn(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) - cache := &kvcache.DummyCache{} + tx, err := coreDB.BeginTemporalRw(ctx) + defer tx.Rollback() + asrt.NoError(err) + sd, err := state.NewSharedDomains(tx, logger) + asrt.NoError(err) + defer sd.Close() + cache := kvcache.NewDummy() pool, err := New(ctx, ch, nil, coreDB, cfg, cache, *u256.N1, shanghaiTime, nil /* agraBlock */, nil /* cancunTime */, nil, nil, nil, nil, func() {}, nil, logger, WithFeeCalculator(nil)) asrt.NoError(err) - tx, err := coreDB.BeginRw(ctx) - defer tx.Rollback() + + sndr := accounts3.Account{Nonce: 0, Balance: *uint256.NewInt(math.MaxUint64)} + sndrBytes := accounts3.SerialiseV3(&sndr) + err = sd.DomainPut(kv.AccountsDomain, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, nil, sndrBytes, nil, 0) asrt.NoError(err) - sndr := sender{nonce: 0, balance: *uint256.NewInt(math.MaxUint64)} - sndrBytes := make([]byte, EncodeSenderLengthForStorage(sndr.nonce, sndr.balance)) - EncodeSender(sndr.nonce, sndr.balance, sndrBytes) - err = tx.Put(kv.PlainState, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, sndrBytes) + err = sd.Flush(ctx, tx) asrt.NoError(err) txn := &TxnSlot{ @@ -961,7 +997,13 @@ func TestTooHighGasLimitTxnValidation(t *testing.T) { } var addr [20]byte addr[0] = 1 - v := types2.EncodeAccountBytesV3(2, uint256.NewInt(1*common.Ether), make([]byte, 32), 1) + acc := accounts3.Account{ + Nonce: 2, + Balance: *uint256.NewInt(1 * common.Ether), + CodeHash: common.Hash{}, + Incarnation: 1, + } + v := accounts3.SerialiseV3(&acc) change.ChangeBatch[0].Changes = append(change.ChangeBatch[0].Changes, &remote.AccountChange{ Action: remote.Action_UPSERT, Address: gointerfaces.ConvertAddressToH160(addr), @@ -1001,7 +1043,7 @@ func TestSetCodeTxnValidationWithLargeAuthorizationValues(t *testing.T) { coreDB, _ := temporaltest.NewTestDB(t, datadir.New(t.TempDir())) cfg := txpoolcfg.DefaultConfig chainID := *maxUint256 - cache := &kvcache.DummyCache{} + cache := kvcache.NewDummy() logger := log.New() pool, err := New(ctx, ch, nil, coreDB, cfg, cache, chainID, common.Big0 /* shanghaiTime */, nil, /* agraBlock */ common.Big0 /* cancunTime */, common.Big0 /* pragueTime */, nil, nil, nil, func() {}, nil, logger, WithFeeCalculator(nil)) @@ -1010,11 +1052,16 @@ func TestSetCodeTxnValidationWithLargeAuthorizationValues(t *testing.T) { tx, err := coreDB.BeginRw(ctx) defer tx.Rollback() assert.NoError(t, err) + sd, err := state.NewSharedDomains(tx, logger) + assert.NoError(t, err) + defer sd.Close() + + sndr := accounts3.Account{Nonce: 0, Balance: *uint256.NewInt(math.MaxUint64)} + sndrBytes := accounts3.SerialiseV3(&sndr) + err = sd.DomainPut(kv.AccountsDomain, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, nil, sndrBytes, nil, 0) + assert.NoError(t, err) - sndr := sender{nonce: 0, balance: *uint256.NewInt(math.MaxUint64)} - sndrBytes := make([]byte, EncodeSenderLengthForStorage(sndr.nonce, sndr.balance)) - EncodeSender(sndr.nonce, sndr.balance, sndrBytes) - err = tx.Put(kv.PlainState, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, sndrBytes) + err = sd.Flush(ctx, tx) assert.NoError(t, err) txn := &TxnSlot{ @@ -1072,7 +1119,13 @@ func TestBlobTxnReplacement(t *testing.T) { addr[0] = 1 // Add 1 eth to the user account, as a part of change - v := types2.EncodeAccountBytesV3(2, uint256.NewInt(1*common.Ether), make([]byte, 32), 1) + acc := accounts3.Account{ + Nonce: 2, + Balance: *uint256.NewInt(1 * common.Ether), + CodeHash: common.Hash{}, + Incarnation: 1, + } + v := accounts3.SerialiseV3(&acc) change.ChangeBatch[0].Changes = append(change.ChangeBatch[0].Changes, &remote.AccountChange{ Action: remote.Action_UPSERT, @@ -1251,7 +1304,13 @@ func TestDropRemoteAtNoGossip(t *testing.T) { } var addr [20]byte addr[0] = 1 - v := types2.EncodeAccountBytesV3(2, uint256.NewInt(1*common.Ether), make([]byte, 32), 1) + acc := accounts3.Account{ + Nonce: 2, + Balance: *uint256.NewInt(1 * common.Ether), + CodeHash: common.Hash{}, + Incarnation: 1, + } + v := accounts3.SerialiseV3(&acc) change.ChangeBatch[0].Changes = append(change.ChangeBatch[0].Changes, &remote.AccountChange{ Action: remote.Action_UPSERT, Address: gointerfaces.ConvertAddressToH160(addr), @@ -1353,7 +1412,13 @@ func TestBlobSlots(t *testing.T) { var addr [20]byte // Add 1 eth to the user account, as a part of change - v := types2.EncodeAccountBytesV3(0, uint256.NewInt(1*common.Ether), make([]byte, 32), 1) + acc := accounts3.Account{ + Nonce: 0, + Balance: *uint256.NewInt(1 * common.Ether), + CodeHash: common.Hash{}, + Incarnation: 1, + } + v := accounts3.SerialiseV3(&acc) for i := 0; i < 11; i++ { addr[0] = uint8(i + 1) @@ -1418,7 +1483,13 @@ func TestGasLimitChanged(t *testing.T) { h1 := gointerfaces.ConvertHashToH256([32]byte{}) var addr [20]byte addr[0] = 1 - v := types2.EncodeAccountBytesV3(0, uint256.NewInt(1*common.Ether), make([]byte, 32), 1) + acc := accounts3.Account{ + Nonce: 0, + Balance: *uint256.NewInt(1 * common.Ether), + CodeHash: common.Hash{}, + Incarnation: 1, + } + v := accounts3.SerialiseV3(&acc) tx, err := db.BeginRw(ctx) require.NoError(err) defer tx.Rollback() diff --git a/txnprovider/txpool/senders.go b/txnprovider/txpool/senders.go index 4b0ad0a4170..f81beacf5f5 100644 --- a/txnprovider/txpool/senders.go +++ b/txnprovider/txpool/senders.go @@ -18,6 +18,7 @@ package txpool import ( "fmt" + "github.com/erigontech/erigon-lib/types/accounts" "math" "math/bits" @@ -29,7 +30,6 @@ import ( remote "github.com/erigontech/erigon-lib/gointerfaces/remoteproto" "github.com/erigontech/erigon-lib/kv/kvcache" "github.com/erigontech/erigon-lib/log/v3" - types2 "github.com/erigontech/erigon-lib/types" "github.com/erigontech/erigon/txnprovider/txpool/txpoolcfg" ) @@ -222,7 +222,7 @@ func (sc *sendersBatch) getOrCreateID(addr common.Address, logger log.Logger) (u return id, traced } -func (sc *sendersBatch) info(cacheView kvcache.CacheView, id uint64) (nonce uint64, balance uint256.Int, err error) { +func (sc *sendersBatch) info(cacheView kvcache.CacheView, id uint64) (uint64, uint256.Int, error) { addr, ok := sc.senderID2Addr[id] if !ok { panic("must not happen") @@ -234,17 +234,12 @@ func (sc *sendersBatch) info(cacheView kvcache.CacheView, id uint64) (nonce uint if len(encoded) == 0 { return 0, uint256.Int{}, nil } - if cacheView.StateV3() { - var bp *uint256.Int - nonce, bp, _ = types2.DecodeAccountBytesV3(encoded) - balance = *bp - } else { - nonce, balance, err = DecodeSender(encoded) - } + acc := accounts.Account{} + err = accounts.DeserialiseV3(&acc, encoded) if err != nil { return 0, uint256.Int{}, err } - return nonce, balance, nil + return acc.Nonce, acc.Balance, nil } func (sc *sendersBatch) registerNewSenders(newTxns *TxnSlots, logger log.Logger) (err error) { @@ -311,39 +306,3 @@ func EncodeSender(nonce uint64, balance uint256.Int, buffer []byte) { buffer[0] = byte(fieldSet) } - -// Decode the sender's balance and nonce from encoded byte-slice -func DecodeSender(enc []byte) (nonce uint64, balance uint256.Int, err error) { - if len(enc) == 0 { - return - } - - var fieldSet = enc[0] - var pos = 1 - - if fieldSet&1 > 0 { - decodeLength := int(enc[pos]) - - if len(enc) < pos+decodeLength+1 { - return nonce, balance, fmt.Errorf( - "malformed CBOR for Account.Nonce: %s, Length %d", - enc[pos+1:], decodeLength) - } - - nonce = common.BytesToUint64(enc[pos+1 : pos+decodeLength+1]) - pos += decodeLength + 1 - } - - if fieldSet&2 > 0 { - decodeLength := int(enc[pos]) - - if len(enc) < pos+decodeLength+1 { - return nonce, balance, fmt.Errorf( - "malformed CBOR for Account.Nonce: %s, Length %d", - enc[pos+1:], decodeLength) - } - - (&balance).SetBytes(enc[pos+1 : pos+decodeLength+1]) - } - return -}