mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-01-24 19:19:21 +00:00
add premix tool
This commit is contained in:
parent
101c17d126
commit
013d935642
75
premix/poststate_tracer.js.template
Normal file
75
premix/poststate_tracer.js.template
Normal file
@ -0,0 +1,75 @@
|
||||
{
|
||||
postState: null,
|
||||
accounts: [$1],
|
||||
|
||||
// lookupAccount injects the specified account into the postState object.
|
||||
lookupAccount: function(addr, db){
|
||||
var acc = toHex(addr);
|
||||
if (this.postState[acc] === undefined) {
|
||||
this.postState[acc] = {
|
||||
balance: '0x' + db.getBalance(addr).toString(16),
|
||||
nonce: db.getNonce(addr),
|
||||
code: toHex(db.getCode(addr)),
|
||||
storage: {}
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
// lookupStorage injects the specified storage entry of the given account into
|
||||
// the postState object.
|
||||
lookupStorage: function(addr, key, db){
|
||||
var acc = toHex(addr);
|
||||
var idx = toHex(key);
|
||||
|
||||
if (this.postState[acc].storage[idx] === undefined) {
|
||||
var val = toHex(db.getState(addr, key));
|
||||
if (val != "0x0000000000000000000000000000000000000000000000000000000000000000") {
|
||||
this.postState[acc].storage[idx] = toHex(db.getState(addr, key));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// result is invoked when all the opcodes have been iterated over and returns
|
||||
// the final result of the tracing.
|
||||
result: function(ctx, db) {
|
||||
this.lookupAccount(ctx.from, db);
|
||||
this.lookupAccount(ctx.to, db);
|
||||
|
||||
for(var i in this.accounts) {
|
||||
this.lookupAccount(toAddress(this.accounts[i]), db)
|
||||
}
|
||||
|
||||
// Return the assembled allocations (postState)
|
||||
return this.postState;
|
||||
},
|
||||
|
||||
// step is invoked for every opcode that the VM executes.
|
||||
step: function(log, db) {
|
||||
// Add the current account if we just started tracing
|
||||
if (this.postState === null){
|
||||
this.postState = {};
|
||||
// Balance will potentially be wrong here, since this will include the value
|
||||
// sent along with the message. We fix that in 'result()'.
|
||||
this.lookupAccount(log.contract.getAddress(), db);
|
||||
}
|
||||
// Whenever new state is accessed, add it to the postState
|
||||
switch (log.op.toString()) {
|
||||
case "EXTCODECOPY": case "EXTCODESIZE": case "BALANCE":
|
||||
this.lookupAccount(toAddress(log.stack.peek(0).toString(16)), db);
|
||||
break;
|
||||
case "CREATE":
|
||||
var from = log.contract.getAddress();
|
||||
this.lookupAccount(toContract(from, db.getNonce(from)), db);
|
||||
break;
|
||||
case "CALL": case "CALLCODE": case "DELEGATECALL": case "STATICCALL":
|
||||
this.lookupAccount(toAddress(log.stack.peek(1).toString(16)), db);
|
||||
break;
|
||||
case 'SSTORE':case 'SLOAD':
|
||||
this.lookupStorage(log.contract.getAddress(), toWord(log.stack.peek(0).toString(16)), db);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
// fault is invoked when the actual execution of an opcode fails.
|
||||
fault: function(log, db) {}
|
||||
}
|
107
premix/premix.nim
Normal file
107
premix/premix.nim
Normal file
@ -0,0 +1,107 @@
|
||||
import
|
||||
json, downloader, stint, strutils,
|
||||
../nimbus/tracer, chronicles, prestate
|
||||
|
||||
proc fakeAlloc(n: JsonNode) =
|
||||
const
|
||||
chunk = repeat('0', 64)
|
||||
|
||||
for i in 1 ..< n.len:
|
||||
if not n[i].hasKey("memory"): return
|
||||
let
|
||||
prevMem = n[i-1]["memory"]
|
||||
currMem = n[i]["memory"]
|
||||
|
||||
if currMem.len > prevMem.len:
|
||||
let diff = currMem.len - prevMem.len
|
||||
for _ in 0 ..< diff:
|
||||
prevMem.add %chunk
|
||||
|
||||
proc requestPostState(n: JsonNode, jsTracer: string): JsonNode =
|
||||
let txs = n["transactions"]
|
||||
if txs.len > 0:
|
||||
result = newJArray()
|
||||
let tracer = %{
|
||||
"tracer": %jsTracer
|
||||
}
|
||||
for tx in txs:
|
||||
let txHash = tx["hash"]
|
||||
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.add txTrace
|
||||
|
||||
proc requestPostState(thisBlock: Block): JsonNode =
|
||||
let
|
||||
tmp = readFile("poststate_tracer.js.template")
|
||||
tracer = tmp % [ $thisBlock.jsonData["miner"] ]
|
||||
requestPostState(thisBlock.jsonData, tracer)
|
||||
|
||||
proc copyAccount(acc: JsonNode): JsonNode =
|
||||
result = newJObject()
|
||||
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
|
||||
|
||||
proc updateAccount(a, b: JsonNode) =
|
||||
a["balance"] = newJString(b["balance"].getStr)
|
||||
a["nonce"] = newJString(b["nonce"].getStr)
|
||||
a["code"] = newJString(b["code"].getStr)
|
||||
var storage = a["storage"]
|
||||
for k, v in b["storage"]:
|
||||
storage[k] = newJString(v.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 generatePremixData(nimbus: JsonNode, blockNumber: Uint256, thisBlock: Block, postState, accounts: JsonNode) =
|
||||
let
|
||||
receipts = toJson(thisBlock.receipts)
|
||||
txTraces = nimbus["txTraces"]
|
||||
|
||||
for trace in txTraces:
|
||||
trace["structLogs"].fakeAlloc()
|
||||
|
||||
var geth = %{
|
||||
"blockNumber": %blockNumber.toHex,
|
||||
"txTraces": thisBlock.traces,
|
||||
"receipts": receipts,
|
||||
"block": thisBlock.jsonData,
|
||||
"postState": postState,
|
||||
"accounts": accounts
|
||||
}
|
||||
|
||||
var metaData = %{
|
||||
"nimbus": nimbus,
|
||||
"geth": geth
|
||||
}
|
||||
|
||||
var data = "var debugMetaData = " & metaData.pretty & "\n"
|
||||
writeFile("premixData.js", data)
|
||||
|
||||
proc main() =
|
||||
let
|
||||
nimbus = parseFile("debug_meta_data.json")
|
||||
blockNumber = UInt256.fromHex(nimbus["blockNumber"].getStr())
|
||||
thisBlock = downloader.requestBlock(blockNumber, {DownloadReceipts, DownloadTxTrace})
|
||||
postState = requestPostState(thisBlock)
|
||||
accounts = processPostState(postState)
|
||||
|
||||
generatePremixData(nimbus, blockNumber, thisBlock, postState, accounts)
|
||||
generatePrestate(nimbus, blockNumber, thisBlock)
|
||||
|
||||
main()
|
@ -3,13 +3,11 @@ import
|
||||
../nimbus/db/[db_chain, storage_types], rlp, eth_common,
|
||||
../nimbus/p2p/chain, ../nimbus/tracer
|
||||
|
||||
proc generatePrestate*(nimbus: JsonNode) =
|
||||
proc generatePrestate*(nimbus: JsonNode, blockNumber: Uint256, thisBlock: Block) =
|
||||
let
|
||||
state = nimbus["state"]
|
||||
blockNumber = 49439.u256
|
||||
parentNumber = blockNumber - 1.u256
|
||||
parentBlock = requestBlock(parentNumber)
|
||||
thisBlock = requestBlock(blockNumber)
|
||||
headerHash = rlpHash(thisBlock.header)
|
||||
|
||||
var
|
||||
|
Loading…
x
Reference in New Issue
Block a user