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); }
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); }
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); }
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); }
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); }