diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index 77a8f9417..37cbe9f75 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -32,7 +32,6 @@ import ( "github.com/ledgerwatch/erigon-lib/kv" state2 "github.com/ledgerwatch/erigon-lib/state" types2 "github.com/ledgerwatch/erigon-lib/types" - "github.com/ledgerwatch/erigon/eth/ethconfig" "github.com/ledgerwatch/erigon/turbo/services" "github.com/ledgerwatch/log/v3" @@ -184,13 +183,7 @@ func (b *SimulatedBackend) emptyPendingBlock() { panic(err) } b.pendingReaderTx = tx - - if ethconfig.EnableHistoryV4InTest { - panic("implement me") - //b.pendingReader = state.NewReaderV4(b.pendingReaderTx.(kv.TemporalTx)) - } else { - b.pendingReader = state.NewPlainStateReader(b.pendingReaderTx) - } + b.pendingReader = b.m.NewStateReader(b.pendingReaderTx) b.pendingState = state.New(b.pendingReader) } diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index dd326f5b1..0b390e0c3 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -24,11 +24,13 @@ import ( "github.com/ledgerwatch/erigon-lib/chain" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/kv" + "github.com/ledgerwatch/erigon/common" "github.com/ledgerwatch/erigon/common/math" "github.com/ledgerwatch/erigon/consensus/ethash" "github.com/ledgerwatch/erigon/core/state" "github.com/ledgerwatch/erigon/core/types" + "github.com/ledgerwatch/erigon/turbo/rpchelper" ) type Prestate struct { @@ -73,9 +75,9 @@ type stEnvMarshaling struct { BaseFee *math.HexOrDecimal256 } -func MakePreState(chainRules *chain.Rules, tx kv.RwTx, accounts types.GenesisAlloc) (*state.PlainStateReader, *state.PlainStateWriter) { +func MakePreState(chainRules *chain.Rules, tx kv.RwTx, accounts types.GenesisAlloc) (state.StateReader, *state.PlainStateWriter) { var blockNr uint64 = 0 - stateReader, stateWriter := state.NewPlainStateReader(tx), state.NewPlainStateWriter(tx, tx, blockNr) + stateReader, stateWriter := rpchelper.NewLatestStateReader(tx), state.NewPlainStateWriter(tx, tx, blockNr) statedb := state.New(stateReader) //ibs for addr, a := range accounts { statedb.SetCode(addr, a.Code) diff --git a/cmd/rpcdaemon/commands/otterscan_contract_creator.go b/cmd/rpcdaemon/commands/otterscan_contract_creator.go index 793a9ab0e..8b49f9631 100644 --- a/cmd/rpcdaemon/commands/otterscan_contract_creator.go +++ b/cmd/rpcdaemon/commands/otterscan_contract_creator.go @@ -13,12 +13,11 @@ import ( "github.com/ledgerwatch/erigon-lib/kv/order" "github.com/ledgerwatch/erigon-lib/kv/rawdbv3" "github.com/ledgerwatch/erigon-lib/kv/temporal/historyv2" - "github.com/ledgerwatch/erigon/core/state/temporal" - "github.com/ledgerwatch/erigon/eth/stagedsync/stages" "github.com/ledgerwatch/log/v3" - "github.com/ledgerwatch/erigon/core/state" + "github.com/ledgerwatch/erigon/core/state/temporal" "github.com/ledgerwatch/erigon/core/types/accounts" + "github.com/ledgerwatch/erigon/turbo/rpchelper" ) type ContractCreatorData struct { @@ -33,8 +32,8 @@ func (api *OtterscanAPIImpl) GetContractCreator(ctx context.Context, addr common } defer tx.Rollback() - reader := state.NewPlainStateReader(tx) - plainStateAcc, err := reader.ReadAccountData(addr) + latestState := rpchelper.NewLatestStateReader(tx) + plainStateAcc, err := latestState.ReadAccountData(addr) if err != nil { return nil, err } @@ -57,14 +56,6 @@ func (api *OtterscanAPIImpl) GetContractCreator(ctx context.Context, addr common var acc accounts.Account if api.historyV3(tx) { ttx := tx.(kv.TemporalTx) - headNumber, err := stages.GetStageProgress(tx, stages.Execution) - if err != nil { - return nil, err - } - lastTxNum, err := rawdbv3.TxNums.Max(tx, headNumber) - if err != nil { - return nil, err - } // Contract; search for creation tx; navigate forward on AccountsHistory/ChangeSets // @@ -75,7 +66,7 @@ func (api *OtterscanAPIImpl) GetContractCreator(ctx context.Context, addr common // so it is optimal to search from the beginning even if the contract has multiple // incarnations. var prevTxnID, nextTxnID uint64 - it, err := ttx.IndexRange(temporal.AccountsHistoryIdx, addr[:], 0, int(lastTxNum+1), order.Asc, kv.Unlim) + it, err := ttx.IndexRange(temporal.AccountsHistoryIdx, addr[:], 0, -1, order.Asc, kv.Unlim) if err != nil { return nil, err } @@ -92,10 +83,9 @@ func (api *OtterscanAPIImpl) GetContractCreator(ctx context.Context, addr common v, ok, err := ttx.HistoryGet(temporal.AccountsHistory, addr[:], txnID) if err != nil { - log.Error("Unexpected error, couldn't find changeset", "txNum", i, "addr", addr) + log.Error("Unexpected error, couldn't find changeset", "txNum", txnID, "addr", addr) return nil, err } - fmt.Printf("i: %d, %t, %x\n", i, ok, v) if !ok { err = fmt.Errorf("couldn't find history txnID=%v addr=%v", txnID, addr) @@ -107,7 +97,7 @@ func (api *OtterscanAPIImpl) GetContractCreator(ctx context.Context, addr common continue } - if err := acc.DecodeForStorage(v); err != nil { + if err := accounts.DeserialiseV3(&acc, v); err != nil { return nil, err } // Found the shard where the incarnation change happens; ignore all next index values @@ -145,7 +135,7 @@ func (api *OtterscanAPIImpl) GetContractCreator(ctx context.Context, addr common return false } - if err := acc.DecodeForStorage(v); err != nil { + if err := accounts.DeserialiseV3(&acc, v); err != nil { searchErr = err return false } diff --git a/cmd/rpcdaemon/commands/otterscan_transaction_by_sender_and_nonce.go b/cmd/rpcdaemon/commands/otterscan_transaction_by_sender_and_nonce.go index 06381ef9e..dfdb3baf4 100644 --- a/cmd/rpcdaemon/commands/otterscan_transaction_by_sender_and_nonce.go +++ b/cmd/rpcdaemon/commands/otterscan_transaction_by_sender_and_nonce.go @@ -62,7 +62,7 @@ func (api *OtterscanAPIImpl) GetTransactionBySenderAndNonce(ctx context.Context, continue } - if err := acc.DecodeForStorage(v); err != nil { + if err := accounts.DeserialiseV3(&acc, v); err != nil { return nil, err } // Desired nonce was found in this chunk @@ -99,10 +99,11 @@ func (api *OtterscanAPIImpl) GetTransactionBySenderAndNonce(ctx context.Context, return false } - if err := acc.DecodeForStorage(v); err != nil { + if err := accounts.DeserialiseV3(&acc, v); err != nil { searchErr = err return false } + // Since the state contains the nonce BEFORE the block changes, we look for // the block when the nonce changed to be > the desired once, which means the // previous history block contains the actual change; it may contain multiple diff --git a/cmd/rpcdaemon/commands/parity_api.go b/cmd/rpcdaemon/commands/parity_api.go index 604b232f0..c39d8afa9 100644 --- a/cmd/rpcdaemon/commands/parity_api.go +++ b/cmd/rpcdaemon/commands/parity_api.go @@ -9,8 +9,8 @@ import ( "github.com/ledgerwatch/erigon-lib/common/hexutility" "github.com/ledgerwatch/erigon-lib/common/length" "github.com/ledgerwatch/erigon-lib/kv" + "github.com/ledgerwatch/erigon/turbo/rpchelper" - "github.com/ledgerwatch/erigon/core/state" "github.com/ledgerwatch/erigon/rpc" ) @@ -46,7 +46,7 @@ func (api *ParityAPIImpl) ListStorageKeys(ctx context.Context, account libcommon return nil, fmt.Errorf("listStorageKeys cannot open tx: %w", err) } defer tx.Rollback() - a, err := state.NewPlainStateReader(tx).ReadAccountData(account) + a, err := rpchelper.NewLatestStateReader(tx).ReadAccountData(account) if err != nil { return nil, err } else if a == nil { diff --git a/core/blockchain.go b/core/blockchain.go index 36465ae59..bb3c8c72b 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -117,7 +117,6 @@ func ExecuteBlockEphemerally( vmConfig.Tracer = tracer writeTrace = true } - receipt, _, err := ApplyTransaction(chainConfig, blockHashFunc, engine, nil, gp, ibs, noop, header, tx, usedGas, *vmConfig) if writeTrace { if ftracer, ok := vmConfig.Tracer.(vm.FlushableTracer); ok { diff --git a/core/chain_makers.go b/core/chain_makers.go index 10b9129b5..ec257eb19 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -25,8 +25,6 @@ import ( libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/length" "github.com/ledgerwatch/erigon-lib/kv" - "github.com/ledgerwatch/erigon/core/systemcontracts" - "github.com/ledgerwatch/erigon/eth/ethconfig" "github.com/ledgerwatch/log/v3" "github.com/ledgerwatch/erigon/common" @@ -34,9 +32,12 @@ import ( "github.com/ledgerwatch/erigon/consensus/merge" "github.com/ledgerwatch/erigon/consensus/misc" "github.com/ledgerwatch/erigon/core/state" + "github.com/ledgerwatch/erigon/core/systemcontracts" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/core/vm" + "github.com/ledgerwatch/erigon/eth/ethconfig" "github.com/ledgerwatch/erigon/params" + "github.com/ledgerwatch/erigon/turbo/rpchelper" "github.com/ledgerwatch/erigon/turbo/trie" ) @@ -355,13 +356,11 @@ func GenerateChain(config *chain.Config, parent *types.Block, engine consensus.E var txNum uint64 for i := 0; i < n; i++ { - var stateReader state.StateReader + stateReader := rpchelper.NewLatestStateReader(tx) var stateWriter state.StateWriter - if ethconfig.EnableHistoryV4InTest { panic("implement me on v4") } else { - stateReader = state.NewPlainStateReader(tx) stateWriter = state.NewPlainStateWriter(tx, nil, parent.NumberU64()+uint64(i)+1) } ibs := state.New(stateReader) diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index 8113ac04a..dc0818bcb 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -384,10 +384,16 @@ func ReadStorageBody(db kv.Getter, hash libcommon.Hash, number uint64) (types.Bo return *bodyForStorage, nil } -func CanonicalTxnByID(db kv.Getter, id uint64) (types.Transaction, error) { - txIdKey := make([]byte, 8) - binary.BigEndian.PutUint64(txIdKey, id) - v, err := db.GetOne(kv.EthTx, txIdKey) +func TxnByIdxInBlock(db kv.Getter, blockHash libcommon.Hash, blockNum uint64, txIdxInBlock int) (types.Transaction, error) { + b, err := ReadBodyForStorageByKey(db, dbutils.BlockBodyKey(blockNum, blockHash)) + if err != nil { + return nil, err + } + if b == nil { + return nil, nil + } + + v, err := db.GetOne(kv.EthTx, hexutility.EncodeTs(b.BaseTxId+1+uint64(txIdxInBlock))) if err != nil { return nil, err } diff --git a/tests/state_test_util.go b/tests/state_test_util.go index e64f025f0..bb9464d92 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -45,6 +45,7 @@ import ( "github.com/ledgerwatch/erigon/crypto" "github.com/ledgerwatch/erigon/params" "github.com/ledgerwatch/erigon/rlp" + "github.com/ledgerwatch/erigon/turbo/rpchelper" "github.com/ledgerwatch/erigon/turbo/trie" ) @@ -194,12 +195,7 @@ func (t *StateTest) RunNoVerify(tx kv.RwTx, subtest StateSubtest, vmconfig vm.Co return nil, libcommon.Hash{}, UnsupportedForkError{subtest.Fork} } - var r state.StateReader - if ethconfig.EnableHistoryV4InTest { - panic("implement me") - } else { - r = state.NewPlainStateReader(tx) - } + r := rpchelper.NewLatestStateReader(tx) statedb := state.New(r) var w state.StateWriter @@ -311,12 +307,7 @@ func (t *StateTest) RunNoVerify(tx kv.RwTx, subtest StateSubtest, vmconfig vm.Co } func MakePreState(rules *chain.Rules, tx kv.RwTx, accounts types.GenesisAlloc, blockNr uint64) (*state.IntraBlockState, error) { - var r state.StateReader - if ethconfig.EnableHistoryV4InTest { - panic("implement me") - } else { - r = state.NewPlainStateReader(tx) - } + r := rpchelper.NewLatestStateReader(tx) statedb := state.New(r) for addr, a := range accounts { statedb.SetCode(addr, a.Code) diff --git a/turbo/rpchelper/helper.go b/turbo/rpchelper/helper.go index 418a5dccf..b29653686 100644 --- a/turbo/rpchelper/helper.go +++ b/turbo/rpchelper/helper.go @@ -11,6 +11,7 @@ import ( "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/core/state" "github.com/ledgerwatch/erigon/core/systemcontracts" + "github.com/ledgerwatch/erigon/eth/ethconfig" "github.com/ledgerwatch/erigon/eth/stagedsync/stages" "github.com/ledgerwatch/erigon/rpc" ) @@ -129,3 +130,11 @@ func CreateHistoryStateReader(tx kv.Tx, blockNumber uint64, txnIndex int, histor r.SetTxNum(uint64(int(minTxNum) + txnIndex + 1)) return r, nil } + +func NewLatestStateReader(tx kv.Getter) state.StateReader { + if ethconfig.EnableHistoryV4InTest { + panic("implement me") + //b.pendingReader = state.NewReaderV4(b.pendingReaderTx.(kv.TemporalTx)) + } + return state.NewPlainStateReader(tx) +} diff --git a/turbo/snapshotsync/block_reader.go b/turbo/snapshotsync/block_reader.go index ec4fab4e6..f9b935f4a 100644 --- a/turbo/snapshotsync/block_reader.go +++ b/turbo/snapshotsync/block_reader.go @@ -3,7 +3,6 @@ package snapshotsync import ( "bytes" "context" - "encoding/binary" "fmt" "github.com/ledgerwatch/erigon-lib/common" @@ -685,29 +684,14 @@ func (r *BlockReader) txnByHash(txnHash common.Hash, segments []*TxnSegment, buf // TxnByIdxInBlock - doesn't include system-transactions in the begin/end of block // return nil if 0 < i < body.TxAmount -func (r *BlockReader) TxnByIdxInBlock(ctx context.Context, tx kv.Getter, blockNum uint64, i int) (txn types.Transaction, err error) { +func (r *BlockReader) TxnByIdxInBlock(ctx context.Context, tx kv.Getter, blockNum uint64, txIdxInBlock int) (txn types.Transaction, err error) { blocksAvailable := r.sn.BlocksAvailable() if blocksAvailable == 0 || blockNum > blocksAvailable { canonicalHash, err := rawdb.ReadCanonicalHash(tx, blockNum) if err != nil { return nil, err } - var k [8 + 32]byte - binary.BigEndian.PutUint64(k[:], blockNum) - copy(k[8:], canonicalHash[:]) - b, err := rawdb.ReadBodyForStorageByKey(tx, k[:]) - if err != nil { - return nil, err - } - if b == nil { - return nil, nil - } - - txn, err = rawdb.CanonicalTxnByID(tx, b.BaseTxId+1+uint64(i)) - if err != nil { - return nil, err - } - return txn, nil + return rawdb.TxnByIdxInBlock(tx, canonicalHash, blockNum, txIdxInBlock) } view := r.sn.View() @@ -727,7 +711,7 @@ func (r *BlockReader) TxnByIdxInBlock(ctx context.Context, tx kv.Getter, blockNu } // if block has no transactions, or requested txNum out of non-system transactions length - if b.TxAmount == 2 || i == -1 || i >= int(b.TxAmount-2) { + if b.TxAmount == 2 || txIdxInBlock == -1 || txIdxInBlock >= int(b.TxAmount-2) { return nil, nil } @@ -736,7 +720,7 @@ func (r *BlockReader) TxnByIdxInBlock(ctx context.Context, tx kv.Getter, blockNu return } // +1 because block has system-txn in the beginning of block - return r.txnByID(b.BaseTxId+1+uint64(i), txnSeg, nil) + return r.txnByID(b.BaseTxId+1+uint64(txIdxInBlock), txnSeg, nil) } // TxnLookup - find blockNumber and txnID by txnHash