X-Git-Url: https://git.novaco.in/?p=electrum-server.git;a=blobdiff_plain;f=backends%2Fbitcoind%2Fstorage.py;h=cca9645eb141b9d161df4e84c5ec095876269bb3;hp=826251d7379830b9a0243690dc0809403d2435bb;hb=b9d74456c47ed3a54c73185d449ff7f23cb6edf4;hpb=edf99953d190264578cd0bab26b7537d9f36c555 diff --git a/backends/bitcoind/storage.py b/backends/bitcoind/storage.py index 826251d..cca9645 100644 --- a/backends/bitcoind/storage.py +++ b/backends/bitcoind/storage.py @@ -22,12 +22,11 @@ class Storage(object): self.shared = shared self.hash_list = {} self.parents = {} - self.root_hash = None self.test_reorgs = test_reorgs try: - self.db_tree = plyvel.DB(os.path.join(self.dbpath,'addr'), create_if_missing=True, compression=None) - self.db = plyvel.DB(os.path.join(self.dbpath,'utxo'), create_if_missing=True, compression=None) + self.db_utxo = plyvel.DB(os.path.join(self.dbpath,'utxo'), create_if_missing=True, compression=None) + self.db_addr = plyvel.DB(os.path.join(self.dbpath,'addr'), create_if_missing=True, compression=None) self.db_hist = plyvel.DB(os.path.join(self.dbpath,'hist'), create_if_missing=True, compression=None) self.db_undo = plyvel.DB(os.path.join(self.dbpath,'undo'), create_if_missing=True, compression=None) except: @@ -55,6 +54,11 @@ class Storage(object): return + # compute root hash + d = self.get_node('') + self.root_hash, v = self.get_node_hash('',d,None) + print_log("UTXO tree root hash:", self.root_hash.encode('hex')) + print_log("Coins in database:", v) # convert between bitcoin addresses and 20 bytes keys used for storage. def address_to_key(self, addr): @@ -64,14 +68,17 @@ class Storage(object): return hash_160_to_bc_address(addr) - def get_address_path(self, addr): + def get_proof(self, addr): key = self.address_to_key(addr) - p = self.get_path(key) - p.append(key) + i = self.db_utxo.iterator(start=key) + k, _ = i.next() + + p = self.get_path(k) + p.append(k) out = [] for item in p: - v = self.db_tree.get(item) + v = self.db_utxo.get(item) out.append((item.encode('hex'), v.encode('hex'))) return out @@ -79,7 +86,7 @@ class Storage(object): def get_balance(self, addr): key = self.address_to_key(addr) - i = self.db_tree.iterator(start=key) + i = self.db_utxo.iterator(start=key) k, _ = i.next() if not k.startswith(key): return 0 @@ -93,7 +100,7 @@ class Storage(object): key = self.address_to_key(addr) out = [] - for k, v in self.db_tree.iterator(start=key): + for k, v in self.db_utxo.iterator(start=key): if not k.startswith(key): break if len(k) == KEYLENGTH: @@ -137,7 +144,7 @@ class Storage(object): def get_address(self, txi): - addr = self.db.get(txi) + addr = self.db_addr.get(txi) return self.key_to_address(addr) if addr else None @@ -183,12 +190,12 @@ class Storage(object): if batch: batch.put(key, out) else: - self.db_tree.put(key, out) + self.db_utxo.put(key, out) def get_node(self, key): - s = self.db_tree.get(key) + s = self.db_utxo.get(key) if s is None: return @@ -215,7 +222,7 @@ class Storage(object): word = target key = '' path = [ '' ] - i = self.db_tree.iterator() + i = self.db_utxo.iterator() while key != target: @@ -263,7 +270,7 @@ class Storage(object): # write s = (int_to_hex(value, 8) + int_to_hex(height,4)).decode('hex') - self.db_tree.put(target, s) + self.db_utxo.put(target, s) # the hash of a node is the txid _hash = target[20:52] self.update_node_hash(target, path, _hash, value) @@ -322,7 +329,7 @@ class Storage(object): # batch write modified nodes - batch = self.db_tree.write_batch() + batch = self.db_utxo.write_batch() for k, v in nodes.items(): self.put_node(k, v, batch) batch.write() @@ -352,7 +359,7 @@ class Storage(object): word = target key = '' path = [ '' ] - i = self.db_tree.iterator(start='') + i = self.db_utxo.iterator(start='') while key != target: @@ -375,7 +382,7 @@ class Storage(object): assert key not in path path.append(key) else: - print_log('not in tree', self.db_tree.get(key+word[0]), new_key.encode('hex')) + print_log('not in tree', self.db_utxo.get(key+word[0]), new_key.encode('hex')) return False else: assert key in path @@ -387,12 +394,12 @@ class Storage(object): def delete_address(self, leaf): path = self.get_path(leaf) if path is False: - print_log("addr not in tree", leaf.encode('hex'), self.key_to_address(leaf[0:20]), self.db_tree.get(leaf)) + print_log("addr not in tree", leaf.encode('hex'), self.key_to_address(leaf[0:20]), self.db_utxo.get(leaf)) raise - s = self.db_tree.get(leaf) + s = self.db_utxo.get(leaf) - self.db_tree.delete(leaf) + self.db_utxo.delete(leaf) if leaf in self.hash_list: self.hash_list.pop(leaf) @@ -405,12 +412,12 @@ class Storage(object): if len(items) == 1: letter, v = items.items()[0] - self.db_tree.delete(parent) + self.db_utxo.delete(parent) if parent in self.hash_list: self.hash_list.pop(parent) # we need the exact length for the iteration - i = self.db_tree.iterator() + i = self.db_utxo.iterator() i.seek(parent+letter) k, v = i.next() @@ -431,7 +438,7 @@ class Storage(object): def get_children(self, x): - i = self.db_tree.iterator() + i = self.db_utxo.iterator() l = 0 while l <256: i.seek(x+chr(l)) @@ -450,7 +457,7 @@ class Storage(object): def get_parent(self, x): """ return parent and skip string""" - i = self.db_tree.iterator() + i = self.db_utxo.iterator() for j in range(len(x)): p = x[0:-j-1] i.seek(p) @@ -471,8 +478,8 @@ class Storage(object): def close(self): - self.db_tree.close() - self.db.close() + self.db_utxo.close() + self.db_addr.close() self.db_hist.close() self.db_undo.close() @@ -485,7 +492,7 @@ class Storage(object): self.add_address(key + txo, value, tx_height) # backlink - self.db.put(txo, key) + self.db_addr.put(txo, key) @@ -497,8 +504,15 @@ class Storage(object): self.delete_address(key + txo) # backlink - self.db.delete(txo) + self.db_addr.delete(txo) + + def get_utxo_value(self, addr, txi): + key = self.address_to_key(addr) + leaf = key + txi + s = self.db_utxo.get(leaf) + value = hex_to_int(s[0:8]) + return value def set_spent(self, addr, txi, txid, index, height, undo): @@ -511,7 +525,7 @@ class Storage(object): undo[leaf] = value, in_height # delete backlink txi-> addr - self.db.delete(txi) + self.db_addr.delete(txi) # add to history s = self.db_hist.get(addr) @@ -528,7 +542,7 @@ class Storage(object): leaf = key + txi # restore backlink - self.db.put(txi, key) + self.db_addr.put(txi, key) v, height = undo.pop(leaf) self.add_address(leaf, v, height)