Exemple #1
0
        public void SmartContracts_GasMeter_NewHasNoConsumedGas()
        {
            var gas      = new RuntimeObserver.Gas(1000);
            var gasMeter = new GasMeter(gas);

            Assert.Equal(RuntimeObserver.Gas.None, gasMeter.GasConsumed);
        }
Exemple #2
0
        public void SmartContracts_GasMeter_NewHasCorrectInitialGas()
        {
            var gas      = new RuntimeObserver.Gas(1000);
            var gasMeter = new GasMeter(gas);

            Assert.Equal(gas, gasMeter.GasLimit);
        }
 /// <summary>
 /// Creates a new result for a successful state transition.
 /// </summary>
 public static StateTransitionResult Ok(RuntimeObserver.Gas gasConsumed,
                                        uint160 contractAddress,
                                        object result = null)
 {
     return(new StateTransitionResult(
                new StateTransitionSuccess(gasConsumed, contractAddress, result)));
 }
Exemple #4
0
        public void SmartContracts_GasMeter_NewHasAllAvailableGas()
        {
            var gas      = new RuntimeObserver.Gas(1000);
            var gasMeter = new GasMeter(gas);

            Assert.Equal(gas, gasMeter.GasAvailable);
        }
Exemple #5
0
        public (Money, TxOut) Process(ContractTxData contractTxData,
                                      ulong mempoolFee,
                                      uint160 sender,
                                      RuntimeObserver.Gas gasConsumed,
                                      bool outOfGas)
        {
            Money fee = mempoolFee;

            if (outOfGas)
            {
                this.logger.LogTrace("(-)[OUTOFGAS_EXCEPTION]");
                return(fee, null);
            }

            var refund = new Money(contractTxData.GasCostBudget - (gasConsumed * contractTxData.GasPrice));

            TxOut ret = null;

            if (refund > 0)
            {
                fee -= refund;
                ret  = this.CreateRefund(sender, refund);
            }

            return(fee, ret);
        }
Exemple #6
0
        public void SmartContract_GasMeter_DoesNotHaveEnoughGasOperation()
        {
            var gas           = new RuntimeObserver.Gas(1000);
            var operationCost = new RuntimeObserver.Gas(1500);
            var gasMeter      = new GasMeter(gas);

            Assert.Throws <OutOfGasException>(() => gasMeter.Spend(operationCost));
        }
        /// <summary>
        /// Creates a new result for a failed state transition due to a VM exception.
        /// </summary>
        public static StateTransitionResult Fail(RuntimeObserver.Gas gasConsumed, VmExecutionError vmError)
        {
            // If VM execution ran out of gas we return a different kind of state transition error.
            StateTransitionErrorKind errorKind = vmError.ErrorKind == VmExecutionErrorKind.OutOfGas
                        ? StateTransitionErrorKind.OutOfGas
                        : StateTransitionErrorKind.VmError;

            return(new StateTransitionResult(new StateTransitionError(gasConsumed, errorKind, vmError.Message)));
        }
 public StateTransitionSuccess(
     RuntimeObserver.Gas gasConsumed,
     uint160 contractAddress,
     object result = null)
 {
     this.GasConsumed     = gasConsumed;
     this.ContractAddress = contractAddress;
     this.ExecutionResult = result;
 }
Exemple #9
0
        public byte[] FetchBytes(uint160 address, byte[] key)
        {
            byte[] encodedKey = this.keyEncodingStrategy.GetBytes(key);
            byte[] value      = this.stateDb.GetStorageValue(address, encodedKey);

            RuntimeObserver.Gas operationCost = GasPriceList.StorageRetrieveOperationCost(encodedKey, value);
            this.gasMeter.Spend(operationCost);

            return(value);
        }
Exemple #10
0
        public void StoreBytes(uint160 address, byte[] key, byte[] value)
        {
            byte[] encodedKey = this.keyEncodingStrategy.GetBytes(key);
            RuntimeObserver.Gas operationCost = GasPriceList.StorageSaveOperationCost(
                encodedKey,
                value);

            this.gasMeter.Spend(operationCost);
            this.stateDb.SetStorageValue(address, encodedKey, value);
        }
Exemple #11
0
        /// <inheritdoc/>
        public void Spend(RuntimeObserver.Gas gasToSpend)
        {
            if (this.GasAvailable >= gasToSpend)
            {
                this.GasAvailable -= gasToSpend;
                return;
            }

            this.GasAvailable = (RuntimeObserver.Gas) 0;

            throw new OutOfGasException("Went over gas limit of " + this.GasLimit);
        }
