diff --git a/nimbus/p2p/chain.nim b/nimbus/p2p/chain.nim index 706cc550b..f0bc7bd5a 100644 --- a/nimbus/p2p/chain.nim +++ b/nimbus/p2p/chain.nim @@ -1,6 +1,6 @@ import ../db/[db_chain, state_db], eth_common, chronicles, ../vm_state, ../vm_types, ../transaction, ranges, ../vm/[computation, interpreter_dispatch, message], ../constants, stint, nimcrypto, - ../vm_state_transactions, sugar, ../utils, eth_trie/db + ../vm_state_transactions, sugar, ../utils, eth_trie/db, ../tracer, ./executor, json type Chain* = ref object of AbstractChainDB @@ -30,72 +30,6 @@ method getSuccessorHeader*(c: Chain, h: BlockHeader, output: var BlockHeader): b method getBlockBody*(c: Chain, blockHash: KeccakHash): BlockBodyRef = result = nil -proc processTransaction*(db: var AccountStateDB, t: Transaction, sender: EthAddress, vmState: BaseVMState): UInt256 = - ## Process the transaction, write the results to db. - ## Returns amount of ETH to be rewarded to miner - echo "Sender: ", sender - echo "txHash: ", t.rlpHash - # Inct nonce: - db.setNonce(sender, db.getNonce(sender) + 1) - var transactionFailed = false - - #t.dump - - # TODO: combine/refactor re validate - let upfrontGasCost = t.gasLimit.u256 * t.gasPrice.u256 - let upfrontCost = upfrontGasCost + t.value - var balance = db.getBalance(sender) - if balance < upfrontCost: - if balance <= upfrontGasCost: - result = balance - balance = 0.u256 - else: - result = upfrontGasCost - balance -= upfrontGasCost - transactionFailed = true - else: - balance -= upfrontCost - - db.setBalance(sender, balance) - if transactionFailed: - return - - var gasUsed = t.payload.intrinsicGas.GasInt # += 32000 appears in Homestead when contract create - - if gasUsed > t.gasLimit: - echo "Transaction failed. Out of gas." - transactionFailed = true - else: - if t.isContractCreation: - # TODO: re-derive sender in callee for cleaner interface, perhaps - return applyCreateTransaction(db, t, vmState, sender) - - else: - let code = db.getCode(t.to) - if code.len == 0: - # Value transfer - echo "Transfer ", t.value, " from ", sender, " to ", t.to - - db.addBalance(t.to, t.value) - else: - # Contract call - echo "Contract call" - - debug "Transaction", sender, to = t.to, value = t.value, hasCode = code.len != 0 - let msg = newMessage(t.gasLimit, t.gasPrice, t.to, sender, t.value, t.payload, code.toSeq) - # TODO: Run the vm - - if gasUsed > t.gasLimit: - gasUsed = t.gasLimit - - var refund = (t.gasLimit - gasUsed).u256 * t.gasPrice.u256 - if transactionFailed: - refund += t.value - - db.addBalance(sender, refund) - - return gasUsed.u256 * t.gasPrice.u256 - method persistBlocks*(c: Chain, headers: openarray[BlockHeader], bodies: openarray[BlockBody]) = # Run the VM here assert(headers.len == bodies.len) @@ -149,6 +83,10 @@ method persistBlocks*(c: Chain, headers: openarray[BlockHeader], bodies: openarr if headers[i].stateRoot != stateDb.rootHash: echo "Wrong state root in block ", headers[i].blockNumber, ". Expected: ", headers[i].stateRoot, ", Actual: ", stateDb.rootHash, " arrived from ", c.db.getCanonicalHead().stateRoot + let trace = traceTransaction(c.db, headers[i], bodies[i], bodies[i].transactions.len - 1, {}) + echo "NIMBUS TRACE" + echo trace.pretty() + assert(headers[i].stateRoot == stateDb.rootHash) discard c.db.persistHeaderToDb(headers[i]) diff --git a/nimbus/p2p/executor.nim b/nimbus/p2p/executor.nim new file mode 100644 index 000000000..b87f95be3 --- /dev/null +++ b/nimbus/p2p/executor.nim @@ -0,0 +1,69 @@ +import ../db/[db_chain, state_db], ../transaction, eth_common, + ../vm_state, ../vm_types, ../vm_state_transactions, ranges, + chronicles, ../vm/[computation, interpreter_dispatch, message] + +proc processTransaction*(db: var AccountStateDB, t: Transaction, sender: EthAddress, vmState: BaseVMState): UInt256 = + ## Process the transaction, write the results to db. + ## Returns amount of ETH to be rewarded to miner + echo "Sender: ", sender + echo "txHash: ", t.rlpHash + # Inct nonce: + db.setNonce(sender, db.getNonce(sender) + 1) + var transactionFailed = false + + #t.dump + + # TODO: combine/refactor re validate + let upfrontGasCost = t.gasLimit.u256 * t.gasPrice.u256 + let upfrontCost = upfrontGasCost + t.value + var balance = db.getBalance(sender) + if balance < upfrontCost: + if balance <= upfrontGasCost: + result = balance + balance = 0.u256 + else: + result = upfrontGasCost + balance -= upfrontGasCost + transactionFailed = true + else: + balance -= upfrontCost + + db.setBalance(sender, balance) + if transactionFailed: + return + + var gasUsed = t.payload.intrinsicGas.GasInt # += 32000 appears in Homestead when contract create + + if gasUsed > t.gasLimit: + echo "Transaction failed. Out of gas." + transactionFailed = true + else: + if t.isContractCreation: + # TODO: re-derive sender in callee for cleaner interface, perhaps + return applyCreateTransaction(db, t, vmState, sender) + + else: + let code = db.getCode(t.to) + if code.len == 0: + # Value transfer + echo "Transfer ", t.value, " from ", sender, " to ", t.to + + db.addBalance(t.to, t.value) + else: + # Contract call + echo "Contract call" + + debug "Transaction", sender, to = t.to, value = t.value, hasCode = code.len != 0 + let msg = newMessage(t.gasLimit, t.gasPrice, t.to, sender, t.value, t.payload, code.toSeq) + # TODO: Run the vm + + if gasUsed > t.gasLimit: + gasUsed = t.gasLimit + + var refund = (t.gasLimit - gasUsed).u256 * t.gasPrice.u256 + if transactionFailed: + refund += t.value + + db.addBalance(sender, refund) + + return gasUsed.u256 * t.gasPrice.u256 diff --git a/nimbus/tracer.nim b/nimbus/tracer.nim index abed86f80..b3d7b99ca 100644 --- a/nimbus/tracer.nim +++ b/nimbus/tracer.nim @@ -1,6 +1,6 @@ import db/[db_chain, state_db, capturedb], eth_common, utils, json, - constants, vm_state, vm_types, transaction, p2p/chain, + constants, vm_state, vm_types, transaction, p2p/executor, eth_trie/db, nimcrypto proc getParentHeader(self: BaseChainDB, header: BlockHeader): BlockHeader = @@ -10,7 +10,7 @@ proc prefixHex(x: openArray[byte]): string = "0x" & toHex(x, true) proc traceTransaction*(db: BaseChainDB, header: BlockHeader, - body: BlockBody, txIndex: int, tracerFlags: set[TracerFlags]): JsonNode = + body: BlockBody, txIndex: int, tracerFlags: set[TracerFlags] = {}): JsonNode = let parent = db.getParentHeader(header) # we add a memory layer between backend/lower layer db