diff --git a/stateless/multi_keys.nim b/stateless/multi_keys.nim index b33948949..48a62e8db 100644 --- a/stateless/multi_keys.nim +++ b/stateless/multi_keys.nim @@ -14,9 +14,10 @@ type of false: storageKeys*: MultikeysRef address*: EthAddress + codeTouched*: bool Multikeys* = object - keys: seq[KeyData] + keys*: seq[KeyData] MultikeysRef* = ref Multikeys @@ -27,7 +28,7 @@ type mask*: uint groups*: array[16, Group] - AccountKey* = tuple[address: EthAddress, storageKeys: MultikeysRef] + AccountKey* = tuple[address: EthAddress, codeTouched: bool, storageKeys: MultikeysRef] MatchGroup* = tuple[match: bool, group: Group] func cmpHash(a, b: KeyHash): int = @@ -64,6 +65,7 @@ proc newMultiKeys*(keys: openArray[AccountKey]): MultikeysRef = storageMode: false, hash: keccak(a.address).data, address: a.address, + codeTouched: a.codeTouched, storageKeys: a.storageKeys) result.keys.sort(cmpHash) @@ -127,18 +129,13 @@ iterator groups*(m: MultikeysRef, depth: int, n: NibblesSeq, parentGroup: Group) haveGroup = false yield (matchResult, groupResult) -func keyData*(m: MultikeysRef, g: Group): KeyData = - doAssert(g.first == g.last) - result = m.keys[g.first] - -iterator keyDatas*(m: MultikeysRef, g: Group): KeyData = +iterator keyDatas*(m: MultikeysRef, g: Group): var KeyData = for i in g.first..g.last: yield m.keys[i] -iterator addresses*(m :MultikeysRef): EthAddress = - for x in m.keys: - yield x.address - iterator storageKeys*(m :MultikeysRef): MultikeysRef = for x in m.keys: yield x.storageKeys + +func match*(kd: KeyData, n: NibblesSeq, depth: int): bool {.inline.} = + compareNibbles(kd.hash, depth, n) diff --git a/stateless/test_block_witness.nim b/stateless/test_block_witness.nim index d83e9d045..cde4b2635 100644 --- a/stateless/test_block_witness.nim +++ b/stateless/test_block_witness.nim @@ -59,9 +59,6 @@ proc setupStateDB(tester: var Tester, wantedState: JsonNode, stateDB: var Accoun storageKeys.add(slot.toBytesBE) stateDB.setStorage(account, slot, fromHex(UInt256, value.getStr)) - var sKeys = if storageKeys.len != 0: newMultiKeys(storageKeys) else: MultikeysRef(nil) - keys.add((account, sKeys)) - let nonce = accountData{"nonce"}.getHexadecimalInt.AccountNonce let code = accountData{"code"}.getStr.safeHexToSeqByte let balance = UInt256.fromHex accountData{"balance"}.getStr @@ -70,6 +67,10 @@ proc setupStateDB(tester: var Tester, wantedState: JsonNode, stateDB: var Accoun stateDB.setCode(account, code) stateDB.setBalance(account, balance) + let sKeys = if storageKeys.len != 0: newMultiKeys(storageKeys) else: MultikeysRef(nil) + let codeTouched = code.len > 0 + keys.add((account, codeTouched, sKeys)) + tester.keys = newMultiKeys(keys) stateDB.persist() result = stateDB.rootHash diff --git a/stateless/test_witness_keys.nim b/stateless/test_witness_keys.nim index 267932c91..7783d033b 100644 --- a/stateless/test_witness_keys.nim +++ b/stateless/test_witness_keys.nim @@ -8,11 +8,12 @@ import type DB = TrieDatabaseRef - StorageKeys = tuple[hash: Hash256, keys: MultikeysRef] + StorageKeys = tuple[storageRoot: Hash256, keys: MultikeysRef] AccountDef = object storageKeys: MultiKeysRef account: Account + codeTouched: bool proc randU256(): UInt256 = var bytes: array[32, byte] @@ -55,13 +56,16 @@ proc randStorage(db: DB): StorageKeys = proc randAccount(db: DB): AccountDef = result.account.nonce = randNonce() result.account.balance = randU256() + let z = randStorage(db) result.account.codeHash = randCode(db) - (result.account.storageRoot, result.storageKeys) = randStorage(db) + result.account.storageRoot = z.storageRoot + result.storageKeys = z.keys + result.codeTouched = rand(0..1) == 0 proc randAddress(): EthAddress = discard randomBytes(result.addr, sizeof(result)) -proc runTest(numPairs: int, testStatusIMPL: var TestStatus) = +proc runTest(numPairs: int, testStatusIMPL: var TestStatus, useRogueKeys: static[bool] = false) = var memDB = newMemoryDB() var trie = initSecureHexaryTrie(memDB) var addrs = newSeq[AccountKey](numPairs) @@ -69,10 +73,15 @@ proc runTest(numPairs: int, testStatusIMPL: var TestStatus) = for i in 0.. 32 + test "rogue address ignored": + runTest(rand(1..30), testStatusIMPL, useRogueKeys = true) + main() diff --git a/stateless/witness_from_tree.nim b/stateless/witness_from_tree.nim index 432df9426..d60e53f6c 100644 --- a/stateless/witness_from_tree.nim +++ b/stateless/witness_from_tree.nim @@ -201,13 +201,18 @@ proc getBranchRecurseAux(wb: var WitnessBuilder, z: var StackElem) = ) getBranchRecurseAux(wb, zz) else: - let kd = keyData(z.keys, mg.group) - if z.storageMode: - doAssert(kd.storageMode) - writeAccountStorageLeafNode(wb, kd.storageSlot, value.toBytes.decode(UInt256), k, z.node, z.depth) - else: - doAssert(not kd.storageMode) - writeAccountNode(wb, kd.storageKeys, kd.address, value.toBytes.decode(Account), k, z.node, z.depth) + # this should be only one match + # if there is more than one match + # it means we encounter a rogue address + for kd in keyDatas(z.keys, mg.group): + if not match(kd, k, z.depth): continue # this is the rogue address + kd.visited = true + if z.storageMode: + doAssert(kd.storageMode) + writeAccountStorageLeafNode(wb, kd.storageSlot, value.toBytes.decode(UInt256), k, z.node, z.depth) + else: + doAssert(not kd.storageMode) + writeAccountNode(wb, kd.storageKeys, kd.address, value.toBytes.decode(Account), k, z.node, z.depth) if not match: writeHashNode(wb, keccak(z.node).data) of 17: