mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-01-11 12:54:13 +00:00
poststate processing
This commit is contained in:
parent
451eaed620
commit
f1bb0d1b31
@ -39,9 +39,10 @@ task test, "Run tests":
|
||||
test "all_tests"
|
||||
# debugging tools don't yet have tests
|
||||
# but they should be compilable
|
||||
buildBinary "premix", "premix/"
|
||||
buildBinary "persist", "premix/"
|
||||
buildBinary "debug", "premix/"
|
||||
exec "nim c premix/premix"
|
||||
exec "nim c premix/persist"
|
||||
exec "nim c premix/debug"
|
||||
exec "nim c premix/dumper"
|
||||
|
||||
task nimbus, "Build Nimbus":
|
||||
buildBinary "nimbus", "nimbus/"
|
||||
|
@ -2,7 +2,7 @@ import
|
||||
db/[db_chain, state_db, capturedb], eth_common, utils, json,
|
||||
constants, vm_state, vm_types, transaction, p2p/executor,
|
||||
eth_trie/db, nimcrypto, strutils, ranges, ./utils/addresses,
|
||||
chronicles
|
||||
chronicles, rpc/hexstrings
|
||||
|
||||
proc getParentHeader(self: BaseChainDB, header: BlockHeader): BlockHeader =
|
||||
self.getBlockHeader(header.parentHash)
|
||||
@ -46,19 +46,19 @@ proc getRecipient*(tx: Transaction): EthAddress =
|
||||
proc captureAccount(n: JsonNode, db: AccountStateDB, address: EthAddress, name: string) =
|
||||
var jaccount = newJObject()
|
||||
jaccount["name"] = %name
|
||||
jaccount["address"] = %($address)
|
||||
jaccount["address"] = %("0x" & $address)
|
||||
let account = db.getAccount(address)
|
||||
jaccount["nonce"] = %(account.nonce.toHex)
|
||||
jaccount["balance"] = %(account.balance.toHex)
|
||||
jaccount["nonce"] = %(encodeQuantity(account.nonce).toLowerAscii)
|
||||
jaccount["balance"] = %("0x" & account.balance.toHex)
|
||||
|
||||
let code = db.getCode(address)
|
||||
jaccount["codeHash"] = %(($account.codeHash).toLowerAscii)
|
||||
jaccount["code"] = %(toHex(code.toOpenArray, true))
|
||||
jaccount["storageRoot"] = %(($account.storageRoot).toLowerAscii)
|
||||
jaccount["codeHash"] = %("0x" & ($account.codeHash).toLowerAscii)
|
||||
jaccount["code"] = %("0x" & toHex(code.toOpenArray, true))
|
||||
jaccount["storageRoot"] = %("0x" & ($account.storageRoot).toLowerAscii)
|
||||
|
||||
var storage = newJObject()
|
||||
for key, value in db.storage(address):
|
||||
storage[key.dumpHex] = %(value.dumpHex)
|
||||
storage["0x" & key.dumpHex] = %("0x" & value.dumpHex)
|
||||
jaccount["storage"] = storage
|
||||
|
||||
n.add jaccount
|
||||
|
@ -120,6 +120,7 @@ function opCodeRenderer(txId, nimbus, geth) {
|
||||
}
|
||||
|
||||
function transactionsRenderer(txId, nimbus, geth) {
|
||||
txId = parseInt(txId);
|
||||
$('#transactionsTitle').text(`Tx #${(txId+1)}`);
|
||||
let container = $('#transactionsContainer').empty();
|
||||
|
||||
@ -130,13 +131,17 @@ function transactionsRenderer(txId, nimbus, geth) {
|
||||
premix.renderRow(body, nimbus, geth, x);
|
||||
}
|
||||
|
||||
// TODO: receipt logs
|
||||
// TODO: render receipt logs
|
||||
}
|
||||
|
||||
txId = parseInt(txId);
|
||||
let ntx = nimbus.txTraces[txId];
|
||||
let gtx = geth.txTraces[txId];
|
||||
|
||||
if(ntx.returnValue.length == 0) {
|
||||
ntx.returnValue = "0x";
|
||||
}
|
||||
|
||||
let ncr = $.extend({
|
||||
gas: ntx.gas,
|
||||
returnValue: ntx.returnValue
|
||||
@ -155,36 +160,52 @@ function transactionsRenderer(txId, nimbus, geth) {
|
||||
}
|
||||
|
||||
function headerRenderer(nimbus, geth) {
|
||||
function emptyAccount() {
|
||||
return {
|
||||
address: '',
|
||||
nonce: '',
|
||||
balance: '',
|
||||
codeHash: '',
|
||||
code: '',
|
||||
storageRoot: '',
|
||||
storage: {}
|
||||
};
|
||||
}
|
||||
|
||||
let container = $('#headerContainer').empty();
|
||||
|
||||
let ncs = nimbus.stateDump.after;
|
||||
let gcs = geth.accounts;
|
||||
let accounts = [];
|
||||
|
||||
|
||||
for(var n of ncs) {
|
||||
n.address = '0x' + n.address;
|
||||
n.balance = '0x' + n.balance;
|
||||
n.code = '0x' + n.code;
|
||||
let g = gcs[n.address];
|
||||
|
||||
for(var address in ncs) {
|
||||
let n = ncs[address];
|
||||
n.address = address;
|
||||
if(gcs[address]) {
|
||||
let geth = gcs[address];
|
||||
geth.address = address;
|
||||
accounts.push({name: n.name, nimbus: n, geth: geth});
|
||||
delete gcs[address];
|
||||
} else {
|
||||
accounts.push({name: n.name, nimbus: n, geth: emptyAccount()});
|
||||
}
|
||||
}
|
||||
|
||||
/*"name": "internalTx0",
|
||||
"address": "0000000000000000000000000000000000000004",
|
||||
"nonce": "0000000000000000",
|
||||
"balance": "0",
|
||||
"codeHash": "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
|
||||
"code": "",
|
||||
"storageRoot": "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"storage": {}*/
|
||||
|
||||
/*"0xf927a40c8b7f6e07c5af7fa2155b4864a4112b13": {
|
||||
"balance": "0x607c9cea65ef7e19dd8",
|
||||
"nonce": "0000000000000000",
|
||||
"code": "0x",
|
||||
"storage": {}*/
|
||||
|
||||
for(var address in gcs) {
|
||||
let geth = gcs[address];
|
||||
geth.address = address;
|
||||
accounts.push({name: "unknown", nimbus: emptyAccount(), geth: geth});
|
||||
}
|
||||
|
||||
for(var acc of accounts) {
|
||||
$(`<h4>Account Name: ${acc.name}</h4>`).appendTo(container);
|
||||
let body = premix.newTable(container);
|
||||
const fields = ['address', 'nonce', 'balance', 'codeHash', 'code', 'storageRoot'];
|
||||
for(var x of fields) {
|
||||
premix.renderRow(body, acc.nimbus, acc.geth, x);
|
||||
}
|
||||
$('<hr class="uk-divider-icon">').appendTo(container);
|
||||
}
|
||||
}
|
||||
|
||||
function generateNavigation(txs, nimbus, geth) {
|
||||
@ -201,8 +222,8 @@ function generateNavigation(txs, nimbus, geth) {
|
||||
let list = $('<ul class="uk-nav uk-dropdown-nav"/>').appendTo(div);
|
||||
|
||||
for(var i in txs) {
|
||||
let id = i.toString();
|
||||
$(`<li class="uk-active"><a rel="${id}" href="#">TX #${id}</a></li>`).appendTo(list);
|
||||
let id = parseInt(i) + 1;
|
||||
$(`<li class="uk-active"><a rel="${i}" href="#">TX #${id}</a></li>`).appendTo(list);
|
||||
}
|
||||
|
||||
list.find('li a').click(function(ev) {
|
||||
|
@ -61,16 +61,16 @@ proc requestReceipts(n: JsonNode): seq[Receipt] =
|
||||
result.add parseReceipt(rec)
|
||||
|
||||
proc requestTxTraces(n: JsonNode): JsonNode =
|
||||
result = newJArray()
|
||||
let txs = n["transactions"]
|
||||
if txs.len > 0:
|
||||
result = newJArray()
|
||||
for tx in txs:
|
||||
let txHash = tx["hash"]
|
||||
let txTrace = request("debug_traceTransaction", %[txHash])
|
||||
if txTrace.kind == JNull:
|
||||
error "requested trace not available", txHash=txHash
|
||||
raise newException(ValueError, "Error when retrieving transaction trace")
|
||||
result.add txTrace
|
||||
if txs.len == 0: return
|
||||
for tx in txs:
|
||||
let txHash = tx["hash"]
|
||||
let txTrace = request("debug_traceTransaction", %[txHash])
|
||||
if txTrace.kind == JNull:
|
||||
error "requested trace not available", txHash=txHash
|
||||
raise newException(ValueError, "Error when retrieving transaction trace")
|
||||
result.add txTrace
|
||||
|
||||
proc requestBlock*(blockNumber: BlockNumber, flags: set[DownloadFlags] = {}): Block =
|
||||
var header = request("eth_getBlockByNumber", %[%blockNumber.prefixHex, %true])
|
||||
|
@ -1,13 +1,11 @@
|
||||
const postStateTracer* = """{
|
||||
postState: null,
|
||||
postState: {},
|
||||
|
||||
// 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: {}
|
||||
};
|
||||
@ -19,9 +17,9 @@ const postStateTracer* = """{
|
||||
lookupStorage: function(addr, key, db){
|
||||
var acc = toHex(addr);
|
||||
var idx = toHex(key);
|
||||
|
||||
this.lookupAccount(addr, db);
|
||||
if (this.postState[acc].storage[idx] === undefined) {
|
||||
this.postState[acc].storage[idx] = "";//toHex(db.getState(addr, key));
|
||||
this.postState[acc].storage[idx] = "";
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -6,7 +6,7 @@ import
|
||||
import
|
||||
../nimbus/[transaction, rpc/hexstrings]
|
||||
|
||||
func hexToInt(s: string, T: typedesc[SomeInteger]): T =
|
||||
func hexToInt*(s: string, T: typedesc[SomeInteger]): T =
|
||||
var i = 0
|
||||
if s[i] == '0' and (s[i+1] in {'x', 'X'}): inc(i, 2)
|
||||
if s.len - i > sizeof(T) * 2:
|
||||
|
@ -29,20 +29,53 @@ proc requestTrace(txHash, tracer: JsonNode): JsonNode =
|
||||
raise newException(ValueError, "Error when retrieving transaction postState")
|
||||
result = txTrace
|
||||
|
||||
proc requestPostState(n: JsonNode, jsTracer: string): JsonNode =
|
||||
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)
|
||||
|
||||
if tx["to"].kind == JNull:
|
||||
let t = parseTransaction(tx)
|
||||
let code = request("eth_getCode", %[%t.getRecipient.prefixHex, number])
|
||||
return code.getStr.len > 2 # "0x"
|
||||
|
||||
let code = request("eth_getCode", %[tx["to"], number])
|
||||
result = code.getStr.len > 2 # "0x"
|
||||
|
||||
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 tx["to"].kind != JNull:
|
||||
result.add newJObject()
|
||||
continue
|
||||
let
|
||||
txHash = tx["hash"]
|
||||
txTrace = requestTrace(txHash, tracer)
|
||||
result.add txTrace
|
||||
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)
|
||||
@ -59,45 +92,37 @@ proc requestBlockState(postState: JsonNode, thisBlock: Block) =
|
||||
storage.add %k
|
||||
let trace = request("eth_getProof", %[%address, storage, number])
|
||||
account["codeHash"] = trace["codeHash"]
|
||||
account["storageHash"] = trace["storageHash"]
|
||||
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 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(toHex(acc["nonce"].getInt))
|
||||
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)
|
||||
a["balance"] = newJString(b["balance"].getStr)
|
||||
a["nonce"] = newJString(toHex(b["nonce"].getInt))
|
||||
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 requestBlockState(postState: JsonNode, thisBlock: Block, addresses: seq[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"],
|
||||
"storageHash": trace["storageHash"],
|
||||
"balance": trace["balance"],
|
||||
"nonce": trace["nonce"],
|
||||
"code": newJString("0x"),
|
||||
"storage": newJObject()
|
||||
}
|
||||
txTrace[address] = account
|
||||
postState.add txTrace
|
||||
a["storageRoot"] = newJString(b["storageRoot"].getStr)
|
||||
a["codeHash"] = newJString(b["codeHash"].getStr)
|
||||
|
||||
proc processPostState(postState: JsonNode): JsonNode =
|
||||
var accounts = newJObject()
|
||||
@ -111,8 +136,19 @@ proc processPostState(postState: JsonNode): JsonNode =
|
||||
|
||||
result = accounts
|
||||
|
||||
proc removePostStateDup(nimbus: JsonNode) =
|
||||
let postState = nimbus["stateDump"]["after"]
|
||||
var accounts = newJObject()
|
||||
for acc in postState:
|
||||
let address = acc["address"].getStr
|
||||
if accounts.hasKey(address):
|
||||
updateAccount(accounts[address], acc)
|
||||
else:
|
||||
accounts[address] = copyAccount(acc)
|
||||
nimbus["stateDump"]["after"] = accounts
|
||||
|
||||
proc requestPostState(thisBlock: Block): JsonNode =
|
||||
let postState = requestPostState(thisBlock.jsonData, postStateTracer)
|
||||
let postState = requestPostState(thisBlock.jsonData, postStateTracer, thisBlock)
|
||||
requestBlockState(postState, thisBlock)
|
||||
|
||||
var addresses = @[thisBlock.header.coinbase]
|
||||
@ -170,6 +206,7 @@ proc main() =
|
||||
thisBlock = downloader.requestBlock(blockNumber, {DownloadReceipts, DownloadTxTrace})
|
||||
accounts = requestPostState(thisBlock)
|
||||
|
||||
removePostStateDup(nimbus)
|
||||
generatePremixData(nimbus, blockNumber, thisBlock, accounts)
|
||||
generatePrestate(nimbus, blockNumber, thisBlock)
|
||||
printDebugInstruction(blockNumber)
|
||||
|
Loading…
x
Reference in New Issue
Block a user