/// <summary>
        /// Applies an internally generated contract creation message to the current state.
        /// </summary>
        public StateTransitionResult Apply(IState state, InternalCreateMessage message)
        {
            bool enoughBalance = this.EnsureSenderHasEnoughBalance(state, message.From, message.Amount);

            if (!enoughBalance)
            {
                return(StateTransitionResult.Fail((Gas)0, StateTransitionErrorKind.InsufficientBalance));
            }

            byte[] contractCode = state.ContractState.GetCode(message.From);

            uint160 address = state.GenerateAddress(this.AddressGenerator);

            // For internal creates we need to add the value contained in the contract invocation transaction
            // to the internal transfer list. This must occur before we apply the message to the state.
            // For external creates we do not need to do this.
            state.AddInternalTransfer(new TransferInfo
            {
                From  = message.From,
                To    = address,
                Value = message.Amount
            });

            StateTransitionResult result = this.ApplyCreate(state, message.Parameters, contractCode, message, address, message.Type);

            return(result);
        }
Esempio n. 2
0
        /// <summary>
        /// Applies an internally generated contract creation message to the current state.
        /// </summary>
        public StateTransitionResult Apply(InternalCreateMessage message)
        {
            bool enoughBalance = this.EnsureContractHasEnoughBalance(message.From, message.Amount);

            if (!enoughBalance)
            {
                throw new InsufficientBalanceException();
            }

            byte[] contractCode = this.intermediateState.GetCode(message.From);

            StateTransitionResult result = this.ApplyCreate(message.Parameters, contractCode, message, message.Type);

            // For successful internal creates we need to add the transfer to the internal transfer list.
            // For external creates we do not need to do this.
            if (result.IsSuccess)
            {
                this.internalTransfers.Add(new TransferInfo
                {
                    From  = message.From,
                    To    = result.Success.ContractAddress,
                    Value = message.Amount
                });
            }

            return(result);
        }
Esempio n. 3
0
        /// <summary>
        /// Applies an internally generated contract creation message to the current state.
        /// </summary>
        public StateTransitionResult Apply(IState state, InternalCreateMessage message)
        {
            bool enoughBalance = this.EnsureSenderHasEnoughBalance(state, message.From, message.Amount);

            if (!enoughBalance)
            {
                return(StateTransitionResult.Fail((Gas)0, StateTransitionErrorKind.InsufficientBalance)); // Trivial - just return and let the MethodCall gas account for it.
            }
            var gasMeter = new GasMeter(message.GasLimit);

            gasMeter.Spend((Gas)GasPriceList.CreateCost);

            byte[] contractCode = state.ContractState.GetCode(message.From);

            uint160 address = state.GenerateAddress(this.AddressGenerator);

            // For internal creates we need to add the value contained in the contract invocation transaction
            // to the internal transfer list. This must occur before we apply the message to the state.
            // For external creates we do not need to do this.
            state.AddInternalTransfer(new TransferInfo(message.From, address, message.Amount));

            StateTransitionResult result = this.ApplyCreate(state, message.Parameters, contractCode, message, address, gasMeter, message.Type);

            return(result);
        }
Esempio n. 4
0
        /// <summary>
        /// Applies an internally generated contract creation message to the current state.
        /// </summary>
        public StateTransitionResult Apply(IState state, InternalCreateMessage message)
        {
            bool enoughBalance = this.EnsureContractHasEnoughBalance(state, message.From, message.Amount);

            if (!enoughBalance)
            {
                return(StateTransitionResult.Fail((Gas)0, StateTransitionErrorKind.InsufficientBalance));
            }

            byte[] contractCode = state.ContractState.GetCode(message.From);

            StateTransitionResult result = this.ApplyCreate(state, message.Parameters, contractCode, message, message.Type);

            // For successful internal creates we need to add the transfer to the internal transfer list.
            // For external creates we do not need to do this.
            if (result.IsSuccess)
            {
                state.AddInternalTransfer(new TransferInfo
                {
                    From  = message.From,
                    To    = result.Success.ContractAddress,
                    Value = message.Amount
                });
            }

            return(result);
        }
        ///<inheritdoc />
        public ICreateResult Create <T>(ISmartContractState smartContractState,
                                        ulong amountToTransfer,
                                        object[] parameters,
                                        ulong gasLimit = 0)
        {
            Gas gasRemaining = smartContractState.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,
                (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);
            }

            smartContractState.GasMeter.Spend(result.GasConsumed);

            return(result.IsSuccess
                ? CreateResult.Succeeded(result.Success.ContractAddress.ToAddress())
                : CreateResult.Failed());
        }
        ///<inheritdoc />
        public ICreateResult Create <T>(ISmartContractState smartContractState,
                                        ulong amountToTransfer,
                                        object[] parameters,
                                        ulong gasLimit = 0)
        {
            ulong gasBudget = (gasLimit != 0) ? gasLimit : smartContractState.GasMeter.GasAvailable;

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

            var result = this.state.Apply(message);

            return(result.IsSuccess
                ? CreateResult.Succeeded(result.Success.ContractAddress.ToAddress(this.network))
                : CreateResult.Failed());
        }