From 628a5d5dac9b4077f6bf81d8d67b1e31a3d1566c Mon Sep 17 00:00:00 2001 From: JimmyShi22 <417711026@qq.com> Date: Fri, 6 Feb 2026 21:28:03 +0800 Subject: [PATCH] rm innerTx and preExec --- .../test.geth.external.rpc.config.toml | 2 - devnet/config-op/test.geth.rpc.config.toml | 2 - devnet/config-op/test.geth.seq.config.toml | 2 - devnet/entrypoint/reth-external-rpc.sh | 10 +- devnet/op-geth/test/e2e/smoke_test.go | 681 ------------------ devnet/op-geth/test/e2e/test_utils_xlayer.go | 40 - devnet/op-geth/test/operations/rpc_all.go | 55 -- devnet/op-geth/test/operations/rpc_client.go | 26 - devnet/scripts/setup-cgt-function.sh | 5 +- scripts/dev-utils/compare-legacy-rpc.md | 3 - scripts/dev-utils/compare-legacy-rpc.sh | 371 +--------- scripts/dev-utils/legacy-rpc-test.sh | 36 - 12 files changed, 8 insertions(+), 1225 deletions(-) diff --git a/devnet/config-op/test.geth.external.rpc.config.toml b/devnet/config-op/test.geth.external.rpc.config.toml index 45a62a03..aa3c9de4 100644 --- a/devnet/config-op/test.geth.external.rpc.config.toml +++ b/devnet/config-op/test.geth.external.rpc.config.toml @@ -31,7 +31,5 @@ GlobalQueue = 100000 AccountSlots = 50000 AccountQueue = 10000 -[Eth.XLayer] -EnableInnerTx = true [Eth.GPO] MinSuggestedPriorityFee = 1 diff --git a/devnet/config-op/test.geth.rpc.config.toml b/devnet/config-op/test.geth.rpc.config.toml index 076f90b6..b1a739ac 100644 --- a/devnet/config-op/test.geth.rpc.config.toml +++ b/devnet/config-op/test.geth.rpc.config.toml @@ -39,7 +39,5 @@ GlobalQueue = 100000 AccountSlots = 50000 AccountQueue = 10000 -[Eth.XLayer] -EnableInnerTx = true [Eth.GPO] MinSuggestedPriorityFee = 1 diff --git a/devnet/config-op/test.geth.seq.config.toml b/devnet/config-op/test.geth.seq.config.toml index 334d45ed..8fa7c626 100644 --- a/devnet/config-op/test.geth.seq.config.toml +++ b/devnet/config-op/test.geth.seq.config.toml @@ -31,7 +31,5 @@ GlobalQueue = 100000 AccountSlots = 50000 AccountQueue = 10000 -[Eth.XLayer] -EnableInnerTx = false [Eth.GPO] MinSuggestedPriorityFee = 1 diff --git a/devnet/entrypoint/reth-external-rpc.sh b/devnet/entrypoint/reth-external-rpc.sh index 5b4cd13f..8119dba0 100755 --- a/devnet/entrypoint/reth-external-rpc.sh +++ b/devnet/entrypoint/reth-external-rpc.sh @@ -11,13 +11,6 @@ if [ "${JEMALLOC_PROFILING:-false}" = "true" ]; then echo "Jemalloc profiling enabled: _RJEM_MALLOC_CONF=$_RJEM_MALLOC_CONF" fi -# Build the optional innertx flag -INNERTX_FLAG="" -if [ "${ENABLE_INNERTX_RPC:-false}" = "true" ]; then - INNERTX_FLAG="--xlayer.enable-innertx" - echo "Inner transaction tracking enabled for RPC" -fi - # Read the first argument (1 or 0), default to 0 if not provided FLASHBLOCKS_RPC=${FLASHBLOCKS_RPC:-"true"} @@ -52,8 +45,7 @@ CMD="op-reth node \ --txpool.max-pending-txns=100000 \ --txpool.max-new-txns=100000 \ --rpc.eth-proof-window=10000 \ - --rollup.sequencer-http=http://op-geth-rpc:8545 - $INNERTX_FLAG" + --rollup.sequencer-http=http://op-geth-rpc:8545" # For flashblocks architecture. Enable flashblocks RPC if [ "$FLASHBLOCK_ENABLED" = "true" ] && [ "$FLASHBLOCKS_RPC" = "true" ]; then diff --git a/devnet/op-geth/test/e2e/smoke_test.go b/devnet/op-geth/test/e2e/smoke_test.go index dc98d5d6..b60e9451 100644 --- a/devnet/op-geth/test/e2e/smoke_test.go +++ b/devnet/op-geth/test/e2e/smoke_test.go @@ -539,687 +539,6 @@ func TestTxPoolRPC(t *testing.T) { }) } -// TestInnerTransactionRPC tests inner transaction related RPC methods -func TestInnerTx(t *testing.T) { - if testing.Short() { - t.Skip() - } - - ctx := context.Background() - client, err := ethclient.Dial(operations.DefaultL2NetworkURL) - require.NoError(t, err) - defer client.Close() - - EnsureContractsDeployed(t) - - preexecPrivateKey, err := crypto.HexToECDSA(TmpSenderPrivateKey) - require.NoError(t, err) - preexecFrom := crypto.PubkeyToAddress(preexecPrivateKey.PublicKey) - - // Call ContractA's triggerCall function which will call ContractB's dummy function - // triggerCall() function selector: 0xf18c388a - triggerCallData := common.Hex2Bytes("f18c388a") - - signedContractATxHash, err := MakeContractCall(t, ctx, client, preexecPrivateKey, ContractAAddr, triggerCallData, 200000, nil) - require.NoError(t, err) - - contractAReceipt, err := client.TransactionReceipt(ctx, signedContractATxHash) - require.NoError(t, err) - - // Call ContractC's setValue function - contractCSetValueData := common.Hex2Bytes("552410770000000000000000000000000000000000000000000000000000000000000123") - signedContractCSetValueTxHash, err := MakeContractCall(t, ctx, client, preexecPrivateKey, ContractCAddr, contractCSetValueData, 200000, nil) - require.NoError(t, err) - fmt.Printf("signedContractCSetValueTxHash: %s\n", signedContractCSetValueTxHash.Hex()) - - // Call ContractC's getValue function - contractCGetValueData := common.Hex2Bytes("20965255") - signedContractCGetValueTxHash, err := MakeContractCall(t, ctx, client, preexecPrivateKey, ContractCAddr, contractCGetValueData, 200000, nil) - require.NoError(t, err) - contractCGetValueReceipt, err := client.TransactionReceipt(ctx, signedContractCGetValueTxHash) - require.NoError(t, err) - - t.Run("GetInternalTransactions", func(t *testing.T) { - innerTxs, err := operations.EthGetInternalTransactions(signedContractCGetValueTxHash) - require.NoError(t, err) - require.NotNil(t, innerTxs, "Inner transactions result should not be nil") - require.Len(t, innerTxs, 1, "Should have exactly 1 inner transaction for getValue call") - - innerTx := innerTxs[0] - require.NotNil(t, innerTx, "innerTx should not be nil") - - expectedInnerTx := &types.InnerTx{ - Dept: *big.NewInt(0), - InternalIndex: *big.NewInt(0), - CallType: "", - Name: "", - TraceAddress: "", - CodeAddress: "", - From: preexecFrom.Hex(), - To: ContractCAddr.Hex(), - Input: "", - Output: "0x0000000000000000000000000000000000000000000000000000000000000123", - IsError: false, - Error: "", - Value: "", - ValueWei: "0", - CallValueWei: "0x0", - } - - ValidateInnerTransactionMatch(t, innerTx, expectedInnerTx, "ContractC getValue inner transaction") - require.Equal(t, contractCGetValueReceipt.GasUsed, innerTx.GasUsed, "GasUsed should be the same as the gasUsed in transaction receipt for getValue call") - require.Equal(t, uint64(200000), innerTx.Gas, "Gas should be the same as the gas in transaction receipt for getValue call") - }) - - t.Run("GetInternalTransactions_WithDeepInnerTransactions", func(t *testing.T) { - innerTxs, err := operations.EthGetInternalTransactions(signedContractATxHash) - require.NoError(t, err) - require.NotNil(t, innerTxs, "Inner transactions result should not be nil") - require.Len(t, innerTxs, 2, "Should have exactly 2 inner transactions: EOA->ContractA and ContractA->ContractB") - - // Validate first inner transaction: EOA -> ContractA (triggerCall) - expectedInnertx1 := &types.InnerTx{ - Dept: *big.NewInt(0), - InternalIndex: *big.NewInt(0), - CallType: "", - Name: "", - TraceAddress: "", - CodeAddress: "", - From: preexecFrom.Hex(), - To: ContractAAddr.Hex(), - Input: "", - Output: "", - IsError: false, - Error: "", - Value: "", - ValueWei: "0", - CallValueWei: "0x0", - } - ValidateInnerTransactionMatch(t, innerTxs[0], expectedInnertx1, "First inner transaction (EOA -> ContractA)") - - // gasUsed of first inner transaction should be the same as the gasUsed in transaction receipt - require.Equal(t, contractAReceipt.GasUsed, innerTxs[0].GasUsed, "First inner transaction GasUsed should be the same as contractAReceipt.GasUsed") - require.Equal(t, uint64(200000), innerTxs[0].Gas, "Gas should be the same as the gas in transaction receipt for getValue call") - - // Validate second inner transaction: ContractA -> ContractB (dummy call) - expectedInnertx2 := &types.InnerTx{ - Dept: *big.NewInt(1), - InternalIndex: *big.NewInt(0), - CallType: "call", - Name: "call_0", - TraceAddress: "", - CodeAddress: "", - From: ContractAAddr.Hex(), - To: ContractBAddr.Hex(), - Input: "0x32e43a11", - Output: "", - IsError: false, - Error: "", - Value: "", - ValueWei: "0", - CallValueWei: "0x0", - } - ValidateInnerTransactionMatch(t, innerTxs[1], expectedInnertx2, "Second inner transaction (ContractA -> ContractB)") - - // gasUsed of second inner transaction should be less than the gasUsed in transaction receipt - require.Less(t, innerTxs[1].GasUsed, contractAReceipt.GasUsed, "Second inner transaction GasUsed should be the less than contractAReceipt.GasUsed") - }) - - t.Run("GetInternalTransactions_WithOutput", func(t *testing.T) { - innerTxs, err := operations.EthGetInternalTransactions(signedContractCGetValueTxHash) - require.NoError(t, err) - require.NotNil(t, innerTxs, "Inner transactions result should not be nil") - require.Len(t, innerTxs, 1, "Should have exactly 1 inner transaction for getValue call") - - innerTx := innerTxs[0] - require.NotNil(t, innerTx, "innerTx should not be nil") - - expectedInnerTx := &types.InnerTx{ - Dept: *big.NewInt(0), - InternalIndex: *big.NewInt(0), - CallType: "", - Name: "", - TraceAddress: "", - CodeAddress: "", - From: preexecFrom.Hex(), - To: ContractCAddr.Hex(), - Input: "", - Output: "0x0000000000000000000000000000000000000000000000000000000000000123", - IsError: false, - Error: "", - Value: "", - ValueWei: "0", - CallValueWei: "0x0", - } - - ValidateInnerTransactionMatch(t, innerTx, expectedInnerTx, "ContractC getValue inner transaction with output") - require.Equal(t, contractCGetValueReceipt.GasUsed, innerTx.GasUsed, "GasUsed should be the same as the gasUsed in transaction receipt") - }) - t.Run("GetInternalTransactions_Batch", func(t *testing.T) { - // Send multiple transactions in a batch - txHashes := TransTokenBatch(t, ctx, client, uint256.NewInt(params.GWei), operations.DefaultL2NewAcc1Address, 10, operations.DefaultRichPrivateKey) - require.Len(t, txHashes, 10, "Should have created 10 transactions") - - // Verify each transaction has exactly 1 inner transaction - numInnerTxs := 0 - for i, txHash := range txHashes { - fmt.Printf("Getting inner transactions for tx %d: %s\n", i, txHash) - innerTxs, err := operations.EthGetInternalTransactions(common.HexToHash(txHash)) - require.NoError(t, err, "Failed to get inner transactions for tx %d: %s", i, txHash) - require.Len(t, innerTxs, 1, "Transaction %d (%s) should have exactly 1 inner transaction, got %d", i, txHash, len(innerTxs)) - - txReceipt, err := client.TransactionReceipt(ctx, common.HexToHash(txHash)) - require.NoError(t, err, "Failed to get transaction receipt for tx %d: %s", i, txHash) - - innerTx := innerTxs[0] - require.NotNil(t, innerTx, "innerTx should not be nil for tx %d", i) - - expectedInnerTx := &types.InnerTx{ - Dept: *big.NewInt(0), - InternalIndex: *big.NewInt(0), - CallType: "", - Name: "", - TraceAddress: "", - CodeAddress: "", - From: operations.DefaultRichAddress, - To: operations.DefaultL2NewAcc1Address, - Input: "", - Output: "", - IsError: false, - Error: "", - Value: "", - ValueWei: strconv.FormatUint(params.GWei, 10), - CallValueWei: hexutil.EncodeUint64(params.GWei), - } - - ValidateInnerTransactionMatch(t, innerTx, expectedInnerTx, fmt.Sprintf("Batch transaction %d", i)) - require.Equal(t, txReceipt.GasUsed, innerTx.GasUsed, "GasUsed should be the same as the gasUsed in transaction receipt for batch transaction %d", i) - numInnerTxs++ - } - require.Equal(t, 10, numInnerTxs, "Should have 10 inner transactions for all 10 transactions") - }) - - t.Run("GetBlockInternalTransactions_Batch", func(t *testing.T) { - // Send multiple transactions in a batch - txHashes := TransTokenBatch(t, ctx, client, uint256.NewInt(params.GWei), operations.DefaultL2NewAcc1Address, 5, operations.DefaultRichPrivateKey) - require.Len(t, txHashes, 5, "Should have created 5 transactions") - - blockNumbers := make(map[uint64][]int) - - for i, txHashStr := range txHashes { - txHash := common.HexToHash(txHashStr) - receipt, err := client.TransactionReceipt(ctx, txHash) - require.NoError(t, err, "Failed to get receipt for tx %d", i) - - blockNum := receipt.BlockNumber.Uint64() - blockNumbers[blockNum] = append(blockNumbers[blockNum], i) - } - - totalValidatedTxs := 0 - - for blockNum, txIndices := range blockNumbers { - fmt.Printf("Testing block %d with %d transactions\n", blockNum, len(txIndices)) - - blockInnerTxs, err := operations.EthGetBlockInternalTransactions(rpc.BlockNumber(blockNum)) - require.NoError(t, err, "Failed to get block internal transactions for block %d", blockNum) - require.NotNil(t, blockInnerTxs, "Block inner transactions should not be nil for block %d", blockNum) - - // Verify all transactions in this block are present in block internal transactions - batchTxsInBlock := 0 - for _, txIdx := range txIndices { - txHash := common.HexToHash(txHashes[txIdx]) - blockInnerTxsForTx, exists := blockInnerTxs[txHash] - require.True(t, exists, "Transaction %d (%s) should be in block %d internal transactions", txIdx, txHashes[txIdx], blockNum) - require.Len(t, blockInnerTxsForTx, 1, "Transaction %d should have exactly 1 inner transaction", txIdx) - batchTxsInBlock++ - - innerTx := blockInnerTxsForTx[0] - - // Compare with individual transaction inner transactions - individualInnerTxs, err := operations.EthGetInternalTransactions(txHash) - require.NoError(t, err, "Failed to get individual inner transactions for tx %d", txIdx) - require.Len(t, individualInnerTxs, 1, "Individual inner transactions should have 1 entry for tx %d", txIdx) - - ValidateInnerTransactionMatch(t, individualInnerTxs[0], innerTx, fmt.Sprintf("batch tx %d comparison", txIdx)) - } - - totalValidatedTxs += batchTxsInBlock - } - - require.Equal(t, len(txHashes), totalValidatedTxs, "Should have validated all batch transactions") - fmt.Printf("Successfully validated all %d transactions across %d blocks\n", totalValidatedTxs, len(blockNumbers)) - }) - - t.Run("GetInnerTransactions_FailedTransactions", func(t *testing.T) { - amount := uint256.NewInt(params.GWei) - toAddress := ContractAAddr.String() - - txHash := TransTokenFail(t, ctx, client, TmpSenderPrivateKey, amount, toAddress) - - innerTxs, err := operations.EthGetInternalTransactions(txHash) - require.NoError(t, err, "Should be able to get inner transactions") - require.Len(t, innerTxs, 1, "Should have exactly 1 inner transaction for failed transfer") - - txReceipt, err := client.TransactionReceipt(ctx, txHash) - require.NoError(t, err, "Should be able to get transaction receipt") - - innerTx := innerTxs[0] - require.NotNil(t, innerTx, "innerTx should not be nil") - - senderPrivateKey, err := crypto.HexToECDSA(TmpSenderPrivateKey) - require.NoError(t, err) - senderAddress := crypto.PubkeyToAddress(senderPrivateKey.PublicKey) - - expectedInnerTx := &types.InnerTx{ - Dept: *big.NewInt(0), - InternalIndex: *big.NewInt(0), - CallType: "", - Name: "", - TraceAddress: "", - CodeAddress: "", - From: senderAddress.Hex(), - To: toAddress, - Input: "", - Output: "", - IsError: true, - Error: "execution reverted", - Value: "", - ValueWei: strconv.FormatUint(amount.Uint64(), 10), - CallValueWei: hexutil.EncodeUint64(amount.Uint64()), - } - - ValidateInnerTransactionMatch(t, innerTx, expectedInnerTx, "Failed transaction inner transaction") - require.Equal(t, txReceipt.GasUsed, innerTx.GasUsed, "GasUsed should be the same as the gasUsed in transaction receipt for failed transaction") - }) - - t.Run("SpecialBlockNumberFormats", func(t *testing.T) { - // Test "latest" format - latestResult, err := operations.EthGetBlockInternalTransactions(rpc.LatestBlockNumber) - require.NoError(t, err) - require.NotNil(t, latestResult, "Latest block should return a valid map") - fmt.Printf("'latest' block contains %d transactions with inner transactions\n", len(latestResult)) - - // Test "earliest" format - earliestResult, err := operations.EthGetBlockInternalTransactions(rpc.EarliestBlockNumber) - require.NoError(t, err) - require.NotNil(t, earliestResult, "Earliest block should return a valid map") - fmt.Printf("'earliest' block contains %d transactions with inner transactions\n", len(earliestResult)) - }) -} - -func TestTransactionPreExec(t *testing.T) { - if testing.Short() { - t.Skip() - } - - EnsureContractsDeployed(t) - - contractAABI, err := abi.JSON(strings.NewReader(constants.ContractAABIJson)) - require.NoError(t, err) - calldata, err := contractAABI.Pack("triggerCall") - require.NoError(t, err) - - ethClient, err := ethclient.Dial(operations.DefaultL2NetworkURL) - require.NoError(t, err) - defer ethClient.Close() - - fromAddr := common.HexToAddress("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266") - - // Fund the test address for gas validation tests - ctx := context.Background() - fundingAmount := uint256.NewInt(5000000000000000000) - fundingTxHash := TransToken(t, ctx, ethClient, fundingAmount, fromAddr.String()) - t.Logf("Funded test address %s with 5 ETH, tx: %s", fromAddr.Hex(), fundingTxHash) - - t.Run("InnerTransactionTracking", func(t *testing.T) { - // Test contract call with inner transactions - txRequest := map[string]interface{}{ - "from": fromAddr.Hex(), "to": ContractAAddr.Hex(), "gas": "0x30000", - "gasPrice": "0x4a817c800", "value": "0x0", "nonce": "0x1", - "data": fmt.Sprintf("0x%x", calldata), - } - stateOverride := map[string]interface{}{ - fromAddr.Hex(): map[string]interface{}{"balance": "0x1000000000000000000000"}, - } - - result, err := operations.EthTransactionPreExec(txRequest, "latest", stateOverride) - require.NoError(t, err) - - preExecResults, ok := result.([]interface{}) - require.True(t, ok, "Expected result to be an array") - require.Len(t, preExecResults, 1) - - preExecResult, ok := preExecResults[0].(map[string]interface{}) - require.True(t, ok, "Expected preExecResult to be a map") - require.NotNil(t, preExecResult["logs"]) - require.NotNil(t, preExecResult["stateDiff"]) - require.NotNil(t, preExecResult["gasUsed"]) - require.NotNil(t, preExecResult["blockNumber"]) - - innerTxList, ok := preExecResult["innerTxs"].([]interface{}) - require.True(t, ok) - require.GreaterOrEqual(t, len(innerTxList), 1) - - firstInnerTx := innerTxList[0].(map[string]interface{}) - require.Equal(t, "call", firstInnerTx["call_type"]) - require.Equal(t, strings.ToLower(ContractAAddr.Hex()), strings.ToLower(common.HexToAddress(firstInnerTx["to"].(string)).Hex())) - require.Equal(t, "0xf18c388a", firstInnerTx["input"].(string)) - require.False(t, firstInnerTx["is_error"].(bool), "Expected is_error to be false for the first inner transaction") - - secondInnerTx := innerTxList[1].(map[string]interface{}) - require.Equal(t, "call", secondInnerTx["call_type"]) - require.Equal(t, strings.ToLower(ContractAAddr.Hex()), strings.ToLower(common.HexToAddress(secondInnerTx["from"].(string)).Hex())) - require.Equal(t, strings.ToLower(ContractBAddr.Hex()), strings.ToLower(common.HexToAddress(secondInnerTx["to"].(string)).Hex())) - require.Equal(t, "0x32e43a11", secondInnerTx["input"].(string)) - - name := secondInnerTx["name"].(string) - require.True(t, name[len(name)-1] >= '0' && name[len(name)-1] <= '9') - require.False(t, secondInnerTx["is_error"].(bool), "Expected is_error to be false for the second inner transaction") - }) - - t.Run("GasValidation", func(t *testing.T) { - balance, err := ethClient.BalanceAt(ctx, fromAddr, nil) - require.NoError(t, err) - balanceETH := new(big.Float).Quo(new(big.Float).SetInt(balance), new(big.Float).SetFloat64(1e18)) - t.Logf("Test address balance: %s ETH", balanceETH.String()) - - t.Run("ContractCall", func(t *testing.T) { - txRequest := map[string]interface{}{ - "from": fromAddr.Hex(), "to": ContractAAddr.Hex(), "gas": "0x100000", - "gasPrice": "0x4a817c800", "value": "0x0", "nonce": "0x1", - "data": fmt.Sprintf("0x%x", calldata), - } - - // Get gasUsed from eth_transactionPreExec - result, err := operations.EthTransactionPreExec(txRequest, "latest", nil) - require.NoError(t, err) - resultSlice := result.([]interface{}) - validationResult := ValidateResult(t, resultSlice[0], "gas_comparison_contract_call") - preExecGasUsed := validationResult.GasUsed - - // Get gas estimate from eth_estimateGas - estimateGasRequest := map[string]interface{}{ - "from": fromAddr.Hex(), "to": ContractAAddr.Hex(), - "data": fmt.Sprintf("0x%x", calldata), - } - - var estimateResult string - err = ethClient.Client().Call(&estimateResult, "eth_estimateGas", estimateGasRequest, "latest") - require.NoError(t, err) - - estimatedGas, err := strconv.ParseUint(strings.TrimPrefix(estimateResult, "0x"), 16, 64) - require.NoError(t, err) - - // Validation: Both should be very close - tolerance := uint64(5000) // Allow 5K gas difference for binary search precision - - require.Greater(t, preExecGasUsed, uint64(21000), "Gas should be > 21000 for contract call") - require.Greater(t, estimatedGas, uint64(21000), "Estimated gas should be > 21000 for contract call") - - diff := uint64(0) - if estimatedGas > preExecGasUsed { - diff = estimatedGas - preExecGasUsed - } else { - diff = preExecGasUsed - estimatedGas - } - - require.LessOrEqual(t, diff, tolerance, - "Gas difference too large: preExec=%d, estimate=%d, diff=%d", - preExecGasUsed, estimatedGas, diff) - }) - - t.Run("SimpleTransfer", func(t *testing.T) { - transferTx := map[string]interface{}{ - "from": fromAddr.Hex(), "to": "0x742d35Cc4cF52f9234E96bC29d7F6a0c91d87b06", - "value": "0x1000000000000000", "gas": "0x5208", // 21000 in hex - "gasPrice": "0x4a817c800", "nonce": "0x2", - } - - // PreExec gas usage - result, err := operations.EthTransactionPreExec(transferTx, "latest", nil) - require.NoError(t, err) - resultSlice := result.([]interface{}) - validationResult := ValidateResult(t, resultSlice[0], "gas_comparison_transfer") - transferPreExecGas := validationResult.GasUsed - - // Estimate gas usage - transferEstimate := map[string]interface{}{ - "from": fromAddr.Hex(), "to": "0x742d35Cc4cF52f9234E96bC29d7F6a0c91d87b06", - "value": "0x1000000000000000", - } - var estimateResult string - err = ethClient.Client().Call(&estimateResult, "eth_estimateGas", transferEstimate, "latest") - require.NoError(t, err) - transferEstimatedGas, err := strconv.ParseUint(strings.TrimPrefix(estimateResult, "0x"), 16, 64) - require.NoError(t, err) - - // Simple transfers should be exactly 21000 gas - require.Equal(t, uint64(21000), transferPreExecGas, "Simple transfer should use exactly 21000 gas") - require.Equal(t, uint64(21000), transferEstimatedGas, "Simple transfer estimate should be exactly 21000 gas") - }) - - t.Run("CreateOperation", func(t *testing.T) { - factoryABI, err := abi.JSON(strings.NewReader(constants.ContractFactoryABIJson)) - require.NoError(t, err) - createCalldata, err := factoryABI.Pack("createSimpleStorage", big.NewInt(999)) - require.NoError(t, err) - - createTx := map[string]interface{}{ - "from": fromAddr.Hex(), "to": FactoryAddr.Hex(), "gas": "0x200000", - "gasPrice": "0x4a817c800", "value": "0x0", "nonce": "0x3", - "data": fmt.Sprintf("0x%x", createCalldata), - } - - // PreExec gas usage for CREATE - result, err := operations.EthTransactionPreExec(createTx, "latest", nil) - require.NoError(t, err) - resultSlice := result.([]interface{}) - validationResult := ValidateResult(t, resultSlice[0], "gas_comparison_create") - createPreExecGas := validationResult.GasUsed - - // Estimate gas for CREATE - createEstimate := map[string]interface{}{ - "from": fromAddr.Hex(), "to": FactoryAddr.Hex(), - "data": fmt.Sprintf("0x%x", createCalldata), - } - var estimateResult string - err = ethClient.Client().Call(&estimateResult, "eth_estimateGas", createEstimate, "latest") - require.NoError(t, err) - createEstimatedGas, err := strconv.ParseUint(strings.TrimPrefix(estimateResult, "0x"), 16, 64) - require.NoError(t, err) - - createDiff := uint64(0) - if createEstimatedGas > createPreExecGas { - createDiff = createEstimatedGas - createPreExecGas - } else { - createDiff = createPreExecGas - createEstimatedGas - } - - require.LessOrEqual(t, createDiff, uint64(50000), - "CREATE gas difference too large: preExec=%d, estimate=%d, diff=%d", - createPreExecGas, createEstimatedGas, createDiff) - }) - }) - - t.Run("SimpleEthTransfer", func(t *testing.T) { - transactionArgs := CreateBasicTransaction( - "0x0165878a594ca255338adfa4d48449f69242eb8f", - "0x1111111111111111111111111111111111111111", - "0x0", "0x5208", "0x4a817c800", "0x0", "") - - stateOverrides := CreateDefaultStateOverrides() - stateOverrides["0x0165878a594ca255338adfa4d48449f69242eb8f"].(map[string]interface{})["code"] = "0x608060405234801561001057600080fd5b50600436106100b45760003560e01c80638da5cb5b116100715780638da5cb5b1461013b57" - - result, err := operations.EthTransactionPreExec(transactionArgs, "latest", stateOverrides) - require.NoError(t, err) - resultSlice := result.([]interface{}) - validationResult := ValidateResult(t, resultSlice[0], "simple_eth_transfer") - - CheckSuccessfulResult(t, validationResult, "0x0165878a594ca255338adfa4d48449f69242eb8f", "simple ETH transfer") - require.Empty(t, validationResult.InnerTxs, "Simple ETH transfer should not have inner transactions") - require.Equal(t, validationResult.GasUsed, uint64(21000), "Simple ETH transfer should use exactly 21000 gas") - }) - - t.Run("EIP1559Transactions", func(t *testing.T) { - testCases := []struct { - name string - txFields map[string]interface{} - }{ - {"maxFeePerGas_only", map[string]interface{}{"maxFeePerGas": "0x4a817c800"}}, - {"maxFeePerGas_with_maxPriorityFeePerGas", map[string]interface{}{ - "maxFeePerGas": "0x4a817c800", - "maxPriorityFeePerGas": "0x3b9aca00", - }}, - } - - stateOverrides := CreateDefaultStateOverrides() - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - // Create base transaction with EIP-1559 fields - transactionArgs := CreateBasicTransaction( - "0x0165878a594ca255338adfa4d48449f69242eb8f", - "0x1111111111111111111111111111111111111111", - "0x0", "0x5208", "0x4a817c800", "0x0", "") - - for key, value := range tc.txFields { - transactionArgs[key] = value - } - - // Remove gasPrice field for EIP-1559 transactions - delete(transactionArgs, "gasPrice") - - result, err := operations.EthTransactionPreExec(transactionArgs, "latest", stateOverrides) - require.NoError(t, err) - resultSlice := result.([]interface{}) - validationResult := ValidateResult(t, resultSlice[0], tc.name) - CheckSuccessfulResult(t, validationResult, "0x0165878a594ca255338adfa4d48449f69242eb8f", "Support EIP-1559 transactions") - require.GreaterOrEqual(t, validationResult.GasUsed, uint64(21000), "Transaction should use more than 21000 gas") - require.Greater(t, validationResult.BlockNumber.Uint64(), uint64(1), "Block Number should be greater than 1") - require.Empty(t, validationResult.InnerTxs, "Inner Transactions should be empty") - require.Empty(t, validationResult.Logs, "Logs should be empty") - }) - } - }) - - t.Run("EIP7702Transactions", func(t *testing.T) { - testCases := []struct { - name string - addresses []string - }{ - {"authorizationList_single", []string{"0x1111111111111111111111111111111111111111"}}, - {"authorizationList_multiple", []string{"0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"}}, - } - - stateOverrides := CreateDefaultStateOverrides() - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - // Create base transaction with authorization list - transactionArgs := CreateBasicTransaction( - "0x0165878a594ca255338adfa4d48449f69242eb8f", - "0x1111111111111111111111111111111111111111", - "0x0", "0x15f90", "0x4a817c800", "0x0", "") - transactionArgs["authorizationList"] = CreateAuthorizationList(tc.addresses) - - result, err := operations.EthTransactionPreExec(transactionArgs, "latest", stateOverrides) - require.NoError(t, err) - resultSlice := result.([]interface{}) - validationResult := ValidateResult(t, resultSlice[0], tc.name) - CheckSuccessfulResult(t, validationResult, "0x0165878a594ca255338adfa4d48449f69242eb8f", "Support EIP-7702 transactions") - require.GreaterOrEqual(t, validationResult.GasUsed, uint64(21000), "Transaction should use more than 21000 gas") - require.Greater(t, validationResult.BlockNumber.Uint64(), uint64(1), "Block Number should be greater than 1") - require.Empty(t, validationResult.InnerTxs, "Inner Transactions should be empty") - require.Empty(t, validationResult.Logs, "Logs should be empty") - }) - } - }) - - t.Run("ContractCallWithStateOverrides", func(t *testing.T) { - contractBAddr := "0x2222222222222222222222222222222222222222" - contractCAddr := "0x3333333333333333333333333333333333333333" - - stateOverrides := CreateDefaultStateOverrides() - - // Set up ContractB with ContractC's address in storage slot 1 - stateOverrides[contractBAddr] = map[string]interface{}{ - "code": "0x" + constants.ContractBBytecodeStr, - "storage": map[string]interface{}{ - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000003333333333333333333333333333333333333333", // ContractC address in slot 1 - }, - } - - // Set up ContractC with initial storage value - stateOverrides[contractCAddr] = map[string]interface{}{ - "code": "0x" + constants.ContractCBytecodeStr, - "storage": map[string]interface{}{ - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000064", // Initial value = 100 - }, - } - - transactionArgs := CreateBasicTransaction( - "0x0165878a594ca255338adfa4d48449f69242eb8f", - contractBAddr, "0x0", "0x200000", "0x4a817c800", - "0x0", "0x32e43a11") // dummy() function selector - - result, err := operations.EthTransactionPreExec(transactionArgs, "latest", stateOverrides) - require.NoError(t, err) - resultSlice := result.([]interface{}) - validationResult := ValidateResult(t, resultSlice[0], "dummy_call") - - for _, txResult := range resultSlice { - testName := "ContractCallWithStateOverrides" - validationResult := ValidateResult(t, txResult, testName) - - CheckSuccessfulResult(t, validationResult, "0x0165878a594ca255338adfa4d48449f69242eb8f", testName) - } - - require.Greater(t, validationResult.GasUsed, uint64(21000), "Contract call should use more than 21000 gas") - require.Equal(t, 0, len(validationResult.InnerTxs), "Should have no inner transactions") - }) - - t.Run("NonceTooLow", func(t *testing.T) { - // Test transactions with nonces lower than the account's current nonce - transactions := []map[string]interface{}{ - CreateBasicTransaction( - "0x0165878a594ca255338adfa4d48449f69242eb8f", - "0x5fbdb2315678afecb367f032d93f642f64180aa3", - "0x0", "0x30000", "0x4a817c800", "0x1", ""), // nonce = 1 - CreateBasicTransaction( - "0x0165878a594ca255338adfa4d48449f69242eb8f", - "0x5fbdb2315678afecb367f032d93f642f64180aa3", - "0x0", "0x30000", "0x4a817c800", "0x2", ""), // nonce = 2 - } - - stateOverrides := map[string]interface{}{ - "0x0165878a594ca255338adfa4d48449f69242eb8f": map[string]interface{}{ - "balance": "0x56bc75e2d630eb20000", - "code": "0x608060405234801561001057600080fd5b50600436106100b45760003560e01c80638da5cb5b116100715780638da5cb5b1461013b57", - "nonce": "0x3", // Account nonce = 3 - }, - } - - var result []interface{} - for _, tx := range transactions { - txResult, err := operations.EthTransactionPreExec(tx, "latest", stateOverrides) - require.NoError(t, err) - txResultSlice := txResult.([]interface{}) - require.Len(t, txResultSlice, 1, "Expected single transaction result") - result = append(result, txResultSlice[0]) - } - - for i, txResult := range result { - testName := fmt.Sprintf("transaction_%d_nonce_too_low", i+1) - validationResult := ValidateResult(t, txResult, testName) - - CheckErrorResult(t, validationResult, "nonce too low", testName) - - require.Equal(t, uint64(0), validationResult.GasUsed, "%s should use 0 gas when rejected", testName) - require.Len(t, validationResult.InnerTxs, 0, "%s should have no inner transactions when rejected", testName) - } - }) -} - func TestNewTransactionTypes(t *testing.T) { if testing.Short() { t.Skip() diff --git a/devnet/op-geth/test/e2e/test_utils_xlayer.go b/devnet/op-geth/test/e2e/test_utils_xlayer.go index bb5ac727..e46461d1 100644 --- a/devnet/op-geth/test/e2e/test_utils_xlayer.go +++ b/devnet/op-geth/test/e2e/test_utils_xlayer.go @@ -38,29 +38,8 @@ type ValidationError struct { Msg string `json:"msg"` } -// ValidationInnerTx represents an inner transaction for test validation -type ValidationInnerTx 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"` -} - // ValidationResult represents a typed structure matching PreResult for test validation type ValidationResult struct { - InnerTxs []ValidationInnerTx `json:"innerTxs"` Logs []types.Log `json:"logs"` StateDiff map[string]interface{} `json:"stateDiff"` Error ValidationError `json:"error"` @@ -534,25 +513,6 @@ func EncodeComplexCall(target common.Address) []byte { return data } -// validateInnerTransactionMatch validates that two inner transactions match each other -func ValidateInnerTransactionMatch(t *testing.T, innerTx1, innerTx2 *types.InnerTx, contextMsg string) { - require.Equal(t, innerTx1.From, innerTx2.From, "%s: From addresses should match", contextMsg) - require.Equal(t, innerTx1.To, innerTx2.To, "%s: To addresses should match", contextMsg) - require.Equal(t, innerTx1.Input, innerTx2.Input, "%s: Input data should match", contextMsg) - require.Equal(t, innerTx1.Output, innerTx2.Output, "%s: Output data should match", contextMsg) - require.Equal(t, innerTx1.IsError, innerTx2.IsError, "%s: Error status should match", contextMsg) - require.Equal(t, innerTx1.CallType, innerTx2.CallType, "%s: Call types should match", contextMsg) - require.Equal(t, innerTx1.ValueWei, innerTx2.ValueWei, "%s: ValueWei should match", contextMsg) - require.Equal(t, innerTx1.CallValueWei, innerTx2.CallValueWei, "%s: CallValueWei should match", contextMsg) - require.Equal(t, innerTx1.Error, innerTx2.Error, "%s: Error messages should match", contextMsg) - require.Equal(t, innerTx1.Dept, innerTx2.Dept, "%s: Dept should match", contextMsg) - require.Equal(t, innerTx1.InternalIndex, innerTx2.InternalIndex, "%s: InternalIndex should match", contextMsg) - require.Equal(t, innerTx1.Name, innerTx2.Name, "%s: Name should match", contextMsg) - require.Equal(t, innerTx1.TraceAddress, innerTx2.TraceAddress, "%s: TraceAddress should match", contextMsg) - require.Equal(t, innerTx1.CodeAddress, innerTx2.CodeAddress, "%s: CodeAddress should match", contextMsg) - require.Equal(t, innerTx1.Value, innerTx2.Value, "%s: Value should match", contextMsg) -} - // CreateBasicTransaction creates a standard transaction with common fields func CreateBasicTransaction(from, to, value, gas, gasPrice, nonce, data string) map[string]interface{} { tx := map[string]interface{}{ diff --git a/devnet/op-geth/test/operations/rpc_all.go b/devnet/op-geth/test/operations/rpc_all.go index 171f077c..bd849905 100644 --- a/devnet/op-geth/test/operations/rpc_all.go +++ b/devnet/op-geth/test/operations/rpc_all.go @@ -8,9 +8,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rpc" ) // DebugTraceBlockByHash traces all transactions in the block given by block hash @@ -383,31 +381,6 @@ func EthGetStorageAt(address common.Address, position string, block string) (str return result, nil } -// EthTransactionPreExec executes a transaction and returns the result without creating a transaction on chain -func EthTransactionPreExec(txRequest interface{}, blockParameter string, stateOverride interface{}) (interface{}, error) { - if clientRPC == nil { - return nil, fmt.Errorf("RPC client not initialized") - } - - var result interface{} - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) - defer cancel() - - var args []interface{} - args = append(args, []interface{}{txRequest}) // eth_transactionPreExec expects array of transactions - args = append(args, blockParameter) - if stateOverride != nil { - args = append(args, stateOverride) - } - - err := clientRPC.Client().CallContext(ctx, &result, "eth_transactionPreExec", args...) - if err != nil { - return nil, err - } - - return result, nil -} - // EthGetTransactionByBlockHashAndIndex returns information about a transaction by block hash and transaction index position func EthGetTransactionByBlockHashAndIndex(blockHash common.Hash, index string) (interface{}, error) { var result interface{} @@ -450,34 +423,6 @@ func EthGetTransactionByHash(txHash common.Hash) (interface{}, error) { return result, nil } -// EthGetInternalTransactions returns the internal transactions for a given transaction hash -func EthGetInternalTransactions(txHash common.Hash) ([]*types.InnerTx, error) { - var result []*types.InnerTx - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) - defer cancel() - - err := clientRPC.Client().CallContext(ctx, &result, "eth_getInternalTransactions", txHash) - if err != nil { - return nil, err - } - - return result, nil -} - -// EthGetBlockInternalTransactions returns the internal transactions for a given block number -func EthGetBlockInternalTransactions(blockNumber rpc.BlockNumber) (map[common.Hash][]*types.InnerTx, error) { - var result map[common.Hash][]*types.InnerTx - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) - defer cancel() - - err := clientRPC.Client().CallContext(ctx, &result, "eth_getBlockInternalTransactions", blockNumber) - if err != nil { - return nil, err - } - - return result, nil -} - // EthGetTransactionReceipt returns the receipt of a transaction by transaction hash func EthGetTransactionReceipt(txHash common.Hash) (interface{}, error) { var result interface{} diff --git a/devnet/op-geth/test/operations/rpc_client.go b/devnet/op-geth/test/operations/rpc_client.go index 547f09a5..16120666 100644 --- a/devnet/op-geth/test/operations/rpc_client.go +++ b/devnet/op-geth/test/operations/rpc_client.go @@ -112,32 +112,6 @@ func GetBlockHashByNumber(block uint64) (string, error) { return blockData.Hash().String(), nil } -func GetInternalTransactions(hash common.Hash) ([]interface{}, error) { - var result []interface{} - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) - defer cancel() - - err := clientRPC.Client().CallContext(ctx, &result, "eth_getInternalTransactions", hash) - if err != nil { - return nil, err - } - - return result, nil -} - -func GetBlockInternalTransactions(block *big.Int) (map[common.Hash][]interface{}, error) { - var result map[common.Hash][]interface{} - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) - defer cancel() - - err := clientRPC.Client().CallContext(ctx, &result, "eth_getBlockInternalTransactions", hexutil.EncodeBig(block)) - if err != nil { - return nil, err - } - - return result, nil -} - func GetTransactionByHash(hash common.Hash) (*types.Transaction, error) { var result types.Transaction ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) diff --git a/devnet/scripts/setup-cgt-function.sh b/devnet/scripts/setup-cgt-function.sh index 7ecc411e..74f2374c 100755 --- a/devnet/scripts/setup-cgt-function.sh +++ b/devnet/scripts/setup-cgt-function.sh @@ -92,8 +92,9 @@ setup_cgt() { # Get required addresses from state.json echo "📝 Step 2: Running Custom Gas Token setup script..." STATE_JSON="$CONFIG_DIR/state.json" - SYSTEM_CONFIG_PROXY_ADDRESS=$(jq -r '.opChainDeployments[0].SystemConfigProxy' "$STATE_JSON") - OPTIMISM_PORTAL_PROXY_ADDRESS=$(jq -r '.opChainDeployments[0].OptimismPortalProxy' "$STATE_JSON") + # Use grep instead of jq to avoid dependency + SYSTEM_CONFIG_PROXY_ADDRESS=$(grep -o '"SystemConfigProxy"[[:space:]]*:[[:space:]]*"[^"]*"' "$STATE_JSON" | head -1 | sed 's/.*"\([^"]*\)".*/\1/') + OPTIMISM_PORTAL_PROXY_ADDRESS=$(grep -o '"OptimismPortalProxy"[[:space:]]*:[[:space:]]*"[^"]*"' "$STATE_JSON" | head -1 | sed 's/.*"\([^"]*\)".*/\1/') # Export required environment variables for the setup script export SYSTEM_CONFIG_PROXY_ADDRESS="$SYSTEM_CONFIG_PROXY_ADDRESS" diff --git a/scripts/dev-utils/compare-legacy-rpc.md b/scripts/dev-utils/compare-legacy-rpc.md index 6f295fcd..7b185139 100644 --- a/scripts/dev-utils/compare-legacy-rpc.md +++ b/scripts/dev-utils/compare-legacy-rpc.md @@ -35,9 +35,6 @@ Based on [op-geth migration RPC implementation](https://github.com/okx/op-geth/p | 20 | `eth_call` | ✅ | Supports BlockNumber, BlockHash, BlockTag | | 21 | `eth_estimateGas` | ✅ | Supports BlockNumber, BlockHash, BlockTag | | 22 | `eth_createAccessList` | ✅ | EIP-2930 access list creation | -| 23 | `eth_transactionPreExec` | ✅ | XLayer custom method | -| 24 | `eth_getInternalTransactions` | ✅ | Query by transaction hash | -| 25 | `eth_getBlockInternalTransactions` | ✅ | Query by BlockNumber or BlockTag (not BlockHash) | | 26 | `eth_newFilter` | ❌ | Real-time query only | | 27 | `eth_getFilterLogs` | ❌ | Real-time query only | | 28 | `eth_getFilterChanges` | ❌ | Real-time query only | diff --git a/scripts/dev-utils/compare-legacy-rpc.sh b/scripts/dev-utils/compare-legacy-rpc.sh index 94722970..369daa1b 100755 --- a/scripts/dev-utils/compare-legacy-rpc.sh +++ b/scripts/dev-utils/compare-legacy-rpc.sh @@ -2128,7 +2128,7 @@ log_section "Phase 7: New Legacy RPC Methods Tests" echo "" log_info "🔍 Testing newly added Legacy RPC methods" -log_info " eth_call, eth_estimateGas, eth_createAccessList, eth_transactionPreExec" +log_info " eth_call, eth_estimateGas, eth_createAccessList" echo "" # ======================================== @@ -2411,144 +2411,13 @@ log_info " across legacy/local blocks with data consistency validation." echo " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "" -# ======================================== -# Phase 7.4: eth_transactionPreExec Tests -# ======================================== - -log_section "Phase 7.4: eth_transactionPreExec Tests (XLayer Custom Method)" - -echo "" -log_info "Testing XLayer custom transaction pre-execution..." -echo "" - -# Prepare pre-exec request using simple EOA-to-EOA transfer -PRE_EXEC_ARGS="[{\"from\":\"$ACTIVE_EOA_ADDRESS\",\"to\":\"$TEST_ADDR\",\"value\":\"0x0\"}]" - -# Test 7.4.1: eth_transactionPreExec (legacy block) -log_info "Test 7.4.1: eth_transactionPreExec (legacy block)" -response=$(rpc_call "eth_transactionPreExec" "[$PRE_EXEC_ARGS,\"$LEGACY_BLOCK_HEX\",null]") -check_result_legacy_tolerant "$response" "eth_transactionPreExec (legacy BlockNumber)" - -# Test 7.4.2: eth_transactionPreExec (cutoff block) -log_info "Test 7.4.2: eth_transactionPreExec (cutoff block)" -response=$(rpc_call "eth_transactionPreExec" "[$PRE_EXEC_ARGS,\"$BOUNDARY_BLOCK_HEX\",null]") -check_result_legacy_tolerant "$response" "eth_transactionPreExec (cutoff)" - -# Test 7.4.3: eth_transactionPreExec (local block) -log_info "Test 7.4.3: eth_transactionPreExec (local block)" -response=$(rpc_call "eth_transactionPreExec" "[$PRE_EXEC_ARGS,\"$LOCAL_BLOCK_HEX\",null]") -check_result_legacy_tolerant "$response" "eth_transactionPreExec (local BlockNumber)" - -# Test 7.4.4: eth_transactionPreExec with 'latest' tag -log_info "Test 7.4.4: eth_transactionPreExec with 'latest' tag" -response=$(rpc_call "eth_transactionPreExec" "[$PRE_EXEC_ARGS,\"latest\",null]") -check_result_legacy_tolerant "$response" "eth_transactionPreExec (latest)" - -# Test 7.4.5: eth_transactionPreExec data consistency (if supported by Legacy RPC) -log_info "Test 7.4.5: eth_transactionPreExec data consistency (legacy block)" -TOTAL_TESTS=$((TOTAL_TESTS + 1)) - -# Get responses from both endpoints -reth_response=$(rpc_call "eth_transactionPreExec" "[$PRE_EXEC_ARGS,\"$LEGACY_BLOCK_HEX\",null]") -legacy_response=$(rpc_call_legacy "eth_transactionPreExec" "[$PRE_EXEC_ARGS,\"$LEGACY_BLOCK_HEX\",null]") - -# Check if both succeeded -reth_has_error=$(echo "$reth_response" | jq -e '.error' > /dev/null 2>&1 && echo "true" || echo "false") -legacy_has_error=$(echo "$legacy_response" | jq -e '.error' > /dev/null 2>&1 && echo "true" || echo "false") - -if [ "$reth_has_error" = "true" ] || [ "$legacy_has_error" = "true" ]; then - # Handle errors same as check_data_consistency - if [ "$reth_has_error" = "true" ] && [ "$legacy_has_error" = "true" ]; then - reth_error_msg=$(echo "$reth_response" | jq -r '.error.message') - legacy_error_msg=$(echo "$legacy_response" | jq -r '.error.message') - legacy_error_code=$(echo "$legacy_response" | jq -r '.error.code // ""') - - # Check if both returned 403/not whitelisted errors - reth_is_403=false - legacy_is_403=false - - if [[ "$reth_error_msg" == *"403"* ]] || [[ "$reth_error_msg" == *"not whitelisted"* ]]; then - reth_is_403=true - fi - - if [[ "$legacy_error_msg" == *"403"* ]] || \ - [[ "$legacy_error_msg" == *"not whitelisted"* ]] || \ - [[ "$legacy_error_code" == "-32601" ]]; then - legacy_is_403=true - fi - - if [ "$reth_is_403" = "true" ] && [ "$legacy_is_403" = "true" ]; then - log_warning "eth_transactionPreExec consistency - Both returned 403/not whitelisted" - echo " Skipping - method not supported by Legacy RPC" - SKIPPED_TESTS=$((SKIPPED_TESTS + 1)) - else - log_error "eth_transactionPreExec consistency - Both returned errors" - FAILED_TESTS=$((FAILED_TESTS + 1)) - FAILED_TEST_NAMES+=("eth_transactionPreExec consistency") - fi - elif [ "$reth_has_error" = "true" ]; then - log_error "eth_transactionPreExec consistency - Reth returned error" - FAILED_TESTS=$((FAILED_TESTS + 1)) - FAILED_TEST_NAMES+=("eth_transactionPreExec consistency") - else - log_warning "eth_transactionPreExec consistency - Legacy RPC returned error" - SKIPPED_TESTS=$((SKIPPED_TESTS + 1)) - fi -else - # Both succeeded - normalize and compare - # Reth returns blockNumber as hex string ("0x28d36bd") - # Legacy returns blockNumber as decimal number (42809021) - # Normalize both to hex for comparison - - reth_result=$(echo "$reth_response" | jq -c '.result') - legacy_result=$(echo "$legacy_response" | jq -c '.result') - - # Extract blockNumber from Legacy response and convert decimal to hex - legacy_block_num=$(echo "$legacy_result" | jq -r '.[0].blockNumber // empty') - if [ -n "$legacy_block_num" ] && [ "$legacy_block_num" != "null" ]; then - # Convert decimal to hex - legacy_block_hex=$(printf "0x%x" "$legacy_block_num" 2>/dev/null || echo "$legacy_block_num") - - # Replace blockNumber in legacy result with hex format - legacy_normalized=$(echo "$legacy_result" | jq --arg hex "$legacy_block_hex" 'map(.blockNumber = $hex)') - else - legacy_normalized=$(echo "$legacy_result" | jq -c '.') - fi - - # Sort keys for consistent comparison - reth_sorted=$(echo "$reth_result" | jq -cS '.') - legacy_sorted=$(echo "$legacy_normalized" | jq -cS '.') - - if [ "$reth_sorted" = "$legacy_sorted" ]; then - log_success "eth_transactionPreExec: Reth matches Legacy RPC (after format normalization) ✓" - log_info " → blockNumber format normalized (decimal → hex: $legacy_block_num → $legacy_block_hex)" - PASSED_TESTS=$((PASSED_TESTS + 1)) - else - log_error "eth_transactionPreExec: Data MISMATCH ✗" - echo " Reth (hex): ${reth_sorted:0:200}..." - echo " Legacy (normalized): ${legacy_sorted:0:200}..." - FAILED_TESTS=$((FAILED_TESTS + 1)) - FAILED_TEST_NAMES+=("eth_transactionPreExec consistency") - fi -fi - -echo "" -log_info "📊 Phase 7.4 Summary:" -echo " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -log_info " eth_transactionPreExec tests verify XLayer's custom pre-execution" -log_info " method across legacy/local blocks. Uses legacy_tolerant checks" -log_info " as this is a custom XLayer method." -echo " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -echo "" - log_info "📊 Phase 7 Complete Summary:" echo " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -log_info " Tested 4 new Legacy RPC methods with comprehensive coverage:" +log_info " Tested 3 Legacy RPC methods with comprehensive coverage:" log_info " ✓ eth_call (9 tests)" log_info " ✓ eth_estimateGas (9 tests)" log_info " ✓ eth_createAccessList (7 tests)" -log_info " ✓ eth_transactionPreExec (5 tests)" -log_info " Total: 30 new tests covering all test dimensions" +log_info " Total: 25 tests covering all test dimensions" echo " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "" @@ -3420,242 +3289,10 @@ log_section "Phase 12: Internal Transactions Tests" # Calculate boundary blocks if not already set ensure_boundary_blocks -echo "" -log_info "🔍 Testing internal transaction query methods" -log_info " eth_getInternalTransactions, eth_getBlockInternalTransactions" -echo "" - -# ======================================== -# Phase 12.1: eth_getInternalTransactions Tests -# ======================================== - -log_section "Phase 12.1: eth_getInternalTransactions Tests" - -echo "" -log_info "Testing internal transactions by transaction hash..." -echo "" - -# Test 12.1.1: eth_getInternalTransactions (legacy tx with internal txs) -log_info "Test 12.1.1: eth_getInternalTransactions (legacy transaction)" -response=$(rpc_call "eth_getInternalTransactions" "[\"$REAL_LEGACY_TX\"]") -if check_result_legacy_tolerant "$response" "eth_getInternalTransactions (legacy tx)"; then - internal_txs=$(echo "$response" | jq -r '.result | length') - log_info " → Found $internal_txs internal transactions" -fi - -# Test 12.1.2: eth_getInternalTransactions (cutoff block transaction) -log_info "Test 12.1.2: eth_getInternalTransactions (cutoff block tx)" -if [ -n "$LEGACY_TX_HASH" ] && [ "$LEGACY_TX_HASH" != "null" ]; then - response=$(rpc_call "eth_getInternalTransactions" "[\"$LEGACY_TX_HASH\"]") - check_result_legacy_tolerant "$response" "eth_getInternalTransactions (cutoff tx)" -fi - -# Test 12.1.3: eth_getInternalTransactions (local tx with internal txs) -log_info "Test 12.1.3: eth_getInternalTransactions (local transaction)" -response=$(rpc_call "eth_getInternalTransactions" "[\"$REAL_LOCAL_TX\"]") -if check_result_legacy_tolerant "$response" "eth_getInternalTransactions (local tx)"; then - internal_txs=$(echo "$response" | jq -r '.result | length') - log_info " → Found $internal_txs internal transactions" -fi - -# Test 12.1.4: Data consistency (Reth vs Legacy RPC) -log_info "Test 12.1.4: eth_getInternalTransactions data consistency" -check_data_consistency "eth_getInternalTransactions" "[\"$REAL_LEGACY_TX\"]" "eth_getInternalTransactions consistency" - -# Test 12.1.5: All-zero transaction hash -log_info "Test 12.1.5: eth_getInternalTransactions with all-zero tx hash" -TOTAL_TESTS=$((TOTAL_TESTS + 1)) -ZERO_TX_HASH="0x0000000000000000000000000000000000000000000000000000000000000000" -response=$(rpc_call "eth_getInternalTransactions" "[\"$ZERO_TX_HASH\"]") -if echo "$response" | jq -e '.error' > /dev/null 2>&1; then - log_success "All-zero tx hash returns error ✓" - PASSED_TESTS=$((PASSED_TESTS + 1)) -elif echo "$response" | jq -e '.result == null' > /dev/null 2>&1; then - log_success "All-zero tx hash returns null (correct) ✓" - PASSED_TESTS=$((PASSED_TESTS + 1)) -else - log_warning "All-zero tx hash accepted (implementation may handle it)" - SKIPPED_TESTS=$((SKIPPED_TESTS + 1)) -fi - -# Test 12.1.6: Random non-existent transaction hash -log_info "Test 12.1.6: eth_getInternalTransactions with random tx hash" -TOTAL_TESTS=$((TOTAL_TESTS + 1)) -RANDOM_TX_HASH="0x$(openssl rand -hex 32 2>/dev/null || echo "abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890")" -response=$(rpc_call "eth_getInternalTransactions" "[\"$RANDOM_TX_HASH\"]") -if echo "$response" | jq -e '.result == null' > /dev/null 2>&1; then - log_success "Random tx hash returns null (correct) ✓" - PASSED_TESTS=$((PASSED_TESTS + 1)) -elif echo "$response" | jq -e '.result == []' > /dev/null 2>&1; then - log_success "Random tx hash returns empty array (acceptable) ✓" - PASSED_TESTS=$((PASSED_TESTS + 1)) -else - log_warning "Random tx hash handling varies (implementation-dependent)" - SKIPPED_TESTS=$((SKIPPED_TESTS + 1)) -fi - -# Test 12.1.7: Simple transfer (no internal transactions) -log_info "Test 12.1.7: eth_getInternalTransactions (simple transfer, no internal txs)" -# Use a transaction that should not have internal transactions -response=$(rpc_call "eth_getInternalTransactions" "[\"$LEGACY_TX_HASH\"]") -if check_result_legacy_tolerant "$response" "eth_getInternalTransactions (simple transfer)"; then - result=$(echo "$response" | jq -r '.result') - if [ "$result" = "null" ] || [ "$result" = "[]" ]; then - log_info " → Correctly returns null/empty for simple transfer" - else - internal_count=$(echo "$result" | jq 'length') - log_info " → Found $internal_count internal transactions" - fi -fi - -echo "" -log_info "📊 Phase 12.1 Summary:" -echo " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -log_info " eth_getInternalTransactions tests verify internal tx queries" -log_info " by transaction hash, covering legacy/local blocks and edge cases." -echo " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -echo "" - # ======================================== -# Phase 12.2: eth_getBlockInternalTransactions Tests +# Phase 13: Comprehensive Summary # ======================================== -log_section "Phase 12.2: eth_getBlockInternalTransactions Tests" - -echo "" -log_info "Testing internal transactions by block identifier..." -echo "" - -# Test 12.2.1: eth_getBlockInternalTransactions (legacy block) -log_info "Test 12.2.1: eth_getBlockInternalTransactions (legacy BlockNumber)" -response=$(rpc_call "eth_getBlockInternalTransactions" "[\"$LEGACY_BLOCK_HEX\"]") -if check_result_legacy_tolerant "$response" "eth_getBlockInternalTransactions (legacy)"; then - result=$(echo "$response" | jq -r '.result') - if [ "$result" != "null" ]; then - tx_count=$(echo "$result" | jq 'length') - log_info " → Found $tx_count transactions with internal txs" - fi -fi - -# Test 12.2.2: eth_getBlockInternalTransactions (cutoff-1) -log_info "Test 12.2.2: eth_getBlockInternalTransactions (cutoff-1)" -response=$(rpc_call "eth_getBlockInternalTransactions" "[\"$LAST_LEGACY_HEX\"]") -check_result_legacy_tolerant "$response" "eth_getBlockInternalTransactions (cutoff-1)" - -# Test 12.2.3: eth_getBlockInternalTransactions (cutoff) -log_info "Test 12.2.3: eth_getBlockInternalTransactions (cutoff)" -response=$(rpc_call "eth_getBlockInternalTransactions" "[\"$BOUNDARY_BLOCK_HEX\"]") -check_result_legacy_tolerant "$response" "eth_getBlockInternalTransactions (cutoff)" - -# Test 12.2.4: eth_getBlockInternalTransactions (cutoff+1) -log_info "Test 12.2.4: eth_getBlockInternalTransactions (cutoff+1)" -response=$(rpc_call "eth_getBlockInternalTransactions" "[\"$FIRST_LOCAL_HEX\"]") -check_result_legacy_tolerant "$response" "eth_getBlockInternalTransactions (cutoff+1)" - -# Test 12.2.5: eth_getBlockInternalTransactions (local block) -log_info "Test 12.2.5: eth_getBlockInternalTransactions (local BlockNumber)" -response=$(rpc_call "eth_getBlockInternalTransactions" "[\"$LOCAL_BLOCK_HEX\"]") -if check_result_legacy_tolerant "$response" "eth_getBlockInternalTransactions (local)"; then - result=$(echo "$response" | jq -r '.result') - if [ "$result" != "null" ]; then - tx_count=$(echo "$result" | jq 'length') - log_info " → Found $tx_count transactions with internal txs" - fi -fi - -echo "" -log_info "Testing BlockTag parameters..." -echo "" - -# Test 12.2.6: eth_getBlockInternalTransactions with 'earliest' -log_info "Test 12.2.6: eth_getBlockInternalTransactions with 'earliest'" -response=$(rpc_call "eth_getBlockInternalTransactions" "[\"earliest\"]") -if check_result_legacy_tolerant "$response" "eth_getBlockInternalTransactions (earliest)"; then - result=$(echo "$response" | jq -r '.result') - if [ "$result" = "null" ] || [ "$result" = "[]" ]; then - log_info " → Genesis block has no transactions (expected)" - fi -fi - -# Test 12.2.7: eth_getBlockInternalTransactions with 'latest' -log_info "Test 12.2.7: eth_getBlockInternalTransactions with 'latest'" -response=$(rpc_call "eth_getBlockInternalTransactions" "[\"latest\"]") -if check_result_legacy_tolerant "$response" "eth_getBlockInternalTransactions (latest)"; then - result=$(echo "$response" | jq -r '.result') - if [ "$result" != "null" ]; then - tx_count=$(echo "$result" | jq 'length') - log_info " → Latest block: found $tx_count transactions with internal txs" - fi -fi - -# Test 12.2.8: eth_getBlockInternalTransactions with 'pending' -log_info "Test 12.2.8: eth_getBlockInternalTransactions with 'pending'" -response=$(rpc_call "eth_getBlockInternalTransactions" "[\"pending\"]") -check_result_legacy_tolerant "$response" "eth_getBlockInternalTransactions (pending)" - -echo "" -log_info "Testing edge cases and invalid inputs..." -echo "" - -# Test 12.2.9: Future block number -log_info "Test 12.2.9: eth_getBlockInternalTransactions with future block" -TOTAL_TESTS=$((TOTAL_TESTS + 1)) -FUTURE_BLOCK_HEX="0xffffffff" -response=$(rpc_call "eth_getBlockInternalTransactions" "[\"$FUTURE_BLOCK_HEX\"]") -if echo "$response" | jq -e '.error' > /dev/null 2>&1; then - log_success "Future block returns error ✓" - PASSED_TESTS=$((PASSED_TESTS + 1)) -elif echo "$response" | jq -e '.result == null' > /dev/null 2>&1; then - log_success "Future block returns null (acceptable) ✓" - PASSED_TESTS=$((PASSED_TESTS + 1)) -else - log_warning "Future block handling varies" - SKIPPED_TESTS=$((SKIPPED_TESTS + 1)) -fi - -# Test 12.2.10: Genesis block (0x0) -log_info "Test 12.2.10: eth_getBlockInternalTransactions (genesis block)" -TOTAL_TESTS=$((TOTAL_TESTS + 1)) -response=$(rpc_call "eth_getBlockInternalTransactions" "[\"0x0\"]") -result=$(echo "$response" | jq -r '.result') -if [ "$result" = "null" ] || [ "$result" = "[]" ]; then - log_success "Genesis block returns null/empty (correct) ✓" - PASSED_TESTS=$((PASSED_TESTS + 1)) -elif echo "$response" | jq -e '.error' > /dev/null 2>&1; then - log_success "Genesis block returns error (acceptable) ✓" - PASSED_TESTS=$((PASSED_TESTS + 1)) -else - log_warning "Genesis block handling varies" - SKIPPED_TESTS=$((SKIPPED_TESTS + 1)) -fi - -echo "" -log_info "Testing data consistency..." -echo "" - -# Test 12.2.11: Data consistency (Reth vs Legacy RPC) -log_info "Test 12.2.11: eth_getBlockInternalTransactions consistency (Reth vs Legacy)" -check_data_consistency "eth_getBlockInternalTransactions" "[\"$LEGACY_BLOCK_HEX\"]" "eth_getBlockInternalTransactions consistency" - -echo "" -log_info "📊 Phase 12.2 Summary:" -echo " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -log_info " eth_getBlockInternalTransactions tests verify internal tx queries" -log_info " by block identifier (BlockNumber/BlockTag), covering" -log_info " legacy/cutoff/local blocks, edge cases, and data consistency." -log_info " Note: BlockHash parameter is NOT supported by this method." -echo " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -echo "" - -log_info "📊 Phase 12 Complete Summary:" -echo " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -log_info " Tested 2 internal transaction query methods:" -log_info " ✓ eth_getInternalTransactions (7 tests)" -log_info " ✓ eth_getBlockInternalTransactions (14 tests)" -log_info " Total: 21 new tests covering all test dimensions" -echo " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -echo "" - fi # ======================================== diff --git a/scripts/dev-utils/legacy-rpc-test.sh b/scripts/dev-utils/legacy-rpc-test.sh index 3563b420..67a95d05 100755 --- a/scripts/dev-utils/legacy-rpc-test.sh +++ b/scripts/dev-utils/legacy-rpc-test.sh @@ -13,10 +13,6 @@ FOR_OP_BLOCK_HASH="0xdc33d8c0ec9de14fc2c21bd6077309a0a856df22821bd092a2513426e09 FOR_ERIGON_TRANSACTION_HASH="0x8d7c7927a74c0245f06b1da06bfaa727396c2bd47349de6f7fc579febce30fae" # transaction in block 42800000 FOR_OP_TRANSACTION_HASH="0x9b52d72be301ae6928830be4a1cf25749f2d230a4bee940f1b55e9311960a4f5" -# Real test parameters from production -PREEXEC_FROM="0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266" -PREEXEC_TO="0x8ec198c4149280e4004a64531648640b862fb887" - # Real contract address CONTRACT_ADDRESS="0x4AAaCCfe00090665Dd74C56Db013978891D142f4" @@ -159,24 +155,6 @@ call_rpc "eth_getBlockReceipts" "[\"0x$(printf '%x' $BELOW)\"]" \ call_rpc "eth_getBlockReceipts" "[\"latest\"]" \ "eth_getBlockReceipts (latest) → LOCAL" -echo -e "\n${GREEN}=== BlockChainAPI: TransactionPreExec (XLayer Specific) ===${NC}" - -call_rpc "eth_transactionPreExec" \ - "[[{\"from\":\"$PREEXEC_FROM\",\"to\":\"$PREEXEC_TO\",\"gas\":\"0x30000\",\"gasPrice\":\"0x4a817c800\",\"value\":\"0x0\",\"nonce\":\"0x11\",\"data\":\"0xf18c388a\"}], {\"blockNumber\":\"0x$(printf '%x' $BELOW)\"}, {\"$PREEXEC_FROM\":{\"balance\":\"0x56bc75e2d630eb20000\"}}]" \ - "eth_transactionPreExec (block number $BELOW with state override) → PROXY" - -call_rpc "eth_transactionPreExec" \ - "[[{\"from\":\"$PREEXEC_FROM\",\"to\":\"$PREEXEC_TO\",\"gas\":\"0x30000\",\"gasPrice\":\"0x4a817c800\",\"value\":\"0x0\",\"nonce\":\"0x11\",\"data\":\"0xf18c388a\"}], {\"blockHash\":\"$FOR_ERIGON_BLOCK_HASH\"}, {\"$PREEXEC_FROM\":{\"balance\":\"0x56bc75e2d630eb20000\"}}]" \ - "eth_transactionPreExec (erigon block hash with state override) → fallback to PROXY" - -call_rpc "eth_transactionPreExec" \ - "[[{\"from\":\"$PREEXEC_FROM\",\"to\":\"$PREEXEC_TO\",\"gas\":\"0x30000\",\"gasPrice\":\"0x4a817c800\",\"value\":\"0x0\",\"nonce\":\"0x11\",\"data\":\"0xf18c388a\"}], \"latest\", {\"$PREEXEC_FROM\":{\"balance\":\"0x56bc75e2d630eb20000\"}}]" \ - "eth_transactionPreExec (latest with state override) → LOCAL" - -call_rpc "eth_transactionPreExec" \ - "[[{\"from\":\"$PREEXEC_FROM\",\"to\":\"$PREEXEC_TO\",\"gas\":\"0x30000\",\"gasPrice\":\"0x4a817c800\",\"value\":\"0x0\",\"nonce\":\"0x11\",\"data\":\"0xf18c388a\"}], {\"blockHash\":\"$FOR_OP_BLOCK_HASH\"}, {\"$PREEXEC_FROM\":{\"balance\":\"0x56bc75e2d630eb20000\"}}]" \ - "eth_transactionPreExec (op-geth block hash with state override) → LOCAL" - # ============================================ # TransactionAPI Tests # ============================================ @@ -249,20 +227,6 @@ call_rpc "eth_getTransactionCount" "[\"$TEST_ADDR\", \"0x$(printf '%x' $BELOW)\" call_rpc "eth_getTransactionCount" "[\"$TEST_ADDR\", \"latest\"]" \ "eth_getTransactionCount (latest) → LOCAL" -echo -e "\n${GREEN}=== TransactionAPI: Internal Transactions (XLayer Specific) ===${NC}" - -call_rpc "eth_getBlockInternalTransactions" "[\"0x$(printf '%x' $BELOW)\"]" \ - "eth_getBlockInternalTransactions (block $BELOW) → PROXY" - -call_rpc "eth_getBlockInternalTransactions" "[\"latest\"]" \ - "eth_getBlockInternalTransactions (latest) → LOCAL" - -call_rpc "eth_getInternalTransactions" "[\"$FOR_OP_TRANSACTION_HASH\"]" \ - "eth_getInternalTransactions (op-geth tx) → LOCAL" - -call_rpc "eth_getInternalTransactions" "[\"$FOR_ERIGON_TRANSACTION_HASH\"]" \ - "eth_getInternalTransactions (erigon tx) → fallback to PROXY" - # ============================================ # FilterAPI Tests # ============================================