Simplify state root api (#2864)

`updateOk` is obsolete and always set to true - callers should not have
to care about this detail

also take the opportunity to clean up storage root naming
This commit is contained in:
Jacek Sieka 2024-11-22 14:15:35 +01:00 committed by GitHub
parent ac2f3a4358
commit 652539e628
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 58 additions and 84 deletions

View File

@ -93,13 +93,11 @@ type
{.noRaise.} {.noRaise.}
## Fetch an account record from the database indexed by `accPath`. ## Fetch an account record from the database indexed by `accPath`.
AristoApiFetchAccountStateRootFn* = AristoApiFetchStateRootFn* =
proc(db: AristoDbRef; proc(db: AristoDbRef;
updateOk: bool;
): Result[Hash32,AristoError] ): Result[Hash32,AristoError]
{.noRaise.} {.noRaise.}
## Fetch the Merkle hash of the account root. Force update if the ## Fetch the Merkle hash of the account root.
## argument `updateOK` is set `true`.
AristoApiFetchStorageDataFn* = AristoApiFetchStorageDataFn* =
proc(db: AristoDbRef; proc(db: AristoDbRef;
@ -113,11 +111,9 @@ type
AristoApiFetchStorageRootFn* = AristoApiFetchStorageRootFn* =
proc(db: AristoDbRef; proc(db: AristoDbRef;
accPath: Hash32; accPath: Hash32;
updateOk: bool;
): Result[Hash32,AristoError] ): Result[Hash32,AristoError]
{.noRaise.} {.noRaise.}
## Fetch the Merkle hash of the storage root related to `accPath`. Force ## Fetch the Merkle hash of the storage root related to `accPath`.
## update if the argument `updateOK` is set `true`.
AristoApiFindTxFn* = AristoApiFindTxFn* =
proc(db: AristoDbRef; proc(db: AristoDbRef;
@ -425,7 +421,7 @@ type
fetchLastSavedState*: AristoApiFetchLastSavedStateFn fetchLastSavedState*: AristoApiFetchLastSavedStateFn
fetchAccountRecord*: AristoApiFetchAccountRecordFn fetchAccountRecord*: AristoApiFetchAccountRecordFn
fetchAccountStateRoot*: AristoApiFetchAccountStateRootFn fetchStateRoot*: AristoApiFetchStateRootFn
fetchStorageData*: AristoApiFetchStorageDataFn fetchStorageData*: AristoApiFetchStorageDataFn
fetchStorageRoot*: AristoApiFetchStorageRootFn fetchStorageRoot*: AristoApiFetchStorageRootFn
@ -472,7 +468,7 @@ type
AristoApiProfFetchLastSavedStateFn = "fetchLastSavedState" AristoApiProfFetchLastSavedStateFn = "fetchLastSavedState"
AristoApiProfFetchAccountRecordFn = "fetchAccountRecord" AristoApiProfFetchAccountRecordFn = "fetchAccountRecord"
AristoApiProfFetchAccountStateRootFn = "fetchAccountStateRoot" AristoApiProfFetchStateRootFn = "fetchStateRoot"
AristoApiProfFetchStorageDataFn = "fetchStorageData" AristoApiProfFetchStorageDataFn = "fetchStorageData"
AristoApiProfFetchStorageRootFn = "fetchStorageRoot" AristoApiProfFetchStorageRootFn = "fetchStorageRoot"
@ -534,7 +530,7 @@ when AutoValidateApiHooks:
doAssert not api.fetchLastSavedState.isNil doAssert not api.fetchLastSavedState.isNil
doAssert not api.fetchAccountRecord.isNil doAssert not api.fetchAccountRecord.isNil
doAssert not api.fetchAccountStateRoot.isNil doAssert not api.fetchStateRoot.isNil
doAssert not api.fetchStorageData.isNil doAssert not api.fetchStorageData.isNil
doAssert not api.fetchStorageRoot.isNil doAssert not api.fetchStorageRoot.isNil
@ -601,7 +597,7 @@ func init*(api: var AristoApiObj) =
api.fetchLastSavedState = fetchLastSavedState api.fetchLastSavedState = fetchLastSavedState
api.fetchAccountRecord = fetchAccountRecord api.fetchAccountRecord = fetchAccountRecord
api.fetchAccountStateRoot = fetchAccountStateRoot api.fetchStateRoot = fetchStateRoot
api.fetchStorageData = fetchStorageData api.fetchStorageData = fetchStorageData
api.fetchStorageRoot = fetchStorageRoot api.fetchStorageRoot = fetchStorageRoot
@ -650,7 +646,7 @@ func dup*(api: AristoApiRef): AristoApiRef =
fetchLastSavedState: api.fetchLastSavedState, fetchLastSavedState: api.fetchLastSavedState,
fetchAccountRecord: api.fetchAccountRecord, fetchAccountRecord: api.fetchAccountRecord,
fetchAccountStateRoot: api.fetchAccountStateRoot, fetchStateRoot: api.fetchStateRoot,
fetchStorageData: api.fetchStorageData, fetchStorageData: api.fetchStorageData,
fetchStorageRoot: api.fetchStorageRoot, fetchStorageRoot: api.fetchStorageRoot,
@ -742,10 +738,10 @@ func init*(
AristoApiProfFetchAccountRecordFn.profileRunner: AristoApiProfFetchAccountRecordFn.profileRunner:
result = api.fetchAccountRecord(a, b) result = api.fetchAccountRecord(a, b)
profApi.fetchAccountStateRoot = profApi.fetchStateRoot =
proc(a: AristoDbRef; b: bool): auto = proc(a: AristoDbRef; b: bool): auto =
AristoApiProfFetchAccountStateRootFn.profileRunner: AristoApiProfFetchStateRootFn.profileRunner:
result = api.fetchAccountStateRoot(a, b) result = api.fetchStateRoot(a, b)
profApi.fetchStorageData = profApi.fetchStorageData =
proc(a: AristoDbRef; b, stoPath: Hash32): auto = proc(a: AristoDbRef; b, stoPath: Hash32): auto =
@ -753,9 +749,9 @@ func init*(
result = api.fetchStorageData(a, b, stoPath) result = api.fetchStorageData(a, b, stoPath)
profApi.fetchStorageRoot = profApi.fetchStorageRoot =
proc(a: AristoDbRef; b: Hash32; c: bool): auto = proc(a: AristoDbRef; b: Hash32): auto =
AristoApiProfFetchStorageRootFn.profileRunner: AristoApiProfFetchStorageRootFn.profileRunner:
result = api.fetchStorageRoot(a, b, c) result = api.fetchStorageRoot(a, b)
profApi.findTx = profApi.findTx =
proc(a: AristoDbRef; b: RootedVertexID; c: HashKey): auto = proc(a: AristoDbRef; b: RootedVertexID; c: HashKey): auto =

View File

@ -80,20 +80,13 @@ proc retrieveAccountLeaf(
proc retrieveMerkleHash( proc retrieveMerkleHash(
db: AristoDbRef; db: AristoDbRef;
root: VertexID; root: VertexID;
updateOk: bool;
): Result[Hash32,AristoError] = ): Result[Hash32,AristoError] =
let key = let key =
if updateOk:
db.computeKey((root, root)).valueOr: db.computeKey((root, root)).valueOr:
if error == GetVtxNotFound: if error == GetVtxNotFound:
return ok(EMPTY_ROOT_HASH) return ok(EMPTY_ROOT_HASH)
return err(error) return err(error)
else:
let (key, _) = db.getKeyRc((root, root)).valueOr:
if error == GetKeyNotFound:
return ok(EMPTY_ROOT_HASH) # empty sub-tree
return err(error)
key
ok key.to(Hash32) ok key.to(Hash32)
proc hasAccountPayload( proc hasAccountPayload(
@ -219,12 +212,11 @@ proc fetchAccountRecord*(
ok leafVtx.lData.account ok leafVtx.lData.account
proc fetchAccountStateRoot*( proc fetchStateRoot*(
db: AristoDbRef; db: AristoDbRef;
updateOk: bool;
): Result[Hash32,AristoError] = ): Result[Hash32,AristoError] =
## Fetch the Merkle hash of the account root. ## Fetch the Merkle hash of the account root.
db.retrieveMerkleHash(VertexID(1), updateOk) db.retrieveMerkleHash(VertexID(1))
proc hasPathAccount*( proc hasPathAccount*(
db: AristoDbRef; db: AristoDbRef;
@ -248,14 +240,13 @@ proc fetchStorageData*(
proc fetchStorageRoot*( proc fetchStorageRoot*(
db: AristoDbRef; db: AristoDbRef;
accPath: Hash32; accPath: Hash32;
updateOk: bool;
): Result[Hash32,AristoError] = ): Result[Hash32,AristoError] =
## Fetch the Merkle hash of the storage root related to `accPath`. ## Fetch the Merkle hash of the storage root related to `accPath`.
let stoID = db.fetchStorageIdImpl(accPath).valueOr: let stoID = db.fetchStorageIdImpl(accPath).valueOr:
if error == FetchPathNotFound: if error == FetchPathNotFound:
return ok(EMPTY_ROOT_HASH) # no sub-tree return ok(EMPTY_ROOT_HASH) # no sub-tree
return err(error) return err(error)
db.retrieveMerkleHash(stoID, updateOk) db.retrieveMerkleHash(stoID)
proc hasPathStorage*( proc hasPathStorage*(
db: AristoDbRef; db: AristoDbRef;

View File

@ -243,7 +243,7 @@ proc jLogger(
func to(w: AristoApiProfNames; T: type TracePfx): T = func to(w: AristoApiProfNames; T: type TracePfx): T =
case w: case w:
of AristoApiProfFetchAccountRecordFn, of AristoApiProfFetchAccountRecordFn,
AristoApiProfFetchAccountStateRootFn, AristoApiProfFetchStateRootFn,
AristoApiProfDeleteAccountRecordFn, AristoApiProfDeleteAccountRecordFn,
AristoApiProfMergeAccountRecordFn: AristoApiProfMergeAccountRecordFn:
return TrpAccounts return TrpAccounts
@ -466,26 +466,25 @@ proc ariTraceRecorder(tr: TraceRecorderRef) =
debug logTxt $info, level, accPath, accRec debug logTxt $info, level, accPath, accRec
ok accRec ok accRec
tracerApi.fetchAccountStateRoot = tracerApi.fetchStateRoot =
proc(mpt: AristoDbRef; proc(mpt: AristoDbRef;
updateOk: bool;
): Result[Hash32,AristoError] = ): Result[Hash32,AristoError] =
const info = AristoApiProfFetchAccountStateRootFn const info = AristoApiProfFetchStateRootFn
when CoreDbNoisyCaptJournal: when CoreDbNoisyCaptJournal:
let level = tr.topLevel() let level = tr.topLevel()
# Find entry on DB # Find entry on DB
let state = api.fetchAccountStateRoot(mpt, updateOk).valueOr: let state = api.fetchStateRoot(mpt).valueOr:
when CoreDbNoisyCaptJournal: when CoreDbNoisyCaptJournal:
debug logTxt $info, level, updateOk, error debug logTxt $info, level, error
tr.jLogger logRecord(info, TrqFind, error) tr.jLogger logRecord(info, TrqFind, error)
return err(error) return err(error)
tr.jLogger logRecord(info, TrqFind, state) tr.jLogger logRecord(info, TrqFind, state)
when CoreDbNoisyCaptJournal: when CoreDbNoisyCaptJournal:
debug logTxt $info, level, updateOk, state debug logTxt $info, level, state
ok state ok state
tracerApi.fetchStorageData = tracerApi.fetchStorageData =
@ -514,7 +513,6 @@ proc ariTraceRecorder(tr: TraceRecorderRef) =
tracerApi.fetchStorageRoot = tracerApi.fetchStorageRoot =
proc(mpt: AristoDbRef; proc(mpt: AristoDbRef;
accPath: Hash32; accPath: Hash32;
updateOk: bool;
): Result[Hash32,AristoError] = ): Result[Hash32,AristoError] =
const info = AristoApiProfFetchStorageRootFn const info = AristoApiProfFetchStorageRootFn
@ -522,16 +520,16 @@ proc ariTraceRecorder(tr: TraceRecorderRef) =
let level = tr.topLevel() let level = tr.topLevel()
# Find entry on DB # Find entry on DB
let state = api.fetchStorageRoot(mpt, accPath, updateOk).valueOr: let state = api.fetchStorageRoot(mpt, accPath).valueOr:
when CoreDbNoisyCaptJournal: when CoreDbNoisyCaptJournal:
debug logTxt $info, level, accPath, updateOk, error debug logTxt $info, level, accPath, error
tr.jLogger(accPath, logRecord(info, TrqFind, error)) tr.jLogger(accPath, logRecord(info, TrqFind, error))
return err(error) return err(error)
tr.jLogger(accPath, logRecord(info, TrqFind, state)) tr.jLogger(accPath, logRecord(info, TrqFind, state))
when CoreDbNoisyCaptJournal: when CoreDbNoisyCaptJournal:
debug logTxt $info, level, accPath, updateOk, state debug logTxt $info, level, accPath, state
ok state ok state
tracerApi.deleteAccountRecord = tracerApi.deleteAccountRecord =

View File

@ -530,21 +530,17 @@ proc hasPath*(
acc.ifTrackNewApi: acc.ifTrackNewApi:
debug logTxt, api, elapsed, accPath=($$accPath), result debug logTxt, api, elapsed, accPath=($$accPath), result
proc stateRoot*(acc: CoreDbAccRef; updateOk = false): CoreDbRc[Hash32] = proc getStateRoot*(acc: CoreDbAccRef): CoreDbRc[Hash32] =
## This function retrieves the Merkle state hash of the accounts ## This function retrieves the Merkle state hash of the accounts
## column (if available.) ## column (if available.)
##
## If the argument `updateOk` is set `true`, the Merkle hashes of the
## database will be updated first (if needed, at all).
##
acc.setTrackNewApi AccStateFn acc.setTrackNewApi AccStateFn
result = block: result = block:
let rc = acc.call(fetchAccountStateRoot, acc.mpt, updateOk) let rc = acc.call(fetchStateRoot, acc.mpt)
if rc.isOk: if rc.isOk:
ok(rc.value) ok(rc.value)
else: else:
err(rc.error.toError $api) err(rc.error.toError $api)
acc.ifTrackNewApi: debug logTxt, api, elapsed, updateOK, result acc.ifTrackNewApi: debug logTxt, api, elapsed, result
# ------------ storage --------------- # ------------ storage ---------------
@ -647,36 +643,32 @@ proc slotMerge*(
debug logTxt, api, elapsed, accPath=($$accPath), debug logTxt, api, elapsed, accPath=($$accPath),
stoPath=($$stoPath), stoData, result stoPath=($$stoPath), stoData, result
proc slotState*( proc slotStorageRoot*(
acc: CoreDbAccRef; acc: CoreDbAccRef;
accPath: Hash32; accPath: Hash32;
updateOk = false;
): CoreDbRc[Hash32] = ): CoreDbRc[Hash32] =
## This function retrieves the Merkle state hash of the storage data ## This function retrieves the Merkle state hash of the storage data
## column (if available) related to the account indexed by the key ## column (if available) related to the account indexed by the key
## `accPath`.`. ## `accPath`.`.
## ##
## If the argument `updateOk` is set `true`, the Merkle hashes of the acc.setTrackNewApi AccSlotStorageRootFn
## database will be updated first (if needed, at all).
##
acc.setTrackNewApi AccSlotStateFn
result = block: result = block:
let rc = acc.call(fetchStorageRoot, acc.mpt, accPath, updateOk) let rc = acc.call(fetchStorageRoot, acc.mpt, accPath)
if rc.isOk: if rc.isOk:
ok(rc.value) ok(rc.value)
else: else:
err(rc.error.toError $api) err(rc.error.toError $api)
acc.ifTrackNewApi: acc.ifTrackNewApi:
debug logTxt, api, elapsed, accPath=($$accPath), updateOk, result debug logTxt, api, elapsed, accPath=($$accPath), result
proc slotStateEmpty*( proc slotStorageEmpty*(
acc: CoreDbAccRef; acc: CoreDbAccRef;
accPath: Hash32; accPath: Hash32;
): CoreDbRc[bool] = ): CoreDbRc[bool] =
## This function returns `true` if the storage data column is empty or ## This function returns `true` if the storage data column is empty or
## missing. ## missing.
## ##
acc.setTrackNewApi AccSlotStateEmptyFn acc.setTrackNewApi AccSlotStorageEmptyFn
result = block: result = block:
let rc = acc.call(hasStorageData, acc.mpt, accPath) let rc = acc.call(hasStorageData, acc.mpt, accPath)
if rc.isOk: if rc.isOk:
@ -686,12 +678,12 @@ proc slotStateEmpty*(
acc.ifTrackNewApi: acc.ifTrackNewApi:
debug logTxt, api, elapsed, accPath=($$accPath), result debug logTxt, api, elapsed, accPath=($$accPath), result
proc slotStateEmptyOrVoid*( proc slotStorageEmptyOrVoid*(
acc: CoreDbAccRef; acc: CoreDbAccRef;
accPath: Hash32; accPath: Hash32;
): bool = ): bool =
## Convenience wrapper, returns `true` where `slotStateEmpty()` would fail. ## Convenience wrapper, returns `true` where `slotStorageEmpty()` would fail.
acc.setTrackNewApi AccSlotStateEmptyOrVoidFn acc.setTrackNewApi AccSlotStorageEmptyOrVoidFn
result = block: result = block:
let rc = acc.call(hasStorageData, acc.mpt, accPath) let rc = acc.call(hasStorageData, acc.mpt, accPath)
if rc.isOk: if rc.isOk:
@ -707,14 +699,13 @@ proc recast*(
acc: CoreDbAccRef; acc: CoreDbAccRef;
accPath: Hash32; accPath: Hash32;
accRec: CoreDbAccount; accRec: CoreDbAccount;
updateOk = false;
): CoreDbRc[Account] = ): CoreDbRc[Account] =
## Complete the argument `accRec` to the portable Ethereum representation ## Complete the argument `accRec` to the portable Ethereum representation
## of an account statement. This conversion may fail if the storage colState ## of an account statement. This conversion may fail if the storage colState
## hash (see `slotState()` above) is currently unavailable. ## hash (see `slotStorageRoot()` above) is currently unavailable.
## ##
acc.setTrackNewApi AccRecastFn acc.setTrackNewApi AccRecastFn
let rc = acc.call(fetchStorageRoot, acc.mpt, accPath, updateOk) let rc = acc.call(fetchStorageRoot, acc.mpt, accPath)
result = block: result = block:
if rc.isOk: if rc.isOk:
ok Account( ok Account(
@ -725,8 +716,8 @@ proc recast*(
else: else:
err(rc.error.toError $api) err(rc.error.toError $api)
acc.ifTrackNewApi: acc.ifTrackNewApi:
let slotState = if rc.isOk: $$(rc.value) else: "n/a" let storageRoot = if rc.isOk: $$(rc.value) else: "n/a"
debug logTxt, api, elapsed, accPath=($$accPath), slotState, result debug logTxt, api, elapsed, accPath=($$accPath), storageRoot, result
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Public transaction related methods # Public transaction related methods

View File

@ -45,9 +45,9 @@ type
AccSlotHasPathFn = "slotHasPath" AccSlotHasPathFn = "slotHasPath"
AccSlotMergeFn = "slotMerge" AccSlotMergeFn = "slotMerge"
AccSlotProofFn = "slotProof" AccSlotProofFn = "slotProof"
AccSlotStateFn = "slotState" AccSlotStorageRootFn = "slotStorageRoot"
AccSlotStateEmptyFn = "slotStateEmpty" AccSlotStorageEmptyFn = "slotStorageEmpty"
AccSlotStateEmptyOrVoidFn = "slotStateEmptyOrVoid" AccSlotStorageEmptyOrVoidFn = "slotStorageEmptyOrVoid"
AccSlotPairsIt = "slotPairs" AccSlotPairsIt = "slotPairs"
BaseFinishFn = "finish" BaseFinishFn = "finish"

View File

@ -371,13 +371,11 @@ proc init*(x: typedesc[LedgerRef], db: CoreDbRef): LedgerRef =
init(x, db, false) init(x, db, false)
proc getStateRoot*(ac: LedgerRef): Hash32 = proc getStateRoot*(ac: LedgerRef): Hash32 =
const info = "state(): "
# make sure all savepoint already committed # make sure all savepoint already committed
doAssert(ac.savePoint.parentSavepoint.isNil) doAssert(ac.savePoint.parentSavepoint.isNil)
# make sure all cache already committed # make sure all cache already committed
doAssert(ac.isDirty == false) doAssert(ac.isDirty == false)
ac.ledger.stateRoot(updateOk=true).valueOr: ac.ledger.getStateRoot().expect("working database")
raiseAssert info & $$error
proc isTopLevelClean*(ac: LedgerRef): bool = proc isTopLevelClean*(ac: LedgerRef): bool =
## Getter, returns `true` if all pending data have been commited. ## Getter, returns `true` if all pending data have been commited.
@ -514,7 +512,7 @@ proc contractCollision*(ac: LedgerRef, address: Address): bool =
return return
acc.statement.nonce != 0 or acc.statement.nonce != 0 or
acc.statement.codeHash != EMPTY_CODE_HASH or acc.statement.codeHash != EMPTY_CODE_HASH or
not ac.ledger.slotStateEmptyOrVoid(acc.toAccountKey) not ac.ledger.slotStorageEmptyOrVoid(acc.toAccountKey)
proc accountExists*(ac: LedgerRef, address: Address): bool = proc accountExists*(ac: LedgerRef, address: Address): bool =
let acc = ac.getAccount(address, false) let acc = ac.getAccount(address, false)
@ -600,7 +598,7 @@ proc clearStorage*(ac: LedgerRef, address: Address) =
let acc = ac.getAccount(address) let acc = ac.getAccount(address)
acc.flags.incl {Alive, NewlyCreated} acc.flags.incl {Alive, NewlyCreated}
let empty = ac.ledger.slotStateEmpty(acc.toAccountKey).valueOr: return let empty = ac.ledger.slotStorageEmpty(acc.toAccountKey).valueOr: return
if not empty: if not empty:
# need to clear the storage from the database first # need to clear the storage from the database first
let acc = ac.makeDirty(address, cloneStorage = false) let acc = ac.makeDirty(address, cloneStorage = false)
@ -733,14 +731,14 @@ iterator accounts*(ac: LedgerRef): Account =
doAssert(ac.savePoint.parentSavepoint.isNil) doAssert(ac.savePoint.parentSavepoint.isNil)
for _, acc in ac.savePoint.cache: for _, acc in ac.savePoint.cache:
yield ac.ledger.recast( yield ac.ledger.recast(
acc.toAccountKey, acc.statement, updateOk=true).value acc.toAccountKey, acc.statement).value
iterator pairs*(ac: LedgerRef): (Address, Account) = iterator pairs*(ac: LedgerRef): (Address, Account) =
# make sure all savepoint already committed # make sure all savepoint already committed
doAssert(ac.savePoint.parentSavepoint.isNil) doAssert(ac.savePoint.parentSavepoint.isNil)
for address, acc in ac.savePoint.cache: for address, acc in ac.savePoint.cache:
yield (address, ac.ledger.recast( yield (address, ac.ledger.recast(
acc.toAccountKey, acc.statement, updateOk=true).value) acc.toAccountKey, acc.statement).value)
iterator storage*( iterator storage*(
ac: LedgerRef; ac: LedgerRef;
@ -771,7 +769,7 @@ proc getStorageRoot*(ac: LedgerRef, address: Address): Hash32 =
# the storage root will not be updated # the storage root will not be updated
let acc = ac.getAccount(address, false) let acc = ac.getAccount(address, false)
if acc.isNil: EMPTY_ROOT_HASH if acc.isNil: EMPTY_ROOT_HASH
else: ac.ledger.slotState(acc.toAccountKey).valueOr: EMPTY_ROOT_HASH else: ac.ledger.slotStorageRoot(acc.toAccountKey).valueOr: EMPTY_ROOT_HASH
proc update(wd: var WitnessData, acc: AccountRef) = proc update(wd: var WitnessData, acc: AccountRef) =
# once the code is touched make sure it doesn't get reset back to false in another update # once the code is touched make sure it doesn't get reset back to false in another update

View File

@ -189,14 +189,14 @@ proc traceTransactionImpl(
before.captureAccount(stateDb, miner, minerName) before.captureAccount(stateDb, miner, minerName)
stateDb.persist() stateDb.persist()
stateDiff["beforeRoot"] = %(stateDb.getStateRoot().toHex) stateDiff["beforeRoot"] = %(stateDb.getStateRoot().toHex)
discard com.db.ctx.getAccounts.stateRoot(updateOk=true) # lazy hashing! discard com.db.ctx.getAccounts.getStateRoot() # lazy hashing!
stateCtx = CaptCtxRef.init(com, stateDb.getStateRoot()) stateCtx = CaptCtxRef.init(com, stateDb.getStateRoot())
let rc = vmState.processTransaction(tx, sender, header) let rc = vmState.processTransaction(tx, sender, header)
gasUsed = if rc.isOk: rc.value else: 0 gasUsed = if rc.isOk: rc.value else: 0
if idx.uint64 == txIndex: if idx.uint64 == txIndex:
discard com.db.ctx.getAccounts.stateRoot(updateOk=true) # lazy hashing! discard com.db.ctx.getAccounts.getStateRoot() # lazy hashing!
after.captureAccount(stateDb, sender, senderName) after.captureAccount(stateDb, sender, senderName)
after.captureAccount(stateDb, recipient, recipientName) after.captureAccount(stateDb, recipient, recipientName)
after.captureAccount(stateDb, miner, minerName) after.captureAccount(stateDb, miner, minerName)

View File

@ -59,7 +59,7 @@ proc parseEnv(node: JsonNode): TestEnv =
result.pre = node["pre"] result.pre = node["pre"]
proc rootExists(db: CoreDbRef; root: Hash32): bool = proc rootExists(db: CoreDbRef; root: Hash32): bool =
let state = db.ctx.getAccounts().stateRoot(updateOk=true).valueOr: let state = db.ctx.getAccounts().getStateRoot().valueOr:
return false return false
state == root state == root