def listunspent(self, addr): key = self.address_to_key(addr) if key is None: raise BaseException('Invalid ulord address', addr) out = [] with self.db_utxo.lock: for k, v in self.db_utxo.db.iterator(start=key): if not k.startswith(key): break if len(k) == KEYLENGTH: txid = k[20:52].encode('hex') txpos = hex_to_int(k[52:56]) h = hex_to_int(v[8:12]) v = hex_to_int(v[0:8]) out.append({ 'tx_hash': txid, 'tx_pos': txpos, 'height': h, 'value': v }) if len(out) == 1000: print_log('addr has large amount of utxos', addr) out.sort(key=lambda x: x['height']) return out
def get_outpoint_from_claim_id(self, claim_id): txid_nout = self.db_claim_outpoint.get(claim_id) if txid_nout is None: return None txid = txid_nout[0:64] nout = hex_to_int(txid_nout[64:72].decode('hex')) amount = hex_to_int(txid_nout[72:88].decode('hex')) return txid, nout, amount
def set_spent(self, addr, txi, txid, index, height, undo): key = self.address_to_key(addr) leaf = key + txi s = self.delete_key(leaf) value = hex_to_int(s[0:8]) in_height = hex_to_int(s[8:12]) undo[leaf] = value, in_height # delete backlink txi-> addr self.db_addr.delete(txi) # add to history s = self.db_hist.get(addr) if s is None: s = '' txo = (txid + int_to_hex(index, 4) + int_to_hex(height, 4)).decode('hex') s += txi + int_to_hex(in_height, 4).decode('hex') + txo self.db_hist.put(addr, s)
def get_history(self, addr): out = [] o = self.listunspent(addr) for item in o: out.append((item['height'], item['tx_hash'])) h = self.db_hist.get(addr) if h: for item in re.findall('.{80}', h, flags=re.DOTALL): txi = item[0:32].encode('hex') hi = hex_to_int(item[36:40]) txo = item[40:72].encode('hex') ho = hex_to_int(item[76:80]) out.append((hi, txi)) out.append((ho, txo)) # uniqueness out = set(out) # sort by height then tx_hash out = sorted(out) return map(lambda x: {'height': x[0], 'tx_hash': x[1]}, out)
def delete_key(self, leaf): path = self.get_path(leaf) #print_log("delete key", leaf.encode('hex'), map(lambda x: x.encode('hex'), path)) s = self.db_utxo.get(leaf) self.db_utxo.delete(leaf) if leaf in self.hash_list: self.hash_list.pop(leaf) parent = path[-1] letter = leaf[len(parent)] parent_node = self.get_node(parent) parent_node.remove(letter) # remove key if it has a single child if parent_node.is_singleton(parent) and parent != '': # print "deleting parent", parent.encode('hex') self.db_utxo.delete(parent) if parent in self.hash_list: self.hash_list.pop(parent) l = parent_node.get_singleton() _hash, value = parent_node.get(l) skip = self.get_skip(parent + l) otherleaf = parent + l + skip gp = path[-2] gp_items = self.get_node(gp) letter = otherleaf[len(gp)] new_skip = otherleaf[len(gp) + 1:] gp_items.set(letter, None, 0) self.set_skip(gp + letter, new_skip) # print "gp new_skip", gp.encode('hex'), new_skip.encode('hex') self.put_node(gp, gp_items) # note: k is not necessarily a leaf if len(otherleaf) == KEYLENGTH: ss = self.db_utxo.get(otherleaf) _hash, value = otherleaf[20:52], hex_to_int(ss[0:8]) else: _hash, value = None, None self.update_node_hash(otherleaf, path[:-1], _hash, value) else: self.put_node(parent, parent_node) _hash, value = None, None self.update_node_hash(parent, path[:-1], _hash, value) return s
def get_hash(self, x, parent): if x: assert self.k != 0 skip_string = x[len(parent) + 1:] if x != '' else '' x = 0 v = 0 hh = '' for i in xrange(256): if (self.k & (1 << i)) != 0: ss = self.s[x:x + 40] hh += ss[0:32] v += hex_to_int(ss[32:40]) x += 40 try: _hash = Hash(skip_string + hh) except: _hash = None if x: assert self.k != 0 return _hash, v
def get(self, c): x = self.indexof(c) ss = self.s[x:x + 40] _hash = ss[0:32] value = hex_to_int(ss[32:40]) return _hash, value
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