public void SmartContracts_MeteredPersistenceStrategy_TestGasConsumed() { byte[] testKey = new byte[] { 1 }; byte[] testValue = new byte[] { 2 }; uint160 testAddress = uint160.One; var sr = new Mock <IContractStateRepository>(); sr.Setup(m => m.SetStorageValue( It.IsAny <uint160>(), It.IsAny <byte[]>(), It.IsAny <byte[]>())); Gas availableGas = (Gas)100000; GasMeter gasMeter = new GasMeter(availableGas); MeteredPersistenceStrategy strategy = new MeteredPersistenceStrategy( sr.Object, gasMeter, this.keyEncodingStrategy ); strategy.StoreBytes( testAddress, testKey, testValue); sr.Verify(s => s.SetStorageValue(testAddress, testKey, testValue)); // Test that gas is used Assert.True(gasMeter.GasConsumed < availableGas); }
public void TestGasInjector_OutOfGasFails() { SmartContractCompilationResult compilationResult = SmartContractCompiler.CompileFile("SmartContracts/OutOfGasTest.cs"); Assert.True(compilationResult.Success); byte[] originalAssemblyBytes = compilationResult.Compilation; var gasLimit = (Gas)500000; var gasMeter = new GasMeter(gasLimit); var persistenceStrategy = new MeteredPersistenceStrategy(this.repository, gasMeter, this.keyEncodingStrategy); var persistentState = new PersistentState(persistenceStrategy, TestAddress.ToUint160(this.network), this.network); var internalTxExecutorFactory = new InternalTransactionExecutorFactory(this.keyEncodingStrategy, this.loggerFactory, this.network); var vm = new ReflectionVirtualMachine(internalTxExecutorFactory, this.loggerFactory); var executionContext = new SmartContractExecutionContext(new Block(0, TestAddress), new Message(TestAddress, TestAddress, 0, (Gas)500000), TestAddress.ToUint160(this.network), 1); var result = vm.ExecuteMethod( originalAssemblyBytes, "UseAllGas", executionContext, gasMeter, persistentState, repository); Assert.NotNull(result.ExecutionException); Assert.Equal((Gas)0, gasMeter.GasAvailable); Assert.Equal(gasLimit, result.GasConsumed); Assert.Equal(gasLimit, gasMeter.GasConsumed); }
public void SmartContracts_GasInjector_MultipleParamConstructorGasInjectedSuccess() { SmartContractCompilationResult compilationResult = SmartContractCompiler.Compile(TestMultipleConstructorSource); Assert.True(compilationResult.Success); byte[] originalAssemblyBytes = compilationResult.Compilation; var gasLimit = (Gas)500000; var gasMeter = new GasMeter(gasLimit); var persistenceStrategy = new MeteredPersistenceStrategy(this.repository, gasMeter, new BasicKeyEncodingStrategy()); var persistentState = new PersistentState(persistenceStrategy, TestAddress.ToUint160(this.network), this.network); var internalTxExecutorFactory = new InternalTransactionExecutorFactory(this.keyEncodingStrategy, this.loggerFactory, this.network); var vm = new ReflectionVirtualMachine(internalTxExecutorFactory, this.loggerFactory); var executionContext = new SmartContractExecutionContext(new Block(0, TestAddress), new Message(TestAddress, TestAddress, 0, (Gas)500000), TestAddress.ToUint160(this.network), 1, new[] { "Tset Owner" }); var result = vm.Create( originalAssemblyBytes, executionContext, gasMeter, persistentState, repository); // Constructor: 15 // Property setter: 12 // Storage: 150 Assert.Equal((Gas)177, result.GasConsumed); }
public void VM_Throws_Exception_CanCatch() { SmartContractCompilationResult compilationResult = SmartContractCompiler.CompileFile("SmartContracts/ThrowExceptionContract.cs"); Assert.True(compilationResult.Success); byte[] contractCode = compilationResult.Compilation; var gasLimit = (Gas)100; var gasMeter = new GasMeter(gasLimit); var persistenceStrategy = new MeteredPersistenceStrategy(this.repository, gasMeter, this.keyEncodingStrategy); var persistentState = new PersistentState(persistenceStrategy, TestAddress.ToUint160(this.network), this.network); var internalTxExecutorFactory = new InternalTransactionExecutorFactory(this.keyEncodingStrategy, this.loggerFactory, this.network); var vm = new ReflectionVirtualMachine(internalTxExecutorFactory, this.loggerFactory); var context = new SmartContractExecutionContext( new Block(0, TestAddress), new Message(TestAddress, TestAddress, 0, gasLimit), TestAddress.ToUint160(this.network), 1, new object[] { } ); var result = vm.ExecuteMethod( contractCode, "ThrowException", context, gasMeter, persistentState, this.repository); Assert.Equal(typeof(Exception), result.ExecutionException.GetType()); }
public ReflectionVirtualMachineTests() { this.network = new SmartContractsRegTest(); this.keyEncodingStrategy = BasicKeyEncodingStrategy.Default; this.loggerFactory = new ExtendedLoggerFactory(); this.loggerFactory.AddConsoleWithFilters(); this.gasLimit = (Gas)10000; this.gasMeter = new GasMeter(this.gasLimit); this.state = new ContractStateRepositoryRoot(new NoDeleteSource <byte[], byte[]>(new MemoryDictionarySource())); var persistenceStrategy = new MeteredPersistenceStrategy(this.state, this.gasMeter, this.keyEncodingStrategy); this.persistentState = new PersistentState(persistenceStrategy, TestAddress.ToUint160(this.network), this.network); }
public void TestGasInjector() { SmartContractCompilationResult compilationResult = SmartContractCompiler.Compile(TestSource); Assert.True(compilationResult.Success); byte[] originalAssemblyBytes = compilationResult.Compilation; var resolver = new DefaultAssemblyResolver(); resolver.AddSearchDirectory(AppContext.BaseDirectory); int aimGasAmount; using (ModuleDefinition moduleDefinition = ModuleDefinition.ReadModule( new MemoryStream(originalAssemblyBytes), new ReaderParameters { AssemblyResolver = resolver })) { TypeDefinition contractType = moduleDefinition.GetType(ContractName); MethodDefinition testMethod = contractType.Methods.FirstOrDefault(x => x.Name == MethodName); aimGasAmount = testMethod?.Body?.Instructions? .Count ?? 10000000; } var gasLimit = (Gas)500000; var gasMeter = new GasMeter(gasLimit); var persistenceStrategy = new MeteredPersistenceStrategy(this.repository, gasMeter, this.keyEncodingStrategy); var persistentState = new PersistentState(persistenceStrategy, TestAddress.ToUint160(this.network), this.network); var internalTxExecutorFactory = new InternalTransactionExecutorFactory(this.keyEncodingStrategy, this.loggerFactory, this.network); var vm = new ReflectionVirtualMachine(internalTxExecutorFactory, this.loggerFactory); var executionContext = new SmartContractExecutionContext( new Block(0, TestAddress), new Message(TestAddress, TestAddress, 0, (Gas)500000), TestAddress.ToUint160(this.network), 1, new object[] { 1 }); var result = vm.ExecuteMethod( originalAssemblyBytes, MethodName, executionContext, gasMeter, persistentState, this.repository); Assert.Equal(aimGasAmount, Convert.ToInt32(result.GasConsumed)); }
public void VM_ExecuteContract_WithoutParameters() { //Get the contract execution code------------------------ SmartContractCompilationResult compilationResult = SmartContractCompiler.CompileFile("SmartContracts/StorageTest.cs"); Assert.True(compilationResult.Success); byte[] contractExecutionCode = compilationResult.Compilation; //------------------------------------------------------- //Call smart contract and add to transaction------------- var carrier = SmartContractCarrier.CallContract(1, new uint160(1), "StoreData", 1, (Gas)500000); var transactionCall = new Transaction(); transactionCall.AddInput(new TxIn()); TxOut callTxOut = transactionCall.AddOutput(0, new Script(carrier.Serialize())); //------------------------------------------------------- //Deserialize the contract from the transaction---------- var deserializedCall = SmartContractCarrier.Deserialize(transactionCall); //------------------------------------------------------- var repository = new ContractStateRepositoryRoot(new NoDeleteSource <byte[], byte[]>(new MemoryDictionarySource())); IContractStateRepository stateRepository = repository.StartTracking(); var gasMeter = new GasMeter(deserializedCall.CallData.GasLimit); var persistenceStrategy = new MeteredPersistenceStrategy(repository, gasMeter, this.keyEncodingStrategy); var persistentState = new PersistentState(persistenceStrategy, deserializedCall.CallData.ContractAddress, this.network); var internalTxExecutorFactory = new InternalTransactionExecutorFactory(this.keyEncodingStrategy, this.loggerFactory, this.network); var vm = new ReflectionVirtualMachine(internalTxExecutorFactory, this.loggerFactory); var sender = deserializedCall.Sender?.ToString() ?? TestAddress.ToString(); var context = new SmartContractExecutionContext( new Block(1, new Address("2")), new Message( new Address(deserializedCall.CallData.ContractAddress.ToString()), new Address(sender), deserializedCall.Value, deserializedCall.CallData.GasLimit ), TestAddress.ToUint160(this.network), deserializedCall.CallData.GasPrice ); var result = vm.ExecuteMethod( contractExecutionCode, "StoreData", context, gasMeter, persistentState, repository); stateRepository.Commit(); Assert.Equal(Encoding.UTF8.GetBytes("TestValue"), stateRepository.GetStorageValue(deserializedCall.CallData.ContractAddress, Encoding.UTF8.GetBytes("TestKey"))); Assert.Equal(Encoding.UTF8.GetBytes("TestValue"), repository.GetStorageValue(deserializedCall.CallData.ContractAddress, Encoding.UTF8.GetBytes("TestKey"))); }
public void VM_CreateContract_WithParameters() { //Get the contract execution code------------------------ SmartContractCompilationResult compilationResult = SmartContractCompiler.CompileFile("SmartContracts/Auction.cs"); Assert.True(compilationResult.Success); byte[] contractExecutionCode = compilationResult.Compilation; //------------------------------------------------------- // //Call smart contract and add to transaction------------- string[] methodParameters = new string[] { string.Format("{0}#{1}", (int)SmartContractCarrierDataType.ULong, 5), }; var carrier = SmartContractCarrier.CreateContract(1, contractExecutionCode, 1, (Gas)500000, methodParameters); var transactionCall = new Transaction(); transactionCall.AddInput(new TxIn()); TxOut callTxOut = transactionCall.AddOutput(0, new Script(carrier.Serialize())); //------------------------------------------------------- //Deserialize the contract from the transaction---------- var deserializedCall = SmartContractCarrier.Deserialize(transactionCall); //------------------------------------------------------- var repository = new ContractStateRepositoryRoot(new NoDeleteSource <byte[], byte[]>(new MemoryDictionarySource())); IContractStateRepository track = repository.StartTracking(); var gasMeter = new GasMeter(deserializedCall.CallData.GasLimit); var persistenceStrategy = new MeteredPersistenceStrategy(repository, gasMeter, new BasicKeyEncodingStrategy()); var persistentState = new PersistentState(persistenceStrategy, TestAddress.ToUint160(this.network), this.network); var internalTxExecutorFactory = new InternalTransactionExecutorFactory(this.keyEncodingStrategy, this.loggerFactory, this.network); var vm = new ReflectionVirtualMachine(internalTxExecutorFactory, this.loggerFactory); var context = new SmartContractExecutionContext( new Block(1, TestAddress), new Message( TestAddress, TestAddress, deserializedCall.Value, deserializedCall.CallData.GasLimit ), TestAddress.ToUint160(this.network), deserializedCall.CallData.GasPrice, deserializedCall.MethodParameters ); var result = vm.Create( contractExecutionCode, context, gasMeter, persistentState, repository); track.Commit(); Assert.Equal(6, BitConverter.ToInt16(track.GetStorageValue(context.Message.ContractAddress.ToUint160(this.network), Encoding.UTF8.GetBytes("EndBlock")), 0)); Assert.Equal(TestAddress.ToUint160(this.network).ToBytes(), track.GetStorageValue(context.Message.ContractAddress.ToUint160(this.network), Encoding.UTF8.GetBytes("Owner"))); }