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:
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):
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
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
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:
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
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
word = target
key = ''
path = [ '' ]
- i = self.db_tree.iterator()
+ i = self.db_utxo.iterator()
while key != target:
# 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)
# 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()
word = target
key = ''
path = [ '' ]
- i = self.db_tree.iterator(start='')
+ i = self.db_utxo.iterator(start='')
while key != target:
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
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)
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()
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))
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)
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()
self.add_address(key + txo, value, tx_height)
# backlink
- self.db.put(txo, key)
+ self.db_addr.put(txo, key)
self.delete_address(key + txo)
# backlink
- self.db.delete(txo)
+ self.db_addr.delete(txo)
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)
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)