Esempio n. 1
0
        public void Call_Contract_Failure()
        {
            var parameters     = new object[] { };
            var contractTxData = new ContractTxData(1, 1, (RuntimeObserver.Gas) 1000, uint160.One, "TestMethod", parameters);

            StateTransitionResult stateTransitionResult = StateTransitionResult.Fail((RuntimeObserver.Gas) 100, StateTransitionErrorKind.VmError);

            var    fixture  = new ExecutorFixture(contractTxData);
            IState snapshot = fixture.State.Object.Snapshot();

            fixture.StateProcessor
            .Setup(s => s.Apply(snapshot, It.IsAny <ExternalCallMessage>()))
            .Returns(stateTransitionResult);

            IStateRepository trackedMock = Mock.Of <IStateRepository>();

            fixture.ContractStateRoot.Setup(s => s.StartTracking()).Returns(trackedMock);

            var sut = new LocalExecutor(
                fixture.LoggerFactory,
                fixture.CallDataSerializer.Object,
                fixture.ContractStateRoot.Object,
                fixture.StateFactory.Object,
                fixture.StateProcessor.Object,
                fixture.ContractPrimitiveSerializer.Object);

            ILocalExecutionResult result = sut.Execute(fixture.ContractTransactionContext.BlockHeight,
                                                       fixture.ContractTransactionContext.Sender,
                                                       fixture.ContractTransactionContext.TxOutValue,
                                                       contractTxData);

            fixture.StateFactory.Verify(sf => sf
                                        .Create(
                                            trackedMock,
                                            It.IsAny <IBlock>(),
                                            fixture.ContractTransactionContext.TxOutValue,
                                            It.IsAny <uint256>()),
                                        Times.Once);

            // We only apply the message to the snapshot.
            fixture.StateProcessor.Verify(sm => sm.Apply(snapshot, It.Is <ExternalCallMessage>(m =>
                                                                                               m.Method.Name == contractTxData.MethodName &&
                                                                                               m.Method.Parameters == contractTxData.MethodParameters &&
                                                                                               m.Amount == fixture.ContractTransactionContext.TxOutValue &&
                                                                                               m.From == fixture.ContractTransactionContext.Sender &&
                                                                                               m.To == contractTxData.ContractAddress)), Times.Once);

            // Should never transition to the snapshot.
            fixture.State.Verify(sm => sm.TransitionTo(snapshot), Times.Never);

            // Should never save on the state
            fixture.ContractStateRoot.Verify(sr => sr.Commit(), Times.Never);

            Assert.Equal(stateTransitionResult.Error.VmError, result.ErrorMessage);
            Assert.True(result.Revert);
            Assert.Equal <IReadOnlyList <TransferInfo> >(fixture.State.Object.InternalTransfers, result.InternalTransfers);
            Assert.Equal(stateTransitionResult.GasConsumed, result.GasConsumed);
            Assert.Null(result.Return);
            Assert.Equal <IList <Log> >(fixture.State.Object.GetLogs(fixture.ContractPrimitiveSerializer.Object), result.Logs);
        }
        public IActionResult LocalCallSmartContractTransaction([FromBody] BuildCallContractTransactionRequest request)
        {
            if (!this.ModelState.IsValid)
            {
                return(ModelStateErrors.BuildErrorResponse(this.ModelState));
            }

            // Rewrite the method name to a property name
            this.RewritePropertyGetterName(request);

            BuildCallContractTransactionResponse response = this.smartContractTransactionService.BuildCallTx(request);

            Transaction transaction = this.network.CreateTransaction(response.Hex);

            var transactionContext = new ContractTransactionContext(
                (ulong)this.chain.Height,
                uint160.Zero,
                0, // Safe to set this to 0 here, it's only used for the refund which we do not create when executing locally
                request.Sender.ToUint160(this.network),
                transaction);

            ILocalExecutionResult result = this.localExecutor.Execute(transactionContext);

            return(Json(result));
        }
        public IActionResult LocalCallSmartContractTransaction([FromBody] LocalCallContractRequest request)
        {
            if (!this.ModelState.IsValid)
            {
                return(ModelStateErrors.BuildErrorResponse(this.ModelState));
            }

            // Rewrite the method name to a property name
            this.RewritePropertyGetterName(request);

            try
            {
                ContractTxData txData = this.smartContractTransactionService.BuildLocalCallTxData(request);

                ILocalExecutionResult result = this.localExecutor.Execute(
                    (ulong)this.chainIndexer.Height,
                    request.Sender?.ToUint160(this.network) ?? new uint160(),
                    string.IsNullOrWhiteSpace(request.Amount) ? (Money)request.Amount : 0,
                    txData);

                return(this.Json(result, new JsonSerializerSettings
                {
                    ContractResolver = new ContractParametersContractResolver(this.network)
                }));
            }
            catch (MethodParameterStringSerializerException e)
            {
                return(this.Json(ErrorHelpers.BuildErrorResponse(HttpStatusCode.InternalServerError, e.Message,
                                                                 "Error deserializing method parameters")));
            }
        }
        public void Create_Contract_Failure()
        {
            var contractTxData = new ContractTxData(1, 1, (Gas)1000, new byte[] { 0xAA, 0xBB, 0xCC });

            StateTransitionResult stateTransitionResult = StateTransitionResult.Fail((Gas)100, StateTransitionErrorKind.VmError);

            var    fixture  = new ExecutorFixture(contractTxData);
            IState snapshot = fixture.State.Object.Snapshot();

            fixture.StateProcessor
            .Setup(s => s.Apply(snapshot, It.IsAny <ExternalCreateMessage>()))
            .Returns(stateTransitionResult);

            IStateRepository trackedMock = Mock.Of <IStateRepository>();

            fixture.ContractStateRoot.Setup(s => s.StartTracking()).Returns(trackedMock);

            var sut = new LocalExecutor(
                fixture.LoggerFactory,
                fixture.CallDataSerializer.Object,
                fixture.ContractStateRoot.Object,
                fixture.StateFactory.Object,
                fixture.StateProcessor.Object,
                fixture.ContractPrimitiveSerializer.Object);

            ILocalExecutionResult result = sut.Execute(fixture.ContractTransactionContext);

            fixture.CallDataSerializer.Verify(s => s.Deserialize(fixture.Data), Times.Once);

            fixture.StateFactory.Verify(sf => sf
                                        .Create(
                                            trackedMock,
                                            It.IsAny <IBlock>(),
                                            fixture.ContractTransactionContext.TxOutValue,
                                            fixture.ContractTransactionContext.TransactionHash),
                                        Times.Once);

            // We only apply the message to the snapshot.
            fixture.StateProcessor.Verify(sm => sm.Apply(fixture.State.Object.Snapshot(),
                                                         It.Is <ExternalCreateMessage>(m =>
                                                                                       m.Code == contractTxData.ContractExecutionCode &&
                                                                                       m.Parameters == contractTxData.MethodParameters)), Times.Once);

            // Should never transition to the snapshot.
            fixture.State.Verify(sm => sm.TransitionTo(fixture.State.Object.Snapshot()), Times.Never);

            // Should never save on the state
            fixture.ContractStateRoot.Verify(sr => sr.Commit(), Times.Never);

            Assert.Equal(stateTransitionResult.Error.VmError, result.ErrorMessage);
            Assert.True(result.Revert);
            Assert.Equal(fixture.State.Object.InternalTransfers, result.InternalTransfers);
            Assert.Equal(stateTransitionResult.GasConsumed, result.GasConsumed);
            Assert.Null(result.Return);
            Assert.Equal(fixture.State.Object.GetLogs(fixture.ContractPrimitiveSerializer.Object), result.Logs);
        }
