public void SmartContractList_ListHasValueTest() { var listName = "testList"; var source = new MemoryDictionarySource(); var root = new ContractStateRepositoryRoot(source); IContractStateRepository state = root.StartTracking(); IPersistenceStrategy persistenceStrategy = new PersistenceStrategy(state); var persistentState = new PersistentState( persistenceStrategy, uint160.One, this.network); var list = new SmartContractList <string>(persistentState, listName); Assert.Equal((uint)0, list.Count); var testItem = "Test"; list.Add(testItem); var item1 = list.GetValue(0); Assert.Equal(testItem, item1); }
public void Repository_CommitAndRollbackTest() { ISource <byte[], byte[]> stateDB = new NoDeleteSource <byte[], byte[]>(new MemoryDictionarySource()); ContractStateRepositoryRoot repository = new ContractStateRepositoryRoot(stateDB); IContractStateRepository txTrack = repository.StartTracking(); txTrack.CreateAccount(testAddress); txTrack.SetStorageValue(testAddress, dog, cat); txTrack.Commit(); repository.Commit(); byte[] root1 = repository.Root; IContractStateRepository txTrack2 = repository.StartTracking(); txTrack2.SetStorageValue(testAddress, dog, fish); txTrack2.Rollback(); IContractStateRepository txTrack3 = repository.StartTracking(); txTrack3.SetStorageValue(testAddress, dodecahedron, bird); txTrack3.Commit(); repository.Commit(); byte[] upToDateRoot = repository.Root; Assert.Equal(cat, repository.GetStorageValue(testAddress, dog)); Assert.Equal(bird, repository.GetStorageValue(testAddress, dodecahedron)); IContractStateRepository snapshot = repository.GetSnapshotTo(root1); repository.SyncToRoot(root1); Assert.Equal(cat, snapshot.GetStorageValue(testAddress, dog)); Assert.Null(snapshot.GetStorageValue(testAddress, dodecahedron)); }
/// <summary> /// Initialize a smart contract executor for the block assembler or consensus validator. /// <para> /// After the contract has been executed, it will process any fees and/or refunds. /// </para> /// </summary> public ISmartContractExecutor CreateExecutor( IContractStateRepository stateRepository, ISmartContractTransactionContext transactionContext) { return(new Executor(this.loggerFactory, this.contractPrimitiveSerializer, this.serializer, stateRepository, this.refundProcessor, this.transferProcessor, this.vm)); }
public void SmartContractList_CanAccessValueUsingIndexTest() { var listName = "testList"; var source = new MemoryDictionarySource(); var root = new ContractStateRepositoryRoot(source); IContractStateRepository state = root.StartTracking(); IPersistenceStrategy persistenceStrategy = new PersistenceStrategy(state); var persistentState = new PersistentState( persistenceStrategy, uint160.One, this.network); var list = new SmartContractList <string>(persistentState, listName); Assert.Equal((uint)0, list.Count); // Set a value in the list list.Add("Test"); list.Add("Test2"); var testItem = list.GetValue(0); var testItem2 = list.GetValue(1); var firstItemHash = $"{listName}[0]"; var secondItemHash = $"{listName}[1]"; var item = persistentState.GetString(firstItemHash); var item2 = persistentState.GetString(secondItemHash); Assert.Equal(testItem, item); Assert.Equal(testItem2, item2); }
///<inheritdoc /> public ICreateResult Create <T>(ISmartContractState smartContractState, ulong amountToTransfer, object[] parameters, ulong gasLimit = 0) { // TODO: Expend any neccessary costs. ulong gasBudget = (gasLimit != 0) ? gasLimit : DefaultGasLimit; // Ensure we have enough gas left to be able to fund the new GasMeter. if (smartContractState.GasMeter.GasAvailable < gasBudget) { throw new InsufficientGasException(); } var nestedGasMeter = new GasMeter((Gas)gasBudget); // Check balance. EnsureContractHasEnoughBalance(smartContractState, amountToTransfer); // Build objects for VM byte[] contractCode = this.contractStateRepository.GetCode(smartContractState.Message.ContractAddress.ToUint160(this.network)); // TODO: Fix this when calling from constructor. var context = new TransactionContext( this.transactionContext.TransactionHash, this.transactionContext.BlockHeight, this.transactionContext.Coinbase, smartContractState.Message.ContractAddress.ToUint160(this.network), amountToTransfer, this.transactionContext.GetNonceAndIncrement()); IContractStateRepository track = this.contractStateRepository.StartTracking(); var createData = new CreateData(nestedGasMeter.GasLimit, contractCode, parameters); // Do create in vm VmExecutionResult result = this.vm.Create(nestedGasMeter, track, createData, context, typeof(T).Name); // Update parent gas meter. smartContractState.GasMeter.Spend(nestedGasMeter.GasConsumed); var revert = result.ExecutionException != null; if (revert) { this.logger.LogTrace("(-)[CONTRACT_EXECUTION_FAILED]"); track.Rollback(); return(CreateResult.Failed()); } this.logger.LogTrace("(-)[CONTRACT_EXECUTION_SUCCEEDED]"); track.Commit(); // TODO: Add internaltransfer update here this.contractLogHolder.AddRawLogs(result.RawLogs); return(CreateResult.Succeeded(result.NewContractAddress.ToAddress(this.network))); }
public MeteredPersistenceStrategy(IContractStateRepository stateDb, IGasMeter gasMeter, IKeyEncodingStrategy keyEncodingStrategy) { Guard.NotNull(stateDb, nameof(stateDb)); Guard.NotNull(gasMeter, nameof(gasMeter)); Guard.NotNull(gasMeter, nameof(keyEncodingStrategy)); this.stateDb = stateDb; this.gasMeter = gasMeter; this.keyEncodingStrategy = keyEncodingStrategy; }
/// <summary> /// If the address to where the funds will be tranferred to is a contract, instantiate and execute it. /// </summary> private ITransferResult ExecuteTransferFundsToContract(byte[] contractCode, ISmartContractState smartContractState, Address addressTo, ulong amountToTransfer, TransferFundsToContract contractDetails) { this.logger.LogTrace("({0}:{1},{2}:{3})", nameof(addressTo), addressTo, nameof(amountToTransfer), amountToTransfer); ulong gasBudget = contractDetails.GasBudget == 0 ? DefaultGasLimit : contractDetails.GasBudget; // Ensure we have enough gas left to be able to fund the new GasMeter. if (smartContractState.GasMeter.GasAvailable < gasBudget) { throw new InsufficientGasException(); } var nestedGasMeter = new GasMeter((Gas)gasBudget); IContractStateRepository track = this.contractStateRepository.StartTracking(); var callData = new CallData(smartContractState.GasMeter.GasLimit, addressTo.ToUint160(this.network), contractDetails.ContractMethodName, contractDetails.MethodParameters); var context = new TransactionContext( this.transactionContext.TransactionHash, this.transactionContext.BlockHeight, this.transactionContext.Coinbase, smartContractState.Message.ContractAddress.ToUint160(this.network), amountToTransfer, this.transactionContext.GetNonceAndIncrement()); VmExecutionResult result = this.vm.ExecuteMethod(nestedGasMeter, track, callData, context); // Update parent gas meter. smartContractState.GasMeter.Spend(nestedGasMeter.GasConsumed); var revert = result.ExecutionException != null; if (revert) { track.Rollback(); return(TransferResult.Failed(result.ExecutionException)); } track.Commit(); this.internalTransferList.Add(new TransferInfo { From = smartContractState.Message.ContractAddress.ToUint160(this.network), To = addressTo.ToUint160(this.network), Value = amountToTransfer }); this.logger.LogTrace("(-)"); return(TransferResult.Transferred(result.Result)); }
public void Repository_CommitPushesToUnderlyingSource() { ISource <byte[], byte[]> stateDB = new NoDeleteSource <byte[], byte[]>(new MemoryDictionarySource()); ContractStateRepositoryRoot repository = new ContractStateRepositoryRoot(stateDB); IContractStateRepository txTrack = repository.StartTracking(); txTrack.CreateAccount(testAddress); txTrack.SetStorageValue(testAddress, dog, cat); Assert.Null(repository.GetStorageValue(testAddress, dog)); txTrack.Commit(); Assert.Equal(cat, repository.GetStorageValue(testAddress, dog)); }
public TransactionCondenser(uint160 contractAddress, ILoggerFactory loggerFactory, IList <TransferInfo> transfers, IContractStateRepository stateRepository, Network network, ISmartContractTransactionContext transactionContext) { this.contractAddress = contractAddress; this.logger = loggerFactory.CreateLogger(this.GetType()); this.network = network; this.transactionContext = transactionContext; this.stateRepository = stateRepository; this.transfers = transfers; this.nVouts = new Dictionary <uint160, uint>(); this.txBalances = new Dictionary <uint160, ulong>(); this.unspents = new List <ContractUnspentOutput>(); }
public void Test20DBreeze() { DBreezeEngine engine = new DBreezeEngine(DbreezeTestLocation); using (DBreeze.Transactions.Transaction t = engine.GetTransaction()) { t.RemoveAllKeys(DbreezeTestDb, true); t.Commit(); } ISource <byte[], byte[]> stateDB = new NoDeleteSource <byte[], byte[]>(new DBreezeByteStore(engine, DbreezeTestDb)); ContractStateRepositoryRoot repository = new ContractStateRepositoryRoot(stateDB); byte[] root = repository.Root; uint160 cowAddress = new uint160(cow); uint160 horseAddress = new uint160(horse); IContractStateRepository track2 = repository.StartTracking(); //repository track2.SetStorageValue(cowAddress, cowKey1, cowVal1); track2.SetStorageValue(horseAddress, horseKey1, horseVal1); track2.Commit(); repository.Commit(); byte[] root2 = repository.Root; track2 = repository.StartTracking(); //repository track2.SetStorageValue(cowAddress, cowKey2, cowVal0); track2.SetStorageValue(horseAddress, horseKey2, horseVal0); track2.Commit(); repository.Commit(); byte[] root3 = repository.Root; IContractStateRepository snapshot = new ContractStateRepositoryRoot(stateDB, root); Assert.Null(snapshot.GetStorageValue(cowAddress, cowKey1)); Assert.Null(snapshot.GetStorageValue(cowAddress, cowKey2)); Assert.Null(snapshot.GetStorageValue(horseAddress, horseKey1)); Assert.Null(snapshot.GetStorageValue(horseAddress, horseKey2)); snapshot = new ContractStateRepositoryRoot(stateDB, root2); Assert.Equal(cowVal1, snapshot.GetStorageValue(cowAddress, cowKey1)); Assert.Null(snapshot.GetStorageValue(cowAddress, cowKey2)); Assert.Equal(horseVal1, snapshot.GetStorageValue(horseAddress, horseKey1)); Assert.Null(snapshot.GetStorageValue(horseAddress, horseKey2)); snapshot = new ContractStateRepositoryRoot(stateDB, root3); Assert.Equal(cowVal1, snapshot.GetStorageValue(cowAddress, cowKey1)); Assert.Equal(cowVal0, snapshot.GetStorageValue(cowAddress, cowKey2)); Assert.Equal(horseVal1, snapshot.GetStorageValue(horseAddress, horseKey1)); Assert.Equal(horseVal0, snapshot.GetStorageValue(horseAddress, horseKey2)); }
public SmartContractExecutorTests() { this.keyEncodingStrategy = BasicKeyEncodingStrategy.Default; this.loggerFactory = new ExtendedLoggerFactory(); this.loggerFactory.AddConsoleWithFilters(); this.network = new SmartContractsRegTest(); this.refundProcessor = new SmartContractResultRefundProcessor(this.loggerFactory); this.state = new ContractStateRepositoryRoot(new NoDeleteSource <byte[], byte[]>(new MemoryDictionarySource())); this.transferProcessor = new SmartContractResultTransferProcessor(this.loggerFactory, this.network); this.validator = new SmartContractValidator(new ISmartContractValidator[] { }); this.internalTxExecutorFactory = new InternalTransactionExecutorFactory(this.keyEncodingStrategy, loggerFactory, this.network); this.vm = new ReflectionVirtualMachine(this.internalTxExecutorFactory, loggerFactory); }
/// <summary> /// Initialize a smart contract executor for the block assembler or consensus validator. /// <para> /// After the contract has been executed, it will process any fees and/or refunds. /// </para> /// </summary> public ISmartContractExecutor CreateExecutor( IContractStateRepository stateRepository, ISmartContractTransactionContext transactionContext) { if (transactionContext.IsCreate) { return(new CreateSmartContract(this.keyEncodingStrategy, this.loggerFactory, this.network, stateRepository, this.validator, this.refundProcessor, this.transferProcessor, this.vm)); } return(new CallSmartContract(this.keyEncodingStrategy, this.loggerFactory, this.network, stateRepository, this.refundProcessor, this.transferProcessor, this.vm)); }
/// <inheritdoc /> public Transaction Process(SmartContractCarrier carrier, IContractStateRepository stateSnapshot, ISmartContractTransactionContext transactionContext, IList <TransferInfo> internalTransfers, bool reversionRequired) { if (reversionRequired) { // Send back funds if (carrier.Value > 0) { return(CreateRefundTransaction(transactionContext)); } } // If contract received no funds and made no transfers, do nothing. if (carrier.Value == 0 && !internalTransfers.Any()) { return(null); } // TODO we should not be generating addresses in here! uint160 contractAddress = null; if (carrier.CallData.ContractAddress == uint160.Zero) { contractAddress = carrier.GetNewContractAddress(); } else { contractAddress = carrier.CallData.ContractAddress; } // If contract had no balance, received funds, but made no transfers, assign the current UTXO. if (stateSnapshot.GetUnspent(contractAddress) == null && carrier.Value > 0 && !internalTransfers.Any()) { stateSnapshot.SetUnspent(contractAddress, new ContractUnspentOutput { Value = carrier.Value, Hash = carrier.TransactionHash, Nvout = carrier.Nvout }); return(null); } // All other cases we need a condensing transaction var transactionCondenser = new TransactionCondenser(contractAddress, this.loggerFactory, internalTransfers, stateSnapshot, this.network, transactionContext); return(transactionCondenser.CreateCondensingTransaction()); }
public void Test4() { MemoryDictionarySource source = new MemoryDictionarySource(); ContractStateRepositoryRoot root = new ContractStateRepositoryRoot(source); IContractStateRepository repository = root.StartTracking(); repository.SetStorageValue(new uint160(cow), cowKey, cowValue); repository.SetStorageValue(new uint160(horse), horseKey, horseValue); repository.Commit(); Assert.Equal(cowValue, root.GetStorageValue(new uint160(cow), cowKey)); Assert.Equal(horseValue, root.GetStorageValue(new uint160(horse), horseKey)); }
public InternalTransactionExecutor( IContractStateRepository contractStateRepository, List <TransferInfo> internalTransferList, IKeyEncodingStrategy keyEncodingStrategy, ILoggerFactory loggerFactory, Network network) { this.contractStateRepository = contractStateRepository; this.internalTransferList = internalTransferList; this.keyEncodingStrategy = keyEncodingStrategy; this.loggerFactory = loggerFactory; this.logger = loggerFactory.CreateLogger(this.GetType()); this.network = network; }
public Executor(ILoggerFactory loggerFactory, ICallDataSerializer serializer, IContractStateRepository stateSnapshot, ISmartContractResultRefundProcessor refundProcessor, ISmartContractResultTransferProcessor transferProcessor, ISmartContractVirtualMachine vm) { this.logger = loggerFactory.CreateLogger(this.GetType()); this.stateSnapshot = stateSnapshot; this.refundProcessor = refundProcessor; this.transferProcessor = transferProcessor; this.vm = vm; this.serializer = serializer; }
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; //------------------------------------------------------- //Set the calldata for the transaction---------- var methodParameters = new object[] { (ulong)5 }; var callData = new CreateData((Gas)5000000, contractExecutionCode, methodParameters); Money value = Money.Zero; //------------------------------------------------------- var repository = new ContractStateRepositoryRoot(new NoDeleteSource <byte[], byte[]>(new MemoryDictionarySource())); IContractStateRepository track = repository.StartTracking(); var gasMeter = new GasMeter(callData.GasLimit); var internalTxExecutorFactory = new InternalTransactionExecutorFactory(this.keyEncodingStrategy, this.loggerFactory, this.network); var vm = new ReflectionVirtualMachine(this.validator, internalTxExecutorFactory, this.loggerFactory, this.network, this.addressGenerator); var transactionContext = new TransactionContext( txHash: uint256.One, blockHeight: 1, coinbase: TestAddress.ToUint160(this.network), sender: TestAddress.ToUint160(this.network), amount: value ); VmExecutionResult result = vm.Create(gasMeter, repository, callData, transactionContext); track.Commit(); var endBlockValue = track.GetStorageValue(result.NewContractAddress, Encoding.UTF8.GetBytes("EndBlock")); Assert.Equal(6, BitConverter.ToInt16(endBlockValue, 0)); Assert.Equal(TestAddress.ToUint160(this.network).ToBytes(), track.GetStorageValue(result.NewContractAddress, Encoding.UTF8.GetBytes("Owner"))); }
public void Test12() { ContractStateRepositoryRoot repository = new ContractStateRepositoryRoot(new MemoryDictionarySource()); IContractStateRepository track = repository.StartTracking(); track.SetCode(new uint160(cow), cowCode); track.SetCode(new uint160(horse), horseCode); Assert.Equal(cowCode, track.GetCode(new uint160(cow))); Assert.Equal(horseCode, track.GetCode(new uint160(horse))); track.Rollback(); Assert.Null(repository.GetCode(new uint160(cow))); Assert.Null(repository.GetCode(new uint160(horse))); }
public InternalTransactionExecutor(ITransactionContext transactionContext, ISmartContractVirtualMachine vm, IContractStateRepository contractStateRepository, List <TransferInfo> internalTransferList, IKeyEncodingStrategy keyEncodingStrategy, ILoggerFactory loggerFactory, Network network) { this.transactionContext = transactionContext; this.contractStateRepository = contractStateRepository; this.internalTransferList = internalTransferList; this.keyEncodingStrategy = keyEncodingStrategy; this.loggerFactory = loggerFactory; this.logger = loggerFactory.CreateLogger(this.GetType()); this.network = network; this.vm = vm; }
/// <summary> /// Creates a new instance of a smart contract by invoking the contract's constructor /// </summary> public VmExecutionResult Create(byte[] contractCode, ISmartContractExecutionContext context, IGasMeter gasMeter, IPersistentState persistentState, IContractStateRepository repository) { this.logger.LogTrace("()"); byte[] gasInjectedCode = SmartContractGasInjector.AddGasCalculationToConstructor(contractCode); Type contractType = Load(gasInjectedCode); var internalTransferList = new List <TransferInfo>(); IInternalTransactionExecutor internalTransactionExecutor = this.internalTransactionExecutorFactory.Create(repository, internalTransferList); var balanceState = new BalanceState(repository, context.Message.Value, internalTransferList); var contractState = new SmartContractState( context.Block, context.Message, persistentState, gasMeter, internalTransactionExecutor, new InternalHashHelper(), () => balanceState.GetBalance(context.ContractAddress)); // Invoke the constructor of the provided contract code LifecycleResult result = SmartContractConstructor.Construct(contractType, contractState, context.Parameters); if (!result.Success) { LogException(result.Exception); this.logger.LogTrace("(-)[CREATE_CONTRACT_INSTANTIATION_FAILED]:{0}={1}", nameof(gasMeter.GasConsumed), gasMeter.GasConsumed); return(VmExecutionResult.Error(gasMeter.GasConsumed, result.Exception.InnerException ?? result.Exception)); } else { this.logger.LogTrace("[CREATE_CONTRACT_INSTANTIATION_SUCCEEDED]"); } this.logger.LogTrace("(-):{0}={1}", nameof(gasMeter.GasConsumed), gasMeter.GasConsumed); return(VmExecutionResult.Success(internalTransferList, gasMeter.GasConsumed, result.Object)); }
public IInternalTransactionExecutor Create(ISmartContractVirtualMachine vm, IContractLogHolder contractLogHolder, IContractStateRepository stateRepository, List <TransferInfo> internalTransferList, ITransactionContext transactionContext) { return(new InternalTransactionExecutor( transactionContext, vm, contractLogHolder, stateRepository, internalTransferList, this.keyEncodingStrategy, this.loggerFactory, this.network )); }
public CallSmartContract(IKeyEncodingStrategy keyEncodingStrategy, ILoggerFactory loggerFactory, Network network, IContractStateRepository stateSnapshot, ISmartContractResultRefundProcessor refundProcessor, ISmartContractResultTransferProcessor transferProcessor, ISmartContractVirtualMachine vm) { this.logger = loggerFactory.CreateLogger(this.GetType()); this.loggerFactory = loggerFactory; this.stateSnapshot = stateSnapshot; this.network = network; this.keyEncodingStrategy = keyEncodingStrategy; this.refundProcessor = refundProcessor; this.transferProcessor = transferProcessor; this.vm = vm; }
public void Test20() { ISource <byte[], byte[]> stateDB = new NoDeleteSource <byte[], byte[]>(new MemoryDictionarySource()); ContractStateRepositoryRoot repository = new ContractStateRepositoryRoot(stateDB); byte[] root = repository.Root; uint160 cowAddress = new uint160(cow); uint160 horseAddress = new uint160(horse); IContractStateRepository track2 = repository.StartTracking(); //repository track2.SetStorageValue(cowAddress, cowKey1, cowVal1); track2.SetStorageValue(horseAddress, horseKey1, horseVal1); track2.Commit(); repository.Commit(); byte[] root2 = repository.Root; track2 = repository.StartTracking(); //repository track2.SetStorageValue(cowAddress, cowKey2, cowVal0); track2.SetStorageValue(horseAddress, horseKey2, horseVal0); track2.Commit(); repository.Commit(); byte[] root3 = repository.Root; IContractStateRepository snapshot = new ContractStateRepositoryRoot(stateDB, root); Assert.Null(snapshot.GetStorageValue(cowAddress, cowKey1)); Assert.Null(snapshot.GetStorageValue(cowAddress, cowKey2)); Assert.Null(snapshot.GetStorageValue(horseAddress, horseKey1)); Assert.Null(snapshot.GetStorageValue(horseAddress, horseKey2)); snapshot = new ContractStateRepositoryRoot(stateDB, root2); Assert.Equal(cowVal1, snapshot.GetStorageValue(cowAddress, cowKey1)); Assert.Null(snapshot.GetStorageValue(cowAddress, cowKey2)); Assert.Equal(horseVal1, snapshot.GetStorageValue(horseAddress, horseKey1)); Assert.Null(snapshot.GetStorageValue(horseAddress, horseKey2)); snapshot = new ContractStateRepositoryRoot(stateDB, root3); Assert.Equal(cowVal1, snapshot.GetStorageValue(cowAddress, cowKey1)); Assert.Equal(cowVal0, snapshot.GetStorageValue(cowAddress, cowKey2)); Assert.Equal(horseVal1, snapshot.GetStorageValue(horseAddress, horseKey1)); Assert.Equal(horseVal0, snapshot.GetStorageValue(horseAddress, horseKey2)); }
/// <summary> /// If the address to where the funds will be tranferred to is a contract, instantiate and execute it. /// </summary> private ITransferResult ExecuteTransferFundsToContract(byte[] contractCode, ISmartContractState smartContractState, Address addressTo, ulong amountToTransfer, TransferFundsToContract contractDetails) { this.logger.LogTrace("({0}:{1},{2}:{3})", nameof(addressTo), addressTo, nameof(amountToTransfer), amountToTransfer); IContractStateRepository track = this.contractStateRepository.StartTracking(); IPersistenceStrategy persistenceStrategy = new MeteredPersistenceStrategy(track, smartContractState.GasMeter, this.keyEncodingStrategy); IPersistentState newPersistentState = new PersistentState(persistenceStrategy, addressTo.ToUint160(this.network), this.network); var newMessage = new Message(addressTo, smartContractState.Message.ContractAddress, amountToTransfer, (Gas)(smartContractState.Message.GasLimit - smartContractState.GasMeter.GasConsumed)); ISmartContractExecutionContext newContext = new SmartContractExecutionContext(smartContractState.Block, newMessage, addressTo.ToUint160(this.network), 0, contractDetails.MethodParameters); ISmartContractVirtualMachine vm = new ReflectionVirtualMachine(new InternalTransactionExecutorFactory(this.keyEncodingStrategy, this.loggerFactory, this.network), this.loggerFactory); var result = vm.ExecuteMethod( contractCode, contractDetails.ContractMethodName, newContext, smartContractState.GasMeter, newPersistentState, track); var revert = result.ExecutionException != null; if (revert) { track.Rollback(); return(TransferResult.Failed(result.ExecutionException)); } track.Commit(); this.internalTransferList.Add(new TransferInfo { From = smartContractState.Message.ContractAddress.ToUint160(this.network), To = addressTo.ToUint160(this.network), Value = amountToTransfer }); this.logger.LogTrace("(-)"); return(TransferResult.Transferred(result.Result)); }
public void VM_ExecuteContract_WithParameters() { //Get the contract execution code------------------------ SmartContractCompilationResult compilationResult = SmartContractCompiler.CompileFile("SmartContracts/StorageTestWithParameters.cs"); Assert.True(compilationResult.Success); byte[] contractExecutionCode = compilationResult.Compilation; //------------------------------------------------------- //Set the calldata for the transaction---------- var methodParameters = new object[] { (short)5 }; var callData = new CallData((Gas)5000000, new uint160(1), "StoreData", methodParameters); Money value = Money.Zero; //------------------------------------------------------- var repository = new ContractStateRepositoryRoot(new NoDeleteSource <byte[], byte[]>(new MemoryDictionarySource())); IContractStateRepository track = repository.StartTracking(); var gasMeter = new GasMeter(callData.GasLimit); var internalTxExecutorFactory = new InternalTransactionExecutorFactory(this.keyEncodingStrategy, this.loggerFactory, this.network); var vm = new ReflectionVirtualMachine(this.validator, internalTxExecutorFactory, this.loggerFactory, this.network, this.addressGenerator); uint160 address = TestAddress.ToUint160(this.network); var transactionContext = new TransactionContext(uint256.One, 1, address, address, value); repository.SetCode(callData.ContractAddress, contractExecutionCode); repository.SetContractType(callData.ContractAddress, "StorageTestWithParameters"); VmExecutionResult result = vm.ExecuteMethod(gasMeter, repository, callData, transactionContext); track.Commit(); Assert.Equal(5, BitConverter.ToInt16(track.GetStorageValue(callData.ContractAddress, Encoding.UTF8.GetBytes("orders")), 0)); Assert.Equal(5, BitConverter.ToInt16(repository.GetStorageValue(callData.ContractAddress, Encoding.UTF8.GetBytes("orders")), 0)); }
/// <summary> /// If the address to where the funds will be tranferred to is a contract, instantiate and execute it. /// </summary> private ITransferResult ExecuteTransferFundsToContract(byte[] contractCode, ISmartContractState smartContractState, Address addressTo, ulong amountToTransfer, TransferFundsToContract contractDetails) { this.logger.LogTrace("({0}:{1},{2}:{3})", nameof(addressTo), addressTo, nameof(amountToTransfer), amountToTransfer); IContractStateRepository track = this.contractStateRepository.StartTracking(); var callData = new CallData(smartContractState.GasMeter.GasLimit, addressTo.ToUint160(this.network), contractDetails.ContractMethodName, contractDetails.MethodParameters); var context = new TransactionContext( this.transactionContext.TransactionHash, this.transactionContext.BlockHeight, this.transactionContext.Coinbase, smartContractState.Message.ContractAddress.ToUint160(this.network), amountToTransfer); var result = this.vm.ExecuteMethod(smartContractState.GasMeter, track, callData, context); var revert = result.ExecutionException != null; if (revert) { track.Rollback(); return(TransferResult.Failed(result.ExecutionException)); } track.Commit(); this.internalTransferList.Add(new TransferInfo { From = smartContractState.Message.ContractAddress.ToUint160(this.network), To = addressTo.ToUint160(this.network), Value = amountToTransfer }); this.logger.LogTrace("(-)"); return(TransferResult.Transferred(result.Result)); }
public void SmartContractList_ListHasCountTest() { var listName = "testList"; var source = new MemoryDictionarySource(); var root = new ContractStateRepositoryRoot(source); IContractStateRepository state = root.StartTracking(); IPersistenceStrategy persistenceStrategy = new PersistenceStrategy(state); var persistentState = new PersistentState( persistenceStrategy, this.contractPrimitiveSerializer, uint160.One); var list = new SmartContractList <string>(persistentState, listName); Assert.Equal((uint)0, list.Count); list.Add("Test"); Assert.Equal((uint)1, list.Count); }
/// <inheritdoc /> public Transaction Process(IContractStateRepository stateSnapshot, uint160 contractAddress, ISmartContractTransactionContext transactionContext, IList <TransferInfo> internalTransfers, bool reversionRequired) { if (reversionRequired) { // Send back funds if (transactionContext.TxOutValue > 0) { return(CreateRefundTransaction(transactionContext)); } } // If contract received no funds and made no transfers, do nothing. if (transactionContext.TxOutValue == 0 && !internalTransfers.Any()) { return(null); } // If contract had no balance, received funds, but made no transfers, assign the current UTXO. if (stateSnapshot.GetUnspent(contractAddress) == null && transactionContext.TxOutValue > 0 && !internalTransfers.Any()) { stateSnapshot.SetUnspent(contractAddress, new ContractUnspentOutput { Value = transactionContext.TxOutValue, Hash = transactionContext.TransactionHash, Nvout = transactionContext.Nvout }); return(null); } // All other cases we need a condensing transaction var transactionCondenser = new TransactionCondenser(contractAddress, this.loggerFactory, internalTransfers, stateSnapshot, this.network, transactionContext); return(transactionCondenser.CreateCondensingTransaction()); }
public void SmartContractList_ListEnumerationTest() { var listName = "testList"; var source = new MemoryDictionarySource(); var root = new ContractStateRepositoryRoot(source); IContractStateRepository state = root.StartTracking(); IPersistenceStrategy persistenceStrategy = new PersistenceStrategy(state); var persistentState = new PersistentState( persistenceStrategy, uint160.One, this.network); var list = new SmartContractList <string>(persistentState, listName); Assert.Equal((uint)0, list.Count); var items = new List <string> { "this is a test", "we should try to find a way", "to paramaterize our tests" }; foreach (var item in items) { // No AddRange list.Add(item); } Assert.Equal((uint)items.Count, list.Count); for (var i = 0; i < list.Count; i++) { Assert.Equal(items[i], list.GetValue((uint)i)); } }
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; //------------------------------------------------------- //Set the calldata for the transaction---------- var callData = new CallData((Gas)5000000, new uint160(1), "StoreData"); Money value = Money.Zero; //------------------------------------------------------- var repository = new ContractStateRepositoryRoot(new NoDeleteSource <byte[], byte[]>(new MemoryDictionarySource())); IContractStateRepository stateRepository = repository.StartTracking(); var gasMeter = new GasMeter(callData.GasLimit); uint160 address = TestAddress.ToUint160(this.network); var transactionContext = new TransactionContext(uint256.One, 1, address, address, 0); repository.SetCode(callData.ContractAddress, contractExecutionCode); repository.SetContractType(callData.ContractAddress, "StorageTest"); VmExecutionResult result = this.vm.ExecuteMethod(gasMeter, repository, callData, transactionContext); stateRepository.Commit(); Assert.Equal(Encoding.UTF8.GetBytes("TestValue"), stateRepository.GetStorageValue(callData.ContractAddress, Encoding.UTF8.GetBytes("TestKey"))); Assert.Equal(Encoding.UTF8.GetBytes("TestValue"), repository.GetStorageValue(callData.ContractAddress, Encoding.UTF8.GetBytes("TestKey"))); }