public void Trace_each_tx_separate() { GethLikeTxTrace trace = ExecuteAndTrace( (byte)Instruction.PUSH1, 0, (byte)Instruction.PUSH1, 0, (byte)Instruction.ADD, (byte)Instruction.PUSH1, 0, (byte)Instruction.SSTORE); Execute( (byte)Instruction.PUSH1, 0, (byte)Instruction.PUSH1, 0, (byte)Instruction.ADD, (byte)Instruction.PUSH1, 0, (byte)Instruction.SSTORE); Assert.AreEqual(5, trace.Entries.Count, "number of entries"); GethTxTraceEntry entry = trace.Entries[1]; Assert.AreEqual(1, entry.Depth, nameof(entry.Depth)); Assert.AreEqual(79000 - GasCostOf.VeryLow, entry.Gas, nameof(entry.Gas)); Assert.AreEqual(GasCostOf.VeryLow, entry.GasCost, nameof(entry.GasCost)); Assert.AreEqual(0, entry.Memory.Count, nameof(entry.Memory)); Assert.AreEqual(1, entry.Stack.Count, nameof(entry.Stack)); Assert.AreEqual(1, trace.Entries[4].Storage.Count, nameof(entry.Storage)); Assert.AreEqual(2, entry.Pc, nameof(entry.Pc)); Assert.AreEqual("PUSH1", entry.Operation, nameof(entry.Operation)); }
private static GethLikeTxTrace MockGethLikeTrace() { var trace = new GethLikeTxTrace { ReturnValue = new byte[] { 0xA2 } }; trace.Entries.Add(new GethTxTraceEntry { Depth = 1, Gas = 22000, GasCost = 1, Memory = new List <string> { "5".PadLeft(64, '0'), "6".PadLeft(64, '0') }, Operation = "STOP", Pc = 32, Stack = new List <string> { "7".PadLeft(64, '0'), "8".PadLeft(64, '0') }, Storage = new Dictionary <string, string> { { "1".PadLeft(64, '0'), "2".PadLeft(64, '0') }, { "3".PadLeft(64, '0'), "4".PadLeft(64, '0') }, } }); return(trace); }
public void Can_trace_pc() { byte[] code = Prepare.EvmCode .PushData("0x0") // 0 .Op(Instruction.JUMPDEST) // 2 .PushData("0x1") // 3 .Op(Instruction.ADD) // 5 .Op(Instruction.DUP1) // 6 .PushData("0x3") // 7 .Op(Instruction.GT) // 9 .PushData("0x2") // 10 .Op(Instruction.JUMPI) // 12 .Op(Instruction.STOP) // 13 .Done; int[] pcs = new[] { 0, 2, 3, 5, 6, 7, 9, 10, 12, 2, 3, 5, 6, 7, 9, 10, 12, 2, 3, 5, 6, 7, 9, 10, 12, 13 }; GethLikeTxTrace trace = ExecuteAndTrace(code); Assert.AreEqual(pcs.Length, trace.Entries.Count); for (int i = 0; i < pcs.Length; i++) { Assert.AreEqual(pcs[i], trace.Entries[i].Pc); } }
public void Examples_from_eip_spec_are_executed_correctly(string addressHex, string saltHex, string initCodeHex, long gas, string resultHex) { byte[] salt = Bytes.FromHexString(saltHex); byte[] deployedCode = Array.Empty <byte>(); byte[] initCode = Bytes.FromHexString(initCodeHex); byte[] createCode = Prepare.EvmCode .Create2(initCode, salt, 0).Done; TestState.CreateAccount(TestItem.AddressC, 1.Ether()); Keccak createCodeHash = TestState.UpdateCode(createCode); TestState.UpdateCodeHash(TestItem.AddressC, createCodeHash, Spec); byte[] code = Prepare.EvmCode .Call(TestItem.AddressC, 50000) .Done; GethLikeTxTrace trace = ExecuteAndTrace(code); Address expectedAddress = new(resultHex); AssertEip1014(expectedAddress, deployedCode); // Assert.AreEqual(gas, trace.Entries.Single(e => e.Operation == Instruction.CREATE2.ToString()).GasCost); }
public void Can_Run_Smoke_test() { var code = Bytes.FromHexString("0x600060000100"); GethLikeTxTracer txTracer = RunVirtualMachine(code); EthereumJsonSerializer serializer = new EthereumJsonSerializer(); GethLikeTxTrace trace = txTracer.BuildResult(); TestContext.WriteLine(serializer.Serialize(trace, true)); }
public static async Task Main(params string[] args) { // int blockNumber = 6108276; // string hash = "?"; int blockNumber = 316658; string hash = "0x846806c1e1fc530399ad80cec3121b9d90fe24e4665484b995237f7f95e2caa8"; // Console.WriteLine("Block Number:"); // int blockNumber = int.Parse(Console.ReadLine()); string nethPathBase = $"D:\\block_traces\\{blockNumber}\\neth\\"; if (!Directory.Exists(nethPathBase)) { Directory.CreateDirectory(nethPathBase); } string gethPathBase = $"D:\\block_traces\\{blockNumber}\\geth\\"; if (!Directory.Exists(gethPathBase)) { Directory.CreateDirectory(gethPathBase); } BasicJsonRpcClient localhostClient = new BasicJsonRpcClient(KnownRpcUris.Localhost, _serializer, NullLogManager.Instance); // await TraceBlock(localhostClient, blockNumber, nethPathBase); await TraceBlockByHash(localhostClient, hash, nethPathBase); BasicJsonRpcClient gethClient = new BasicJsonRpcClient(KnownRpcUris.Localhost, _serializer, NullLogManager.Instance); // await TraceBlock(gethClient, blockNumber, gethPathBase); await TraceBlockByHash(gethClient, hash, gethPathBase); string nethTx = File.ReadAllText(Path.Combine(nethPathBase, "0.txt")); string gethTx = File.ReadAllText(Path.Combine(gethPathBase, "0.txt")); GethLikeTxTrace gethTrace = _serializer.Deserialize <GethLikeTxTrace>(gethTx); GethLikeTxTrace nethTrace = _serializer.Deserialize <GethLikeTxTrace>(nethTx); _comparer.Compare(gethTrace, nethTrace); // try // { // for (int i = 41; i < 42; i++) await TraceTxByBlockhashAndIndex(KnownRpcUris.Localhost, pathBase, blockNumber, i); // } // catch (Exception e) // { // Console.WriteLine(e); // throw; // } Console.WriteLine("Press any key to exit."); Console.ReadKey(); }
public void Trace_invalid_jump_exception() { byte[] code = Prepare.EvmCode .PushData(255) .Op(Instruction.JUMP) .Done; GethLikeTxTrace trace = ExecuteAndTrace(1L, 21000L + 19000L, code); Assert.True(trace.Entries.Any(e => e.Error != null)); }
public void Trace_memory_out_of_gas_exception() { byte[] code = Prepare.EvmCode .PushData((UInt256)(10 * 1000 * 1000)) .Op(Instruction.MLOAD) .Done; GethLikeTxTrace trace = ExecuteAndTrace(1L, 21000L + 19000L, code); Assert.True(trace.Entries.Any(e => e.Error != null)); }
public void Can_trace_stack_underflow_failure() { byte[] code = Prepare.EvmCode .Op(Instruction.ADD) .Done; GethLikeTxTrace trace = ExecuteAndTrace(code); Assert.AreEqual(trace.Failed, true); Assert.AreEqual("StackUnderflow", trace.Entries[0].Error); }
public void Can_trace_invalid_opcode_failure() { byte[] code = Prepare.EvmCode .Op(Instruction.INVALID) .Done; GethLikeTxTrace trace = ExecuteAndTrace(code); Assert.AreEqual(trace.Failed, true); Assert.AreEqual("BadInstruction", trace.Entries.Last().Error); }
public void Can_Invoke_Address() { var code = Bytes.FromHexString("0x3000"); GethLikeTxTracer txTracer = RunVirtualMachine(code); EthereumJsonSerializer serializer = new EthereumJsonSerializer(); GethLikeTxTrace trace = txTracer.BuildResult(); TestContext.WriteLine(serializer.Serialize(trace, true)); trace.Failed.Should().Be(false); trace.Entries.Last().Stack.Count.Should().Be(1); trace.Entries.Last().Stack.Last().Should().Be(VirtualMachine.BytesZero32.ToHexString()); }
public void Can_Invoke_Range_Proof_Precompile() { var code = Bytes.FromHexString("0x60008080806201000062050000F400"); GethLikeTxTracer txTracer = RunVirtualMachine(code); EthereumJsonSerializer serializer = new EthereumJsonSerializer(); GethLikeTxTrace trace = txTracer.BuildResult(); TestContext.WriteLine(serializer.Serialize(trace, true)); trace.Failed.Should().Be(false); trace.Entries.Last().Stack.Count.Should().Be(1); trace.Entries.Last().Stack.Last().Should().Be(VirtualMachine.BytesOne32.ToHexString()); }
public void Can_trace_invalid_jump_failure() { byte[] code = Prepare.EvmCode .PushData("0xab") .Op(Instruction.JUMP) .Done; GethLikeTxTrace trace = ExecuteAndTrace(code); Assert.AreEqual(trace.Failed, true); Assert.AreEqual("BadJumpDestination", trace.Entries.Last().Error); }
public void Can_Invoke_Gas_Limit() { var code = Bytes.FromHexString("0x4500"); GethLikeTxTracer txTracer = RunVirtualMachine(code); EthereumJsonSerializer serializer = new EthereumJsonSerializer(); GethLikeTxTrace trace = txTracer.BuildResult(); TestContext.WriteLine(serializer.Serialize(trace, true)); trace.Failed.Should().Be(false); trace.Entries.Last().Stack.Count.Should().Be(1); trace.Entries.Last().Stack.Last().Should().Be("f4240".PadLeft(64, '0')); }
public void Blake_precompile() { Address blakeAddress = Address.FromNumber(1 + KatVirtualMachine.CatalystPrecompilesAddressingSpace); string addressCode = blakeAddress.Bytes.ToHexString(false); var code = Bytes.FromHexString("0x602060006080600073" + addressCode + "45fa00"); GethLikeTxTracer txTracer = RunVirtualMachine(code); EthereumJsonSerializer serializer = new EthereumJsonSerializer(); GethLikeTxTrace trace = txTracer.BuildResult(); TestContext.WriteLine(serializer.Serialize(trace, true)); trace.Entries.Last().Stack.First().Should().Be("0000000000000000000000000000000000000000000000000000000000000001"); trace.Entries.Last().Memory.First().Should().Be("378d0caaaa3855f1b38693c1d6ef004fd118691c95c959d4efa950d6d6fcf7c1"); }
public void Trace_vm_errors() { GethLikeTxTrace trace = ExecuteAndTrace(1L, 21000L + 19000L, (byte)Instruction.PUSH1, 1, (byte)Instruction.PUSH1, 1, (byte)Instruction.ADD, (byte)Instruction.PUSH1, 0, (byte)Instruction.SSTORE); Assert.True(trace.Entries.Any(e => e.Error != null)); }
public void Can_trace_stack_overflow_failure() { byte[] code = Prepare.EvmCode .Op(Instruction.JUMPDEST) .PushData("0xab") .PushData("0x0") .Op(Instruction.JUMP) .Done; GethLikeTxTrace trace = ExecuteAndTrace(code); Assert.AreEqual(trace.Failed, true); Assert.AreEqual("StackOverflow", trace.Entries.Last().Error); }
public void Compare(GethLikeTxTrace gethTrace, GethLikeTxTrace nethTrace) { if (gethTrace.Gas != nethTrace.Gas) { _logger.Warn($" gas geth {gethTrace.Gas} != neth {nethTrace.Gas} (diff: {gethTrace.Gas - nethTrace.Gas})"); } byte[] gethReturnValue = gethTrace.ReturnValue; byte[] nethReturnValue = nethTrace.ReturnValue; if (!Bytes.AreEqual(gethReturnValue, nethReturnValue)) { _logger.Warn($" return value geth {gethReturnValue.ToHexString()} != neth {nethReturnValue.ToHexString()}"); } if (gethTrace.Failed != nethTrace.Failed) { _logger.Warn($" failed diff geth {gethTrace.Failed} != neth {nethTrace.Failed}"); } var gethEntries = gethTrace.Entries.ToList(); var nethEntries = nethTrace.Entries.ToList(); int ixDiff = 0; for (int i = 0; i < gethEntries.Count; i++) { // _logger.Info($" comparing evm entry {i}"); var gethEntry = gethEntries[i]; if (gethEntry.Error != null) { ixDiff++; continue; } int nethIx = i - ixDiff; string entryDesc = $"ix {i}/{nethIx} pc {gethEntries[i].Pc} op {gethEntries[i].Operation} gas {gethEntries[i].Gas} | "; if (nethEntries.Count < nethIx + 1) { _logger.Warn($" neth entry missing"); } var nethEntry = nethEntries[nethIx]; if (!CompareEntry(gethEntry, nethEntry, entryDesc)) { break; } } }
public ResultWrapper <GethLikeTxTrace> debug_traceTransaction(Keccak transactionHash, GethTraceOptions options = null) { GethLikeTxTrace transactionTrace = _debugBridge.GetTransactionTrace(transactionHash, options); if (transactionTrace == null) { return(ResultWrapper <GethLikeTxTrace> .Fail($"Cannot find transactionTrace for hash: {transactionHash}", ErrorType.NotFound)); } if (_logger.IsTrace) { _logger.Trace($"{nameof(debug_traceTransaction)} request {transactionHash}, result: trace"); } return(ResultWrapper <GethLikeTxTrace> .Success(transactionTrace)); }
public void Can_trace_opcodes() { byte[] code = Prepare.EvmCode .PushData("0xa01234") .PushData("0x0") .Op(Instruction.STOP) .Done; string[] opCodes = new[] { "PUSH3", "PUSH1", "STOP" }; GethLikeTxTrace trace = ExecuteAndTrace(code); for (int i = 0; i < opCodes.Length; i++) { Assert.AreEqual(opCodes[i], trace.Entries[i].Operation); } }
public void Storage_is_cleared_and_restored_when_moving_between_call_levels() { byte[] deployedCode = new byte[3]; byte[] initCode = Prepare.EvmCode .ForInitOf(deployedCode) .Done; byte[] createCode = Prepare.EvmCode .PersistData("0x1", HexZero) // just to test if storage is restored .Create(initCode, 0) .Op(Instruction.STOP) .Done; TestState.CreateAccount(TestItem.AddressC, 1.Ether()); Keccak createCodeHash = TestState.UpdateCode(createCode); TestState.UpdateCodeHash(TestItem.AddressC, createCodeHash, Spec); byte[] code = Prepare.EvmCode .PersistData("0x2", HexZero) // just to test if storage is restored .PersistData("0x3", HexZero) // just to test if storage is restored .Call(TestItem.AddressC, 70000) .Op(Instruction.STOP) .Done; GethLikeTxTrace trace = ExecuteAndTrace(code); /* depths * { * 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 2x SSTORE + STACK FOR CALL [0..13] * 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 // SSTORE + CALL [14..26] * 3, 3, 3, 3, 3, 3, // CREATE [27..32] * 2, // STOP [33] * 1, // STOP [34] * }; */ Assert.AreEqual(0, trace.Entries[0].SortedStorage.Count, "BEGIN 1"); Assert.AreEqual(2, trace.Entries[13].SortedStorage.Count, "CALL FROM 1"); Assert.AreEqual(0, trace.Entries[14].SortedStorage.Count, "BEGIN 2"); Assert.AreEqual(1, trace.Entries[26].SortedStorage.Count, "CREATE FROM 2"); Assert.AreEqual(0, trace.Entries[27].SortedStorage.Count, "BEGIN 3"); Assert.AreEqual(0, trace.Entries[32].SortedStorage.Count, "END 3"); Assert.AreEqual(1, trace.Entries[33].SortedStorage.Count, "END 2"); Assert.AreEqual(2, trace.Entries[34].SortedStorage.Count, "END 1"); }
public void Memory_is_cleared_and_restored_when_moving_between_call_levels() { byte[] deployedCode = new byte[3]; byte[] initCode = Prepare.EvmCode .ForInitOf(deployedCode) .Done; byte[] createCode = Prepare.EvmCode .StoreDataInMemory(32, SampleHexData1.PadLeft(64, '0')) // just to test if memory is restored .Create(initCode, 0) .Op(Instruction.STOP) .Done; TestState.CreateAccount(TestItem.AddressC, 1.Ether()); Keccak createCodeHash = TestState.UpdateCode(createCode); TestState.UpdateCodeHash(TestItem.AddressC, createCodeHash, Spec); byte[] code = Prepare.EvmCode .StoreDataInMemory(64, SampleHexData2.PadLeft(64, '0')) // just to test if memory is restored .Call(TestItem.AddressC, 50000) .Op(Instruction.STOP) .Done; GethLikeTxTrace trace = ExecuteAndTrace(code); /* depths * { * 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // MEMORY + STACK FOR CALL [0..10] * 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 // MEMORY + CALL [11..23] * 3, 3, 3, 3, 3, 3, // CREATE [24..29] * 2, // STOP [30] * 1, // STOP [21] * }; */ Assert.AreEqual(0, trace.Entries[0].Memory.Count, "BEGIN 1"); Assert.AreEqual(3, trace.Entries[10].Memory.Count, "CALL FROM 1"); Assert.AreEqual(0, trace.Entries[11].Memory.Count, "BEGIN 2"); Assert.AreEqual(2, trace.Entries[23].Memory.Count, "CREATE FROM 2"); Assert.AreEqual(0, trace.Entries[24].Memory.Count, "BEGIN 3"); Assert.AreEqual(1, trace.Entries[29].Memory.Count, "END 3"); Assert.AreEqual(2, trace.Entries[30].Memory.Count, "END 2"); Assert.AreEqual(3, trace.Entries[31].Memory.Count, "END 1"); }
public void Stack_is_cleared_and_restored_when_moving_between_call_levels() { byte[] deployedCode = new byte[3]; byte[] initCode = Prepare.EvmCode .ForInitOf(deployedCode) .Done; byte[] createCode = Prepare.EvmCode .PushData(SampleHexData1) // just to test if stack is restored .Create(initCode, 0) .Op(Instruction.STOP) .Done; TestState.CreateAccount(TestItem.AddressC, 1.Ether()); Keccak createCodeHash = TestState.UpdateCode(createCode); TestState.UpdateCodeHash(TestItem.AddressC, createCodeHash, Spec); byte[] code = Prepare.EvmCode .PushData(SampleHexData1) // just to test if stack is restored .Call(TestItem.AddressC, 50000) .Op(Instruction.STOP) .Done; GethLikeTxTrace trace = ExecuteAndTrace(code); /* depths * { * 1, 1, 1, 1, 1, 1, 1, 1, 1, // SAMPLE STACK + STACK FOR CALL [0..8] * 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 // SAMPLE STACK + CALL [9..19] * 3, 3, 3, 3, 3, 3, // CREATE [20..25] * 2, // STOP [26] * 1, // STOP [27] * }; */ Assert.AreEqual(0, trace.Entries[0].Stack.Count, "BEGIN 1"); Assert.AreEqual(8, trace.Entries[8].Stack.Count, "CALL FROM 1"); Assert.AreEqual(0, trace.Entries[9].Stack.Count, "BEGIN 2"); Assert.AreEqual(4, trace.Entries[19].Stack.Count, "CREATE FROM 2"); Assert.AreEqual(0, trace.Entries[20].Stack.Count, "BEGIN 3"); Assert.AreEqual(2, trace.Entries[2].Stack.Count, "END 3"); Assert.AreEqual(2, trace.Entries[26].Stack.Count, "END 2"); Assert.AreEqual(2, trace.Entries[27].Stack.Count, "END 1"); }
public void Ed25519_precompile_can_verify_correct_sig() { HashProvider hashProvider = new HashProvider(HashingAlgorithm.GetAlgorithmMetadata("blake2b-256")); FfiWrapper cryptoContext = new FfiWrapper(); IPrivateKey signingPrivateKey = cryptoContext.GeneratePrivateKey(); var signingPublicKeyBytes = signingPrivateKey.GetPublicKey().Bytes; var byteCode = PrepareEd25519PrecompileCall(hashProvider, cryptoContext, signingPrivateKey, signingPrivateKey); GethLikeTxTracer txTracer = RunVirtualMachine(byteCode); EthereumJsonSerializer serializer = new EthereumJsonSerializer(); GethLikeTxTrace trace = txTracer.BuildResult(); TestContext.WriteLine(serializer.Serialize(trace, true)); trace.Entries.Last().Stack.First().Should().Be("0000000000000000000000000000000000000000000000000000000000000001"); trace.Entries.Last().Memory.First().Should().StartWith("01"); }
public void Ed25519_precompile_can_report_too_long_input() { var byteCode = Bytes.FromHexString( // PUSH1 32 PUSH1 0 PUSH1 192 PUSH1 0 PUSH20 address GAS STATICCALL // make a call to precompile and pass invalid [0,192) bytes of memory as an input // and store result at [0,1) of memory array // allow precompile to use all the gas required "6001600060c0600073" + GetEd25519PrecompileAddressAsHex() + "45fa00"); GethLikeTxTracer txTracer = RunVirtualMachine(byteCode); EthereumJsonSerializer serializer = new EthereumJsonSerializer(); GethLikeTxTrace trace = txTracer.BuildResult(); TestContext.WriteLine(serializer.Serialize(trace, true)); trace.Entries.Last().Stack.First().Should().Be("0000000000000000000000000000000000000000000000000000000000000000"); }
public void Get_trace() { GethTxTraceEntry entry = new GethTxTraceEntry(); entry.Storage = new Dictionary <string, string> { { "1".PadLeft(64, '0'), "2".PadLeft(64, '0') }, { "3".PadLeft(64, '0'), "4".PadLeft(64, '0') }, }; entry.Memory = new List <string> { "5".PadLeft(64, '0'), "6".PadLeft(64, '0') }; entry.Stack = new List <string> { "7".PadLeft(64, '0'), "8".PadLeft(64, '0') }; entry.Operation = "STOP"; entry.Gas = 22000; entry.GasCost = 1; entry.Depth = 1; var trace = new GethLikeTxTrace(); trace.ReturnValue = Bytes.FromHexString("a2"); trace.Entries.Add(entry); IDebugBridge debugBridge = Substitute.For <IDebugBridge>(); debugBridge.GetTransactionTrace(Arg.Any <Keccak>()).Returns(trace); IConfigProvider configProvider = Substitute.For <IConfigProvider>(); DebugModule module = new DebugModule(configProvider, NullLogManager.Instance, debugBridge, new UnforgivingJsonSerializer()); string response = RpcTest.TestSerializedRequest <IDebugModule>(module, "debug_traceTransaction", TestObject.KeccakA.ToString(true)); Assert.AreEqual("{\"id\":67,\"jsonrpc\":\"2.0\",\"result\":{\"gas\":\"0x0\",\"failed\":false,\"returnValue\":\"0xa2\",\"structLogs\":[{\"pc\":0,\"op\":\"STOP\",\"gas\":22000,\"gasCost\":1,\"depth\":1,\"error\":null,\"stack\":[\"0000000000000000000000000000000000000000000000000000000000000007\",\"0000000000000000000000000000000000000000000000000000000000000008\"],\"memory\":[\"0000000000000000000000000000000000000000000000000000000000000005\",\"0000000000000000000000000000000000000000000000000000000000000006\"],\"storage\":{\"0000000000000000000000000000000000000000000000000000000000000001\":\"0000000000000000000000000000000000000000000000000000000000000002\",\"0000000000000000000000000000000000000000000000000000000000000003\":\"0000000000000000000000000000000000000000000000000000000000000004\"}}]}}", response); }
public void Can_trace_call_depth() { byte[] deployedCode = new byte[3]; byte[] initCode = Prepare.EvmCode .ForInitOf(deployedCode) .Done; byte[] createCode = Prepare.EvmCode .Create(initCode, 0) .Op(Instruction.STOP) .Done; TestState.CreateAccount(TestItem.AddressC, 1.Ether()); Keccak createCodeHash = TestState.UpdateCode(createCode); TestState.UpdateCodeHash(TestItem.AddressC, createCodeHash, Spec); byte[] code = Prepare.EvmCode .Call(TestItem.AddressC, 50000) .Op(Instruction.STOP) .Done; GethLikeTxTrace trace = ExecuteAndTrace(code); int[] depths = new int[] { 1, 1, 1, 1, 1, 1, 1, 1, // STACK FOR CALL 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // CALL 3, 3, 3, 3, 3, 3, // CREATE 2, // STOP 1, // STOP }; Assert.AreEqual(depths.Length, trace.Entries.Count); for (int i = 0; i < depths.Length; i++) { Assert.AreEqual(depths[i], trace.Entries[i].Depth, $"entries[{i}]"); } }
public void Get_trace() { GethTxTraceEntry entry = new GethTxTraceEntry(); entry.Storage = new Dictionary <string, string> { { "1".PadLeft(64, '0'), "2".PadLeft(64, '0') }, { "3".PadLeft(64, '0'), "4".PadLeft(64, '0') }, }; entry.Memory = new List <string> { "5".PadLeft(64, '0'), "6".PadLeft(64, '0') }; entry.Stack = new List <string> { "7".PadLeft(64, '0'), "8".PadLeft(64, '0') }; entry.Operation = "STOP"; entry.Gas = 22000; entry.GasCost = 1; entry.Depth = 1; var trace = new GethLikeTxTrace(); trace.ReturnValue = Bytes.FromHexString("a2"); trace.Entries.Add(entry); debugBridge.GetTransactionTrace(Arg.Any <Keccak>(), Arg.Any <CancellationToken>(), Arg.Any <GethTraceOptions>()).Returns(trace); DebugRpcModule rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig); string response = RpcTest.TestSerializedRequest <IDebugRpcModule>(DebugModuleFactory.Converters, rpcModule, "debug_traceTransaction", TestItem.KeccakA.ToString(true), "{}"); Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"result\":{\"gas\":\"0x0\",\"failed\":false,\"returnValue\":\"0xa2\",\"structLogs\":[{\"pc\":0,\"op\":\"STOP\",\"gas\":22000,\"gasCost\":1,\"depth\":1,\"error\":null,\"stack\":[\"0000000000000000000000000000000000000000000000000000000000000007\",\"0000000000000000000000000000000000000000000000000000000000000008\"],\"memory\":[\"0000000000000000000000000000000000000000000000000000000000000005\",\"0000000000000000000000000000000000000000000000000000000000000006\"],\"storage\":{\"0000000000000000000000000000000000000000000000000000000000000001\":\"0000000000000000000000000000000000000000000000000000000000000002\",\"0000000000000000000000000000000000000000000000000000000000000003\":\"0000000000000000000000000000000000000000000000000000000000000004\"}}]},\"id\":67}", response); }
public void Can_trace_gas() { byte[] code = Prepare.EvmCode .PushData("0x1") .PushData("0x2") .Op(Instruction.ADD) .Op(Instruction.STOP) .Done; int[] gasCosts = new int[] { 3, 3, 3, 0 }; GethLikeTxTrace trace = ExecuteAndTrace(code); int gasTotal = 0; for (int i = 0; i < gasCosts.Length; i++) { Assert.AreEqual(79000 - gasTotal, trace.Entries[i].Gas, $"gas[{i}]"); Assert.AreEqual(gasCosts[i], trace.Entries[i].GasCost, $"gasCost[{i}]"); gasTotal += gasCosts[i]; } }
public void Can_trace_stack() { byte[] code = Prepare.EvmCode .PushData(SampleHexData1) .PushData(HexZero) .Op(Instruction.POP) .Op(Instruction.STOP) .Done; GethLikeTxTrace trace = ExecuteAndTrace(code); Assert.AreEqual(0, trace.Entries[0].Stack.Count, "entry[0] length"); Assert.AreEqual(1, trace.Entries[1].Stack.Count, "entry[1] length"); Assert.AreEqual(SampleHexData1.PadLeft(64, '0'), trace.Entries[1].Stack[0], "entry[1][0]"); Assert.AreEqual(2, trace.Entries[2].Stack.Count, "entry[2] length"); Assert.AreEqual(SampleHexData1.PadLeft(64, '0'), trace.Entries[2].Stack[0], "entry[2][0]"); Assert.AreEqual(HexZero.PadLeft(64, '0'), trace.Entries[2].Stack[1], "entry[2][1]"); Assert.AreEqual(1, trace.Entries[3].Stack.Count, "entry[3] length"); Assert.AreEqual(SampleHexData1.PadLeft(64, '0'), trace.Entries[3].Stack[0], "entry[3][0]"); }