Exemple #12
0
        public void SmartContracts_GasMeter_HasEnoughGasOperation()
        {
            var diff     = (RuntimeObserver.Gas) 100;
            var gas      = new RuntimeObserver.Gas(1000);
            var consumed = (RuntimeObserver.Gas)(gas - diff);
            var gasMeter = new GasMeter(gas);

            gasMeter.Spend(consumed);

            Assert.Equal(consumed, gasMeter.GasConsumed);
            Assert.Equal(diff, gasMeter.GasAvailable);
        }
Exemple #13
0
 /// <summary>
 /// Creates a ContractTxData for contract creation
 /// </summary>
 public ContractTxData(int vmVersion, ulong gasPrice, RuntimeObserver.Gas gasLimit, byte[] code,
                       object[] methodParameters = null)
 {
     this.OpCodeType            = (byte)ScOpcodeType.OP_CREATECONTRACT;
     this.VmVersion             = vmVersion;
     this.GasPrice              = gasPrice;
     this.GasLimit              = gasLimit;
     this.ContractExecutionCode = code;
     this.MethodName            = "";
     this.MethodParameters      = methodParameters;
     this.ContractAddress       = uint160.Zero;
 }
Exemple #14
0
 /// <summary>
 /// Creates a ContractTxData object for a method invocation
 /// </summary>
 public ContractTxData(int vmVersion, ulong gasPrice, RuntimeObserver.Gas gasLimit, uint160 contractAddress,
                       string method, object[] methodParameters = null)
 {
     this.OpCodeType            = (byte)ScOpcodeType.OP_CALLCONTRACT;
     this.VmVersion             = vmVersion;
     this.GasPrice              = gasPrice;
     this.GasLimit              = gasLimit;
     this.ContractAddress       = contractAddress;
     this.MethodName            = method;
     this.MethodParameters      = methodParameters;
     this.ContractExecutionCode = new byte[0];
 }
Exemple #15
0
        ///<inheritdoc />
        public ITransferResult Call(
            ISmartContractState smartContractState,
            Address addressTo,
            ulong amountToTransfer,
            string methodName,
            object[] parameters,
            ulong gasLimit = 0)
        {
            RuntimeObserver.Gas gasRemaining = this.gasMeter.GasAvailable;

            // For a method call, send all the gas unless an amount was selected.Should only call trusted methods so re - entrance is less problematic.
            ulong gasBudget = (gasLimit != 0) ? gasLimit : gasRemaining;

            if (gasRemaining < gasBudget || gasRemaining < GasPriceList.BaseCost)
            {
                return(TransferResult.Failed());
            }

            var message = new InternalCallMessage(
                addressTo.ToUint160(),
                smartContractState.Message.ContractAddress.ToUint160(),
                amountToTransfer,
                (RuntimeObserver.Gas)gasBudget,
                new MethodCall(methodName, parameters)
                );

            // Create a snapshot of the current state
            IState newState = this.state.Snapshot();

            // Apply the message to the snapshot
            StateTransitionResult result = this.stateProcessor.Apply(newState, message);

            // Transition the current state to the new state
            if (result.IsSuccess)
            {
                this.state.TransitionTo(newState);
            }

            this.gasMeter.Spend(result.GasConsumed);

            return(result.IsSuccess
                ? TransferResult.Transferred(result.Success.ExecutionResult)
                : TransferResult.Failed());
        }
Exemple #16
0
        ///<inheritdoc />
        public ICreateResult Create <T>(ISmartContractState smartContractState,
                                        ulong amountToTransfer,
                                        object[] parameters,
                                        ulong gasLimit = 0)
        {
            RuntimeObserver.Gas gasRemaining = this.gasMeter.GasAvailable;

            // For a method call, send all the gas unless an amount was selected.Should only call trusted methods so re - entrance is less problematic.
            ulong gasBudget = (gasLimit != 0) ? gasLimit : gasRemaining;

            Debug.WriteLine("Gas budget:" + gasBudget);

            if (gasRemaining < gasBudget || gasRemaining < GasPriceList.CreateCost)
            {
                return(CreateResult.Failed());
            }

            var message = new InternalCreateMessage(
                smartContractState.Message.ContractAddress.ToUint160(),
                amountToTransfer,
                (RuntimeObserver.Gas)gasBudget,
                parameters,
                typeof(T).Name
                );

            // Create a snapshot of the current state
            IState newState = this.state.Snapshot();

            // Apply the message to the snapshot
            StateTransitionResult result = this.stateProcessor.Apply(newState, message);

            // Transition the current state to the new state
            if (result.IsSuccess)
            {
                this.state.TransitionTo(newState);
            }

            this.gasMeter.Spend(result.GasConsumed);

            return(result.IsSuccess
                ? CreateResult.Succeeded(result.Success.ContractAddress.ToAddress())
                : CreateResult.Failed());
        }
