public void ExternalCall_Code_Null()
        {
            var gasLimit = (Gas)(GasPriceList.BaseCost + 100000);

            var externalCallMessage = new ExternalCallMessage(
                uint160.Zero,
                uint160.Zero,
                0,
                gasLimit,
                new MethodCall("Test")
                );

            this.contractStateRoot
            .Setup(sr => sr.GetCode(externalCallMessage.To))
            .Returns((byte[])null);

            var state = new Mock <IState>();

            state.SetupGet(s => s.ContractState).Returns(this.contractStateRoot.Object);

            var stateProcessor = new StateProcessor(this.vm.Object, this.addressGenerator.Object);

            StateTransitionResult result = stateProcessor.Apply(state.Object, externalCallMessage);

            this.contractStateRoot.Verify(sr => sr.GetCode(externalCallMessage.To), Times.Once);

            Assert.True(result.IsFailure);
            Assert.NotNull(result.Error);
            Assert.Null(result.Error.VmError);
            Assert.Equal(StateTransitionErrorKind.NoCode, result.Error.Kind);
            Assert.Equal((Gas)GasPriceList.BaseCost, result.GasConsumed);
        }
Esempio n. 2
0
        public ILocalExecutionResult Execute(IContractTransactionContext transactionContext)
        {
            Result <ContractTxData> callDataDeserializationResult = this.serializer.Deserialize(transactionContext.Data);

            ContractTxData callData = callDataDeserializationResult.Value;

            bool creation = callData.IsCreateContract;

            var block = new Block(
                transactionContext.BlockHeight,
                transactionContext.CoinbaseAddress.ToAddress()
                );

            IState state = this.stateFactory.Create(
                this.stateRoot.StartTracking(),
                block,
                transactionContext.TxOutValue,
                transactionContext.TransactionHash);

            StateTransitionResult result;
            IState newState = state.Snapshot();

            if (creation)
            {
                var message = new ExternalCreateMessage(
                    transactionContext.Sender,
                    transactionContext.TxOutValue,
                    callData.GasLimit,
                    callData.ContractExecutionCode,
                    callData.MethodParameters
                    );

                result = this.stateProcessor.Apply(newState, message);
            }
            else
            {
                var message = new ExternalCallMessage(
                    callData.ContractAddress,
                    transactionContext.Sender,
                    transactionContext.TxOutValue,
                    callData.GasLimit,
                    new MethodCall(callData.MethodName, callData.MethodParameters)
                    );

                result = this.stateProcessor.Apply(newState, message);
            }

            var executionResult = new LocalExecutionResult
            {
                ErrorMessage      = result.Error?.GetErrorMessage(),
                Revert            = result.IsFailure,
                GasConsumed       = result.GasConsumed,
                Return            = result.Success?.ExecutionResult,
                InternalTransfers = state.InternalTransfers.ToList(),
                Logs = state.GetLogs(this.contractPrimitiveSerializer)
            };

            return(executionResult);
        }
