/// <summary>
        /// Applies an externally generated contract creation message to the current state.
        /// </summary>
        public StateTransitionResult Apply(IState state, ExternalCreateMessage message)
        {
            var gasMeter = new GasMeter(message.GasLimit);

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

            // We need to generate an address here so that we can set the initial balance.
            uint160 address = state.GenerateAddress(this.AddressGenerator);

            // For external creates we need to increment the balance state to take into
            // account any funds sent as part of the original contract invocation transaction.
            state.AddInitialTransfer(new TransferInfo(message.From, address, message.Amount));

            return(ApplyCreate(state, message.Parameters, message.Code, message, address, gasMeter));
        }
        /// <summary>
        /// Applies an externally generated contract method call message to the current state.
        /// </summary>
        public StateTransitionResult Apply(IState state, ExternalCallMessage message)
        {
            var gasMeter = new GasMeter(message.GasLimit);

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

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

            if (contractCode == null || contractCode.Length == 0)
            {
                return(StateTransitionResult.Fail(gasMeter.GasConsumed, StateTransitionErrorKind.NoCode));
            }

            // For external calls we need to increment the balance state to take into
            // account any funds sent as part of the original contract invocation transaction.
            state.AddInitialTransfer(new TransferInfo(message.From, message.To, message.Amount));

            return(ApplyCall(state, message, contractCode, gasMeter));
        }
        /// <summary>
        /// Applies an internally generated contract funds transfer message to the current state.
        /// </summary>
        public StateTransitionResult Apply(IState state, ContractTransferMessage message)
        {
            bool enoughBalance = this.EnsureSenderHasEnoughBalance(state, message.From, message.Amount);

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

            var gasMeter = new GasMeter(message.GasLimit);

            // If it's not a contract, create a regular P2PKH tx
            // If it is a contract, do a regular contract call
            byte[] contractCode = state.ContractState.GetCode(message.To);

            if (contractCode == null || contractCode.Length == 0)
            {
                gasMeter.Spend((Gas)GasPriceList.TransferCost);

                // No contract at this address, create a regular P2PKH xfer
                state.AddInternalTransfer(new TransferInfo(message.From, message.To, message.Amount));

                return(StateTransitionResult.Ok(gasMeter.GasConsumed, message.To));
            }

            var observer         = new Observer(gasMeter, new MemoryMeter(ReflectionVirtualMachine.MemoryUnitLimit));
            var executionContext = new ExecutionContext(observer);

            // For internal contract-contract transfers 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.
            state.AddInternalTransfer(new TransferInfo(message.From, message.To, message.Amount));

            gasMeter.Spend((Gas)GasPriceList.BaseCost);
            StateTransitionResult result = this.ApplyCall(state, message, contractCode, executionContext);

            return(result);
        }