nimbus-eth1/nimbus/tracer.nim

92 lines
3.2 KiB
Nim
Raw Normal View History

2018-12-03 10:54:19 +00:00
import
2018-12-03 16:22:08 +00:00
db/[db_chain, state_db, capturedb], eth_common, utils, json,
2018-12-04 11:42:55 +00:00
constants, vm_state, vm_types, transaction, p2p/executor,
2018-12-11 09:53:05 +00:00
eth_trie/db, nimcrypto, strutils, ranges, ./utils/addresses
2018-12-03 16:22:08 +00:00
proc getParentHeader(self: BaseChainDB, header: BlockHeader): BlockHeader =
self.getBlockHeader(header.parentHash)
proc prefixHex(x: openArray[byte]): string =
"0x" & toHex(x, true)
2018-12-03 10:54:19 +00:00
2018-12-12 00:32:33 +00:00
proc accountToJson(db: AccountStateDB, address: EthAddress, name: string): JsonNode =
2018-12-11 09:53:05 +00:00
result = newJObject()
result["name"] = %name
result["address"] = %($address)
let account = db.getAccount(address)
result["nonce"] = %(account.nonce.toHex)
result["balance"] = %(account.balance.toHex)
let code = db.getCode(address)
result["codeHash"] = %($account.codeHash)
result["code"] = %(toHex(code.toOpenArray, true))
result["storageRoot"] = %($account.storageRoot)
var storage = newJObject()
for key, value in db.storage(address):
storage[key.dumpHex] = %(value.dumpHex)
result["storage"] = storage
proc captureStateAccount(n: JsonNode, db: AccountStateDB, sender: EthAddress, header: BlockHeader, tx: Transaction) =
2018-12-12 00:32:33 +00:00
n.add accountToJson(db, sender, "sender")
n.add accountToJson(db, header.coinbase, "miner")
2018-12-11 09:53:05 +00:00
if tx.isContractCreation:
let contractAddress = generateAddress(sender, tx.accountNonce)
2018-12-12 00:32:33 +00:00
n.add accountToJson(db, contractAddress, "contract")
2018-12-11 09:53:05 +00:00
else:
2018-12-12 00:32:33 +00:00
n.add accountToJson(db, tx.to, "recipient")
2018-12-11 09:53:05 +00:00
2018-12-03 10:54:19 +00:00
proc traceTransaction*(db: BaseChainDB, header: BlockHeader,
2018-12-04 11:42:55 +00:00
body: BlockBody, txIndex: int, tracerFlags: set[TracerFlags] = {}): JsonNode =
2018-12-03 16:22:08 +00:00
let
2018-12-04 01:53:21 +00:00
parent = db.getParentHeader(header)
# we add a memory layer between backend/lower layer db
2018-12-04 01:53:21 +00:00
# and capture state db snapshot during transaction execution
2018-12-03 16:22:08 +00:00
memoryDB = newMemoryDB()
captureDB = newCaptureDB(db.db, memoryDB)
captureTrieDB = trieDB captureDB
captureChainDB = newBaseChainDB(captureTrieDB, false) # prune or not prune?
2018-12-11 09:27:22 +00:00
vmState = newBaseVMState(parent, captureChainDB, tracerFlags)
2018-12-04 01:53:21 +00:00
var stateDb = newAccountStateDB(captureTrieDB, parent.stateRoot, db.pruneTrie)
if header.txRoot == BLANK_ROOT_HASH: return
assert(body.transactions.calcTxRoot == header.txRoot)
2018-12-03 10:54:19 +00:00
assert(body.transactions.len != 0)
2018-12-11 09:53:05 +00:00
var
gasUsed: GasInt
before = newJObject()
after = newJObject()
stateDiff = %{"before": before, "after": after}
2018-12-03 10:54:19 +00:00
for idx, tx in body.transactions:
var sender: EthAddress
if tx.getSender(sender):
2018-12-11 09:27:22 +00:00
if idx == txIndex:
vmState.enableTracing()
2018-12-11 09:53:05 +00:00
before.captureStateAccount(stateDb, sender, header, tx)
2018-12-03 16:22:08 +00:00
let txFee = processTransaction(stateDb, tx, sender, vmState)
gasUsed = (txFee div tx.gasPrice.u256).truncate(GasInt)
2018-12-11 09:53:05 +00:00
2018-12-11 09:27:22 +00:00
if idx == txIndex:
vmState.disableTracing()
2018-12-11 09:53:05 +00:00
after.captureStateAccount(stateDb, sender, header, tx)
2018-12-11 09:27:22 +00:00
break
2018-12-03 10:54:19 +00:00
else:
assert(false, "Could not get sender")
2018-12-03 16:22:08 +00:00
result = vmState.getTracingResult()
result["gas"] = %gasUsed
2018-12-11 09:53:05 +00:00
result["statediff"] = stateDiff
2018-12-03 16:22:08 +00:00
2018-12-04 01:53:21 +00:00
# now we dump captured state db
if TracerFlags.DisableState notin tracerFlags:
var n = newJObject()
for k, v in pairsInMemoryDB(memoryDB):
n[k.prefixHex] = %v.prefixHex
result["state"] = n
2018-12-11 10:05:49 +00:00
2018-12-12 00:32:33 +00:00
proc dumpBlockState*(header: BlockHeader, body: BlockBody): JsonNode =
2018-12-11 10:05:49 +00:00
discard