import "."/[trie_bitseq, trie_defs, db, binaries, trie_utils] export trie_utils type DB = TrieDatabaseRef BinaryTrie* = object db: DB rootHash: TrieNodeKey NodeOverrideError* = object of CatchableError const zeroHash* = default(seq[byte]) proc init*(x: typedesc[BinaryTrie], db: DB, rootHash: openArray[byte]): BinaryTrie = checkValidHashZ(rootHash) result.db = db result.rootHash = @(rootHash) proc getDB*(t: BinaryTrie): auto = t.db proc initBinaryTrie*(db: DB, rootHash: openArray[byte]): 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) proc getAux(self: BinaryTrie, nodeHash: TrieNodeKey, keyPath: TrieBitSeq): seq[byte] = # Empty trie if isZeroHash(nodeHash): return let node = self.fetchNode(nodeHash) # Key-value node descend if node.kind == LEAF_TYPE: if keyPath.len != 0: return return node.value elif node.kind == KV_TYPE: # keyPath too short if keyPath.len == 0: return 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: TrieBitSeq, nodeHash: TrieNodeKey, node: TrieNode, value: openArray[byte], deleteSubtrie = false): TrieNodeKey = # keyPath prefixes match if deleteSubtrie: if keyPath.len < node.keyPath.len and keyPath == node.keyPath[0..