import stew/ranges/[ptr_arith, typedranges, bitranges], eth/rlp/types, trie_defs, db, binaries, trie_utils export types, trie_utils type DB = TrieDatabaseRef BinaryTrie* = object db: DB rootHash: TrieNodeKey NodeOverrideError* = object of Exception let zeroHash* = zeroBytesRange proc init*(x: typedesc[BinaryTrie], db: DB, rootHash: BytesContainer | KeccakHash = zeroHash): BinaryTrie = checkValidHashZ(rootHash) result.db = db result.rootHash = toRange(rootHash) proc getDB*(t: BinaryTrie): auto = t.db proc initBinaryTrie*(db: DB, rootHash: BytesContainer | KeccakHash): BinaryTrie = init(BinaryTrie, db, rootHash) proc initBinaryTrie*(db: DB): BinaryTrie = init(BinaryTrie, db, zeroHash) proc getRootHash*(self: BinaryTrie): TrieNodeKey {.inline.} = self.rootHash template fetchNode(self: BinaryTrie, nodeHash: TrieNodeKey): TrieNode = doAssert(nodeHash.len == 32) parseNode self.db.get(nodeHash.toOpenArray).toRange proc getAux(self: BinaryTrie, nodeHash: TrieNodeKey, keyPath: TrieBitRange): BytesRange = # Empty trie if isZeroHash(nodeHash): return zeroBytesRange let node = self.fetchNode(nodeHash) # Key-value node descend if node.kind == LEAF_TYPE: if keyPath.len != 0: return zeroBytesRange return node.value elif node.kind == KV_TYPE: # keyPath too short if keyPath.len == 0: return zeroBytesRange let sliceLen = min(node.keyPath.len, keyPath.len) if keyPath[0.. (k1 + k2, NODE) if subNode.kind == KV_TYPE: # exploit subNode.keyPath unused prefix bit # to avoid bitVector concat subNode.keyPath.pushFront(blankLeft) result = self.saveKV(subNode.keyPath, subNode.child) # kv node pointing to a branch node elif subNode.kind in {BRANCH_TYPE, LEAF_TYPE}: result = self.saveKV(blankLeft, childNode) else: result = self.saveBranch(newLeftChild, newRightChild) proc setKVNode(self: BinaryTrie, keyPath: TrieBitRange, nodeHash: TrieNodeKey, node: TrieNode, value: BytesRange, deleteSubtrie = false): TrieNodeKey = # keyPath prefixes match if deleteSubtrie: if keyPath.len < node.keyPath.len and keyPath == node.keyPath[0..