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