offline wallets sign transactions using KeyID
authorThomasV <thomasv@gitorious>
Mon, 25 Feb 2013 08:05:45 +0000 (09:05 +0100)
committerThomasV <thomasv@gitorious>
Mon, 25 Feb 2013 08:05:45 +0000 (09:05 +0100)
electrum
lib/bitcoin.py
lib/wallet.py

index 12cf2ed..4fc1b21 100755 (executable)
--- a/electrum
+++ b/electrum
@@ -636,7 +636,11 @@ if __name__ == '__main__':
             r, h = wallet.sendtx( tx )
             print_msg(h)
         else:
-            print_json({"hex":str(tx), "complete":tx.is_complete})
+            out = {"hex":str(tx), "complete":tx.is_complete}
+            if not tx.is_complete: 
+                import json
+                out['input_info'] = repr(tx.inputs_info).replace(' ','')
+            print_json(out)
 
         if is_temporary:
             wallet.imported_keys.pop(from_addr)
@@ -732,41 +736,55 @@ if __name__ == '__main__':
 
     elif cmd == 'signrawtransaction':
         tx = Transaction(args[1])
-        txouts = ast.literal_eval(args[2]) if len(args)>2 else []
+        inputs_info = ast.literal_eval(args[2]) if len(args)>2 else []
         private_keys = ast.literal_eval(args[3]) if len(args)>3 else {}
         unspent_coins = wallet.get_unspent_coins()
 
+        # convert private_keys to dict 
+        pk = {}
+        for sec in private_keys:
+            address = bitcoin.address_from_private_key(sec)
+            pk[address] = sec
+        private_keys = pk
+
         for txin in tx.inputs:
             # convert to own format
             txin['tx_hash'] = txin['prevout_hash']
             txin['index'] = txin['prevout_n']
 
-            for txout in txouts:
-                if txout.get('txid') == txin['tx_hash'] and txout.get('vout') == txin['index']:
-                    txin['raw_output_script'] = txout['scriptPubKey']
-                    txin['redeemScript'] = txout['redeemScript']
+            for item in inputs_info:
+                if item.get('txid') == txin['tx_hash'] and item.get('vout') == txin['index']:
+                    txin['raw_output_script'] = item['scriptPubKey']
+                    txin['redeemScript'] = item.get('redeemScript')
+                    txin['electrumKeyID'] = item.get('electrumKeyID')
                     break
-                
             else:
                 for item in unspent_coins:
                     if txin['tx_hash'] == item['tx_hash'] and txin['index'] == item['index']:
-                        txin['address'] = item['address']
                         txin['raw_output_script'] = item['raw_output_script']
                         break
                 else:
                     # if neither, we might want to get it from the server..
                     raise
 
-        if not private_keys:
-            for txin in tx.inputs:
-                addr = txin['address']
-                private_keys[addr] = wallet.get_private_key(addr, password)
-        else:
-            pk = {}
-            for sec in private_keys:
+            # find the address:
+            from lib import deserialize
+            if txin.get('electrumKeyID'):
+                n, for_change = txin.get('electrumKeyID')
+                sec = wallet.sequence.get_private_key(n, for_change, seed)
                 address = bitcoin.address_from_private_key(sec)
-                pk[address] = sec
-            private_keys = pk
+                txin['address'] = address
+                private_keys[address] = sec
+
+            elif txin.get("redeemScript"):
+                txin['address'] = hash_160_to_bc_address(hash_160(txin.get("redeemScript").decode('hex')), 5)
+
+            elif txin.get("raw_output_script"):
+                addr = deserialize.get_address_from_output_script(txin.get("raw_output_script").decode('hex'))
+                sec = wallet.get_private_key(addr, password)
+                if sec: 
+                    private_keys[addr] = sec
+                    txin['address'] = addr
 
         tx.sign( private_keys )
         print_json({ "hex":str(tx),"complete":tx.is_complete})
index a00b88d..a7b6a02 100644 (file)
@@ -479,6 +479,12 @@ class Transaction:
         self.is_complete = False
         self.inputs = inputs
         self.outputs = outputs
+        extras = []
+        for i in self.inputs:
+            print i
+            e = { 'txid':i['tx_hash'], 'vout':i['index'],'scriptPubKey':i['raw_output_script'] }
+            extras.append(e)
+        self.inputs_info = extras
         return self
 
     def __str__(self):
index 6da01bb..b3599ae 100644 (file)
@@ -190,7 +190,7 @@ class Wallet:
     def get_master_public_key(self):
         return self.sequence.master_public_key
 
-    def get_public_key(self, address):
+    def get_address_index(self, address):
         if address in self.imported_keys.keys():
             raise BaseException("imported key")
 
@@ -200,7 +200,10 @@ class Wallet:
         elif address in self.change_addresses:
             n = self.change_addresses.index(address)
             for_change = True
+        return n,for_change
 
+    def get_public_key(self, address):
+        n, for_change = self.get_address_index(address)
         return self.sequence.get_pubkey(n, for_change)
 
 
@@ -666,6 +669,11 @@ class Wallet:
         outputs = self.add_tx_change(outputs, amount, fee, total, change_addr)
 
         tx = Transaction.from_io(inputs, outputs)
+        for i in range(len(tx.inputs)):
+            addr = tx.inputs[i]['address']
+            n, is_change = self.get_address_index(addr)
+            tx.inputs_info[i]['electrumKeyID'] = (n, is_change)
+
         if not self.seed:
             return tx