Esempio n. 3
0
        public ILocalExecutionResult Execute(ulong blockHeight, uint160 sender, Money txOutValue, ContractTxData callData)
        {
            bool creation = callData.IsCreateContract;

            var block = new Block(
                blockHeight,
                Address.Zero
                );

            IState state = this.stateFactory.Create(
                this.stateRoot.StartTracking(),
                block,
                txOutValue,
                new uint256());

            StateTransitionResult result;
            IState newState = state.Snapshot();

            if (creation)
            {
                var message = new ExternalCreateMessage(
                    sender,
                    txOutValue,
                    callData.GasLimit,
                    callData.ContractExecutionCode,
                    callData.MethodParameters
                    );

                result = this.stateProcessor.Apply(newState, message);
            }
            else
            {
                var message = new ExternalCallMessage(
                    callData.ContractAddress,
                    sender,
                    txOutValue,
                    callData.GasLimit,
                    new MethodCall(callData.MethodName, callData.MethodParameters)
                    );

                result = this.stateProcessor.Apply(newState, message);
            }

            var executionResult = new LocalExecutionResult
            {
                ErrorMessage      = result.Error?.GetErrorMessage(),
                Revert            = result.IsFailure,
                GasConsumed       = result.GasConsumed,
                Return            = result.Success?.ExecutionResult,
                InternalTransfers = state.InternalTransfers.ToList(),
                Logs = state.GetLogs(this.contractPrimitiveSerializer)
            };

            return(executionResult);
        }
        public void ExternalCall_Success()
        {
            var gasLimit          = (Gas)(GasPriceList.BaseCost + 100000);
            var vmExecutionResult = VmExecutionResult.Ok(true, "Test");

            // Code must have a length to pass precondition checks.
            var code     = new byte[1];
            var typeName = "Test";

            var externalCallMessage = new ExternalCallMessage(
                uint160.Zero,
                uint160.Zero,
                0,
                gasLimit,
                new MethodCall("Test", null)
                );

            this.contractStateRoot
            .Setup(sr => sr.GetCode(externalCallMessage.To))
            .Returns(code);

            this.contractStateRoot
            .Setup(sr => sr.GetContractType(externalCallMessage.To))
            .Returns(typeName);

            this.vm.Setup(v =>
                          v.ExecuteMethod(It.IsAny <ISmartContractState>(), externalCallMessage.Method, code, typeName))
            .Returns(vmExecutionResult);

            var state = new Mock <IState>();

            state.SetupGet(s => s.ContractState).Returns(this.contractStateRoot.Object);

            var stateProcessor = new StateProcessor(this.vm.Object, this.addressGenerator.Object);

            StateTransitionResult result = stateProcessor.Apply(state.Object, externalCallMessage);

            state.Verify(s => s.AddInitialTransfer(It.Is <TransferInfo>(t => t.Value == externalCallMessage.Amount && t.To == externalCallMessage.To)));

            this.contractStateRoot.Verify(sr => sr.GetCode(externalCallMessage.To), Times.Once);

            this.contractStateRoot.Verify(sr => sr.GetContractType(externalCallMessage.To), Times.Once);

            state.Verify(s => s.CreateSmartContractState(state.Object, It.IsAny <GasMeter>(), externalCallMessage.To, externalCallMessage, this.contractStateRoot.Object));

            this.vm.Verify(
                v => v.ExecuteMethod(It.IsAny <ISmartContractState>(), externalCallMessage.Method, code, typeName),
                Times.Once);

            Assert.True(result.IsSuccess);
            Assert.NotNull(result.Success);
            Assert.Equal(externalCallMessage.To, result.Success.ContractAddress);
            Assert.Equal(vmExecutionResult.Success.Result, result.Success.ExecutionResult);
            Assert.Equal(GasPriceList.BaseCost, result.GasConsumed);
        }
        public void ExternalCall_Vm_Error()
        {
            var gasLimit          = (Gas)(GasPriceList.BaseCost + 100000);
            var vmExecutionResult = VmExecutionResult.Error(new ContractErrorMessage("Error"));

            // Code must have a length to pass precondition checks.
            var code     = new byte[1];
            var typeName = "Test";

            var externalCallMessage = new ExternalCallMessage(
                uint160.Zero,
                uint160.Zero,
                0,
                gasLimit,
                new MethodCall("Test")
                );

            this.contractStateRoot
            .Setup(sr => sr.GetCode(externalCallMessage.To))
            .Returns(code);

            this.contractStateRoot
            .Setup(sr => sr.GetContractType(externalCallMessage.To))
            .Returns(typeName);

            this.vm.Setup(v =>
                          v.ExecuteMethod(It.IsAny <ISmartContractState>(), externalCallMessage.Method, code, typeName))
            .Returns(vmExecutionResult);

            var state = new Mock <IState>();

            state.SetupGet(s => s.ContractState).Returns(this.contractStateRoot.Object);

            var stateProcessor = new StateProcessor(this.vm.Object, this.addressGenerator.Object);

            StateTransitionResult result = stateProcessor.Apply(state.Object, externalCallMessage);

            this.contractStateRoot.Verify(sr => sr.GetCode(externalCallMessage.To), Times.Once);

            this.contractStateRoot.Verify(sr => sr.GetContractType(externalCallMessage.To), Times.Once);

            state.Verify(s => s.CreateSmartContractState(state.Object, It.IsAny <GasMeter>(), externalCallMessage.To, externalCallMessage, this.contractStateRoot.Object));

            this.vm.Verify(
                v => v.ExecuteMethod(It.IsAny <ISmartContractState>(), externalCallMessage.Method, code, typeName),
                Times.Once);

            Assert.True(result.IsFailure);
            Assert.NotNull(result.Error);
            Assert.Equal(result.Error.VmError, vmExecutionResult.ErrorMessage);
            Assert.Equal(StateTransitionErrorKind.VmError, result.Error.Kind);
            Assert.Equal(GasPriceList.BaseCost, result.GasConsumed);
        }
