simplifly premix code
This commit is contained in:
parent
66ae0145f0
commit
c1881fb061
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue