fix for notifications
[electrum-nvc.git] / scripts / validate_tx
index f09c407..8904c5b 100755 (executable)
@@ -2,61 +2,20 @@
 
 import sys, hashlib
 from electrum import Interface
+from electrum.bitcoin import Hash, rev_hex, int_to_hex, hash_encode, hash_decode
 
 """validate a transaction (SPV)"""
 
-
-Hash = lambda x: hashlib.sha256(hashlib.sha256(x).digest()).digest()
-
-def rev_hex(s):
-    return s.decode('hex')[::-1].encode('hex')
-
-def int_to_hex(i, length=1):
-    s = hex(i)[2:].rstrip('L')
-    s = "0"*(2*length - len(s)) + s
-    return rev_hex(s)
-
-
 i = Interface({'server':'ecdsa.org:50002:s'})
 i.start()
 
 
-def get_header(i, block_height):
-    i.send([('blockchain.block.get_header',[block_height])])
-    while True:
-        r = i.responses.get(True, 100000000000)
-        method = r.get('method') 
-        if method == 'blockchain.block.get_header':
-            break
-    return r.get('result')
-
-
-
-def get_merkle(i, tx_hash):
-
-    i.send([('blockchain.transaction.get_merkle',[tx_hash])])
-    while True:
-        r = i.responses.get(True, 100000000000)
-        method = r.get('method') 
-        if method == 'blockchain.transaction.get_merkle':
-            break
-
-    return r.get('result')
-
-
-def merkle_root(merkle):
-
-    merkle = map (lambda tx_hash: tx_hash.decode('hex')[::-1], merkle)
-    while len(merkle) != 1:
-        if len(merkle)%2: merkle.append( merkle[-1] )
-        n = []
-        while merkle:
-            n.append( Hash( merkle[0] + merkle[1] ) )
-            merkle = merkle[2:]
-
-        merkle = n
-            
-    return merkle[0][::-1].encode('hex')
+def hash_merkle_root(merkle_s, target_hash, pos):
+    h = hash_decode(target_hash)
+    for i in range(len(merkle_s)):
+        item = merkle_s[i]
+        h = Hash( hash_decode(item) + h ) if ((pos >> i) & 1) else Hash( h + hash_decode(item) )
+    return hash_encode(h)
 
 
 def hash_header(res):
@@ -70,19 +29,27 @@ def hash_header(res):
 
 
 def verify_tx(tx_hash):
-    res = get_merkle(i, tx_hash)
-    assert res.get('merkle_root') == merkle_root(res['merkle'])
-    block_height = res.get('block_height')
+    
+    res = i.synchronous_get([ ('blockchain.transaction.get_merkle',[tx_hash]) ])[0]
+    raw_tx = i.synchronous_get([ ('blockchain.transaction.get',[tx_hash, res['block_height']]) ])[0]
+    assert hash_encode(Hash(raw_tx.decode('hex'))) == tx_hash
+
+    merkle_root = hash_merkle_root(res['merkle'], tx_hash, res['pos'])
+    tx_height = res.get('block_height')
+    headers_requests = []
+    for height in range(tx_height-10,tx_height+10):
+        headers_requests.append( ('blockchain.block.get_header',[height]) )
+    headers = i.synchronous_get(headers_requests)
     _hash = None
-    for height in range(block_height-10,block_height+10):
-        header = get_header(i, height)
+    for header in headers:
         if _hash: assert _hash == header.get('prev_block_hash')
         _hash = hash_header(header)
-        #print _hash
-        if height==block_height:
-            assert header.get('merkle_root') == res.get('merkle_root')
-        
-
+        height = header.get('block_height')
+        if height==tx_height:
+            assert header.get('merkle_root') == merkle_root
+            print height, _hash, '*'
+        else:
+            print height, _hash
 
 try:
     tx = sys.argv[1]