simplifly premix code

This commit is contained in:
andri lim 2019-01-15 12:06:46 +07:00 committed by zah
parent 66ae0145f0
commit c1881fb061
3 changed files with 110 additions and 126 deletions

View File

@ -4,108 +4,16 @@ import
js_tracer, eth_common, byteutils, parser, js_tracer, eth_common, byteutils, parser,
nimcrypto, premixcore 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 = proc requestPostState(thisBlock: Block): JsonNode =
let postState = requestPostState(thisBlock.jsonData, postStateTracer, thisBlock) let blockNumber = thisBlock.header.blockNumber
requestBlockState(postState, thisBlock) 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: for uncle in thisBlock.body.uncles:
addresses.add uncle.coinbase premix.requestAccount(blockNumber, uncle.coinbase)
requestBlockState(postState, thisBlock, addresses) removePostStateDup(premix.accounts)
processPostState(postState)
proc generateGethData(thisBlock: Block, blockNumber: Uint256, accounts: JsonNode): JsonNode = proc generateGethData(thisBlock: Block, blockNumber: Uint256, accounts: JsonNode): JsonNode =
let let
@ -138,11 +46,11 @@ proc main() =
echo "usage: premix debugxxx.json" echo "usage: premix debugxxx.json"
quit(QuitFailure) quit(QuitFailure)
try: block:
let let
nimbus = json.parseFile(paramStr(1)) nimbus = json.parseFile(paramStr(1))
blockNumber = UInt256.fromHex(nimbus["blockNumber"].getStr()) blockNumber = UInt256.fromHex(nimbus["blockNumber"].getStr())
thisBlock = downloader.requestBlock(blockNumber, {DownloadReceipts, DownloadTxTrace}) thisBlock = requestBlock(blockNumber, {DownloadReceipts, DownloadTxTrace})
accounts = requestPostState(thisBlock) accounts = requestPostState(thisBlock)
geth = generateGethData(thisBlock, blockNumber, accounts) geth = generateGethData(thisBlock, blockNumber, accounts)
parentNumber = blockNumber - 1.u256 parentNumber = blockNumber - 1.u256
@ -158,7 +66,7 @@ proc main() =
generatePrestate(nimbus, geth, blockNumber, parentBlock.header, thisBlock.header, thisBlock.body) generatePrestate(nimbus, geth, blockNumber, parentBlock.header, thisBlock.header, thisBlock.body)
printDebugInstruction(blockNumber) printDebugInstruction(blockNumber)
except: #except:
echo getCurrentExceptionMsg() #echo getCurrentExceptionMsg()
main() main()

View File

@ -1,4 +1,7 @@
import json, strutils import
json, strutils, stint, parser, downloader,
../nimbus/tracer, chronicles, eth_common,
js_tracer
proc fakeAlloc(n: JsonNode) = proc fakeAlloc(n: JsonNode) =
const const
@ -15,20 +18,6 @@ proc fakeAlloc(n: JsonNode) =
for _ in 0 ..< diff: for _ in 0 ..< diff:
prevMem.add %chunk 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) = proc updateAccount*(a, b: JsonNode) =
if b.hasKey("name"): if b.hasKey("name"):
a["name"] = newJString(b["name"].getStr) a["name"] = newJString(b["name"].getStr)
@ -41,8 +30,12 @@ proc updateAccount*(a, b: JsonNode) =
a["storageRoot"] = newJString(b["storageRoot"].getStr) a["storageRoot"] = newJString(b["storageRoot"].getStr)
a["codeHash"] = newJString(b["codeHash"].getStr) a["codeHash"] = newJString(b["codeHash"].getStr)
proc removePostStateDup(nimbus: JsonNode) = proc copyAccount*(acc: JsonNode): JsonNode =
let postState = nimbus["stateDump"]["after"] result = newJObject()
result["storage"] = newJObject()
updateAccount(result, acc)
proc removePostStateDup*(postState: JsonNode): JsonNode =
var accounts = newJObject() var accounts = newJObject()
for acc in postState: for acc in postState:
let address = acc["address"].getStr let address = acc["address"].getStr
@ -50,12 +43,13 @@ proc removePostStateDup(nimbus: JsonNode) =
updateAccount(accounts[address], acc) updateAccount(accounts[address], acc)
else: else:
accounts[address] = copyAccount(acc) accounts[address] = copyAccount(acc)
nimbus["stateDump"]["after"] = accounts accounts
proc processNimbusData*(nimbus: JsonNode) = proc processNimbusData*(nimbus: JsonNode) =
# remove duplicate accounts with same address # remove duplicate accounts with same address
# and only take newest one # and only take newest one
removePostStateDup(nimbus) let postState = nimbus["stateDump"]["after"]
nimbus["stateDump"]["after"] = removePostStateDup(postState)
let txTraces = nimbus["txTraces"] let txTraces = nimbus["txTraces"]
@ -70,3 +64,90 @@ proc generatePremixData*(nimbus, geth: JsonNode) =
var data = "var premixData = " & premixData.pretty & "\n" var data = "var premixData = " & premixData.pretty & "\n"
writeFile("premixData.js", data) 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)

View File

@ -7,7 +7,6 @@ proc generatePrestate*(nimbus, geth: JsonNode, blockNumber: Uint256, parent, hea
let let
state = nimbus["state"] state = nimbus["state"]
headerHash = rlpHash(header) headerHash = rlpHash(header)
#parentNumber = parent.blockNumber
var var
memoryDB = newMemoryDB() memoryDB = newMemoryDB()
@ -25,10 +24,6 @@ proc generatePrestate*(nimbus, geth: JsonNode, blockNumber: Uint256, parent, hea
let value = hexToSeqByte(v.getStr()) let value = hexToSeqByte(v.getStr())
memoryDB.put(key, value) memoryDB.put(key, value)
#discard chainDB.getBlockHeader(parentNumber)
#discard chainDB.getBlockHeader(blockNumber)
#discard chainDB.getBlockBody(headerHash)
var metaData = %{ var metaData = %{
"blockNumber": %blockNumber.toHex, "blockNumber": %blockNumber.toHex,
"geth": geth "geth": geth