Exemple #17
0
        ///<inheritdoc />
        public ITransferResult Transfer(ISmartContractState smartContractState, Address addressTo, ulong amountToTransfer)
        {
            RuntimeObserver.Gas gasRemaining = this.gasMeter.GasAvailable;

            if (gasRemaining < GasPriceList.TransferCost)
            {
                return(TransferResult.Failed());
            }

            ulong gasBudget = (gasRemaining < DefaultGasLimit)
                ? gasRemaining     // have enough for at least a transfer but not for the DefaultGasLimit
                : DefaultGasLimit; // have enough for anything

            var message = new ContractTransferMessage(
                addressTo.ToUint160(),
                smartContractState.Message.ContractAddress.ToUint160(),
                amountToTransfer,
                (RuntimeObserver.Gas)gasBudget
                );

            // Create a snapshot of the current state
            IState newState = this.state.Snapshot();

            // Apply the message to the snapshot
            StateTransitionResult result = this.stateProcessor.Apply(newState, message);

            // Transition the current state to the new state
            if (result.IsSuccess)
            {
                this.state.TransitionTo(newState);
            }

            this.gasMeter.Spend(result.GasConsumed);

            return(result.IsSuccess
                ? TransferResult.Empty()
                : TransferResult.Failed());
        }
Exemple #18
0
        /// <summary>
        /// Total gas cost to execute the instructions in this segment.
        /// </summary>
        public RuntimeObserver.Gas CalculateGasCost()
        {
            RuntimeObserver.Gas gasTally = (RuntimeObserver.Gas) 0;

            foreach (Instruction instruction in this.Instructions)
            {
                RuntimeObserver.Gas instructionCost = GasPriceList.InstructionOperationCost(instruction);
                gasTally = (RuntimeObserver.Gas)(gasTally + instructionCost);

                if (instruction.IsMethodCall())
                {
                    var methodToCall = (MethodReference)instruction.Operand;

                    // If it's a method outside this contract then we will add some cost.
                    if (this.methodDefinition.DeclaringType != methodToCall.DeclaringType)
                    {
                        RuntimeObserver.Gas methodCallCost = GasPriceList.MethodCallCost(methodToCall);
                        gasTally = (RuntimeObserver.Gas)(gasTally + methodCallCost);
                    }
                }
            }

            return(gasTally);
        }
Exemple #19
0
        public Result <ContractTxData> SerializeCallContract(byte[] smartContractBytes, int vmVersion, ulong gasPrice, RuntimeObserver.Gas gasLimit)
        {
            byte[] contractAddressBytes = smartContractBytes.Slice(PrefixSize, AddressSize);
            var    contractAddress      = new uint160(contractAddressBytes);

            byte[] remaining = smartContractBytes.Slice(CallContractPrefixSize,
                                                        (uint)(smartContractBytes.Length - CallContractPrefixSize));

            IList <byte[]> decodedParams = RLPDecode(remaining);

            string methodName = this.primitiveSerializer.Deserialize <string>(decodedParams[0]);

            object[] methodParameters = this.DeserializeMethodParameters(decodedParams[1]);
            string[] signatures       = (decodedParams.Count > 2) ? this.DeserializeSignatures(decodedParams[2]) : null;

            var callData = new ContractTxData(vmVersion, gasPrice, gasLimit, contractAddress, methodName, methodParameters, signatures);

            return(Result.Ok(callData));
        }
Exemple #20
0
 public void SetGasMeterLimitBelow(RuntimeObserver.Gas maximum)
 {
     this.GasMeter.SetupGet(g => g.GasAvailable).Returns((RuntimeObserver.Gas)(maximum - 1));
 }