Esempio n. 5
0
        public void MockChain_NonFungibleToken()
        {
            using (PoWMockChain chain = new PoWMockChain(2))
            {
                MockChainNode node1 = chain.Nodes[0];
                MockChainNode node2 = chain.Nodes[1];

                node1.MineBlocks(1);

                ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/NonFungibleToken.cs");
                Assert.True(compilationResult.Success);

                // Create contract and ensure code exists
                BuildCreateContractTransactionResponse response = node1.SendCreateContractTransaction(compilationResult.Compilation, 0);
                node2.WaitMempoolCount(1);
                node2.MineBlocks(1);
                Assert.NotNull(node2.GetCode(response.NewContractAddress));
                Assert.NotNull(node1.GetCode(response.NewContractAddress));

                string[] parameters = new string[]
                {
                    this.methodParameterStringSerializer.Serialize(1uL)
                };

                ILocalExecutionResult result   = node1.CallContractMethodLocally("OwnerOf", response.NewContractAddress, 0, parameters);
                uint160 senderAddressUint160   = node1.MinerAddress.Address.ToUint160(node1.CoreNode.FullNode.Network);
                uint160 returnedAddressUint160 = ((Address)result.Return).ToUint160();
                Assert.Equal(senderAddressUint160, returnedAddressUint160);

                // Send tokenId 1 to a new owner
                parameters = new string[]
                {
                    this.methodParameterStringSerializer.Serialize(node1.MinerAddress.Address.ToAddress(node1.CoreNode.FullNode.Network)),
                    this.methodParameterStringSerializer.Serialize(node2.MinerAddress.Address.ToAddress(node1.CoreNode.FullNode.Network)),
                    this.methodParameterStringSerializer.Serialize(1uL)
                };
                BuildCallContractTransactionResponse callResponse = node1.SendCallContractTransaction("TransferFrom", response.NewContractAddress, 0, parameters);
                node2.WaitMempoolCount(1);
                node2.MineBlocks(1);

                parameters = new string[]
                {
                    this.methodParameterStringSerializer.Serialize(1uL)
                };
                result = node1.CallContractMethodLocally("OwnerOf", response.NewContractAddress, 0, parameters);
                uint160 receiverAddressUint160 = node2.MinerAddress.Address.ToUint160(node1.CoreNode.FullNode.Network);
                returnedAddressUint160 = ((Address)result.Return).ToUint160();
                Assert.Equal(receiverAddressUint160, returnedAddressUint160);

                IList <ReceiptResponse> receipts = node1.GetReceipts(response.NewContractAddress, "Transfer");
                Assert.Single(receipts);
            }
        }
        public LocalExecutionResult LocalCallSmartContractTransaction([FromBody] LocalCallContractRequest request)
        {
            // Rewrite the method name to a property name
            this.RewritePropertyGetterName(request);

            ContractTxData txData = this.smartContractTransactionService.BuildLocalCallTxData(request);

            ulong height = request.BlockHeight.HasValue ? request.BlockHeight.Value : (ulong)this.chainIndexer.Height;

            ILocalExecutionResult result = this.localExecutor.Execute(height, request.Sender?.ToUint160(this.network) ?? new uint160(),
                                                                      string.IsNullOrWhiteSpace(request.Amount) ? (Money)request.Amount : 0, txData);

            return(result as LocalExecutionResult);
        }
        public void Token_Standards_Test()
        {
            const ulong totalSupply = 100_000;
            // Deploy contract
            ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/StandardToken.cs");

            Assert.True(compilationResult.Success);
            string[] constructorParams = new string[] { string.Format("{0}#{1}", (int)MethodParameterDataType.UInt, totalSupply) };
            BuildCreateContractTransactionResponse preResponse = this.node1.SendCreateContractTransaction(compilationResult.Compilation, 0, constructorParams);

            this.mockChain.WaitAllMempoolCount(1);
            this.mockChain.MineBlocks(1);
            Assert.NotNull(this.node1.GetCode(preResponse.NewContractAddress));

            decimal amount = 0;

            // Send amount to contract, which will send to wallet address (address without code)
            var base58Address = this.node1.MinerAddress.Address;

            string[] parameters = new string[] { string.Format("{0}#{1}", (int)MethodParameterDataType.Address, base58Address) };
            BuildCallContractTransactionResponse response = this.node1.SendCallContractTransaction(
                nameof(StandardToken.GetBalance),
                preResponse.NewContractAddress,
                amount,
                parameters);

            this.mockChain.WaitAllMempoolCount(1);
            this.mockChain.MineBlocks(1);

            // Contract doesn't maintain any balance
            Assert.Equal((ulong)0, this.node1.GetContractBalance(preResponse.NewContractAddress));

            ILocalExecutionResult result = this.node1.CallContractMethodLocally("GetBalance", preResponse.NewContractAddress, 0, parameters);

            Assert.Equal(totalSupply, result.Return);

            // Receipt is correct
            ReceiptResponse receipt = this.node1.GetReceipt(response.TransactionId.ToString());

            Assert.Equal(response.TransactionId.ToString(), receipt.TransactionHash);
            Assert.Empty(receipt.Logs); // TODO: Could add logs to this test
            Assert.True(receipt.Success);
            Assert.True(receipt.GasUsed > GasPriceList.BaseCost);
            Assert.Null(receipt.NewContractAddress);
            Assert.Equal(this.node1.MinerAddress.Address, receipt.From);
            Assert.Null(receipt.Error);
            Assert.Equal(preResponse.NewContractAddress, receipt.To);
        }
