/// <summary> /// Execute the contract and add all relevant fees and refunds to the block. /// </summary> /// <remarks>TODO: At some point we need to change height to a ulong.</remarks> private IContractExecutionResult ExecuteSmartContract(TxMempoolEntry mempoolEntry) { GetSenderResult getSenderResult = this.senderRetriever.GetSender(mempoolEntry.Transaction, this.coinView, this.inBlock.Select(x => x.Transaction).ToList()); if (!getSenderResult.Success) { throw new ConsensusErrorException(new ConsensusError("sc-block-assembler-addcontracttoblock", getSenderResult.Error)); } IContractTransactionContext transactionContext = new ContractTransactionContext((ulong)this.height, this.coinbaseAddress, mempoolEntry.Fee, getSenderResult.Sender, mempoolEntry.Transaction); IContractExecutor executor = this.executorFactory.CreateExecutor(this.stateSnapshot, transactionContext); IContractExecutionResult result = executor.Execute(transactionContext); this.blockGasConsumed += result.GasConsumed; // As we're not storing receipts, can use only consensus fields. var receipt = new Receipt( new uint256(this.stateSnapshot.Root), result.GasConsumed, result.Logs.ToArray() ); this.receipts.Add(receipt); return(result); }
/// <summary> /// Executes the smart contract part of a transaction /// </summary> protected void ExecuteContractTransaction(RuleContext context, Transaction transaction) { IContractTransactionContext txContext = GetSmartContractTransactionContext(context, transaction); IContractExecutor executor = this.ContractCoinviewRule.ExecutorFactory.CreateExecutor(this.ContractCoinviewRule.OriginalStateRoot, txContext); IContractExecutionResult result = executor.Execute(txContext); var receipt = new Receipt( new uint256(this.ContractCoinviewRule.OriginalStateRoot.Root), result.GasConsumed, result.Logs.ToArray(), txContext.TransactionHash, txContext.Sender, result.To, result.NewContractAddress, !result.Revert, result.ErrorMessage ) { BlockHash = context.ValidationContext.BlockToValidate.GetHash() }; this.receipts.Add(receipt); ValidateRefunds(result.Refund, context.ValidationContext.BlockToValidate.Transactions[0]); if (result.InternalTransaction != null) this.generatedTransaction = result.InternalTransaction; }
/// <summary> /// Execute the contract and add all relevant fees and refunds to the block. /// </summary> /// <remarks>TODO: At some point we need to change height to a ulong.</remarks> private IContractExecutionResult ExecuteSmartContract(TxMempoolEntry mempoolEntry) { // This coinview object can be altered by consensus whilst we're mining. // If this occurred, we would be mining on top of the wrong tip anyway, so // it's okay to throw a ConsensusError which is handled by the miner, and continue. GetSenderResult getSenderResult = this.senderRetriever.GetSender(mempoolEntry.Transaction, this.coinView, this.inBlock.Select(x => x.Transaction).ToList()); if (!getSenderResult.Success) { throw new ConsensusErrorException(new ConsensusError("sc-block-assembler-addcontracttoblock", getSenderResult.Error)); } IContractTransactionContext transactionContext = new ContractTransactionContext((ulong)this.height, this.coinbaseAddress, mempoolEntry.Fee, getSenderResult.Sender, mempoolEntry.Transaction); IContractExecutor executor = this.executorFactory.CreateExecutor(this.stateSnapshot, transactionContext); IContractExecutionResult result = executor.Execute(transactionContext); this.blockGasConsumed += result.GasConsumed; // As we're not storing receipts, can use only consensus fields. var receipt = new Receipt( new uint256(this.stateSnapshot.Root), result.GasConsumed, result.Logs.ToArray() ); this.receipts.Add(receipt); return(result); }
/// <summary> /// Executes the smart contract part of a transaction /// </summary> public void ExecuteContractTransaction(RuleContext context, Transaction transaction) { IContractTransactionContext txContext = this.GetSmartContractTransactionContext(context, transaction); this.CheckFeeAccountsForGas(txContext.Data, txContext.MempoolFee); IContractExecutor executor = this.executorFactory.CreateExecutor(this.mutableStateRepository, txContext); Result <ContractTxData> deserializedCallData = this.callDataSerializer.Deserialize(txContext.Data); IContractExecutionResult result = executor.Execute(txContext); var receipt = new Receipt( new uint256(this.mutableStateRepository.Root), result.GasConsumed, result.Logs.ToArray(), txContext.TransactionHash, txContext.Sender, result.To, result.NewContractAddress, !result.Revert, result.Return?.ToString(), result.ErrorMessage, deserializedCallData.Value.GasPrice, txContext.TxOutValue, deserializedCallData.Value.IsCreateContract ? null : deserializedCallData.Value.MethodName, txContext.BlockHeight) { BlockHash = context.ValidationContext.BlockToValidate.GetHash() }; this.receipts.Add(receipt); if (result.Refund != null) { this.ValidateRefunds(result.Refund, context.ValidationContext.BlockToValidate.Transactions[0]); } if (result.InternalTransaction != null) { this.generatedTransaction = result.InternalTransaction; } this.CheckBlockGasLimit(result.GasConsumed); }
/// <summary> /// Execute the contract and add all relevant fees and refunds to the block. /// </summary> /// <remarks>TODO: At some point we need to change height to a ulong.</remarks> /// <param name="mempoolEntry">The mempool entry containing the smart contract transaction.</param> private IContractExecutionResult ExecuteSmartContract(TxMempoolEntry mempoolEntry) { // This coinview object can be altered by consensus whilst we're mining. // If this occurred, we would be mining on top of the wrong tip anyway, so // it's okay to throw a ConsensusError which is handled by the miner, and continue. GetSenderResult getSenderResult = this.senderRetriever.GetSender(mempoolEntry.Transaction, this.coinView, this.inBlock.Select(x => x.Transaction).ToList()); if (!getSenderResult.Success) { throw new ConsensusErrorException(new ConsensusError("sc-block-assembler-addcontracttoblock", getSenderResult.Error)); } IContractTransactionContext transactionContext = new ContractTransactionContext((ulong)this.height, this.coinbaseAddress, mempoolEntry.Fee, getSenderResult.Sender, mempoolEntry.Transaction); IContractExecutor executor = this.executorFactory.CreateExecutor(this.stateSnapshot, transactionContext); IContractExecutionResult result = executor.Execute(transactionContext); Result <ContractTxData> deserializedCallData = this.callDataSerializer.Deserialize(transactionContext.Data); this.blockGasConsumed += result.GasConsumed; // Store all fields. We will reuse these in CoinviewRule. var receipt = new Receipt( new uint256(this.stateSnapshot.Root), result.GasConsumed, result.Logs.ToArray(), transactionContext.TransactionHash, transactionContext.Sender, result.To, result.NewContractAddress, !result.Revert, result.Return?.ToString(), result.ErrorMessage, deserializedCallData.Value.GasPrice, transactionContext.TxOutValue, deserializedCallData.Value.IsCreateContract ? null : deserializedCallData.Value.MethodName); this.receipts.Add(receipt); return(result); }
/// <summary> /// Executes the smart contract part of a transaction /// </summary> public void ExecuteContractTransaction(RuleContext context, Transaction transaction) { IContractTransactionContext txContext = GetSmartContractTransactionContext(context, transaction); this.CheckFeeAccountsForGas(txContext.Data, txContext.MempoolFee); IContractExecutor executor = this.ContractCoinviewRule.ExecutorFactory.CreateExecutor(this.mutableStateRepository, txContext); IContractExecutionResult result = executor.Execute(txContext); var receipt = new Receipt( new uint256(this.mutableStateRepository.Root), result.GasConsumed, result.Logs.ToArray(), txContext.TransactionHash, txContext.Sender, result.To, result.NewContractAddress, !result.Revert, result.Return?.ToString(), result.ErrorMessage ) { BlockHash = context.ValidationContext.BlockToValidate.GetHash() }; this.receipts.Add(receipt); if (result.Refund != null) { ValidateRefunds(result.Refund, context.ValidationContext.BlockToValidate.Transactions[0]); } if (result.InternalTransaction != null) { this.generatedTransaction = result.InternalTransaction; } }