diff --git a/.cursor/rules/xlayer-db.mdc b/.cursor/rules/xlayer-db.mdc
index 2081b74957..c8de0aff26 100644
--- a/.cursor/rules/xlayer-db.mdc
+++ b/.cursor/rules/xlayer-db.mdc
@@ -43,10 +43,6 @@ globs:
- "cmd/geth/dbcmd.go"
- "core/rawdb/*_test.go"
- "core/rawdb/ancienttest/**/*.go"
-- "core/rawdb/accessors_inner_tx_xlayer.go"
-- "core/types/innertx_xlayer.go"
-- "core/state_processor_xlayer.go"
-- "core/vm/evm_xlayer.go"
alwaysApply: false
---
diff --git a/cmd/utils/flags_xlayer.go b/cmd/utils/flags_xlayer.go
index 176220ed70..19cb97338d 100644
--- a/cmd/utils/flags_xlayer.go
+++ b/cmd/utils/flags_xlayer.go
@@ -15,13 +15,6 @@ import (
)
var (
- // InnerTx
- InnerTxFlag = &cli.BoolFlag{
- Name: "innertx",
- Usage: "Enable inner transaction capture and storage (disabled by default)",
- Value: false,
- Category: flags.XLayerCategory,
- }
// Migration flags for XLayer routing
MigrationBlockFlag = &cli.Uint64Flag{
Name: "migration-block",
@@ -55,7 +48,6 @@ var (
// XLayerFlags are the default flags for X Layer features
XLayerFlags = []cli.Flag{
- InnerTxFlag,
MigrationBlockFlag,
PPRPCUrlFlag,
PPRPCTimeoutFlag,
@@ -66,17 +58,10 @@ var (
// SetXLayerConfig is a public wrapper function to internally call all XLayer configuration functions
func SetXLayerConfig(ctx *cli.Context, cfg *ethconfig.Config) {
- setInnerTxXLayer(ctx, cfg)
setMigrationXLayer(ctx, cfg)
setMonitorXLayer(ctx, cfg)
}
-func setInnerTxXLayer(ctx *cli.Context, cfg *ethconfig.Config) {
- if ctx.IsSet(InnerTxFlag.Name) {
- cfg.XLayer.EnableInnerTx = ctx.Bool(InnerTxFlag.Name)
- }
-}
-
func setMigrationXLayer(ctx *cli.Context, cfg *ethconfig.Config) {
// Migration configuration
if ctx.IsSet(MigrationBlockFlag.Name) {
diff --git a/core/blockchain.go b/core/blockchain.go
index 4032796a8c..de271d4a4e 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -1085,17 +1085,6 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
// removed by the hc.SetHead function.
rawdb.DeleteBody(db, hash, num)
rawdb.DeleteReceipts(db, hash, num)
-
- // For X Layer
- // Delete inner transactions for this block during SetHead rollback
- if block := bc.GetBlock(hash, num); block != nil {
- txCount := len(block.Transactions())
- if err := rawdb.DeleteBlockInnerTxs(db, num, txCount); err != nil {
- log.Error("Failed to delete inner transactions during SetHead rollback",
- "block", num, "hash", hash, "err", err)
- // Continue with rollback even if inner tx deletion fails
- }
- }
}
// Todo(rjl493456442) txlookup, log index, etc
@@ -1629,31 +1618,19 @@ func (bc *BlockChain) writeKnownBlock(block *types.Block) error {
// writeBlockWithState writes block, metadata and corresponding state data to the
// database.
-func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.Receipt, statedb *state.StateDB, sortedInnerTxs [][]*types.InnerTx) error {
+func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.Receipt, statedb *state.StateDB) error {
if !bc.HasHeader(block.ParentHash(), block.NumberU64()-1) {
return consensus.ErrUnknownAncestor
}
// Irrelevant of the canonical status, write the block itself to the database.
//
- // Note all the components of block(hash->number map, header, body, receipts, innerTxs)
+ // Note all the components of block(hash->number map, header, body, receipts)
// should be written atomically. BlockBatch is used for containing all components.
blockBatch := bc.db.NewBatch()
rawdb.WriteBlock(blockBatch, block)
rawdb.WriteReceipts(blockBatch, block.Hash(), block.NumberU64(), receipts)
rawdb.WritePreimages(blockBatch, statedb.Preimages())
- // For X Layer
- // Write inner transactions for each transaction in the block
- for i, txInnerTxs := range sortedInnerTxs {
- if len(txInnerTxs) > 0 {
- if err := rawdb.WriteInnerTxs(blockBatch, block.NumberU64(), uint32(i), txInnerTxs); err != nil {
- log.Error("Failed to write inner transactions to batch",
- "block", block.NumberU64(), "tx", i, "count", len(txInnerTxs), "err", err)
- // Continue processing even if inner tx storage fails
- }
- }
- }
-
if err := blockBatch.Write(); err != nil {
log.Crit("Failed to write block into disk", "err", err)
}
@@ -1728,8 +1705,8 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
// writeBlockAndSetHead is the internal implementation of WriteBlockAndSetHead.
// This function expects the chain mutex to be held.
-func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, emitHeadEvent bool, innerTxs [][]*types.InnerTx) (status WriteStatus, err error) {
- if err := bc.writeBlockWithState(block, receipts, state, innerTxs); err != nil {
+func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, emitHeadEvent bool) (status WriteStatus, err error) {
+ if err := bc.writeBlockWithState(block, receipts, state); err != nil {
return NonStatTy, err
}
currentBlock := bc.CurrentBlock()
@@ -2209,9 +2186,9 @@ func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, s
)
if !setHead {
// Don't set the head, only insert the block
- err = bc.writeBlockWithState(block, res.Receipts, statedb, res.InnerTxs)
+ err = bc.writeBlockWithState(block, res.Receipts, statedb)
} else {
- status, err = bc.writeBlockAndSetHead(block, res.Receipts, res.Logs, statedb, false, res.InnerTxs)
+ status, err = bc.writeBlockAndSetHead(block, res.Receipts, res.Logs, statedb, false)
}
if err != nil {
return nil, err
@@ -2601,11 +2578,6 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Header) error
rawdb.DeleteTxLookupEntry(batch, tx)
}
- // For X Layer - delete inner transactions for all deleted blocks
- for _, block := range deletedBlocks {
- rawdb.DeleteBlockInnerTxsBatch(batch, block.Number().Uint64(), len(block.Transactions()))
- }
-
// Delete all hash markers that are not part of the new canonical chain.
// Because the reorg function does not handle new chain head, all hash
// markers greater than or equal to new chain head should be deleted.
diff --git a/core/rawdb/accessors_inner_tx_xlayer.go b/core/rawdb/accessors_inner_tx_xlayer.go
deleted file mode 100644
index 44d2ddb9da..0000000000
--- a/core/rawdb/accessors_inner_tx_xlayer.go
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2024 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library 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.
-//
-// The go-ethereum library 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 the go-ethereum library. If not, see .
-
-package rawdb
-
-import (
- "encoding/binary"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/ethdb"
- "github.com/ethereum/go-ethereum/log"
- "github.com/ethereum/go-ethereum/rlp"
-)
-
-// Key format: "InnerTx" + blockNum (uint64 big endian) + txIndex (uint32 big endian) -> RLP([]*InnerTx)
-
-const InnerTxPrefix = "InnerTx"
-
-// innerTxKey generates the database key for inner transactions
-// Key format: "InnerTx" + blockNum (uint64 big endian) + txIndex (uint32 big endian)
-func innerTxKey(blockNum uint64, txIndex uint32) []byte {
- key := make([]byte, len(InnerTxPrefix)+8+4)
- copy(key, InnerTxPrefix)
- binary.BigEndian.PutUint64(key[len(InnerTxPrefix):], blockNum)
- binary.BigEndian.PutUint32(key[len(InnerTxPrefix)+8:], txIndex)
- return key
-}
-
-// WriteInnerTxs stores inner transactions for a specific transaction in a block
-func WriteInnerTxs(db ethdb.KeyValueWriter, blockNum uint64, txIndex uint32, innerTxs []*types.InnerTx) error {
- if len(innerTxs) == 0 {
- return nil
- }
-
- key := innerTxKey(blockNum, txIndex)
-
- data, err := rlp.EncodeToBytes(innerTxs)
- if err != nil {
- return err
- }
-
- return db.Put(key, data)
-}
-
-// ReadInnerTxs retrieves inner transactions for a specific transaction in a block
-func ReadInnerTxs(db ethdb.KeyValueReader, blockNum uint64, txIndex uint32) ([]*types.InnerTx, error) {
- key := innerTxKey(blockNum, txIndex)
-
- // First check if the key exists to distinguish between "not found" and "database error"
- exists, err := db.Has(key)
- if err != nil {
- return nil, err // Database error
- }
- if !exists {
- return []*types.InnerTx{}, nil // Key doesn't exist, return empty slice
- }
-
- data, err := db.Get(key)
- if err != nil {
- return nil, err
- }
-
- var innerTxs []*types.InnerTx
- if err := rlp.DecodeBytes(data, &innerTxs); err != nil {
- return nil, err
- }
- return innerTxs, nil
-}
-
-// ReadInnerTxsByTxHash retrieves inner transactions by transaction hash
-// This requires looking up the block number and transaction index first
-func ReadInnerTxsByTxHash(db ethdb.Reader, txHash common.Hash) ([]*types.InnerTx, error) {
- blockNumber := ReadTxLookupEntry(db, txHash)
- if blockNumber == nil {
- return nil, nil
- }
-
- // Get the block to find the transaction index
- block := ReadBlock(db, ReadCanonicalHash(db, *blockNumber), *blockNumber)
- if block == nil {
- return nil, nil
- }
-
- // Find the transaction index within the block
- txIndex := -1
- for i, tx := range block.Transactions() {
- if tx.Hash() == txHash {
- txIndex = i
- break
- }
- }
-
- if txIndex == -1 {
- return nil, nil
- }
-
- return ReadInnerTxs(db, *blockNumber, uint32(txIndex))
-}
-
-// DeleteBlockInnerTxs removes inner transactions for all transactions in a block
-func DeleteBlockInnerTxs(db ethdb.KeyValueWriter, blockNum uint64, txCount int) error {
- for txIndex := 0; txIndex < txCount; txIndex++ {
- key := innerTxKey(blockNum, uint32(txIndex))
- if err := db.Delete(key); err != nil {
- log.Error("Failed to delete inner transactions", "block", blockNum, "tx", txIndex, "err", err)
- }
- }
- return nil
-}
-
-// DeleteBlockInnerTxsBatch adds inner transaction deletion operations for an entire block to a batch
-func DeleteBlockInnerTxsBatch(batch ethdb.Batch, blockNum uint64, txCount int) {
- for txIndex := 0; txIndex < txCount; txIndex++ {
- key := innerTxKey(blockNum, uint32(txIndex))
- if err := batch.Delete(key); err != nil {
- log.Error("Failed to delete inner transactions", "block", blockNum, "tx", txIndex, "err", err)
- }
- }
-}
diff --git a/core/state_processor.go b/core/state_processor.go
index 0e483b7920..b1b955b4bf 100644
--- a/core/state_processor.go
+++ b/core/state_processor.go
@@ -66,10 +66,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
blockHash = block.Hash()
blockNumber = block.Number()
allLogs []*types.Log
- gp = new(GasPool).AddGas(block.GasLimit())
-
- // For X Layer
- allInnerTxs [][]*types.InnerTx
+ gp = new(GasPool).AddGas(block.GasLimit())
)
// Mutate the block and state according to any hard-fork specs
@@ -104,16 +101,13 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
}
statedb.SetTxContext(tx.Hash(), i)
- receipt, innerTxs, err := ApplyTransactionWithEVM_XLayer(msg, gp, statedb, blockNumber, blockHash, context.Time, tx, usedGas, evm)
+ receipt, err := ApplyTransactionWithEVM(msg, gp, statedb, blockNumber, blockHash, context.Time, tx, usedGas, evm)
if err != nil {
return nil, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
}
receipts = append(receipts, receipt)
allLogs = append(allLogs, receipt.Logs...)
-
- // For X Layer
- allInnerTxs = append(allInnerTxs, innerTxs)
}
isIsthmus := config.IsIsthmus(block.Time())
@@ -147,10 +141,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
Receipts: receipts,
Requests: requests,
Logs: allLogs,
- GasUsed: *usedGas,
-
- // For X Layer
- InnerTxs: allInnerTxs,
+ GasUsed: *usedGas,
}, nil
}
diff --git a/core/state_processor_xlayer.go b/core/state_processor_xlayer.go
deleted file mode 100644
index 61f582d102..0000000000
--- a/core/state_processor_xlayer.go
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2019 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library 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.
-//
-// The go-ethereum library 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 the go-ethereum library. If not, see .
-
-package core
-
-import (
- "math/big"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/state"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/core/vm"
-)
-
-func ApplyTransactionWithEVM_XLayer(msg *Message, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, blockTime uint64, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (receipt *types.Receipt, innerTXs []*types.InnerTx, err error) {
- if hooks := evm.Config.Tracer; hooks != nil {
- if hooks.OnTxStart != nil {
- hooks.OnTxStart(evm.GetVMContext(), tx, msg.From)
- }
- if hooks.OnTxEnd != nil {
- defer func() { hooks.OnTxEnd(receipt, err) }()
- }
- }
-
- nonce := tx.Nonce()
- if msg.IsDepositTx && evm.ChainConfig().IsOptimismRegolith(evm.Context.Time) {
- nonce = statedb.GetNonce(msg.From)
- }
-
- // Apply the transaction to the current state (included in the env).
- result, err := ApplyMessage(evm, msg, gp)
- if err != nil {
- return nil, nil, err
- }
- // Update the state with pending changes.
- var root []byte
- if evm.ChainConfig().IsByzantium(blockNumber) {
- evm.StateDB.Finalise(true)
- } else {
- root = statedb.IntermediateRoot(evm.ChainConfig().IsEIP158(blockNumber)).Bytes()
- }
- *usedGas += result.UsedGas
-
- // Merge the tx-local access event into the "block-local" one, in order to collect
- // all values, so that the witness can be built.
- if statedb.Database().TrieDB().IsVerkle() {
- statedb.AccessEvents().Merge(evm.AccessEvents)
- }
-
- // For X Layer
- var innerTxs []*types.InnerTx
- if evm.Config.EnableInnerTxs {
- innerTxs = afterApplyTransaction(evm, result.Failed())
- }
-
- return MakeReceipt(evm, result, statedb, blockNumber, blockHash, blockTime, tx, *usedGas, root, evm.ChainConfig(), nonce), innerTxs, nil
-}
-
-func afterApplyTransaction(env *vm.EVM, failed bool) []*types.InnerTx {
- innerTxs := env.PopInnerTxs()
- if failed {
- for _, innerTx := range innerTxs {
- innerTx.IsError = true
- }
- }
- return innerTxs
-}
diff --git a/core/state_transition.go b/core/state_transition.go
index c9a0b403e9..bc177ee9db 100644
--- a/core/state_transition.go
+++ b/core/state_transition.go
@@ -23,7 +23,6 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
@@ -583,26 +582,12 @@ func (st *stateTransition) innerExecute() (*ExecutionResult, error) {
st.state.Prepare(rules, msg.From, st.evm.Context.Coinbase, msg.To, vm.ActivePrecompiles(rules), msg.AccessList)
var (
- ret []byte
- vmerr error // vm errors do not effect consensus and are therefore not assigned to err
- contractAddr common.Address
+ ret []byte
+ vmerr error // vm errors do not effect consensus and are therefore not assigned to err
)
- // For X Layer
- innerTx := &types.InnerTx{
- Dept: *big.NewInt(0),
- From: msg.From.String(),
- IsError: false,
- Gas: st.gasRemaining + gas,
- ValueWei: st.msg.Value.String(),
- CallValueWei: hexutil.EncodeBig(st.msg.Value),
- }
- st.evm.AddInnerTx(innerTx)
if contractCreation {
- ret, contractAddr, st.gasRemaining, vmerr = st.evm.Create(msg.From, msg.Data, st.gasRemaining, value)
-
- // For X Layer
- innerTx.To = contractAddr.String()
+ ret, _, st.gasRemaining, vmerr = st.evm.Create(msg.From, msg.Data, st.gasRemaining, value)
} else {
// Increment the nonce for the next transaction.
st.state.SetNonce(msg.From, st.state.GetNonce(msg.From)+1, tracing.NonceChangeEoACall)
@@ -626,18 +611,6 @@ func (st *stateTransition) innerExecute() (*ExecutionResult, error) {
// Execute the transaction's call.
ret, st.gasRemaining, vmerr = st.evm.Call(msg.From, st.to(), msg.Data, st.gasRemaining, value)
-
- // For X Layer
- innerTx.To = msg.To.String()
- }
-
- // For X Layer
- if ret != nil {
- innerTx.Output = hexutil.Encode(ret[:])
- }
- if vmerr != nil {
- innerTx.Error = vmerr.Error()
- innerTx.IsError = true
}
// OP-Stack: pre-Regolith: if deposit, skip refunds, skip tipping coinbase
@@ -736,9 +709,6 @@ func (st *stateTransition) innerExecute() (*ExecutionResult, error) {
}
}
- // For X Layer
- innerTx.GasUsed = st.gasUsed()
-
return &ExecutionResult{
UsedGas: st.gasUsed(),
MaxUsedGas: peakGasUsed,
diff --git a/core/types.go b/core/types.go
index c45c21837c..204bbd0590 100644
--- a/core/types.go
+++ b/core/types.go
@@ -56,8 +56,5 @@ type ProcessResult struct {
Receipts types.Receipts
Requests [][]byte
Logs []*types.Log
- GasUsed uint64
-
- // For X Layer
- InnerTxs [][]*types.InnerTx // Inner transactions for each transaction in the block
+ GasUsed uint64
}
diff --git a/core/types/innertx_xlayer.go b/core/types/innertx_xlayer.go
deleted file mode 100644
index c5dcc3ad4d..0000000000
--- a/core/types/innertx_xlayer.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package types
-
-import "math/big"
-
-// InnerTx stores the basic field of an inner tx.
-// NOTE: DON'T change this struct for:
-// 1. It will be written to database, and must be keep the same type When reading history data from db
-// 2. It will be returned by rpc method
-type InnerTx struct {
- Dept big.Int `json:"dept"`
- InternalIndex big.Int `json:"internal_index"`
- CallType string `json:"call_type"`
- Name string `json:"name"`
- TraceAddress string `json:"trace_address"`
- CodeAddress string `json:"code_address"`
- From string `json:"from"`
- To string `json:"to"`
- Input string `json:"input"`
- Output string `json:"output"`
- IsError bool `json:"is_error"`
- Gas uint64 `json:"gas"`
- GasUsed uint64 `json:"gas_used"`
- Value string `json:"value"`
- ValueWei string `json:"value_wei"`
- CallValueWei string `json:"call_value_wei"`
- Error string `json:"error"`
-}
diff --git a/core/vm/evm.go b/core/vm/evm.go
index b885b8f1af..c0db42f2ca 100644
--- a/core/vm/evm.go
+++ b/core/vm/evm.go
@@ -130,9 +130,6 @@ type EVM struct {
// precompiles holds the precompiled contracts for the current epoch
precompiles map[common.Address]PrecompiledContract
- // For X Layer
- innerTxMeta *InnerTxMeta
-
// jumpDests stores results of JUMPDEST analysis.
jumpDests JumpDestCache
@@ -155,13 +152,6 @@ func NewEVM(blockCtx BlockContext, statedb StateDB, chainConfig *params.ChainCon
chainConfig: chainConfig,
chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time),
- // For X Layer
- innerTxMeta: &InnerTxMeta{
- lastDepth: 0,
- indexMap: map[int]int{0: 0},
- InnerTxs: make([]*types.InnerTx, 0),
- },
-
jumpDests: newMapJumpDests(),
hasher: crypto.NewKeccakState(),
}
@@ -236,14 +226,6 @@ func (evm *EVM) SetTxContext(txCtx TxContext) {
txCtx.AccessEvents = state.NewAccessEvents(evm.StateDB.PointCache())
}
evm.TxContext = txCtx
-
- // For X Layer
- evm.innerTxMeta = &InnerTxMeta{
- index: 0,
- lastDepth: 0,
- indexMap: map[int]int{0: 0},
- InnerTxs: make([]*types.InnerTx, 0),
- }
}
// Cancel cancels any running EVM operation. This may be called concurrently and
diff --git a/core/vm/evm_xlayer.go b/core/vm/evm_xlayer.go
deleted file mode 100644
index 20dd183494..0000000000
--- a/core/vm/evm_xlayer.go
+++ /dev/null
@@ -1,131 +0,0 @@
-package vm
-
-import (
- "math/big"
- "strconv"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/hexutil"
- "github.com/ethereum/go-ethereum/core/types"
-)
-
-const (
- CALL_TYP = "call"
- CALLCODE_TYP = "callcode"
- DELEGATECALL_TYP = "delegatecall"
- STATICCAL_TYP = "staticcall"
- CREATE_TYP = "create"
- CREATE2_TYP = "create2"
- SUICIDE_TYP = "suicide"
-)
-
-type InnerTxMeta struct {
- index int
- lastDepth int
- indexMap map[int]int
- InnerTxs []*types.InnerTx
-}
-
-func (evm *EVM) GetInnerTxMeta() *InnerTxMeta {
- return evm.innerTxMeta
-}
-
-func (evm *EVM) AddInnerTx(innerTx *types.InnerTx) {
- evm.innerTxMeta.InnerTxs = append(evm.innerTxMeta.InnerTxs, innerTx)
-}
-
-func (evm *EVM) PopInnerTxs() []*types.InnerTx {
- innertxs := make([]*types.InnerTx, len(evm.innerTxMeta.InnerTxs))
- copy(innertxs, evm.innerTxMeta.InnerTxs)
-
- evm.innerTxMeta.InnerTxs = evm.innerTxMeta.InnerTxs[:0]
- evm.innerTxMeta.index = 0
- evm.innerTxMeta.lastDepth = 0
- // Clear the index map
- for k := range evm.innerTxMeta.indexMap {
- delete(evm.innerTxMeta.indexMap, k)
- }
- return innertxs
-}
-
-func beforeOp(
- evm *EVM,
- callTyp string,
- fromAddr common.Address,
- toAddr *common.Address,
- codeAddr *common.Address,
- input []byte,
- gas uint64,
- value *big.Int) (*types.InnerTx, int) {
- innerTx := &types.InnerTx{
- CallType: callTyp,
- From: fromAddr.String(),
- ValueWei: value.String(),
- CallValueWei: hexutil.EncodeBig(value),
- Gas: gas,
- IsError: false,
- }
-
- if toAddr != nil {
- innerTx.To = toAddr.String()
- }
- if codeAddr != nil {
- innerTx.CodeAddress = codeAddr.String()
- }
-
- if input != nil {
- innerTx.Input = hexutil.Encode(input)
- }
-
- innerTxMeta := evm.GetInnerTxMeta()
- depth := evm.depth
- if depth == innerTxMeta.lastDepth {
- innerTxMeta.index++
- innerTxMeta.indexMap[depth] = innerTxMeta.index
- } else if depth < innerTxMeta.lastDepth {
- innerTxMeta.index = innerTxMeta.indexMap[depth] + 1
- innerTxMeta.indexMap[depth] = innerTxMeta.index
- innerTxMeta.lastDepth = depth
- } else if depth > innerTxMeta.lastDepth {
- innerTxMeta.index = 0
- innerTxMeta.indexMap[depth] = 0
- innerTxMeta.lastDepth = depth
- }
- for i := 1; i <= innerTxMeta.lastDepth; i++ {
- innerTx.Name = innerTx.Name + "_" + strconv.Itoa(innerTxMeta.indexMap[i])
- }
- innerTx.Name = innerTx.CallType + innerTx.Name
- innerTx.Dept = *big.NewInt(int64(depth))
- innerTx.InternalIndex = *big.NewInt(int64(innerTxMeta.index))
-
- evm.AddInnerTx(innerTx)
-
- newIndex := len(evm.GetInnerTxMeta().InnerTxs) - 1
- if newIndex < 0 {
- newIndex = 0
- }
-
- return innerTx, newIndex
-}
-
-func afterOp(evm *EVM, opType string, gas_used uint64, newIndex int, innerTx *types.InnerTx, addr *common.Address, err error, ret []byte) {
- innerTx.GasUsed = gas_used
- if ret != nil {
- innerTx.Output = hexutil.Encode(ret[:])
- }
- if err != nil {
- innerTx.Error = err.Error()
- innerTx.IsError = true
- innerTxMeta := evm.GetInnerTxMeta()
- for _, tx := range innerTxMeta.InnerTxs[newIndex:] {
- tx.IsError = true
- }
- }
-
- switch opType {
- case CREATE_TYP, CREATE2_TYP:
- if addr != nil {
- innerTx.To = addr.String()
- }
- }
-}
diff --git a/core/vm/instructions.go b/core/vm/instructions.go
index 9770c6a53c..07072a48a4 100644
--- a/core/vm/instructions.go
+++ b/core/vm/instructions.go
@@ -18,10 +18,8 @@ package vm
import (
"math"
- "math/big"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
@@ -673,9 +671,7 @@ func opCreate(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
scope.Contract.UseGas(gas, evm.Config.Tracer, tracing.GasChangeCallContractCreation)
- innerTx, newIndex := beforeOp(evm, CREATE_TYP, scope.Contract.Address(), nil, nil, input, gas, value.ToBig())
res, addr, returnGas, suberr := evm.Create(scope.Contract.Address(), input, gas, &value)
- afterOp(evm, CREATE_TYP, gas-returnGas, newIndex, innerTx, &addr, suberr, res)
// Push item on the stack based on the returned error. If the ruleset is
// homestead we must check for CodeStoreOutOfGasError (homestead only
@@ -717,10 +713,8 @@ func opCreate2(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
scope.Contract.UseGas(gas, evm.Config.Tracer, tracing.GasChangeCallContractCreation2)
// reuse size int for stackvalue
stackvalue := size
- innerTx, newIndex := beforeOp(evm, CREATE2_TYP, scope.Contract.Address(), nil, nil, input, gas, endowment.ToBig())
res, addr, returnGas, suberr := evm.Create2(scope.Contract.Address(), input, gas,
&endowment, &salt)
- afterOp(evm, CREATE2_TYP, gas-returnGas, newIndex, innerTx, &addr, suberr, res)
// Push item on the stack based on the returned error.
if suberr != nil {
@@ -758,9 +752,7 @@ func opCall(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
gas += params.CallStipend
}
- innerTx, newIndex := beforeOp(evm, CALL_TYP, scope.Contract.Address(), &toAddr, nil, args, gas, value.ToBig())
ret, returnGas, err := evm.Call(scope.Contract.Address(), toAddr, args, gas, &value)
- afterOp(evm, CALL_TYP, gas-returnGas, newIndex, innerTx, nil, err, ret)
if err != nil {
temp.Clear()
@@ -794,9 +786,7 @@ func opCallCode(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
gas += params.CallStipend
}
- innerTx, newIndex := beforeOp(evm, CALLCODE_TYP, scope.Contract.Address(), &toAddr, &toAddr, args, gas, value.ToBig())
ret, returnGas, err := evm.CallCode(scope.Contract.Address(), toAddr, args, gas, &value)
- afterOp(evm, CALLCODE_TYP, gas-returnGas, newIndex, innerTx, nil, err, ret)
if err != nil {
temp.Clear()
@@ -826,15 +816,8 @@ func opDelegateCall(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
// Get arguments from the memory.
args := scope.Memory.GetPtr(inOffset.Uint64(), inSize.Uint64())
- innerTx, newIndex := beforeOp(evm, DELEGATECALL_TYP, scope.Contract.Address(), &toAddr, nil, args, gas, big.NewInt(0))
ret, returnGas, err := evm.DelegateCall(scope.Contract.Caller(), scope.Contract.Address(), toAddr, args, gas, scope.Contract.value)
- // For X Layer
- innerTx.TraceAddress = scope.Contract.Address().String()
- innerTx.ValueWei = scope.Contract.value.ToBig().String()
- innerTx.CallValueWei = hexutil.EncodeBig(scope.Contract.value.ToBig())
- afterOp(evm, DELEGATECALL_TYP, gas-returnGas, newIndex, innerTx, nil, err, ret)
-
if err != nil {
temp.Clear()
} else {
@@ -862,11 +845,9 @@ func opStaticCall(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
toAddr := common.Address(addr.Bytes20())
// Get arguments from the memory.
args := scope.Memory.GetPtr(inOffset.Uint64(), inSize.Uint64())
- innerTx, newIndex := beforeOp(evm, STATICCAL_TYP, scope.Contract.Address(), &toAddr, nil, args, gas, big.NewInt(0))
ret, returnGas, err := evm.StaticCall(scope.Contract.Address(), toAddr, args, gas)
- afterOp(evm, STATICCAL_TYP, gas-returnGas, newIndex, innerTx, nil, err, ret)
- if err != nil {
+ if err != nil{
temp.Clear()
} else {
temp.SetOne()
@@ -911,11 +892,8 @@ func opSelfdestruct(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
}
beneficiary := scope.Stack.pop()
balance := evm.StateDB.GetBalance(scope.Contract.Address())
- beneficiaryAddr := common.Address(beneficiary.Bytes20())
- innerTx, newIndex := beforeOp(evm, SUICIDE_TYP, scope.Contract.Address(), &beneficiaryAddr, nil, nil, 0, balance.ToBig())
evm.StateDB.AddBalance(beneficiary.Bytes20(), balance, tracing.BalanceIncreaseSelfdestruct)
evm.StateDB.SelfDestruct(scope.Contract.Address())
- afterOp(evm, SUICIDE_TYP, 0, newIndex, innerTx, nil, nil, nil)
if tracer := evm.Config.Tracer; tracer != nil {
if tracer.OnEnter != nil {
diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go
index c4396c8014..1fb0165db2 100644
--- a/core/vm/interpreter.go
+++ b/core/vm/interpreter.go
@@ -42,10 +42,7 @@ type Config struct {
PrecompileOverrides PrecompileOverrides // Precompiles can be swapped / changed / wrapped as needed
NoMaxCodeSize bool // Ignore Max code size and max init code size limits
- CallerOverride func(v common.Address) common.Address // Swap the caller as needed, for VM prank functionality.
-
- // For X Layer
- EnableInnerTxs bool // Calculate inner txs
+ CallerOverride func(v common.Address) common.Address // Swap the caller as needed, for VM prank functionality.
}
// ScopeContext contains the things that are per-call, such as stack and memory,
diff --git a/eth/api_backend.go b/eth/api_backend.go
index 71ddd6d943..d13ebfe1e7 100644
--- a/eth/api_backend.go
+++ b/eth/api_backend.go
@@ -61,12 +61,6 @@ func (b *EthAPIBackend) ChainConfig() *params.ChainConfig {
return b.eth.blockchain.Config()
}
-// For X Layer
-// IsInnerTxEnabled returns whether inner transaction capture is enabled.
-func (b *EthAPIBackend) IsInnerTxEnabled() bool {
- return b.eth.config.XLayer.EnableInnerTx
-}
-
func (b *EthAPIBackend) CurrentBlock() *types.Header {
return b.eth.blockchain.CurrentBlock()
}
diff --git a/eth/api_legacy_xlayer.go b/eth/api_legacy_xlayer.go
index cd493e4122..0c19d512df 100644
--- a/eth/api_legacy_xlayer.go
+++ b/eth/api_legacy_xlayer.go
@@ -109,16 +109,14 @@ func (api *XlayerHybridBlockChainAPI) shouldProxy(ctx context.Context, bNrOrHash
// XlayerHybridBlockChainAPI wraps the standard BlockChainAPI to add migration routing
type XlayerHybridBlockChainAPI struct {
*ethapi.BlockChainAPI
- txPreExecAPI *TxPreExecAPI
- legacyRpc *XlayerLegacyRPCService
+ legacyRpc *XlayerLegacyRPCService
}
// NewXlayerHybridBlockChainAPI creates a new migration-aware BlockChainAPI
-func NewXlayerHybridBlockChainAPI(original *ethapi.BlockChainAPI, txPreExecAPI *TxPreExecAPI, legacyRPCService *XlayerLegacyRPCService) *XlayerHybridBlockChainAPI {
+func NewXlayerHybridBlockChainAPI(original *ethapi.BlockChainAPI, legacyRPCService *XlayerLegacyRPCService) *XlayerHybridBlockChainAPI {
return &XlayerHybridBlockChainAPI{
BlockChainAPI: original,
legacyRpc: legacyRPCService,
- txPreExecAPI: txPreExecAPI,
}
}
@@ -352,32 +350,10 @@ func (api *XlayerHybridBlockChainAPI) GetCode(ctx context.Context, address commo
return api.BlockChainAPI.GetCode(ctx, address, blockNrOrHash)
}
-// eth_transactionPreExec FORWARD
-func (api *XlayerHybridBlockChainAPI) TransactionPreExec(ctx context.Context, origins []PreArgs, blockNrOrHash *rpc.BlockNumberOrHash, stateOverrides *override.StateOverride) ([]PreResult, error) {
- if api.txPreExecAPI == nil {
- return nil, fmt.Errorf("TxPreExecAPI not available")
- }
-
- bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
- if blockNrOrHash != nil {
- bNrOrHash = *blockNrOrHash
- }
-
- shouldProxy := api.shouldProxy(ctx, &bNrOrHash)
- if shouldProxy {
- var result []PreResult
- err := api.legacyRpc.ErigonClient.CallContext(ctx, &result, "eth_transactionPreExec", origins, &bNrOrHash, stateOverrides)
- return result, err
- }
-
- return api.txPreExecAPI.TransactionPreExec(ctx, origins, &bNrOrHash, stateOverrides)
-}
-
// XlayerHybridTransactionAPI wraps the standard TransactionAPI to add migration routing
type XlayerHybridTransactionAPI struct {
*ethapi.TransactionAPI
- TxPreExecAPI *TxPreExecAPI
- legacyRpc *XlayerLegacyRPCService
+ legacyRpc *XlayerLegacyRPCService
}
// NewXlayerHybridTransactionAPI creates a new migration-aware TransactionAPI
@@ -442,34 +418,6 @@ func (api *XlayerHybridTransactionAPI) GetBlockTransactionCountByNumber(ctx cont
return api.TransactionAPI.GetBlockTransactionCountByNumber(ctx, blockNr)
}
-// eth_getBlockInternalTransactions FORWARD
-func (api *XlayerHybridTransactionAPI) GetBlockInternalTransactions(ctx context.Context, blockNr rpc.BlockNumber) (map[common.Hash][]*types.InnerTx, error) {
- // Check if we should proxy to erigon
- if api.legacyRpc.shouldProxyByNumber(blockNr) {
- var result map[common.Hash][]*types.InnerTx
- err := api.legacyRpc.ErigonClient.CallContext(ctx, &result, "eth_getBlockInternalTransactions", hexutil.Uint64(blockNr))
- return result, err
- }
- // Handle locally
- return api.TransactionAPI.GetBlockInternalTransactions(ctx, blockNr)
-}
-
-// eth_getInternalTransactions TransactionAPI LOCAL
-func (api *XlayerHybridTransactionAPI) GetInternalTransactions(ctx context.Context, txHash common.Hash) ([]*types.InnerTx, error) {
- // Check if the transaction exists locally
- tx, err := api.TransactionAPI.GetTransactionByHash(ctx, txHash)
-
- // If transaction doesn't exist locally, try Erigon
- if tx == nil || err != nil {
- var remoteResult []*types.InnerTx
- err := api.legacyRpc.ErigonClient.CallContext(ctx, &remoteResult, "eth_getInternalTransactions", txHash)
- return remoteResult, err
- }
-
- // Transaction exists locally
- return api.TransactionAPI.GetInternalTransactions(ctx, txHash)
-}
-
// eth_getRawTransactionByBlockHashAndIndex TransactionAPI LOCAL
func (api *XlayerHybridTransactionAPI) GetRawTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) hexutil.Bytes {
// Try local first
@@ -792,7 +740,7 @@ func (api *XlayerHybridFilterAPI) Logs(ctx context.Context, crit filters.FilterC
}
// WrapAPIsForXlayer wraps the standard APIs with migration-aware versions
-func WrapAPIsForXlayer(apis []rpc.API, txPreExecAPI *TxPreExecAPI, config *XlayerLegacyRPCService) []rpc.API {
+func WrapAPIsForXlayer(apis []rpc.API, config *XlayerLegacyRPCService) []rpc.API {
if config == nil {
return apis // No migration configured, return original APIs
}
@@ -809,7 +757,7 @@ func WrapAPIsForXlayer(apis []rpc.API, txPreExecAPI *TxPreExecAPI, config *Xlaye
wrapped = append(wrapped, rpc.API{
Namespace: api.Namespace,
Version: api.Version,
- Service: NewXlayerHybridBlockChainAPI(original, txPreExecAPI, config),
+ Service: NewXlayerHybridBlockChainAPI(original, config),
Public: api.Public,
Authenticated: api.Authenticated,
})
diff --git a/eth/api_legacy_xlayer_test.go b/eth/api_legacy_xlayer_test.go
index a946366974..e85449e364 100644
--- a/eth/api_legacy_xlayer_test.go
+++ b/eth/api_legacy_xlayer_test.go
@@ -341,84 +341,6 @@ func (s *mockErigonService) EstimateGas(args map[string]interface{}, blockNrOrHa
return hexutil.Uint64(21000), nil
}
-// TransactionPreExec mocks eth_transactionPreExec and returns mock pre-execution results
-func (s *mockErigonService) TransactionPreExec(origins []PreArgs, blockNrOrHash interface{}, stateOverrides interface{}) ([]PreResult, error) {
- results := make([]PreResult, len(origins))
- for i := range origins {
- results[i] = PreResult{
- InnerTxs: []interface{}{},
- Logs: []interface{}{},
- StateDiff: map[string]interface{}{
- "0x1234567890123456789012345678901234567890": map[string]interface{}{
- "before": "0x3b9aca00",
- "after": "0x3b99f4b8",
- },
- },
- GasUsed: 21000,
- }
- }
- return results, nil
-}
-
-// mockTxPreExecAPI is a mock implementation for local execution
-type mockTxPreExecAPI struct {
- results map[uint64][]PreResult
- hashFails bool
- knownHash common.Hash
-}
-
-func (m *mockTxPreExecAPI) TransactionPreExec(ctx context.Context, origins []PreArgs, blockNrOrHash *rpc.BlockNumberOrHash, stateOverrides *override.StateOverride) ([]PreResult, error) {
- if blockNr, ok := blockNrOrHash.Number(); ok {
- if results, exists := m.results[uint64(blockNr)]; exists {
- return results, nil
- }
- return nil, fmt.Errorf("no results for block %d", blockNr)
- }
-
- if blockHash, ok := blockNrOrHash.Hash(); ok {
- if m.hashFails && blockHash != m.knownHash {
- return nil, fmt.Errorf("block hash not found: %s", blockHash.Hex())
- }
- if results, exists := m.results[0]; exists {
- return results, nil
- }
- }
-
- return nil, fmt.Errorf("no results available")
-}
-
-// mockTxPreExecAPIWrapper wraps the routing logic for testing
-type mockTxPreExecAPIWrapper struct {
- mock *mockTxPreExecAPI
- legacyRpc *XlayerLegacyRPCService
-}
-
-func (w *mockTxPreExecAPIWrapper) TransactionPreExec(ctx context.Context, origins []PreArgs, blockNrOrHash *rpc.BlockNumberOrHash, stateOverrides *override.StateOverride) ([]PreResult, error) {
- bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
- if blockNrOrHash != nil {
- bNrOrHash = *blockNrOrHash
- }
-
- // Route by block number
- if blockNr, ok := bNrOrHash.Number(); ok && blockNr >= 0 {
- if w.legacyRpc.shouldProxyByNumber(blockNr) {
- var result []PreResult
- err := w.legacyRpc.ErigonClient.CallContext(ctx, &result, "eth_transactionPreExec", origins, &bNrOrHash, stateOverrides)
- return result, err
- }
- return w.mock.TransactionPreExec(ctx, origins, &bNrOrHash, stateOverrides)
- }
-
- localResult, err := w.mock.TransactionPreExec(ctx, origins, &bNrOrHash, stateOverrides)
- if err == nil && localResult != nil {
- return localResult, nil
- }
-
- var result []PreResult
- err = w.legacyRpc.ErigonClient.CallContext(ctx, &result, "eth_transactionPreExec", origins, &bNrOrHash, stateOverrides)
- return result, err
-}
-
// createMockErigonServer creates an httptest server that simulates an Erigon RPC endpoint
func createMockErigonServer(t *testing.T) (*httptest.Server, *mockErigonService) {
service := newMockErigonService()
@@ -602,7 +524,7 @@ func TestHybridBlockChainAPI_ProxiesGetStorageAt(t *testing.T) {
}
defer legacy.Close()
- api := NewXlayerHybridBlockChainAPI(nil, nil, legacy)
+ api := NewXlayerHybridBlockChainAPI(nil, legacy)
// Test that we can call Erigon to get storage
ctx := context.Background()
@@ -1634,7 +1556,7 @@ func TestWrapAPIsForXlayer(t *testing.T) {
},
}
- wrappedAPIs := WrapAPIsForXlayer(originalAPIs, nil, legacy)
+ wrappedAPIs := WrapAPIsForXlayer(originalAPIs, legacy)
if len(wrappedAPIs) != 1 {
t.Fatalf("expected 1 API, got %d", len(wrappedAPIs))
}
@@ -1668,7 +1590,7 @@ func TestWrapAPIsForXlayer(t *testing.T) {
},
}
- wrappedAPIs := WrapAPIsForXlayer(originalAPIs, nil, legacy)
+ wrappedAPIs := WrapAPIsForXlayer(originalAPIs, legacy)
if len(wrappedAPIs) != 1 {
t.Fatalf("expected 1 API, got %d", len(wrappedAPIs))
}
@@ -1693,7 +1615,7 @@ func TestWrapAPIsForXlayer(t *testing.T) {
},
}
- wrappedAPIs := WrapAPIsForXlayer(originalAPIs, nil, legacy)
+ wrappedAPIs := WrapAPIsForXlayer(originalAPIs, legacy)
if len(wrappedAPIs) != 1 {
t.Fatalf("expected 1 API, got %d", len(wrappedAPIs))
}
@@ -1715,7 +1637,7 @@ func TestWrapAPIsForXlayer(t *testing.T) {
},
}
- wrappedAPIs := WrapAPIsForXlayer(originalAPIs, nil, legacy)
+ wrappedAPIs := WrapAPIsForXlayer(originalAPIs, legacy)
if len(wrappedAPIs) != 1 {
t.Fatalf("expected 1 API, got %d", len(wrappedAPIs))
}
@@ -1740,7 +1662,7 @@ func TestWrapAPIsForXlayer(t *testing.T) {
},
}
- wrappedAPIs := WrapAPIsForXlayer(originalAPIs, nil, legacy)
+ wrappedAPIs := WrapAPIsForXlayer(originalAPIs, legacy)
if len(wrappedAPIs) != 1 {
t.Fatalf("expected 1 API, got %d", len(wrappedAPIs))
}
@@ -1760,7 +1682,7 @@ func TestWrapAPIsForXlayer(t *testing.T) {
{Namespace: "debug", Service: &struct{}{}, Public: false},
}
- wrappedAPIs := WrapAPIsForXlayer(originalAPIs, nil, legacy)
+ wrappedAPIs := WrapAPIsForXlayer(originalAPIs, legacy)
if len(wrappedAPIs) != 5 {
t.Fatalf("expected 5 APIs, got %d", len(wrappedAPIs))
}
@@ -1792,7 +1714,7 @@ func TestWrapAPIsForXlayer(t *testing.T) {
{Namespace: "eth", Service: ðapi.BlockChainAPI{}, Public: true},
}
- wrappedAPIs := WrapAPIsForXlayer(originalAPIs, nil, nil)
+ wrappedAPIs := WrapAPIsForXlayer(originalAPIs, nil)
if len(wrappedAPIs) != 1 {
t.Fatalf("expected 1 API, got %d", len(wrappedAPIs))
}
@@ -2250,7 +2172,7 @@ func TestNilLegacyService(t *testing.T) {
{Namespace: "eth", Service: originalAPI, Public: true},
}
- wrapped := WrapAPIsForXlayer(apis, nil, nil)
+ wrapped := WrapAPIsForXlayer(apis, nil)
if len(wrapped) != 1 {
t.Fatalf("expected 1 API, got %d", len(wrapped))
}
@@ -2316,191 +2238,3 @@ func TestInvalidBlockRanges(t *testing.T) {
})
}
-// Test XlayerHybridTxPreExecAPI routing for TransactionPreExec
-func TestHybridTxPreExecAPI_RoutingByBlockNumber(t *testing.T) {
- t.Parallel()
-
- // Setup mock Erigon server
- legacy, server, _ := createTestLegacyService(t, 100)
- defer server.Close()
- defer legacy.Close()
-
- // Create a mock local TxPreExecAPI
- mockLocal := &mockTxPreExecAPI{
- results: make(map[uint64][]PreResult),
- }
-
- // Add local results for blocks >= 100
- mockLocal.results[100] = []PreResult{
- {
- InnerTxs: []interface{}{},
- Logs: []interface{}{},
- StateDiff: map[string]interface{}{
- "0xLOCAL": map[string]interface{}{
- "before": "0x1388",
- "after": "0x1377",
- },
- },
- GasUsed: 21000,
- },
- }
- mockLocal.results[150] = mockLocal.results[100]
-
- // Create hybrid API with wrapper
- wrapperAPI := &mockTxPreExecAPIWrapper{
- mock: mockLocal,
- legacyRpc: legacy,
- }
-
- ctx := context.Background()
- sender := common.HexToAddress("0xSender")
- receiver := common.HexToAddress("0xReceiver")
- gas := hexutil.Uint64(21000)
- testArgs := []PreArgs{
- {
- From: &sender,
- To: &receiver,
- Gas: &gas,
- GasPrice: (*hexutil.Big)(big.NewInt(1000000000)),
- Value: (*hexutil.Big)(big.NewInt(1000000000000000000)),
- },
- }
-
- t.Run("Block below migration routes to Erigon", func(t *testing.T) {
- blockNum := rpc.BlockNumber(50)
- blockNrOrHash := rpc.BlockNumberOrHashWithNumber(blockNum)
-
- results, err := wrapperAPI.TransactionPreExec(ctx, testArgs, &blockNrOrHash, nil)
- if err != nil {
- t.Fatalf("TransactionPreExec failed: %v", err)
- }
- if len(results) != 1 {
- t.Fatalf("expected 1 result, got %d", len(results))
- }
-
- // Verify it came from Erigon
- stateDiff, ok := results[0].StateDiff.(map[string]interface{})
- if !ok {
- t.Fatal("expected StateDiff to be map[string]interface{}")
- }
- if _, ok := stateDiff["0x1234567890123456789012345678901234567890"]; !ok {
- t.Error("expected state diff from Erigon mock")
- }
- t.Log("Successfully fell back to Erigon, stateDiff: ", stateDiff)
- })
-
- t.Run("Block at migration threshold routes to local", func(t *testing.T) {
- blockNum := rpc.BlockNumber(100)
- blockNrOrHash := rpc.BlockNumberOrHashWithNumber(blockNum)
-
- results, err := wrapperAPI.TransactionPreExec(ctx, testArgs, &blockNrOrHash, nil)
- if err != nil {
- t.Fatalf("TransactionPreExec failed: %v", err)
- }
- if len(results) != 1 {
- t.Fatalf("expected 1 result, got %d", len(results))
- }
-
- stateDiff, ok := results[0].StateDiff.(map[string]interface{})
- if !ok {
- t.Fatal("expected StateDiff to be map[string]interface{}")
- }
- if _, ok := stateDiff["0xLOCAL"]; !ok {
- t.Error("expected state diff from local mock")
- }
- t.Log("Successfully fell back to local, stateDiff: ", stateDiff)
- })
-
- t.Run("Block above migration routes to local", func(t *testing.T) {
- blockNum := rpc.BlockNumber(150)
- blockNrOrHash := rpc.BlockNumberOrHashWithNumber(blockNum)
-
- results, err := wrapperAPI.TransactionPreExec(ctx, testArgs, &blockNrOrHash, nil)
- if err != nil {
- t.Fatalf("TransactionPreExec failed: %v", err)
- }
- if len(results) != 1 {
- t.Fatalf("expected 1 result, got %d", len(results))
- }
-
- // Verify it came from local
- stateDiff, ok := results[0].StateDiff.(map[string]interface{})
- if !ok {
- t.Fatal("expected StateDiff to be map[string]interface{}")
- }
- if _, ok := stateDiff["0xLOCAL"]; !ok {
- t.Error("expected state diff from local mock")
- }
- t.Log("Successfully fell back to local, stateDiff: ", stateDiff)
- })
-}
-
-// Test XlayerHybridTxPreExecAPI routing for block hash
-func TestHybridTxPreExecAPI_RoutingByBlockHash(t *testing.T) {
- t.Parallel()
-
- // Setup mock Erigon server
- legacy, server, _ := createTestLegacyService(t, 100)
- defer server.Close()
- defer legacy.Close()
-
- mockLocal := &mockTxPreExecAPI{
- results: make(map[uint64][]PreResult),
- hashFails: true,
- knownHash: common.HexToHash("0xLOCAL_HASH"),
- }
-
- mockLocal.results[0] = []PreResult{
- {
- InnerTxs: []interface{}{},
- Logs: []interface{}{},
- StateDiff: map[string]interface{}{
- "0xLOCAL": map[string]interface{}{
- "before": "0x1388",
- "after": "0x1377",
- },
- },
- GasUsed: 21000,
- },
- }
-
- wrapperAPI := &mockTxPreExecAPIWrapper{
- mock: mockLocal,
- legacyRpc: legacy,
- }
-
- ctx := context.Background()
- sender := common.HexToAddress("0xSender")
- receiver := common.HexToAddress("0xReceiver")
- gas := hexutil.Uint64(21000)
- testArgs := []PreArgs{
- {
- From: &sender,
- To: &receiver,
- Gas: &gas,
- GasPrice: (*hexutil.Big)(big.NewInt(1000000000)),
- Value: (*hexutil.Big)(big.NewInt(1000000000000000000)),
- },
- }
-
- t.Run("BlockHash test", func(t *testing.T) {
- blockHash := mockLocal.knownHash
- blockNrOrHash := rpc.BlockNumberOrHashWithHash(blockHash, false)
-
- results, err := wrapperAPI.TransactionPreExec(ctx, testArgs, &blockNrOrHash, nil)
- if err != nil {
- t.Fatalf("TransactionPreExec failed: %v", err)
- }
- if len(results) != 1 {
- t.Fatalf("expected 1 result, got %d", len(results))
- }
-
- stateDiff, ok := results[0].StateDiff.(map[string]interface{})
- if !ok {
- t.Fatal("expected StateDiff to be map[string]interface{}")
- }
- if _, ok := stateDiff["0xLOCAL"]; !ok {
- t.Error("expected state diff from local mock")
- }
- })
-}
diff --git a/eth/api_pre_exec_xlayer.go b/eth/api_pre_exec_xlayer.go
deleted file mode 100644
index 4a6a29a514..0000000000
--- a/eth/api_pre_exec_xlayer.go
+++ /dev/null
@@ -1,663 +0,0 @@
-package eth
-
-import (
- "context"
- "encoding/json"
- "fmt"
- "math/big"
- "math/rand"
- "strings"
- "time"
-
- coreState "github.com/ethereum/go-ethereum/core/state"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/log"
-
- "github.com/ethereum/go-ethereum/accounts/abi"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/hexutil"
- "github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/core/vm"
- "github.com/ethereum/go-ethereum/eth/tracers"
- "github.com/ethereum/go-ethereum/internal/ethapi"
- "github.com/ethereum/go-ethereum/internal/ethapi/override"
- "github.com/ethereum/go-ethereum/rpc"
- "github.com/google/uuid"
-)
-
-const (
- UnKnownErrCode = 1000
- InsufficientBalanceErrCode = 1001
- RevertedErrCode = 1002
- CheckPreArgsErrCode = 1003
-
- MaxGasLimit = 30000000
-)
-
-// PreExecInnerTx defines the structure for inner transactions returned by TransactionPreExec RPC
-// This is specifically designed for the eth_transaction_preexec endpoint
-type PreExecInnerTx struct {
- Dept big.Int `json:"dept"`
- InternalIndex big.Int `json:"internal_index"`
- CallType string `json:"call_type"`
- Name string `json:"name"`
- TraceAddress string `json:"trace_address"`
- CodeAddress string `json:"code_address"`
- From string `json:"from"`
- To string `json:"to"`
- Input string `json:"input"`
- Output string `json:"output"`
- IsError bool `json:"is_error"`
- GasUsed uint64 `json:"gas_used"`
- Value string `json:"value"`
- ValueWei string `json:"value_wei"`
- Error string `json:"error"`
- ReturnGas uint64 `json:"return_gas"`
-}
-
-type PreArgs struct {
- ChainId *big.Int `json:"chainId,omitempty"`
- From *common.Address `json:"from"`
- To *common.Address `json:"to"`
- Gas *hexutil.Uint64 `json:"gas"`
- GasPrice *hexutil.Big `json:"gasPrice"`
- MaxFeePerGas *hexutil.Big `json:"maxFeePerGas"`
- MaxPriorityFeePerGas *hexutil.Big `json:"maxPriorityFeePerGas"`
- Value *hexutil.Big `json:"value"`
- Nonce *hexutil.Uint64 `json:"nonce"`
- Data *hexutil.Bytes `json:"data"`
- Input *hexutil.Bytes `json:"input"`
- AuthorizationList []types.SetCodeAuthorization `json:"authorizationList"`
-}
-
-type CallTracerResult struct {
- Calls []CallTracerResult `json:"calls"`
- From string `json:"from"`
- Gas string `json:"gas"`
- GasUsed string `json:"gasUsed"`
- Input string `json:"input"`
- Output string `json:"output,omitempty"`
- To string `json:"to"`
- Type string `json:"type"`
- Value string `json:"value"`
- Error string `json:"error,omitempty"`
- RevertReason string `json:"revertReason,omitempty"`
-}
-
-type StateAccount struct {
- Balance string `json:"balance"`
- Code string `json:"code"`
- Nonce uint64 `json:"nonce"`
- Storage map[string]string `json:"storage"`
-}
-
-type PreError struct {
- Code int `json:"code"`
- Msg string `json:"msg"`
-}
-
-func (args PreArgs) ToLogString() string {
- argsBytes, _ := json.Marshal(args)
- return string(argsBytes)
-}
-
-func toPreError(err error, result *core.ExecutionResult) PreError {
- preErr := PreError{
- Code: UnKnownErrCode,
- }
- if err != nil {
- preErr.Msg = err.Error()
- }
- if result != nil && result.Err != nil {
- preErr.Msg = result.Err.Error()
- }
- if strings.HasPrefix(preErr.Msg, "execution reverted") {
- preErr.Code = RevertedErrCode
- if result != nil {
- preErr.Msg, _ = abi.UnpackRevert(result.Revert())
- }
- }
- if strings.HasPrefix(preErr.Msg, "out of gas") {
- preErr.Code = RevertedErrCode
- }
- if strings.HasPrefix(preErr.Msg, "insufficient funds for transfer") {
- preErr.Code = InsufficientBalanceErrCode
- }
- if strings.HasPrefix(preErr.Msg, "insufficient balance for transfer") {
- preErr.Code = InsufficientBalanceErrCode
- }
- if strings.HasPrefix(preErr.Msg, "insufficient funds for gas * price") {
- preErr.Code = InsufficientBalanceErrCode
- }
- return preErr
-}
-
-type PreResult struct {
- InnerTxs interface{} `json:"innerTxs"`
- Logs interface{} `json:"logs"`
- StateDiff interface{} `json:"stateDiff"`
- Error PreError `json:"error"`
- GasUsed uint64 `json:"gasUsed"`
- BlockNumber *big.Int `json:"blockNumber"`
-}
-
-func (res PreResult) ToLogString() string {
- // spilt InnerTxs
- innerTxsStr, err := json.Marshal(res.InnerTxs)
- if err == nil {
- innerTxs := make([]*PreExecInnerTx, 0)
- if err := json.Unmarshal(innerTxsStr, &innerTxs); err == nil {
- if len(innerTxs) > 0 {
- innerTx := innerTxs[0]
- if len(innerTx.Input) > 100 {
- innerTx.Input = innerTx.Input[0:100]
- }
- if len(innerTx.Output) > 100 {
- innerTx.Output = innerTx.Output[0:100]
- }
- res.InnerTxs = append([]*PreExecInnerTx{}, innerTx)
- }
- }
- }
- // spilt Logs
- logsStr, err := json.Marshal(res.Logs)
- if err == nil {
- logs := make([]types.Log, 0)
- if err := json.Unmarshal(logsStr, &logs); err == nil {
- if len(logs) > 0 {
- l := logs[0]
- if len(l.Data) > 100 {
- l.Data = l.Data[0:100]
- }
- res.Logs = append([]types.Log{}, l)
- }
- }
- }
- resBytes, _ := json.Marshal(res)
- return string(resBytes)
-}
-
-func toPreResult(innerTxs []*PreExecInnerTx, logs []*types.Log, stateDiff map[string]interface{},
- preError PreError, gasUsed uint64, number *big.Int) PreResult {
- preResult := PreResult{
- Error: preError,
- GasUsed: gasUsed,
- BlockNumber: number,
- }
- if len(innerTxs) > 0 {
- preResult.InnerTxs = innerTxs
- } else {
- preResult.InnerTxs = make([]PreExecInnerTx, 0)
- }
- if len(logs) > 0 {
- preResult.Logs = logs
- } else {
- preResult.Logs = make([]types.Log, 0)
- }
- if len(stateDiff) > 0 {
- preResult.StateDiff = stateDiff
- } else {
- preResult.StateDiff = make(map[string]interface{}, 0)
- }
-
- return preResult
-}
-
-// TxPreExecAPI is the collection of Ethereum full node related APIs for transaction pre exec.
-type TxPreExecAPI struct {
- eth *Ethereum
-}
-
-// NewTxPreExecAPI creates a new instance of TxPreExecAPI.
-func NewTxPreExecAPI(eth *Ethereum) *TxPreExecAPI {
- return &TxPreExecAPI{eth: eth}
-}
-
-func (api *TxPreExecAPI) TransactionPreExec(ctx context.Context, origins []PreArgs, blockNrOrHash *rpc.BlockNumberOrHash, stateOverrides *override.StateOverride) ([]PreResult, error) {
- start := time.Now()
- // gen requestID
- requestID := uuid.NewString()
- defer func(s time.Time, id string) {
- log.Info("Executing TransactionPreExec call finished", "requestID", id, "runtime", time.Since(s))
- }(start, requestID)
- preResList := make([]PreResult, 0)
-
- bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
- if blockNrOrHash != nil {
- bNrOrHash = *blockNrOrHash
- }
- state, header, err := api.eth.APIBackend.StateAndHeaderByNumberOrHash(ctx, bNrOrHash)
-
- if state == nil || err != nil {
- return nil, err
- }
- if stateOverrides != nil {
- err = stateOverrides.Apply(state, nil)
- if err != nil {
- return nil, err
- }
- }
- blockNumber := big.NewInt(0).Set(header.Number)
-
- for i, origin := range origins {
- // Setup context with timeout for each individual transaction
- // ETH RPC EVM Timeout default 5s per transaction
- timeout := api.eth.APIBackend.RPCEVMTimeout()
- txCtx, cancel := context.WithTimeout(ctx, timeout)
- defer cancel()
- var gasUsed uint64
- log.Info("TransactionPreExec", "requestID", requestID, "input index", i, "input args", origin.ToLogString())
-
- var prevArg *PreArgs
- if i > 0 {
- prevArg = &origins[i-1]
- }
- correctedGas, err := preArgsCheck(state, origin, prevArg, i)
- if err != nil {
- preError := PreError{
- Code: CheckPreArgsErrCode,
- Msg: err.Error(),
- }
- preResult := toPreResult(nil, nil, nil, preError, gasUsed, blockNumber)
- preResList = append(preResList, preResult)
- continue
- }
-
- if correctedGas != nil {
- origin.Gas = correctedGas
- }
-
- rawRes, gasUsed, receipt, err := applyMessageWithTracer(txCtx, api, state, origin, header, i, timeout)
- if err != nil {
- log.Error("TransactionPreExec: applyMessageWithTracer failed", "requestID", requestID, "input args", origin.ToLogString(), "error", err.Error())
- preError := toPreError(err, nil)
- preResult := toPreResult(nil, nil, nil, preError, gasUsed, blockNumber)
- preResList = append(preResList, preResult)
- continue
- }
-
- txHash := common.BigToHash(big.NewInt(int64(i)))
-
- preRes, err := processTracerResults(rawRes, state, txHash, header, receipt, gasUsed, blockNumber)
- if err != nil {
- log.Error("TransactionPreExec: processTracerResults failed", "requestID", requestID, "input args", origin.ToLogString(), "error", err.Error())
- preError := toPreError(err, nil)
- preResult := toPreResult(nil, nil, nil, preError, gasUsed, blockNumber)
- preResList = append(preResList, preResult)
- continue
- }
-
- preResList = append(preResList, preRes)
- log.Info("TransactionPreExec execute finished", "requestID", requestID, "input index", i, "result", preRes.ToLogString(), "runtime", time.Since(start))
- }
- return preResList, nil
-}
-
-func convertCallTracerResultToInnerTxs(traceResult interface{}) (result []*PreExecInnerTx, err error) {
- if traceResult == nil {
- return nil, fmt.Errorf("call tracer result is nil")
- }
-
- traceResultStr, err := json.Marshal(traceResult)
- if err != nil {
- return nil, err
- }
- callTx := CallTracerResult{}
- if err := json.Unmarshal(traceResultStr, &callTx); err != nil {
- return nil, err
- }
-
- result = make([]*PreExecInnerTx, 0)
- convertCallToInnerTxsRecursive(callTx, 0, 0, "", false, &result)
- return
-}
-
-// convertCallToInnerTxsRecursive recursively converts a CallTracerResult and all its nested calls to PreExecInnerTx
-func convertCallToInnerTxsRecursive(callTx CallTracerResult, depth int64, index int64, depthIndexRoot string, parentError bool, result *[]*PreExecInnerTx) {
- isError := parentError
- var errorMsg string
- if callTx.Error != "" {
- isError = true
- errorMsg = callTx.Error
- }
- if callTx.Error != "" && callTx.RevertReason != "" {
- isError = true
- errorMsg = fmt.Sprintf("%s,%s", callTx.Error, callTx.RevertReason)
- }
-
- gasUsed := new(big.Int)
- if len(callTx.GasUsed) > 2 && strings.HasPrefix(callTx.GasUsed, "0x") {
- gasUsed, _ = gasUsed.SetString(callTx.GasUsed[2:], 16)
- }
-
- gas := new(big.Int)
- if len(callTx.Gas) > 2 && strings.HasPrefix(callTx.Gas, "0x") {
- gas, _ = gas.SetString(callTx.Gas[2:], 16)
- }
-
- valueWei := ""
- if len(callTx.Value) > 2 && strings.HasPrefix(callTx.Value, "0x") {
- valueWeiInt := new(big.Int)
- valueWeiInt, _ = valueWeiInt.SetString(callTx.Value[2:], 16)
- valueWei = valueWeiInt.String()
- }
-
- gasUint64 := gas.Uint64()
- gasUsedUint64 := gasUsed.Uint64()
- returnGas := uint64(0)
- if gasUint64 > gasUsedUint64 {
- returnGas = gasUint64 - gasUsedUint64
- }
-
- // Handle empty output - ensure it's "0x" instead of ""
- output := callTx.Output
- if output == "" {
- output = "0x"
- }
-
- // Create inner transaction
- innerTx := &PreExecInnerTx{
- Dept: *big.NewInt(depth),
- InternalIndex: *big.NewInt(index),
- CallType: strings.ToLower(callTx.Type),
- TraceAddress: "",
- CodeAddress: "",
- From: common.HexToAddress(callTx.From).Hex(),
- To: common.HexToAddress(callTx.To).Hex(),
- Input: callTx.Input,
- Output: output,
- IsError: isError,
- GasUsed: gasUsedUint64,
- Value: valueWei,
- ValueWei: valueWei,
- Error: errorMsg,
- ReturnGas: returnGas,
- }
-
- // Handle root vs nested call differences
- isRoot := depth == 0
- if isRoot {
- innerTx.Name = strings.ToLower(callTx.Type)
- } else {
- if len(callTx.From) > 2 && strings.HasPrefix(callTx.From, "0x") {
- innerTx.From = "0x000000000000000000000000" + callTx.From[2:]
- }
- if len(callTx.To) > 2 && strings.HasPrefix(callTx.To, "0x") {
- innerTx.To = "0x000000000000000000000000" + callTx.To[2:]
- }
-
- if strings.ToLower(callTx.Type) == "callcode" {
- innerTx.CodeAddress = callTx.To
- }
-
- currentDepthIndexRoot := fmt.Sprintf("%s_%d", depthIndexRoot, index)
- innerTx.Name = fmt.Sprintf("%s%s", innerTx.CallType, currentDepthIndexRoot)
- }
-
- // Add current transaction to result
- *result = append(*result, innerTx)
-
- // Recursively process nested calls
- if len(callTx.Calls) > 0 {
- for i, nestedCall := range callTx.Calls {
- var nestedDepthIndexRoot string
- if isRoot {
- nestedDepthIndexRoot = ""
- } else {
- nestedDepthIndexRoot = fmt.Sprintf("%s_%d", depthIndexRoot, index)
- }
- convertCallToInnerTxsRecursive(nestedCall, depth+1, int64(i), nestedDepthIndexRoot, innerTx.IsError, result)
- }
- }
-}
-
-func convertPrestateTracerResultToStateDiff(traceResult interface{}) (result map[string]interface{}, err error) {
- if traceResult == nil {
- return nil, fmt.Errorf("prestate tracer result is nil")
- }
- result = make(map[string]interface{})
- stateDiffResultStr, err := json.Marshal(traceResult)
- if err != nil {
- return nil, err
- }
- stateAccount := make(map[string]map[common.Address]*StateAccount)
- if err := json.Unmarshal(stateDiffResultStr, &stateAccount); err != nil {
- return nil, err
- }
- var pre, post map[common.Address]*StateAccount
- if preState, exist := stateAccount["pre"]; exist {
- pre = preState
- } else {
- return nil, nil
- }
- if postState, exist := stateAccount["post"]; exist {
- post = postState
- } else {
- return nil, nil
- }
-
- for addr, postState := range post {
- if preState, exist := pre[addr]; exist {
- addrMap := make(map[string]interface{})
- preStateBalance, postStateBalance := new(big.Int), new(big.Int)
- if strings.HasPrefix(preState.Balance, "0x") {
- preStateBalance, _ = big.NewInt(0).SetString(preState.Balance[2:], 16)
- }
- // post state balance
- if strings.HasPrefix(postState.Balance, "0x") {
- postStateBalance, _ = big.NewInt(0).SetString(postState.Balance[2:], 16)
- } else {
- postStateBalance = preStateBalance
- }
- balance := struct {
- Before string `json:"before"`
- After string `json:"after"`
- }{
- Before: preStateBalance.String(),
- After: postStateBalance.String(),
- }
- addrMap["balance"] = balance
- result[addr.String()] = addrMap
- }
- }
-
- return
-}
-
-func applyMessageWithTracer(ctx context.Context, api *TxPreExecAPI, state *coreState.StateDB, origin PreArgs, header *types.Header, index int, timeout time.Duration) (json.RawMessage, uint64, *types.Receipt, error) {
- // get ChainID from ChainConfig
- chainId := api.eth.APIBackend.ChainConfig().ChainID
- txArgs := ethapi.TransactionArgs{
- ChainID: (*hexutil.Big)(chainId),
- From: origin.From,
- To: origin.To,
- Gas: origin.Gas,
- GasPrice: origin.GasPrice,
- MaxFeePerGas: origin.MaxFeePerGas,
- MaxPriorityFeePerGas: origin.MaxPriorityFeePerGas,
- Value: origin.Value,
- Data: origin.Data,
- Input: origin.Input,
- AuthorizationList: origin.AuthorizationList,
- }
-
- if err := txArgs.CallDefaults(api.eth.APIBackend.RPCGasCap(), header.BaseFee, api.eth.APIBackend.ChainConfig().ChainID); err != nil {
- return nil, 0, nil, err
- }
-
- msg := txArgs.ToMessage(header.BaseFee, true)
- tx := txArgs.ToTransaction(types.LegacyTxType)
-
- txHash := common.BigToHash(big.NewInt(int64(index)))
- traceConfig := []byte(`
- {
- "prestateTracer": {
- "diffMode": true
- },
- "callTracer": null
- }
- `)
-
- txctx := &tracers.Context{
- BlockHash: header.Hash(),
- BlockNumber: big.NewInt(0).Set(header.Number),
- TxIndex: 0,
- TxHash: txHash,
- }
- tracer, err := tracers.DefaultDirectory.New("muxTracer", txctx, traceConfig, api.eth.APIBackend.ChainConfig())
- if err != nil {
- return nil, 0, nil, err
- }
-
- hookedState := coreState.NewHookedState(state, tracer.Hooks)
- blockContext := core.NewEVMBlockContext(header, api.eth.BlockChain(), nil, api.eth.APIBackend.ChainConfig(), state)
- evm := vm.NewEVM(blockContext, hookedState, api.eth.APIBackend.ChainConfig(), vm.Config{NoBaseFee: true, Tracer: tracer.Hooks})
-
- // Setup timeout context
- timeoutCtx, cancel := context.WithTimeout(ctx, timeout)
- defer cancel()
-
- go func() {
- <-timeoutCtx.Done()
- evm.Cancel()
- }()
-
- evm.Context.BaseFee = big.NewInt(0)
-
- // blocknumber and time are random to simulate real transactions with propagation delay
- evm.Context.BlockNumber.Add(evm.Context.BlockNumber, big.NewInt(rand.Int63n(6)+6))
- evm.Context.Time += uint64(rand.Int63n(60) + 30)
- gp := new(core.GasPool).AddGas(MaxGasLimit)
- state.SetTxContext(txHash, index)
-
- var gasUsed uint64
- receipt, err := core.ApplyTransactionWithEVM(msg, gp, state, evm.Context.BlockNumber, txctx.BlockHash, evm.Context.Time, tx, &gasUsed, evm)
- if err != nil {
- return nil, gasUsed, nil, err
- }
-
- // If the timer caused an abort, return an appropriate error message
- if evm.Cancelled() {
- return nil, gasUsed, nil, fmt.Errorf("execution aborted (timeout = %v)", timeout)
- }
-
- rawRes, err := tracer.GetResult()
- if err != nil {
- return nil, gasUsed, nil, err
- }
-
- return rawRes, gasUsed, receipt, nil
-}
-
-func processTracerResults(rawRes json.RawMessage, state *coreState.StateDB, txHash common.Hash, header *types.Header, receipt *types.Receipt, gasUsed uint64, blockNumber *big.Int) (PreResult, error) {
- var res map[string]interface{}
- if err := json.Unmarshal(rawRes, &res); err != nil {
- preError := toPreError(err, nil)
- return toPreResult(nil, nil, nil, preError, gasUsed, blockNumber), nil
- }
-
- // convert callTracer result to inner txs
- innerTxs := make([]*PreExecInnerTx, 0)
- if t, exist := res["callTracer"]; exist {
- convertedInnerTxs, err := convertCallTracerResultToInnerTxs(t)
- if err != nil {
- preError := PreError{
- Code: UnKnownErrCode,
- Msg: err.Error(),
- }
- return toPreResult(nil, nil, nil, preError, gasUsed, blockNumber), nil
- }
- // innerTxs are set only when there are deep calls (contract to contract calls) or failed calls
- hasDeepCalls := false
- hasFailedCalls := false
- for _, innerTx := range convertedInnerTxs {
- if innerTx.Dept.Int64() > 0 {
- hasDeepCalls = true
- }
- if innerTx.IsError || innerTx.Error != "" {
- hasFailedCalls = true
- }
- }
- if hasDeepCalls || hasFailedCalls {
- innerTxs = convertedInnerTxs
- }
- }
-
- // convert prestateTracer result to state diff
- stateDiff := make(map[string]interface{}, 0)
- if t, exist := res["prestateTracer"]; exist {
- var err error
- stateDiff, err = convertPrestateTracerResultToStateDiff(t)
- if err != nil {
- preError := PreError{
- Code: UnKnownErrCode,
- Msg: err.Error(),
- }
- return toPreResult(nil, nil, nil, preError, gasUsed, blockNumber), nil
- }
- }
-
- // Create the final result
- preRes := toPreResult(innerTxs, state.GetLogs(txHash, header.Number.Uint64(), header.Hash(), header.Time), stateDiff, PreError{}, gasUsed, blockNumber)
-
- // Handle receipt status failures
- if receipt != nil && receipt.Status == types.ReceiptStatusFailed {
- preRes.Error = toPreError(nil, nil)
- }
-
- // Handle inner transaction errors
- if preRes.Error.Msg == "" && len(innerTxs) != 0 && innerTxs[0].Error != "" {
- preRes.Error = PreError{
- Code: RevertedErrCode,
- Msg: innerTxs[0].Error,
- }
- }
-
- return preRes, nil
-}
-
-func preArgsCheck(state *coreState.StateDB, arg PreArgs, prevArg *PreArgs, index int) (*hexutil.Uint64, error) {
- if arg.From == nil {
- return nil, fmt.Errorf("from is nil")
- }
-
- if arg.To == nil {
- return nil, fmt.Errorf("to is nil")
- }
-
- if arg.Nonce == nil {
- return nil, fmt.Errorf("%s, nonce is nil", arg.From.Hex())
- }
-
- // check whether sender's nonce decreases
- if prevArg != nil && *arg.From == *prevArg.From && (uint64)(*arg.Nonce) <= (uint64)(*prevArg.Nonce) {
- return nil, fmt.Errorf("%v nonce decreases, tx index %d has nonce %d, tx index %d has nonce %d",
- arg.From.Hex(), index-1, (uint64)(*prevArg.Nonce), index, (uint64)(*arg.Nonce))
- }
-
- msgFrom := *arg.From
- msgNonce := uint64(*arg.Nonce)
- stNonce := state.GetNonce(msgFrom)
-
- if stNonce > msgNonce {
- return nil, fmt.Errorf("%w: address %v, tx: %d state: %d", core.ErrNonceTooLow,
- msgFrom.Hex(), msgNonce, stNonce)
- } else if stNonce+1 < stNonce {
- return nil, fmt.Errorf("%w: address %v, nonce: %d", core.ErrNonceMax,
- msgFrom.Hex(), stNonce)
- }
-
- // check gas, if gas value is 0 or > 30000000, return corrected gas value
- if arg.Gas == nil {
- gas := uint64(MaxGasLimit)
- return (*hexutil.Uint64)(&gas), nil
- } else {
- gas := uint64(*arg.Gas)
- if gas == 0 || gas > uint64(MaxGasLimit) {
- gas = uint64(MaxGasLimit)
- return (*hexutil.Uint64)(&gas), nil
- }
- }
-
- return nil, nil
-}
diff --git a/eth/backend.go b/eth/backend.go
index 788f1ae374..264ae545ae 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -263,8 +263,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
EnablePreimageRecording: config.EnablePreimageRecording,
EnableWitnessStats: config.EnableWitnessStats,
StatelessSelfValidation: config.StatelessSelfValidation,
- // For X Layer
- EnableInnerTxs: config.XLayer.EnableInnerTx,
},
// Enables file journaling for the trie database. The journal files will be stored
// within the data directory. The corresponding paths will be either:
@@ -527,17 +525,9 @@ func (s *Ethereum) APIs() []rpc.API {
//// Append any APIs exposed explicitly by the consensus engine
//apis = append(apis, s.engine.APIs(s.BlockChain())...)
- // For XLayer, eth_transactionPreExec
- txPreExecAPI := NewTxPreExecAPI(s)
-
// Xlayer: Wrap APIs with migration routing if configured
if s.xlayerLegacyRPCService != nil {
- apis = WrapAPIsForXlayer(apis, txPreExecAPI, s.xlayerLegacyRPCService)
- } else {
- apis = append(apis, rpc.API{
- Namespace: "eth",
- Service: txPreExecAPI,
- })
+ apis = WrapAPIsForXlayer(apis, s.xlayerLegacyRPCService)
}
// Append any Sequencer APIs as enabled
diff --git a/eth/ethconfig/config_xlayer.go b/eth/ethconfig/config_xlayer.go
index 8706c66292..7f87e2938f 100644
--- a/eth/ethconfig/config_xlayer.go
+++ b/eth/ethconfig/config_xlayer.go
@@ -5,7 +5,6 @@ import (
)
var DefaultXLayerConfig = XLayerConfig{
- EnableInnerTx: true,
LegacyPp: MigrationConfig{
MigrationBlock: nil,
PPRPCUrl: "",
@@ -19,8 +18,7 @@ var DefaultXLayerConfig = XLayerConfig{
// XLayerConfig is the X Layer config used on the eth backend
type XLayerConfig struct {
- EnableInnerTx bool `toml:",omitempty"`
- LegacyPp MigrationConfig `toml:",omitempty"` // The erigon RPC endpoint URL for pre-migration blocks
+ LegacyPp MigrationConfig `toml:",omitempty"` // The erigon RPC endpoint URL for pre-migration blocks
Monitor MonitorConfig `toml:",omitempty"` // Transaction monitoring configuration
}
diff --git a/internal/ethapi/api_xlayer.go b/internal/ethapi/api_xlayer.go
deleted file mode 100644
index 28099a2186..0000000000
--- a/internal/ethapi/api_xlayer.go
+++ /dev/null
@@ -1,66 +0,0 @@
-package ethapi
-
-import (
- "context"
- "errors"
- "fmt"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/rawdb"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/rpc"
-)
-
-// GetInternalTransactions returns the inner transactions for a given transaction hash
-func (api *TransactionAPI) GetInternalTransactions(ctx context.Context, txHash common.Hash) ([]*types.InnerTx, error) {
- // Check if inner transaction feature is enabled
- if xlayerBackend, ok := api.b.(XLayerBackend); ok && !xlayerBackend.IsInnerTxEnabled() {
- return nil, errors.New("unsupported internal transaction method")
- }
-
- innerTxs, err := rawdb.ReadInnerTxsByTxHash(api.b.ChainDb(), txHash)
-
- if err != nil {
- return nil, fmt.Errorf("failed to read inner transactions: %w", err)
- }
-
- if innerTxs == nil {
- return []*types.InnerTx{}, nil
- }
-
- return innerTxs, nil
-}
-
-// GetBlockInternalTransactions returns all inner transactions for all transactions in a block
-func (api *TransactionAPI) GetBlockInternalTransactions(ctx context.Context, blockNr rpc.BlockNumber) (map[common.Hash][]*types.InnerTx, error) {
- // Check if inner transaction feature is enabled
- if xlayerBackend, ok := api.b.(XLayerBackend); ok && !xlayerBackend.IsInnerTxEnabled() {
- return nil, errors.New("unsupported internal transaction method")
- }
-
- block, err := api.b.BlockByNumber(ctx, blockNr)
- if err != nil {
- return nil, fmt.Errorf("failed to get block: %w", err)
- }
- if block == nil {
- return nil, fmt.Errorf("block not found")
- }
-
- blockNum := block.NumberU64()
- transactions := block.Transactions()
- result := make(map[common.Hash][]*types.InnerTx)
-
- // Retrieve inner transactions for each transaction in the block
- for i, tx := range transactions {
- innerTxs, err := rawdb.ReadInnerTxs(api.b.ChainDb(), blockNum, uint32(i))
- if err != nil {
- continue
- }
- if len(innerTxs) > 0 {
- // Use transaction hash as key
- result[tx.Hash()] = innerTxs
- }
- }
-
- return result, nil
-}
diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go
index 8b19e27405..e094bb53be 100644
--- a/internal/ethapi/backend.go
+++ b/internal/ethapi/backend.go
@@ -103,12 +103,6 @@ type Backend interface {
NewMatcherBackend() filtermaps.MatcherBackend
}
-// For X Layer - InnerTxBackend extends Backend with inner transaction support
-type XLayerBackend interface {
- Backend
- IsInnerTxEnabled() bool
-}
-
func GetAPIs(apiBackend Backend) []rpc.API {
nonceLock := new(AddrLocker)
return []rpc.API{