Exemple #21
0
        protected virtual Result <ContractTxData> SerializeCreateContract(byte[] smartContractBytes, int vmVersion, ulong gasPrice, RuntimeObserver.Gas gasLimit)
        {
            byte[] remaining = smartContractBytes.Slice(PrefixSize, (uint)(smartContractBytes.Length - PrefixSize));

            IList <byte[]> decodedParams = RLPDecode(remaining);

            var contractExecutionCode = this.primitiveSerializer.Deserialize <byte[]>(decodedParams[0]);

            object[] methodParameters = this.DeserializeMethodParameters(decodedParams[1]);
            string[] signatures       = (decodedParams.Count > 2) ? this.DeserializeSignatures(decodedParams[2]) : null;

            var callData = new ContractTxData(vmVersion, gasPrice, gasLimit, contractExecutionCode, methodParameters, signatures);

            return(Result.Ok(callData));
        }
 public SignedCodeContractTxData(int vmVersion, ulong gasPrice, RuntimeObserver.Gas gasLimit, byte[] code,
                                 byte[] codeSignature,
                                 object[] methodParameters = null) : base(vmVersion, gasPrice, gasLimit, code, methodParameters)
 {
     this.CodeSignature = codeSignature;
 }
Exemple #23
0
 public void SetGasMeterLimitAbove(RuntimeObserver.Gas minimum)
 {
     this.GasMeter.SetupGet(g => g.GasAvailable).Returns((RuntimeObserver.Gas)(minimum + 1));
 }
        private Result <ContractTxData> SerializeCreateContract(byte[] smartContractBytes, int vmVersion, ulong gasPrice, RuntimeObserver.Gas gasLimit)
        {
            var remaining = smartContractBytes.Slice(PrefixSize, (uint)(smartContractBytes.Length - PrefixSize));

            IList <byte[]> decodedParams = RLPDecode(remaining);

            var contractExecutionCode = this.primitiveSerializer.Deserialize <byte[]>(decodedParams[0]);
            var methodParameters      = this.DeserializeMethodParameters(decodedParams[1]);

            var callData = new ContractTxData(vmVersion, gasPrice, gasLimit, contractExecutionCode, methodParameters);

            return(Result.Ok(callData));
        }
        protected override Result <ContractTxData> SerializeCreateContract(byte[] smartContractBytes, int vmVersion, ulong gasPrice, RuntimeObserver.Gas gasLimit)
        {
            byte[] remaining = smartContractBytes.Slice(PrefixSize, (uint)(smartContractBytes.Length - PrefixSize));

            IList <byte[]> decodedParams = RLPDecode(remaining);

            byte[] codeAndSignature = decodedParams[0];

            IList <byte[]> decodedCodeAndSignature = RLPDecode(codeAndSignature);

            byte[] contractExecutionCode = decodedCodeAndSignature[0];
            byte[] signature             = decodedCodeAndSignature[1];

            object[] methodParameters = this.DeserializeMethodParameters(decodedParams[1]);

            var callData = new SignedCodeContractTxData(vmVersion, gasPrice, gasLimit, contractExecutionCode, signature, methodParameters);

            return(Result.Ok <ContractTxData>(callData));
        }
Exemple #26
0
 public ContractTransferMessage(uint160 to, uint160 from, ulong amount, RuntimeObserver.Gas gasLimit)
     : base(to, from, amount, gasLimit, MethodCall.Receive())
 {
 }
 /// <summary>
 /// Creates a new result for a failed state transition.
 /// </summary>
 public static StateTransitionResult Fail(RuntimeObserver.Gas gasConsumed, StateTransitionErrorKind kind)
 {
     return(new StateTransitionResult(new StateTransitionError(gasConsumed, kind, null)));
 }
 public InternalCallMessage(uint160 to, uint160 from, ulong amount, RuntimeObserver.Gas gasLimit, MethodCall methodCall)
     : base(to, from, amount, gasLimit, methodCall)
 {
 }
Exemple #29
0
 public GasMeter(RuntimeObserver.Gas gasAvailable)
 {
     this.GasAvailable = gasAvailable;
     this.GasLimit     = gasAvailable;
 }
 public StateTransitionError(RuntimeObserver.Gas gasConsumed, StateTransitionErrorKind kind, ContractErrorMessage vmError)
 {
     this.Kind        = kind;
     this.GasConsumed = gasConsumed;
     this.VmError     = vmError;
 }