From f80e689bf86e7ca5998884bca0c7160e6ec81ce5 Mon Sep 17 00:00:00 2001 From: ThomasV Date: Mon, 20 Jan 2014 17:27:20 +0100 Subject: [PATCH] update protocol --- backends/bitcoind/blockchain_processor.py | 44 +++++++++++----- backends/bitcoind/storage.py | 80 +++++++++++++++++++++++++---- 2 files changed, 99 insertions(+), 25 deletions(-) diff --git a/backends/bitcoind/blockchain_processor.py b/backends/bitcoind/blockchain_processor.py index 459e37f..cf5f609 100644 --- a/backends/bitcoind/blockchain_processor.py +++ b/backends/bitcoind/blockchain_processor.py @@ -238,6 +238,7 @@ class BlockchainProcessor(Processor): print_log("ERROR: cannot parse", txid) return None + def get_history(self, addr, cache_only=False): with self.cache_lock: hist = self.history_cache.get(addr) @@ -248,8 +249,7 @@ class BlockchainProcessor(Processor): with self.dblock: try: - h = self.storage.get_history(str((addr))) - hist = self.storage.deserialize(h) + hist = self.storage.get_history(addr) is_known = True except: self.shared.stop() @@ -260,19 +260,10 @@ class BlockchainProcessor(Processor): hist = [] is_known = False - # sort history, because redeeming transactions are next to the corresponding txout - hist.sort(key=lambda tup: tup[2]) - # add memory pool with self.mempool_lock: for txid in self.mempool_hist.get(addr, []): - hist.append((txid, 0, 0)) - - # uniqueness - hist = set(map(lambda x: (x[0], x[2]), hist)) - - # convert to dict - hist = map(lambda x: {'tx_hash': x[0], 'height': x[1]}, hist) + hist.append({'tx_hash':txid, 'height':0}) # add something to distinguish between unused and empty addresses if hist == [] and is_known: @@ -282,6 +273,7 @@ class BlockchainProcessor(Processor): self.history_cache[addr] = hist return hist + def get_status(self, addr, cache_only=False): tx_points = self.get_history(addr, cache_only) if cache_only and tx_points == -1: @@ -476,7 +468,7 @@ class BlockchainProcessor(Processor): elif method == 'blockchain.address.subscribe': try: - address = params[0] + address = str(params[0]) result = self.get_status(address, cache_only) except BaseException, e: error = str(e) + ': ' + address @@ -484,12 +476,36 @@ class BlockchainProcessor(Processor): elif method == 'blockchain.address.get_history': try: - address = params[0] + address = str(params[0]) result = self.get_history(address, cache_only) except BaseException, e: error = str(e) + ': ' + address print_log("error:", error) + elif method == 'blockchain.address.get_balance': + try: + address = str(params[0]) + result = self.storage.get_balance(address) + except BaseException, e: + error = str(e) + ': ' + address + print_log("error:", error) + + elif method == 'blockchain.address.get_path': + try: + address = str(params[0]) + result = self.storage.get_address_path(address) + except BaseException, e: + error = str(e) + ': ' + address + print_log("error:", error) + + elif method == 'blockchain.address.listunspent': + try: + address = str(params[0]) + result = self.storage.listunspent(address) + except BaseException, e: + error = str(e) + ': ' + address + print_log("error:", error) + elif method == 'blockchain.block.get_header': if cache_only: result = -1 diff --git a/backends/bitcoind/storage.py b/backends/bitcoind/storage.py index 2aba8bc..7233e26 100644 --- a/backends/bitcoind/storage.py +++ b/backends/bitcoind/storage.py @@ -63,18 +63,76 @@ class Storage(object): return hash_160_to_bc_address(addr) + def get_address_path(self, addr): + key = self.address_to_key(addr) + p = self.get_path(key) + p.append(key) + + out = [] + for item in p: + v = self.db_tree.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) + k, _ = i.next() + if not k.startswith(key): + return 0 + p = self.get_parent(k) + d = self.get_node(p) + letter = k[len(p)] + return d[letter][1] + + + def listunspent(self, addr): + key = self.address_to_key(addr) + + out = [] + for k, v in self.db_tree.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}) + + out.sort(key=lambda x:x['height']) + return out + + def get_history(self, addr): - addr = self.address_to_key(addr) - x = self.db_tree.get(addr) - if x is None: - return '' - try: - _hash, v, h = x - return h - except: - traceback.print_exc(file=sys.stdout) - self.shared.stop() - raise + out = [] + + o = self.listunspent(addr) + for item in o: + out.append((item['tx_hash'], item['height'])) + + h = self.db_hist.get(addr) + + while h: + item = h[0:80] + h = h[80:] + 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((txi, hi)) + out.append((txo, ho)) + + # sort + out.sort(key=lambda x:x[1]) + + # uniqueness + out = set(out) + + return map(lambda x: {'tx_hash':x[0], 'height':x[1]}, out) + def get_address(self, txi): -- 1.7.1