toffline wallets sign transactions using KeyID - electrum - Electrum Bitcoin wallet
 (HTM) git clone https://git.parazyd.org/electrum
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Submodules
       ---
 (DIR) commit b8a71ff00cdf025eefea637f4c1b23516dccb76e
 (DIR) parent c4f7ce6baea95e26a8ca5c56485d06e7144a1ca7
 (HTM) Author: ThomasV <thomasv@gitorious>
       Date:   Mon, 25 Feb 2013 09:05:45 +0100
       
       offline wallets sign transactions using KeyID
       
       Diffstat:
         M electrum                            |      52 +++++++++++++++++++++----------
         M lib/bitcoin.py                      |       6 ++++++
         M lib/wallet.py                       |      10 +++++++++-
       
       3 files changed, 50 insertions(+), 18 deletions(-)
       ---
 (DIR) diff --git a/electrum b/electrum
       t@@ -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)
       t@@ -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})
 (DIR) diff --git a/lib/bitcoin.py b/lib/bitcoin.py
       t@@ -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):
 (DIR) diff --git a/lib/wallet.py b/lib/wallet.py
       t@@ -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")
        
       t@@ -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)
        
        
       t@@ -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