URI: 
       tsupport for multisig functions - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 972ba397d1eca79a3f6eddd4550480a198a6ae60
   DIR parent f971c80d5812b629d00bdd5760a93889a4f6e0ab
  HTML Author: thomasv <thomasv@gitorious>
       Date:   Wed, 20 Feb 2013 13:10:32 +0100
       
       support for multisig functions
       
       Diffstat:
         M electrum                            |      58 +++++++++++++++++++++++++++++--
         M lib/__init__.py                     |       2 +-
         M lib/bitcoin.py                      |      25 ++++++++++++++++++++++---
         M lib/util.py                         |       6 ++++++
       
       4 files changed, 85 insertions(+), 6 deletions(-)
       ---
   DIR diff --git a/electrum b/electrum
       t@@ -91,6 +91,10 @@ options:\n  --fee, -f: set transaction fee\n  --fromaddr, -s: send from address 
            'unfreeze':'',
            'prioritize':'',
            'unprioritize':'',
       +    'createmultisig':'similar to bitcoind\'s command',
       +    'createrawtransaction':'similar to bitcoind\'s command',
       +    'decoderawtransaction':'similar to bitcoind\'s command',
       +    'signrawtransaction':'similar to bitcoind\'s command',
            }
        
        
       t@@ -103,10 +107,12 @@ offline_commands = [ 'password', 'mktx', 'signtx',
                             'importprivkey', 'seed',
                             'deseed','reseed',
                             'freeze','unfreeze',
       -                     'prioritize','unprioritize']
       +                     'prioritize','unprioritize',
       +                     'createmultisig', 'createrawtransaction', 'decoderawtransaction', 'signrawtransaction'
       +                     ]
        
        
       -protected_commands = ['payto', 'password', 'mktx', 'signtx', 'seed', 'importprivkey','signmessage' ]
       +protected_commands = ['payto', 'password', 'mktx', 'signtx', 'seed', 'importprivkey','signmessage', 'signrawtransaction' ]
        
        # get password routine
        def prompt_password(prompt, confirm=True):
       t@@ -690,5 +696,53 @@ if __name__ == '__main__':
                print_msg(wallet.unprioritize(addr))
        
        
       +    elif cmd == 'createmultisig':
       +        import ast
       +        from lib.bitcoin import *
       +        num = int(args[1])
       +        pubkeys = ast.literal_eval(args[2])
       +        assert isinstance(pubkeys,list)
       +        s = multisig_script(pubkeys, num)
       +        out = { "address": hash_160_to_bc_address(hash_160(s.decode('hex')), 5), "redeemScript":s }
       +        print_json(out)
       +    
       +
       +    elif cmd == 'createrawtransaction':
       +        import ast
       +        inputs = ast.literal_eval(args[1])
       +        outputs = ast.literal_eval(args[2])
       +        inputs = map(lambda x: (None, None, x["txid"], x["vout"], None, None), inputs)
       +        outputs = map(lambda x: (x[0],int(x[1]*1e8)), outputs.items())
       +        tx = raw_tx(inputs, outputs, for_sig = -1) # for_sig=-1 means do not sign
       +        print_msg( tx )
       +
       +
       +    elif cmd == 'decoderawtransaction':
       +        print_json( bitcoin.deserialize(args[1]) )
       +
       +
       +    elif cmd == 'signrawtransaction':
       +        d = bitcoin.deserialize(args[1])
       +        txouts = args[2] if len(args)>2 else []
       +        private_keys = args[3] if len(args)>3 else []
       +        
       +        inputs = []
       +        for x in d['inputs']:
       +            txid = x["prevout_hash"]
       +            nout = x["prevout_n"]
       +            tx = wallet.transactions.get(txid)
       +            txout = tx['outputs'][nout]
       +            addr = txout['address']
       +            v = txout['value']
       +            inputs.append( (addr, v, txid, nout, txout['raw_output_script'], [(None,None)] ) )
       +
       +        outputs = map(lambda x: (x['address'],x['value']), d['outputs'])
       +        print_error("inputs", inputs)
       +        print_error("outputs", outputs)
       +
       +        tx = wallet.signed_tx( inputs, outputs, password )
       +        print_msg(tx)
       +        
       +
            if cmd not in offline_commands and not options.offline:
                synchronizer.stop()
   DIR diff --git a/lib/__init__.py b/lib/__init__.py
       t@@ -1,5 +1,5 @@
        from version import ELECTRUM_VERSION
       -from util import format_satoshis, print_msg, print_error, set_verbosity
       +from util import format_satoshis, print_msg, print_json, print_error, set_verbosity
        from i18n import set_language
        from wallet import WalletSynchronizer
        from wallet_factory import WalletFactory as Wallet
   DIR diff --git a/lib/bitcoin.py b/lib/bitcoin.py
       t@@ -378,14 +378,33 @@ def raw_tx( inputs, outputs, for_sig = None ):
                s += var_int( len(tx_filter(script))/2 )                #  script length
                s += script                                             #  script
            s += int_to_hex(0,4)                                        #  lock time
       -    if for_sig is not None: s += int_to_hex(1, 4)               #  hash type
       +    if for_sig is not None and for_sig != 1: s += int_to_hex(1, 4)               #  hash type
            return tx_filter(s)
        
        
       -def multisig_script(public_keys):
       +def deserialize(raw_tx):
       +    import deserialize
       +    vds = deserialize.BCDataStream()
       +    vds.write(raw_tx.decode('hex'))
       +    return deserialize.parse_Transaction(vds)
       +
       +
       +def multisig_script(public_keys, num=None):
            # supports only "2 of 2", and "2 of 3" transactions
            n = len(public_keys)
       -    s = '52'
       +
       +    if num is None:
       +        num = n
       +
       +    assert num <= n and n <= 3 and n >= 2
       +    
       +    if num==2:
       +        s = '52'
       +    elif num == 3:
       +        s = '53'
       +    else:
       +        raise
       +    
            for k in public_keys:
                s += var_int(len(k)/2)
                s += k
   DIR diff --git a/lib/util.py b/lib/util.py
       t@@ -22,6 +22,12 @@ def print_msg(*args):
            sys.stdout.write(" ".join(args) + "\n")
            sys.stdout.flush()
        
       +def print_json(obj):
       +    import json
       +    s = json.dumps(obj,sort_keys = True, indent = 4)
       +    sys.stdout.write(s + "\n")
       +    sys.stdout.flush()
       +
        
        def check_windows_wallet_migration():
            if os.path.exists(os.path.join(os.environ["LOCALAPPDATA"], "Electrum")):