public async Task TestGenericVars() { // Add all of our accounts to a mapping with the given index as the value. for (int i = 0; i < Accounts.Length; i++) { // We set a value for each account that is non-zero (zero values aren't stored, the storage entry is deleted). await _contract.updateSimpleMapping(Accounts[i], i + 700); } // Add some other values to a nested mapping (every enum will alternate between SECOND and THIRD) for (int i = 1; i <= 10; i++) { await _contract.updateNestedMapping(i, i * 2, (byte)((i % 2) + 1)); } // Throw an exception in a function call. await _contract.throwWithGenericVars(778899, 100).ExpectRevertTransaction(); // Obtain an execution trace and parse locals from the last point in it (where the exception occurred). var executionTrace = await RpcClient.GetExecutionTrace(); ExecutionTraceAnalysis traceAnalysis = new ExecutionTraceAnalysis(executionTrace); // Obtain our local/state variables. var localVariables = traceAnalysis.GetLocalVariables(RpcClient); var stateVariables = traceAnalysis.GetStateVariables(RpcClient); // TODO: Verify variables. Assert.Inconclusive(); }
public async Task InConstructorTest() { ContractExecutionException exec = null; UInt256 testValue = 112233445566778899; try { await VarAnalysisContract.New(testValue, RpcClient); } catch (ContractExecutionException ex) { exec = ex; } // Obtain an execution trace and parse locals from the last point in it (where the exception occurred). var executionTrace = await RpcClient.GetExecutionTrace(); ExecutionTraceAnalysis traceAnalysis = new ExecutionTraceAnalysis(executionTrace); // Obtain our local/state variables. var localVariables = traceAnalysis.GetLocalVariables(); var stateVariables = traceAnalysis.GetStateVariables(); // TODO: Verify variables. Assert.Inconclusive(); }
public async Task ProcessExecutionTraceAnalysis(ExecutionTraceAnalysis traceAnalysis) { // Obtain our thread ID int threadId = System.Threading.Thread.CurrentThread.ManagedThreadId; // Create a thread state for this thread MeadowDebugAdapterThreadState threadState = new MeadowDebugAdapterThreadState(traceAnalysis, threadId); // Acquire the semaphore for processing a trace. await _processTraceSemaphore.WaitAsync(); // Set the thread state in our lookup ThreadStates[threadId] = threadState; // Send an event that our thread has exited. Protocol.SendEvent(new ThreadEvent(ThreadEvent.ReasonValue.Started, threadState.ThreadId)); // Continue our execution. ContinueExecution(threadState, DesiredControlFlow.Continue); // Lock execution is complete. await threadState.Semaphore.WaitAsync(); // Remove the thread from our lookup. ThreadStates.Remove(threadId, out _); // Unlink our data for our thread id. ReferenceContainer.UnlinkThreadId(threadId); // Send an event that our thread has exited. Protocol.SendEvent(new ThreadEvent(ThreadEvent.ReasonValue.Exited, threadState.ThreadId)); // Release the semaphore for processing a trace. _processTraceSemaphore.Release(); }
public async Task RpcExecutionCallback(IJsonRpcClient client, bool expectingException) { // Obtain an execution trace from our client. var executionTrace = await client.GetExecutionTrace(); var executionTraceAnalysis = new ExecutionTraceAnalysis(executionTrace); // Process our execution trace in the debug adapter. await DebugAdapter.ProcessExecutionTraceAnalysis(client, executionTraceAnalysis, expectingException); await Task.CompletedTask; }
public MeadowDebugAdapterThreadState(ExecutionTraceAnalysis traceAnalysis, int threadId) { // Initialize our thread locking Semaphore = new SemaphoreSlim(0, int.MaxValue); // Set our execution trace analysis ExecutionTraceAnalysis = traceAnalysis; // Set our initial step index index _significantStepIndexIndex = 0; // Set our thread id ThreadId = threadId; }
static async Task <Exception> GetExecutionTraceException(IJsonRpcClient rpcClient, JsonRpcError error) { var executionTrace = await rpcClient.GetExecutionTrace(); var traceAnalysis = new ExecutionTraceAnalysis(executionTrace); // Build our aggregate exception var aggregateException = traceAnalysis.GetAggregateException(error.ToException()); if (aggregateException == null) { throw new Exception("RPC error occurred with tracing enabled but no exceptions could be found in the trace data. Please report this issue.", error.ToException()); } return(aggregateException); }
public async Task TestExternalCallDataArgs() { Address[] addresses = new Address[] { new Address("0x7777777777777777777777777777777777777777"), new Address("0x8888888888888888888888888888888888888888"), new Address("0x9999999999999999999999999999999999999999") }; await _contract.throwExternalCallDataArgs(addresses, 10, 10).ExpectRevertTransaction(); // Obtain an execution trace and parse locals from the last point in it (where the exception occurred). var executionTrace = await RpcClient.GetExecutionTrace(); ExecutionTraceAnalysis traceAnalysis = new ExecutionTraceAnalysis(executionTrace); // Obtain our local/state variables. var localVariables = traceAnalysis.GetLocalVariables(RpcClient); var stateVariables = traceAnalysis.GetStateVariables(RpcClient); // TODO: Verify variables. Assert.Inconclusive(); }
public MeadowDebugAdapterThreadState(IJsonRpcClient rpcClient, ExecutionTraceAnalysis traceAnalysis, int threadId, bool expectingException) { // Initialize our thread locking Semaphore = new SemaphoreSlim(0, int.MaxValue); // Set our rpc client RpcClient = rpcClient; // Set our execution trace analysis ExecutionTraceAnalysis = traceAnalysis; // Set our initial step index index _significantStepIndexIndex = 0; // Set our thread id ThreadId = threadId; ExpectingException = expectingException; }
public async Task TestBytesMemory() { // Create a byte array byte[] param1 = { 0x77, 0x88, 0x99, 0x88, 0x77, 0x00, 0x00, 0x00 }; // Throw an exception in a function call (so we can simply check locals on latest execution point, since we have no front end/UI to choose an execution point at the time of writing this). await _contract.throwBytes(param1).ExpectRevertTransaction(); // Obtain an execution trace and parse locals from the last point in it (where the exception occurred). var executionTrace = await RpcClient.GetExecutionTrace(); ExecutionTraceAnalysis traceAnalysis = new ExecutionTraceAnalysis(executionTrace); // Obtain our local/state variables. var localVariables = traceAnalysis.GetLocalVariables(); var stateVariables = traceAnalysis.GetStateVariables(); // TODO: Verify variables. Assert.Inconclusive(); }
public async Task ProcessExecutionTraceAnalysis(IJsonRpcClient rpcClient, ExecutionTraceAnalysis traceAnalysis, bool expectingException) { // We don't have real threads here, only a unique execution context // per RPC callback (eth_call or eth_sendTransactions). // So just use a rolling ID for threads. int threadId = System.Threading.Interlocked.Increment(ref _threadIDCounter); // Create a thread state for this thread MeadowDebugAdapterThreadState threadState = new MeadowDebugAdapterThreadState(rpcClient, traceAnalysis, threadId, expectingException); // Acquire the semaphore for processing a trace. await _processTraceSemaphore.WaitAsync(); // Set the thread state in our lookup ThreadStates[threadId] = threadState; // If we're not exiting, step through our if (!Exiting) { // Send an event that our thread has exited. Protocol.SendEvent(new ThreadEvent(ThreadEvent.ReasonValue.Started, threadState.ThreadId)); // Continue our execution. ContinueExecution(threadState, DesiredControlFlow.Continue); // Lock execution is complete. await threadState.Semaphore.WaitAsync(); // Send an event that our thread has exited. Protocol.SendEvent(new ThreadEvent(ThreadEvent.ReasonValue.Exited, threadState.ThreadId)); } // Remove the thread from our lookup. ThreadStates.Remove(threadId, out _); // Unlink our data for our thread id. ReferenceContainer.UnlinkThreadId(threadId); // Release the semaphore for processing a trace. _processTraceSemaphore.Release(); }
public async Task InDeeperCall() { // Update our values 7 times. for (int i = 0; i < 7; i++) { await _contract.updateStateValues(); } // Throw an exception in a function call (so we can simply check locals on latest execution point, since we have no front end/UI to choose an execution point at the time of writing this). await _contract.indirectThrowWithLocals(778899, 100).ExpectRevertTransaction(); // Obtain an execution trace and parse locals from the last point in it (where the exception occurred). var executionTrace = await RpcClient.GetExecutionTrace(); ExecutionTraceAnalysis traceAnalysis = new ExecutionTraceAnalysis(executionTrace); // Obtain our local/state variables. var localVariables = traceAnalysis.GetLocalVariables(); var stateVariables = traceAnalysis.GetStateVariables(); // TODO: Verify variables. Assert.Inconclusive(); }
public async Task TestStructMemory() { // Update our values 7 times. for (int i = 0; i < 7; i++) { await _contract.updateStateValues(); } // Throw an exception in a function call (so we can simply check locals on latest execution point). await _contract.throwStruct().ExpectRevertTransaction(); // Obtain an execution trace and parse locals from the last point in it (where the exception occurred). var executionTrace = await RpcClient.GetExecutionTrace(); ExecutionTraceAnalysis traceAnalysis = new ExecutionTraceAnalysis(executionTrace); // Obtain our local/state variables. var localVariables = traceAnalysis.GetLocalVariables(RpcClient); var stateVariables = traceAnalysis.GetStateVariables(RpcClient); // TODO: Verify variables. Assert.Inconclusive(); }
static async Task Main(string[] args) { Console.WriteLine("Starting..."); int port; bool meadow = true; if (!meadow) { port = 7545; } else { // Bootstrap our meadow test node server. var testNode = new Meadow.TestNode.TestNodeServer(); // Print our undefined rpc methods. var undefinedRpcMethods = testNode.GetUndefinedRpcMethods(); Console.WriteLine("Warning: following RPC methods are not defined: \n" + string.Join(", ", undefinedRpcMethods.Select(r => r.Value()))); // Start up the server and obtain the port. await testNode.RpcServer.StartAsync(); port = testNode.RpcServer.ServerPort; } async Task <Exception> GetExecutionTraceException(IJsonRpcClient rpcClient, JsonRpcError error) { if (meadow) { var executionTrace = await rpcClient.GetExecutionTrace(); var traceAnalysis = new ExecutionTraceAnalysis(executionTrace); // Build our aggregate exception var aggregateException = traceAnalysis.GetAggregateException(error.ToException()); return(aggregateException); } else { if (error != null) { throw error.ToException(); } else { throw new Exception("Execution exception"); } } } // Connect our client to the server. var client = JsonRpcClient.Create( new Uri($"http://{IPAddress.Loopback}:{port}"), defaultGasLimit: 6_000_000, defaultGasPrice: 0); client.ErrorFormatter = GetExecutionTraceException; // If we're testing meadow, we enable special coverage/tracing options. if (meadow) { await client.SetCoverageEnabled(true); await client.SetTracingEnabled(true); } //var missingConstructorContract = await MissingConstructorChild.New(client); //var someNum = await missingConstructorContract.someNum().Call(); #region ErrorContract // Try deploying the error generating contract and test some calls. var errorContract = await ErrorContract.New(client, new TransactionParams { Gas = 4712388 }); //await errorContract.doRevert().ExpectRevertTransaction(); //await errorContract.doAssert().ExpectRevertTransaction(); //await errorContract.doThrow().ExpectRevertCall(); #endregion #region Inheritance Tests // Test inheritance with an inherited contract. var inheritedContract = await InheritedContract.New(client, new TransactionParams { Gas = 4712388 }); await inheritedContract.testFunction(); await inheritedContract.testFunctionWithInheritedModifier(); // Test inheritance with a seperate file which we inherited from. var multiInheritedContract = await MultifileInheritedContract.New(client, new TransactionParams { Gas = 4712388 }); await multiInheritedContract.testFunction(); await multiInheritedContract.testFunctionWithInheritedModifier(); #endregion try { await FailDeploymentContract.New(client); } catch { } #region Callstack Tests // Try throwing asserts in further call depth and spanning more than one file. await multiInheritedContract.testInheritedAssertThrow().ExpectRevertTransaction(); if (meadow) { // Test parsing an execution trace of the last call/transaction. var executionTrace = await client.GetExecutionTrace(); ExecutionTraceAnalysis traceAnalysis = new ExecutionTraceAnalysis(executionTrace); // Testing: Build our aggregate exception var aggregateException = traceAnalysis.GetAggregateException(); try { throw aggregateException; } catch { } } #endregion #region ExampleContract Tests // Deploy our main example contract var exContract = await ExampleContract.New($"TestName", true, 34, client, new TransactionParams { Gas = 4712388 }); await exContract.testRevert().ExpectRevertTransaction(); await exContract.testBranchCoverage().ExpectRevertTransaction(); if (meadow) { // Test parsing an execution trace of the last call/transaction. var executionTrace = await client.GetExecutionTrace(); ExecutionTraceAnalysis traceAnalysis = new ExecutionTraceAnalysis(executionTrace); // Testing: Build our aggregate exception var aggregateException = traceAnalysis.GetAggregateException(); try { throw aggregateException; } catch { } } // Test the modexp precompile. var modExpTestBytes = await exContract.testModExp( BigIntegerConverter.GetBytes(BigInteger.Parse("1212121323543453245345678346345737475734753745737774573475377734577", CultureInfo.InvariantCulture)), BigIntegerConverter.GetBytes(BigInteger.Parse("3", CultureInfo.InvariantCulture)), BigIntegerConverter.GetBytes(BigInteger.Parse("4345328123928357434573234217343477", CultureInfo.InvariantCulture))) .Call(); var modExpTest = BigIntegerConverter.GetBigInteger(modExpTestBytes, false, modExpTestBytes.Length); // should be 856753145937825219130387866259147 // Test events var eventTest = await exContract.emitDataEvent(1, 2, 3).TransactionReceipt(); var eventLogFirst = eventTest.FirstEventLog <ExampleContract.DataEvent>(); var eventLogLast = eventTest.LastEventLog <ExampleContract.DataEvent>(); var eventLogAll = eventTest.EventLogs <ExampleContract.DataEvent>(); var eventLogsBase = eventTest.EventLogs(); // Test for chris var result = await exContract.getFirstByteFromByte32(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 }).Call(); // Try testing branch coverage (which ends in an assert being thrown) await exContract.testBranchCoverage().ExpectRevertTransaction(); //await exContract.noopFunc(); var echoGasEst = await exContract.echoInt24(34).EstimateGas(); await exContract.testInstructions1().TransactionReceipt(); var transactionReceipt = await exContract.echoInt24(22).TransactionReceipt(); #endregion #region Performance Tests // Define start time for an execution loop to test performance of a few basic calls. DateTime start = DateTime.Now; DateTime iteration = start; // Note: Change the loop condition here as needed. for (int i = 0; i < 1; i++) { var addr = await exContract.echoAddress(new Address(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 })); var int24Test = await exContract.echoInt24(7777); var stringTest = await exContract.echoString("This is a string."); var enabledThingTest = await exContract.enabledThing(); var isNineTest = await exContract.myFunc(9); var givenName = await exContract.givenName(); // Precompile hash tests var sha256HashTest = await exContract.sha256str("hello world"); // should be 0xb94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9 var ripemd160HashTest = await exContract.ripemd160str("hello world"); // should be 0x98c615784ccb5fe5936fbc0cbe9dfdb408d92f0f // This ECRecover test should yield 0x75c8aa4b12bc52c1f1860bc4e8af981d6542cccd. This test data is taken from SigningTests.cs var ecRecoverTest = await exContract.testECRecover( new byte[] { 0xc9, 0xf1, 0xc7, 0x66, 0x85, 0x84, 0x5e, 0xa8, 0x1c, 0xac, 0x99, 0x25, 0xa7, 0x56, 0x58, 0x87, 0xb7, 0x77, 0x1b, 0x34, 0xb3, 0x5e, 0x64, 0x1c, 0xca, 0x85, 0xdb, 0x9f, 0xef, 0xd0, 0xe7, 0x1f }, 0x1c, BigIntegerConverter.GetBytes(BigInteger.Parse("68932463183462156574914988273446447389145511361487771160486080715355143414637", CultureInfo.InvariantCulture)), BigIntegerConverter.GetBytes(BigInteger.Parse("47416572686988136438359045243120473513988610648720291068939984598262749281683", CultureInfo.InvariantCulture))); Console.WriteLine($"#{i}: {DateTime.Now - iteration}"); iteration = DateTime.Now; } DateTime end = DateTime.Now; #endregion // If this is meadow, we do special post-execution tasks. if (meadow) { // Test obtaining coverage maps, disabling them, clearing them. var coverageMaps = await client.GetAllCoverageMaps(); await client.SetCoverageEnabled(false); await client.ClearCoverage(); // Obtain our generated solc data, create a report, and open it. var solcData = GeneratedSolcData.Default.GetSolcData(); // Match coverage contract addresses with deployed contracts that the client keeps track of. var contractInstances = GeneratedSolcData.Default.MatchCoverageData(coverageMaps); var reportPath = Path.GetFullPath("Report"); MiscUtil.ResetDirectory(reportPath); ReportGenerator.CreateReport(GeneratedSolcData.Default.SolidityCompilerVersion, contractInstances, solcData.SolcSourceInfo, solcData.SolcBytecodeInfo, null, null, reportPath); MiscUtil.OpenBrowser(Path.Join(reportPath, ReportGenerator.REPORT_INDEX_FILE)); } // Output our execution loop time. Console.WriteLine($"Total Time: {end - start}"); Console.ReadLine(); }