Esempio n. 8
0
        public IActionResult LocalCallSmartContractTransaction([FromBody] LocalCallContractRequest request)
        {
            if (!this.ModelState.IsValid)
            {
                return(ModelStateErrors.BuildErrorResponse(this.ModelState));
            }

            // Rewrite the method name to a property name
            this.RewritePropertyGetterName(request);

            try
            {
                ContractTxData txData = this.smartContractTransactionService.BuildLocalCallTxData(request);

                var height = request.BlockHeight.HasValue ? request.BlockHeight.Value : (ulong)this.chainIndexer.Height;

                ILocalExecutionResult result = this.localExecutor.Execute(
                    height,
                    request.Sender?.ToUint160(this.network) ?? new uint160(),
                    !string.IsNullOrWhiteSpace(request.Amount) ? (Money)request.Amount : 0,
                    txData);

                var deserializer = new ApiLogDeserializer(this.primitiveSerializer, this.network, result.StateRoot, this.contractAssemblyCache);

                var response = new LocalExecutionResponse
                {
                    InternalTransfers = deserializer.MapTransferInfo(result.InternalTransfers.ToArray()),
                    Logs         = deserializer.MapLogResponses(result.Logs.ToArray()),
                    GasConsumed  = result.GasConsumed,
                    Revert       = result.Revert,
                    ErrorMessage = result.ErrorMessage,
                    Return       = result.Return // All return values should be primitives, let default serializer handle.
                };

                return(this.Json(response, new JsonSerializerSettings
                {
                    ContractResolver = new ContractParametersContractResolver(this.network)
                }));
            }
            catch (MethodParameterStringSerializerException e)
            {
                return(this.Json(ErrorHelpers.BuildErrorResponse(HttpStatusCode.InternalServerError, e.Message,
                                                                 "Error deserializing method parameters")));
            }
        }
