Merge branch 'master' of github.com:spesmilo/electrum
authorthomasv <thomasv@gitorious>
Wed, 20 Feb 2013 12:10:38 +0000 (13:10 +0100)
committerthomasv <thomasv@gitorious>
Wed, 20 Feb 2013 12:10:38 +0000 (13:10 +0100)
electrum
lib/__init__.py
lib/bitcoin.py
lib/util.py

index 0d7aab4..b1e707b 100755 (executable)
--- a/electrum
+++ b/electrum
@@ -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',
     }
 
 
@@ -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):
@@ -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()
index dd81894..191806d 100644 (file)
@@ -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
index d666c2f..c935d80 100644 (file)
@@ -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
index a85e1b5..a76be6b 100644 (file)
@@ -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 platform.release() != "XP":