Exemple #1
0
        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);
        }
Exemple #5
0
        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));
        }
Exemple #6
0
        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();
        }
Exemple #7
0
        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));
        }
Exemple #8
0
        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);
        }
Exemple #11
0
        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());
        }
Exemple #12
0
        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);
        }
Exemple #14
0
        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'));
        }
Exemple #15
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");
        }
Exemple #16
0
        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);
        }
Exemple #18
0
        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;
                }
            }
        }
Exemple #19
0
        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");
        }
Exemple #24
0
        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");
        }
Exemple #25
0
        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");
        }
Exemple #26
0
        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}]");
            }
        }
Exemple #28
0
        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]");
        }