Esempio n. 6
0
        public void Call_Out_Of_Gas_Error()
        {
            var vmExecutionResult = VmExecutionResult.Fail(VmExecutionErrorKind.OutOfGas, "Error");

            // Code must have a length to pass precondition checks.
            var code = new byte[1];

            var callMessage = new ExternalCallMessage(
                uint160.One,
                uint160.Zero,
                10,
                (RuntimeObserver.Gas)(GasPriceList.BaseCost + 100000),
                new MethodCall("Test", new object[] { })
                );

            this.vm.Setup(v => v.ExecuteMethod(
                              It.IsAny <ISmartContractState>(),
                              It.IsAny <ExecutionContext>(),
                              callMessage.Method,
                              code,
                              null))
            .Returns(vmExecutionResult);

            this.contractStateRoot
            .Setup(sr => sr.GetCode(callMessage.To))
            .Returns(code);

            var state = new Mock <IState>();

            state.Setup(s => s.GetBalance(callMessage.From))
            .Returns(callMessage.Amount + 1);
            state.SetupGet(s => s.ContractState).Returns(this.contractStateRoot.Object);

            var stateProcessor = new StateProcessor(this.vm.Object, this.addressGenerator.Object);

            StateTransitionResult result = stateProcessor.Apply(state.Object, callMessage);

            state.Verify(s => s.CreateSmartContractState(state.Object, It.IsAny <RuntimeObserver.IGasMeter>(), callMessage.To, callMessage, this.contractStateRoot.Object));

            this.vm.Verify(
                v => v.ExecuteMethod(
                    It.IsAny <ISmartContractState>(),
                    It.IsAny <ExecutionContext>(),
                    callMessage.Method,
                    code,
                    null),
                Times.Once);

            Assert.True(result.IsFailure);
            Assert.NotNull(result.Error);
            Assert.Equal(result.Error.VmError, vmExecutionResult.Error.Message);
            Assert.Equal(StateTransitionErrorKind.OutOfGas, result.Error.Kind);
        }
Esempio n. 7
0
        public ILocalExecutionResult Execute(ulong blockHeight, uint160 sender, Money txOutValue, ContractTxData callData)
        {
            bool creation = callData.IsCreateContract;

            var block = new Block(
                blockHeight,
                Address.Zero
                );

            ChainedHeader chainedHeader = this.chainIndexer.GetHeader((int)blockHeight);

            var scHeader = chainedHeader?.Header as ISmartContractBlockHeader;

            uint256 hashStateRoot = scHeader?.HashStateRoot ?? new uint256("21B463E3B52F6201C0AD6C991BE0485B6EF8C092E64583FFA655CC1B171FE856"); // StateRootEmptyTrie

            IStateRepositoryRoot stateAtHeight = this.stateRoot.GetSnapshotTo(hashStateRoot.ToBytes());

            IState state = this.stateFactory.Create(
                stateAtHeight.StartTracking(),
                block,
                txOutValue,
                new uint256());

            StateTransitionResult result;
            IState newState = state.Snapshot();

            if (creation)
            {
                var message = new ExternalCreateMessage(
                    sender,
                    txOutValue,
                    callData.GasLimit,
                    callData.ContractExecutionCode,
                    callData.MethodParameters
                    );

                result = this.stateProcessor.Apply(newState, message);
            }
            else
            {
                var message = new ExternalCallMessage(
                    callData.ContractAddress,
                    sender,
                    txOutValue,
                    callData.GasLimit,
                    new MethodCall(callData.MethodName, callData.MethodParameters)
                    );

                result = this.stateProcessor.Apply(newState, message);
            }

            var executionResult = new LocalExecutionResult
            {
                ErrorMessage      = result.Error?.GetErrorMessage(),
                Revert            = result.IsFailure,
                GasConsumed       = result.GasConsumed,
                Return            = result.Success?.ExecutionResult,
                InternalTransfers = newState.InternalTransfers.ToList(),
                Logs      = newState.GetLogs(this.contractPrimitiveSerializer),
                StateRoot = newState.ContractState
            };

            return(executionResult);
        }