From dfc93a74ad1f0a283d99a0a95275df2cf7795c7d Mon Sep 17 00:00:00 2001 From: Jordan Hrycaj Date: Wed, 7 Apr 2021 15:13:28 +0100 Subject: [PATCH] moved validateTransaction() to executor why: not part of VM (see andri's requested change at #573) --- nimbus/p2p/executor.nim | 97 ++++++++++++++++++++++++++++++++ nimbus/vm/state_transactions.nim | 95 ------------------------------- nimbus/vm_state_transactions.nim | 3 +- 3 files changed, 98 insertions(+), 97 deletions(-) diff --git a/nimbus/p2p/executor.nim b/nimbus/p2p/executor.nim index bbab4a0fc..783185273 100644 --- a/nimbus/p2p/executor.nim +++ b/nimbus/p2p/executor.nim @@ -7,6 +7,39 @@ import options, sets, ../vm_types2, ./dao, ../config +proc validateTransaction*(vmState: BaseVMState, tx: Transaction, + sender: EthAddress, fork: Fork): bool = + let balance = vmState.readOnlyStateDB.getBalance(sender) + let nonce = vmState.readOnlyStateDB.getNonce(sender) + + if vmState.cumulativeGasUsed + tx.gasLimit > vmState.blockHeader.gasLimit: + debug "invalid tx: block header gasLimit reached", + maxLimit=vmState.blockHeader.gasLimit, + gasUsed=vmState.cumulativeGasUsed, + addition=tx.gasLimit + return + + let totalCost = tx.gasLimit.u256 * tx.gasPrice.u256 + tx.value + if totalCost > balance: + debug "invalid tx: not enough cash", + available=balance, + require=totalCost + return + + if tx.gasLimit < tx.intrinsicGas(fork): + debug "invalid tx: not enough gas to perform calculation", + available=tx.gasLimit, + require=tx.intrinsicGas(fork) + return + + if tx.accountNonce != nonce: + debug "invalid tx: account nonce mismatch", + txNonce=tx.accountnonce, + accountNonce=nonce + return + + result = true + proc processTransaction*(tx: Transaction, sender: EthAddress, vmState: BaseVMState, fork: Fork): GasInt = ## Process the transaction, write the results to db. ## Returns amount of ETH to be rewarded to miner @@ -196,3 +229,67 @@ proc processBlock*(chainDB: BaseChainDB, header: BlockHeader, body: BlockBody, v # rather than destroyed by trie pruning. But the current block will still get a pruned trie. # If trie pruning deactivated, `applyDeletes` have no effects. dbTx.commit(applyDeletes = false) + + +#[ +method executeTransaction(vmState: BaseVMState, transaction: Transaction): (Computation, BlockHeader) {.base.}= + # Execute the transaction in the vm + # TODO: introduced here: https://github.com/ethereum/py-evm/commit/21c57f2d56ab91bb62723c3f9ebe291d0b132dde + # Refactored/Removed here: https://github.com/ethereum/py-evm/commit/cc991bf + # Deleted here: https://github.com/ethereum/py-evm/commit/746defb6f8e83cee2c352a0ab8690e1281c4227c + raise newException(ValueError, "Must be implemented by subclasses") + + +method addTransaction*(vmState: BaseVMState, transaction: Transaction, c: Computation, b: Block): (Block, Table[string, string]) = + # Add a transaction to the given block and + # return `trieData` to store the transaction data in chaindb in VM layer + # Update the bloomFilter, transaction trie and receipt trie roots, bloom_filter, + # bloom, and usedGas of the block + # transaction: the executed transaction + # computation: the Computation object with executed result + # block: the Block which the transaction is added in + # var receipt = vmState.makeReceipt(transaction, computation) + # vmState.add_receipt(receipt) + + # block.transactions.append(transaction) + + # # Get trie roots and changed key-values. + # tx_root_hash, tx_kv_nodes = make_trie_root_and_nodes(block.transactions) + # receipt_root_hash, receipt_kv_nodes = make_trie_root_and_nodes(self.receipts) + + # trie_data = merge(tx_kv_nodes, receipt_kv_nodes) + + # block.bloom_filter |= receipt.bloom + + # block.header.transaction_root = tx_root_hash + # block.header.receipt_root = receipt_root_hash + # block.header.bloom = int(block.bloom_filter) + # block.header.gas_used = receipt.gas_used + + # return block, trie_data + result = (b, initTable[string, string]()) + +method applyTransaction*( + vmState: BaseVMState, + transaction: Transaction, + b: Block, + isStateless: bool): (Computation, Block, Table[string, string]) = + # Apply transaction to the given block + # transaction: the transaction need to be applied + # b: the block which the transaction applies on + # isStateless: if isStateless, call vmState.addTransaction to set block + + if isStateless: + var ourBlock = b # deepcopy + vmState.blockHeader = b.header + var (computation, blockHeader) = vmState.executeTransaction(transaction) + + ourBlock.header = blockHeader + var trieData: Table[string, string] + (ourBlock, trieData) = vmState.addTransaction(transaction, computation, ourBlock) + + result = (computation, ourBlock, trieData) + else: + var (computation, blockHeader) = vmState.executeTransaction(transaction) + return (computation, nil, initTable[string, string]()) +]# diff --git a/nimbus/vm/state_transactions.nim b/nimbus/vm/state_transactions.nim index 238cd3993..fa17ac4ad 100644 --- a/nimbus/vm/state_transactions.nim +++ b/nimbus/vm/state_transactions.nim @@ -11,38 +11,6 @@ import ../transaction, ./computation, ./interpreter, ./state, ./types -proc validateTransaction*(vmState: BaseVMState, tx: Transaction, sender: EthAddress, fork: Fork): bool = - let balance = vmState.readOnlyStateDB.getBalance(sender) - let nonce = vmState.readOnlyStateDB.getNonce(sender) - - if vmState.cumulativeGasUsed + tx.gasLimit > vmState.blockHeader.gasLimit: - debug "invalid tx: block header gasLimit reached", - maxLimit=vmState.blockHeader.gasLimit, - gasUsed=vmState.cumulativeGasUsed, - addition=tx.gasLimit - return - - let totalCost = tx.gasLimit.u256 * tx.gasPrice.u256 + tx.value - if totalCost > balance: - debug "invalid tx: not enough cash", - available=balance, - require=totalCost - return - - if tx.gasLimit < tx.intrinsicGas(fork): - debug "invalid tx: not enough gas to perform calculation", - available=tx.gasLimit, - require=tx.intrinsicGas(fork) - return - - if tx.accountNonce != nonce: - debug "invalid tx: account nonce mismatch", - txNonce=tx.accountnonce, - accountNonce=nonce - return - - result = true - proc setupComputation*(vmState: BaseVMState, tx: Transaction, sender: EthAddress, fork: Fork) : Computation = var gas = tx.gasLimit - tx.intrinsicGas(fork) assert gas >= 0 @@ -88,66 +56,3 @@ proc refundGas*(c: Computation, tx: Transaction, sender: EthAddress) = c.gasMeter.returnGas min(c.getGasRefund(), maxRefund) c.vmState.mutateStateDB: db.addBalance(sender, c.gasMeter.gasRemaining.u256 * tx.gasPrice.u256) - -#[ -method executeTransaction(vmState: BaseVMState, transaction: Transaction): (Computation, BlockHeader) {.base.}= - # Execute the transaction in the vm - # TODO: introduced here: https://github.com/ethereum/py-evm/commit/21c57f2d56ab91bb62723c3f9ebe291d0b132dde - # Refactored/Removed here: https://github.com/ethereum/py-evm/commit/cc991bf - # Deleted here: https://github.com/ethereum/py-evm/commit/746defb6f8e83cee2c352a0ab8690e1281c4227c - raise newException(ValueError, "Must be implemented by subclasses") - - -method addTransaction*(vmState: BaseVMState, transaction: Transaction, c: Computation, b: Block): (Block, Table[string, string]) = - # Add a transaction to the given block and - # return `trieData` to store the transaction data in chaindb in VM layer - # Update the bloomFilter, transaction trie and receipt trie roots, bloom_filter, - # bloom, and usedGas of the block - # transaction: the executed transaction - # computation: the Computation object with executed result - # block: the Block which the transaction is added in - # var receipt = vmState.makeReceipt(transaction, computation) - # vmState.add_receipt(receipt) - - # block.transactions.append(transaction) - - # # Get trie roots and changed key-values. - # tx_root_hash, tx_kv_nodes = make_trie_root_and_nodes(block.transactions) - # receipt_root_hash, receipt_kv_nodes = make_trie_root_and_nodes(self.receipts) - - # trie_data = merge(tx_kv_nodes, receipt_kv_nodes) - - # block.bloom_filter |= receipt.bloom - - # block.header.transaction_root = tx_root_hash - # block.header.receipt_root = receipt_root_hash - # block.header.bloom = int(block.bloom_filter) - # block.header.gas_used = receipt.gas_used - - # return block, trie_data - result = (b, initTable[string, string]()) - -method applyTransaction*( - vmState: BaseVMState, - transaction: Transaction, - b: Block, - isStateless: bool): (Computation, Block, Table[string, string]) = - # Apply transaction to the given block - # transaction: the transaction need to be applied - # b: the block which the transaction applies on - # isStateless: if isStateless, call vmState.addTransaction to set block - - if isStateless: - var ourBlock = b # deepcopy - vmState.blockHeader = b.header - var (computation, blockHeader) = vmState.executeTransaction(transaction) - - ourBlock.header = blockHeader - var trieData: Table[string, string] - (ourBlock, trieData) = vmState.addTransaction(transaction, computation, ourBlock) - - result = (computation, ourBlock, trieData) - else: - var (computation, blockHeader) = vmState.executeTransaction(transaction) - return (computation, nil, initTable[string, string]()) -]# diff --git a/nimbus/vm_state_transactions.nim b/nimbus/vm_state_transactions.nim index ae5da481f..15a41ab8b 100644 --- a/nimbus/vm_state_transactions.nim +++ b/nimbus/vm_state_transactions.nim @@ -14,7 +14,6 @@ import export vmx.execComputation, vmx.refundGas, - vmx.setupComputation, - vmx.validateTransaction + vmx.setupComputation # End