Esempio n. 9
0
        public void TestChain_Auction()
        {
            // Compile the contract we want to deploy
            ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/Auction.cs");

            Assert.True(compilationResult.Success);

            using (TestChain chain = new TestChain().Initialize())
            {
                // Get an address we can use for deploying
                Base58Address deployerAddress = chain.PreloadedAddresses[0];

                // Create and send transaction to mempool with parameters
                SendCreateContractResult createResult = chain.SendCreateContractTransaction(deployerAddress, compilationResult.Compilation, 0, new object[] { 20uL });

                // Mine a block which will contain our sent transaction
                chain.MineBlocks(1);

                // Check the receipt to see that contract deployment was successful
                ReceiptResponse receipt = chain.GetReceipt(createResult.TransactionId);
                Assert.Equal(deployerAddress, receipt.From);

                // Check that the code is indeed saved on-chain
                byte[] savedCode = chain.GetCode(createResult.NewContractAddress);
                Assert.NotNull(savedCode);

                // Use another identity to bid
                Base58Address bidderAddress = chain.PreloadedAddresses[1];

                // Send a call to the bid method
                SendCallContractResult callResult = chain.SendCallContractTransaction(bidderAddress, "Bid", createResult.NewContractAddress, 1);
                chain.MineBlocks(1);

                // Call a method locally to check the state is as expected
                ILocalExecutionResult localCallResult = chain.CallContractMethodLocally(bidderAddress, "HighestBidder", createResult.NewContractAddress, 0);
                Address storedHighestBidder           = (Address)localCallResult.Return;
                Assert.NotEqual(default(Address), storedHighestBidder); // TODO: A nice way of comparing hex and base58 representations
            }
        }
        public void Call_Contract_Success()
        {
            var parameters     = new object[] { };
            var contractTxData = new ContractTxData(1, 1, (Gas)1000, uint160.One, "TestMethod", parameters);

            VmExecutionResult vmExecutionResult = VmExecutionResult.Ok(new object(), null);

            StateTransitionResult stateTransitionResult = StateTransitionResult.Ok((Gas)100, uint160.One, vmExecutionResult.Success.Result);

            var    fixture  = new ExecutorFixture(contractTxData);
            IState snapshot = fixture.State.Object.Snapshot();

            fixture.StateProcessor
            .Setup(s => s.Apply(snapshot, It.IsAny <ExternalCallMessage>()))
            .Returns(stateTransitionResult);

            IStateRepository trackedMock = Mock.Of <IStateRepository>();

            fixture.ContractStateRoot.Setup(s => s.StartTracking()).Returns(trackedMock);

            var sut = new LocalExecutor(
                fixture.LoggerFactory,
                fixture.CallDataSerializer.Object,
                fixture.ContractStateRoot.Object,
                fixture.StateFactory.Object,
                fixture.StateProcessor.Object,
                fixture.ContractPrimitiveSerializer.Object);

            ILocalExecutionResult result = sut.Execute(fixture.ContractTransactionContext);

            fixture.CallDataSerializer.Verify(s => s.Deserialize(fixture.ContractTransactionContext.Data), Times.Once);

            // Local executor used a tracked staterepository
            fixture.StateFactory.Verify(sf => sf
                                        .Create(
                                            trackedMock,
                                            It.IsAny <IBlock>(),
                                            fixture.ContractTransactionContext.TxOutValue,
                                            fixture.ContractTransactionContext.TransactionHash),
                                        Times.Once);

            // We only apply the message to the snapshot.
            fixture.StateProcessor.Verify(sm => sm.Apply(snapshot, It.Is <ExternalCallMessage>(m =>
                                                                                               m.Method.Name == contractTxData.MethodName &&
                                                                                               m.Method.Parameters == contractTxData.MethodParameters &&
                                                                                               m.Amount == fixture.ContractTransactionContext.TxOutValue &&
                                                                                               m.From == fixture.ContractTransactionContext.Sender &&
                                                                                               m.To == contractTxData.ContractAddress)), Times.Once);

            // Should never transition to the snapshot.
            fixture.State.Verify(sm => sm.TransitionTo(snapshot), Times.Never);

            // Should never save on the state
            fixture.ContractStateRoot.Verify(sr => sr.Commit(), Times.Never);

            Assert.Null(result.ErrorMessage);
            Assert.False(result.Revert);
            Assert.Equal(fixture.State.Object.InternalTransfers, result.InternalTransfers);
            Assert.Equal(stateTransitionResult.GasConsumed, result.GasConsumed);
            Assert.Equal(stateTransitionResult.Success.ExecutionResult, result.Return);
            Assert.Equal(fixture.State.Object.GetLogs(fixture.ContractPrimitiveSerializer.Object), result.Logs);
        }