From c1881fb061f4f02dd47d9543ab95e423f6d80393 Mon Sep 17 00:00:00 2001 From: andri lim Date: Tue, 15 Jan 2019 12:06:46 +0700 Subject: [PATCH] simplifly premix code --- premix/premix.nim | 112 ++++----------------------------------- premix/premixcore.nim | 119 +++++++++++++++++++++++++++++++++++------- premix/prestate.nim | 5 -- 3 files changed, 110 insertions(+), 126 deletions(-) diff --git a/premix/premix.nim b/premix/premix.nim index 7cbd95095..b0dd081fd 100644 --- a/premix/premix.nim +++ b/premix/premix.nim @@ -4,108 +4,16 @@ import js_tracer, eth_common, byteutils, parser, nimcrypto, premixcore -proc jsonTracer(tracer: string): JsonNode = - result = %{ "tracer": %tracer } - -proc requestTrace(txHash, tracer: JsonNode): JsonNode = - let txTrace = request("debug_traceTransaction", %[txHash, tracer]) - if txTrace.kind == JNull: - error "requested postState not available", txHash=txHash - raise newException(ValueError, "Error when retrieving transaction postState") - result = txTrace - -proc requestBlockState(postState: JsonNode, thisBlock: Block, addresses: openArray[EthAddress]) = - let number = %(thisBlock.header.blockNumber.prefixHex) - - var txTrace = newJObject() - for a in addresses: - let address = a.prefixHex - let trace = request("eth_getProof", %[%address, %[], number]) - let account = %{ - "codeHash": trace["codeHash"], - "storageRoot": trace["storageHash"], - "balance": trace["balance"], - "nonce": trace["nonce"], - "code": newJString("0x"), - "storage": newJObject() - } - txTrace[address] = account - postState.add txTrace - -proc hasTracerData(tx: JsonNode, blockNumber: Uint256): bool = - let - number = %(blockNumber.prefixHex) - t = parseTransaction(tx) - code = request("eth_getCode", %[%t.getRecipient.prefixHex, number]) - recipientHasCode = code.getStr.len > 2 # "0x" - - if t.isContractCreation: - return recipientHasCode or t.payload.len > 0 - - recipientHasCode - -proc requestPostState(n: JsonNode, jsTracer: string, thisBlock: Block): JsonNode = - let txs = n["transactions"] - result = newJArray() - if txs.len == 0: return - - let tracer = jsonTracer(jsTracer) - for tx in txs: - if hasTracerData(tx, thisBlock.header.blockNumber): - let - txHash = tx["hash"] - txTrace = requestTrace(txHash, tracer) - result.add txTrace - else: - let t = parseTransaction(tx) - var address: array[2, EthAddress] - address[0] = t.getRecipient - address[1] = t.getSender - requestBlockState(result, thisBlock, address) - -proc padding(x: string): JsonNode = - let val = x.substr(2) - let pad = repeat('0', 64 - val.len) - result = newJString("0x" & pad & val) - -proc requestBlockState(postState: JsonNode, thisBlock: Block) = - let number = %(thisBlock.header.blockNumber.prefixHex) - - for state in postState: - for address, account in state: - var storage = newJArray() - for k, _ in account["storage"]: - storage.add %k - let trace = request("eth_getProof", %[%address, storage, number]) - account["codeHash"] = trace["codeHash"] - account["storageRoot"] = trace["storageHash"] - account["nonce"] = trace["nonce"] - account["balance"] = trace["balance"] - for x in trace["storageProof"]: - account["storage"][x["key"].getStr] = padding(x["value"].getStr()) - -proc processPostState(postState: JsonNode): JsonNode = - var accounts = newJObject() - - for state in postState: - for address, account in state: - if accounts.hasKey(address): - updateAccount(accounts[address], account) - else: - accounts[address] = copyAccount(account) - - result = accounts - proc requestPostState(thisBlock: Block): JsonNode = - let postState = requestPostState(thisBlock.jsonData, postStateTracer, thisBlock) - requestBlockState(postState, thisBlock) + let blockNumber = thisBlock.header.blockNumber + var premix = initPremix() - var addresses = @[thisBlock.header.coinbase] + premix.requestPostState(thisBlock.jsonData, blockNumber) + premix.requestAccount(blockNumber, thisBlock.header.coinbase) for uncle in thisBlock.body.uncles: - addresses.add uncle.coinbase + premix.requestAccount(blockNumber, uncle.coinbase) - requestBlockState(postState, thisBlock, addresses) - processPostState(postState) + removePostStateDup(premix.accounts) proc generateGethData(thisBlock: Block, blockNumber: Uint256, accounts: JsonNode): JsonNode = let @@ -138,11 +46,11 @@ proc main() = echo "usage: premix debugxxx.json" quit(QuitFailure) - try: + block: let nimbus = json.parseFile(paramStr(1)) blockNumber = UInt256.fromHex(nimbus["blockNumber"].getStr()) - thisBlock = downloader.requestBlock(blockNumber, {DownloadReceipts, DownloadTxTrace}) + thisBlock = requestBlock(blockNumber, {DownloadReceipts, DownloadTxTrace}) accounts = requestPostState(thisBlock) geth = generateGethData(thisBlock, blockNumber, accounts) parentNumber = blockNumber - 1.u256 @@ -158,7 +66,7 @@ proc main() = generatePrestate(nimbus, geth, blockNumber, parentBlock.header, thisBlock.header, thisBlock.body) printDebugInstruction(blockNumber) - except: - echo getCurrentExceptionMsg() + #except: + #echo getCurrentExceptionMsg() main() diff --git a/premix/premixcore.nim b/premix/premixcore.nim index 62d7b6334..1d4ab4279 100644 --- a/premix/premixcore.nim +++ b/premix/premixcore.nim @@ -1,4 +1,7 @@ -import json, strutils +import + json, strutils, stint, parser, downloader, + ../nimbus/tracer, chronicles, eth_common, + js_tracer proc fakeAlloc(n: JsonNode) = const @@ -15,20 +18,6 @@ proc fakeAlloc(n: JsonNode) = for _ in 0 ..< diff: prevMem.add %chunk -proc copyAccount*(acc: JsonNode): JsonNode = - result = newJObject() - if acc.hasKey("name"): - result["name"] = newJString(acc["name"].getStr) - result["balance"] = newJString(acc["balance"].getStr) - result["nonce"] = newJString(acc["nonce"].getStr) - result["code"] = newJString(acc["code"].getStr) - var storage = newJObject() - for k, v in acc["storage"]: - storage[k] = newJString(v.getStr) - result["storage"] = storage - result["storageRoot"] = newJString(acc["storageRoot"].getStr) - result["codeHash"] = newJString(acc["codeHash"].getStr) - proc updateAccount*(a, b: JsonNode) = if b.hasKey("name"): a["name"] = newJString(b["name"].getStr) @@ -41,8 +30,12 @@ proc updateAccount*(a, b: JsonNode) = a["storageRoot"] = newJString(b["storageRoot"].getStr) a["codeHash"] = newJString(b["codeHash"].getStr) -proc removePostStateDup(nimbus: JsonNode) = - let postState = nimbus["stateDump"]["after"] +proc copyAccount*(acc: JsonNode): JsonNode = + result = newJObject() + result["storage"] = newJObject() + updateAccount(result, acc) + +proc removePostStateDup*(postState: JsonNode): JsonNode = var accounts = newJObject() for acc in postState: let address = acc["address"].getStr @@ -50,12 +43,13 @@ proc removePostStateDup(nimbus: JsonNode) = updateAccount(accounts[address], acc) else: accounts[address] = copyAccount(acc) - nimbus["stateDump"]["after"] = accounts + accounts proc processNimbusData*(nimbus: JsonNode) = # remove duplicate accounts with same address # and only take newest one - removePostStateDup(nimbus) + let postState = nimbus["stateDump"]["after"] + nimbus["stateDump"]["after"] = removePostStateDup(postState) let txTraces = nimbus["txTraces"] @@ -70,3 +64,90 @@ proc generatePremixData*(nimbus, geth: JsonNode) = var data = "var premixData = " & premixData.pretty & "\n" writeFile("premixData.js", data) + +type + Premix* = object + accounts*: JsonNode + proofs*: JsonNode + +proc initPremix*(): Premix = + result.accounts = newJArray() + result.proofs = newJArray() + +proc hasInternalTx(tx: Transaction, blockNumber: Uint256): bool = + let + number = %(blockNumber.prefixHex) + code = request("eth_getCode", %[%tx.getRecipient.prefixHex, number]) + recipientHasCode = code.getStr.len > 2 # "0x" + + if tx.isContractCreation: + return recipientHasCode or tx.payload.len > 0 + + recipientHasCode + +proc jsonTracer(tracer: string): JsonNode = + result = %{ "tracer": %tracer } + +proc requestInternalTx(txHash, tracer: JsonNode): JsonNode = + let txTrace = request("debug_traceTransaction", %[txHash, tracer]) + if txTrace.kind == JNull: + error "requested postState not available", txHash=txHash + raise newException(ValueError, "Error when retrieving transaction postState") + result = txTrace + +proc requestAccount*(premix: var Premix, blockNumber: Uint256, address: EthAddress) = + let + number = %(blockNumber.prefixHex) + address = address.prefixHex + proof = request("eth_getProof", %[%address, %[], number]) + + let account = %{ + "address": %address, + "codeHash": proof["codeHash"], + "storageRoot": proof["storageHash"], + "balance": proof["balance"], + "nonce": proof["nonce"], + "code": newJString("0x"), + "storage": newJObject() + } + premix.accounts.add account + premix.proofs.add proof + +proc padding(x: string): JsonNode = + let val = x.substr(2) + let pad = repeat('0', 64 - val.len) + result = newJString("0x" & pad & val) + +proc updateAccount(address: string, account: JsonNode, blockNumber: Uint256): JsonNode = + let number = %(blockNumber.prefixHex) + + var storage = newJArray() + for k, _ in account["storage"]: + storage.add %k + + let proof = request("eth_getProof", %[%address, storage, number]) + account["address"] = %address + account["codeHash"] = proof["codeHash"] + account["storageRoot"] = proof["storageHash"] + account["nonce"] = proof["nonce"] + account["balance"] = proof["balance"] + for x in proof["storageProof"]: + x["value"] = padding(x["value"].getStr()) + account["storage"][x["key"].getStr] = x["value"] + proof + +proc requestPostState*(premix: var Premix, n: JsonNode, blockNumber: Uint256) = + let txs = n["transactions"] + if txs.len == 0: return + + let tracer = jsonTracer(postStateTracer) + for t in txs: + let tx = parseTransaction(t) + if hasInternalTx(tx, blockNumber): + let txTrace = requestInternalTx(t["hash"], tracer) + for address, account in txTrace: + premix.proofs.add updateAccount(address, account, blockNumber) + premix.accounts.add account + else: + premix.requestAccount(blockNumber, tx.getRecipient) + premix.requestAccount(blockNumber, tx.getSender) diff --git a/premix/prestate.nim b/premix/prestate.nim index a141bca25..a0d738e21 100644 --- a/premix/prestate.nim +++ b/premix/prestate.nim @@ -7,7 +7,6 @@ proc generatePrestate*(nimbus, geth: JsonNode, blockNumber: Uint256, parent, hea let state = nimbus["state"] headerHash = rlpHash(header) - #parentNumber = parent.blockNumber var memoryDB = newMemoryDB() @@ -25,10 +24,6 @@ proc generatePrestate*(nimbus, geth: JsonNode, blockNumber: Uint256, parent, hea let value = hexToSeqByte(v.getStr()) memoryDB.put(key, value) - #discard chainDB.getBlockHeader(parentNumber) - #discard chainDB.getBlockHeader(blockNumber) - #discard chainDB.getBlockBody(headerHash) - var metaData = %{ "blockNumber": %blockNumber.toHex, "geth": geth