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)));
        }
Пример #6
0
        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;
        }
Пример #7
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);

            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));
        }
Пример #9
0
 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);
 }
Пример #12
0
        /// <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;
 }
Пример #16
0
 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)));
        }
Пример #19
0
 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));
        }
Пример #21
0
 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));
        }
Пример #27
0
        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);
        }
Пример #28
0
        /// <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")));
        }