Skip to content

Commit

Permalink
Completed initial implementation of witness verification.
Browse files Browse the repository at this point in the history
  • Loading branch information
bhartnett committed Dec 29, 2023
1 parent b731202 commit 193952a
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 27 deletions.
21 changes: 1 addition & 20 deletions fluffy/network/state/experimental/state_proof_generation.nim
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,4 @@ proc generateStorageProof*(
state: StorageState,
slotKey: UInt256): StorageProof {.raises: [RlpError].} =
let key = keccakHash(toBytesBE(slotKey)).data
state.getBranch(key).StorageProof

# We might want to use these procs below for interim nodes.
# Supplying a partial key will give all the trie nodes leading up to the key.
# To generate a partial key, hash the full account address or slotKey then truncate it.
# Supplying an empty string as the key will return the root node.
# Avoid using unless required.
# It's not yet clear to me how we can verify these interim nodes because
# they will return as a MissingKey result in the proof verification.
proc generateAccountProof*(
state: AccountState,
key: openArray[byte]): AccountProof {.raises: [RlpError].} =
state.getBranch(key).AccountProof

proc generateStorageProof*(
state: StorageState,
key: openArray[byte]): StorageProof {.raises: [RlpError].} =
state.getBranch(key).StorageProof


state.getBranch(key).StorageProof
12 changes: 9 additions & 3 deletions fluffy/network/state/experimental/state_proof_types.nim
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@

{.push raises: [].}

import
eth/trie
import eth/[common, trie]


type
Expand All @@ -19,6 +18,13 @@ type
AccountProof* = distinct MptProof
StorageProof* = distinct MptProof

Witness* = seq[byte]

AccountData* = object
account*: Account
code* : seq[byte]
storage*: TableRef[UInt256, UInt256]


proc getBranch*(
self: AccountState;
Expand All @@ -30,4 +36,4 @@ proc getBranch*(
self: StorageState;
key: openArray[byte]): seq[seq[byte]] {.borrow.}

proc rootHash*(self: StorageState): KeccakHash {.borrow.}
proc rootHash*(self: StorageState): KeccakHash {.borrow.}
60 changes: 57 additions & 3 deletions fluffy/network/state/experimental/state_proof_verification.nim
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@
{.push raises: [].}

import
std/sequtils,
std/[sequtils, tables],
stint,
eth/[common, rlp, trie/hexary_proof_verification],
stew/results,
./state_proof_types
./state_proof_types,
../../../../stateless/[tree_from_witness, witness_types],
../../../../nimbus/db/[core_db, state_db, state_db/base]

export results


proc verifyAccount*(
trustedStateRoot: KeccakHash,
address: EthAddress,
Expand Down Expand Up @@ -62,3 +63,56 @@ func verifyContractBytecode*(
ok()
else:
err("hash of bytecode doesn't match the expected code hash")

proc buildAccountsTableFromKeys(
db: ReadOnlyStateDB,
keys: openArray[AccountAndSlots]): TableRef[EthAddress, AccountData] {.raises: [RlpError].} =

var accounts = newTable[EthAddress, AccountData]()

for key in keys:
let account = db.getAccount(key.address)
let code = if key.codeLen > 0:
db.AccountStateDB.kvt().get(account.codeHash.data)
else: @[]
var storage = newTable[UInt256, UInt256]()

if code.len() > 0:
for slot in key.slots:
let slotKey = fromBytesBE(UInt256, slot)
let (slotValue, slotExists) = db.getStorage(key.address, slotKey)
if slotExists:
storage[slotKey] = slotValue

accounts[key.address] = AccountData(
account: account,
code: code,
storage: storage)

return accounts

proc verifyWitness*(
trustedStateRoot: KeccakHash,
witness: Witness): Result[TableRef[EthAddress, AccountData], string] =

let db: CoreDbRef = newCoreDbRef(LegacyDbMemory)
var tb = initTreeBuilder(witness, db, {wfEIP170}) # what flags to use here?

try:
let stateRoot = tb.buildTree()
if stateRoot != trustedStateRoot:
return err("witness stateRoot doesn't match trustedStateRoot")

let ac = newAccountStateDB(db, trustedStateRoot, false)
let accounts = buildAccountsTableFromKeys(ReadOnlyStateDB(ac), tb.keys)
ok(accounts)
except Exception as e:
err(e.msg)








2 changes: 1 addition & 1 deletion stateless/tree_from_witness.nim
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ type
db: DB
root: KeccakHash
flags: WitnessFlags
keys: seq[AccountAndSlots]
keys*: seq[AccountAndSlots]

# this TreeBuilder support short node parsing
# but a block witness should not contains short node
Expand Down

0 comments on commit 193952a

Please sign in to comment.