update protocol
authorThomasV <thomasv1@gmx.de>
Mon, 20 Jan 2014 16:27:20 +0000 (17:27 +0100)
committerThomasV <thomasv1@gmx.de>
Mon, 20 Jan 2014 16:27:20 +0000 (17:27 +0100)
backends/bitcoind/blockchain_processor.py
backends/bitcoind/storage.py

index 459e37f..cf5f609 100644 (file)
@@ -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
index 2aba8bc..7233e26 100644 (file)
@@ -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):