|
@@ -1,25 +1,39 @@
|
|
|
#!/usr/bin/env python
|
|
|
+# Convert MMGen 'v1' transaction file (extension '.raw' or '.sig')
|
|
|
+# to MMGen 'v3' ('.rawtx' or '.sigtx' + amounts as strings)
|
|
|
|
|
|
import sys,os
|
|
|
repo_root = os.path.split(os.path.abspath(os.path.dirname(sys.argv[0])))[0]
|
|
|
sys.path = [repo_root] + sys.path
|
|
|
|
|
|
from mmgen.common import *
|
|
|
-from mmgen.tx import *
|
|
|
|
|
|
opts_data = lambda: {
|
|
|
- 'desc': "Convert MMGen transaction file from old format to new format",
|
|
|
+ 'desc': "Convert MMGen transaction file from v1 format to v3 format",
|
|
|
'usage': "<tx file>",
|
|
|
'options': """
|
|
|
--h, --help Print this help message
|
|
|
--S, --stdout Write data to STDOUT instead of file
|
|
|
+-h, --help Print this help message
|
|
|
+-d, --outdir=d Output files to directory 'd' instead of working dir
|
|
|
+-q, --quiet Write (and overwrite) files without prompting
|
|
|
+-S, --stdout Write data to STDOUT instead of file
|
|
|
"""
|
|
|
}
|
|
|
|
|
|
cmd_args = opts.init(opts_data)
|
|
|
|
|
|
+from mmgen.tx import *
|
|
|
+
|
|
|
if len(cmd_args) != 1: opts.usage()
|
|
|
def parse_tx_file(infile):
|
|
|
+ from ast import literal_eval
|
|
|
+
|
|
|
+ def eval_io_data(raw_data,desc):
|
|
|
+ import re
|
|
|
+ d = literal_eval(re.sub(r"[A-Za-z]+?\(('.+?')\)",r'\1',raw_data))
|
|
|
+ assert type(d) == list,'{} data not a list!'.format(desc)
|
|
|
+ assert len(d),'no {}!'.format(desc)
|
|
|
+ for e in d: e['amount'] = g.proto.coin_amt(e['amount'])
|
|
|
+ return d
|
|
|
|
|
|
err_fmt = 'Invalid {} in transaction file'
|
|
|
tx_data = get_lines_from_file(infile)
|
|
@@ -37,9 +51,9 @@ def parse_tx_file(infile):
|
|
|
err_str = 'hex data'
|
|
|
unhexlify(tx_hex)
|
|
|
err_str = 'inputs data'
|
|
|
- inputs = eval(inputs)
|
|
|
+ inputs = eval_io_data(inputs,'inputs')
|
|
|
err_str = 'btc-to-mmgen address map data'
|
|
|
- outputs = eval(outputs)
|
|
|
+ outputs = literal_eval(outputs)
|
|
|
if comment:
|
|
|
from mmgen.bitcoin import b58decode
|
|
|
comment = b58decode(comment)
|
|
@@ -53,17 +67,17 @@ def parse_tx_file(infile):
|
|
|
else:
|
|
|
return metadata.split(),tx_hex,inputs,outputs,comment
|
|
|
|
|
|
-def find_block_by_time(c,timestamp):
|
|
|
+def find_block_by_time(timestamp):
|
|
|
secs = decode_timestamp(timestamp)
|
|
|
- block_num = c.getblockcount()
|
|
|
+ block_num = g.rpch.getblockcount()
|
|
|
# print 'secs:',secs, 'last block:',last_block
|
|
|
top,bot = block_num,0
|
|
|
m = 'Searching for block'
|
|
|
msg_r(m)
|
|
|
for i in range(40):
|
|
|
msg_r('.')
|
|
|
- bhash = c.getblockhash(block_num)
|
|
|
- block = c.getblock(bhash)
|
|
|
+ bhash = g.rpch.getblockhash(block_num)
|
|
|
+ block = g.rpch.getblock(bhash)
|
|
|
# print 'block_num:',block_num, 'mediantime:',block['mediantime'], 'target:',secs
|
|
|
cur_secs = block['mediantime']
|
|
|
if cur_secs > secs:
|
|
@@ -79,33 +93,33 @@ def find_block_by_time(c,timestamp):
|
|
|
|
|
|
tx = MMGenTX()
|
|
|
|
|
|
-metadata,tx.hex,inputs,b2m_map,tx.label = parse_tx_file(cmd_args[0])
|
|
|
+metadata,tx.hex,inputs,outputs,tx.label = parse_tx_file(cmd_args[0])
|
|
|
tx.txid,send_amt,tx.timestamp = metadata
|
|
|
tx.send_amt = Decimal(send_amt)
|
|
|
|
|
|
g.testnet = False
|
|
|
g.rpc_host = 'localhost'
|
|
|
-c = bitcoin_connection()
|
|
|
+rpc_init()
|
|
|
|
|
|
for i in inputs:
|
|
|
if not 'mmid' in i and 'account' in i:
|
|
|
- from mmgen.tw import parse_tw_acct_label
|
|
|
- a,b = parse_tw_acct_label(i['account'])
|
|
|
- if a:
|
|
|
- i['mmid'] = a.decode('utf8')
|
|
|
- if b: i['comment'] = b.decode('utf8')
|
|
|
+ lbl = TwLabel(i['account'])
|
|
|
+ i['mmid'] = lbl.mmid
|
|
|
+ i['comment'] = lbl.comment
|
|
|
|
|
|
-tx.inputs = tx.decode_io_oldfmt(inputs)
|
|
|
+tx.inputs = tx.MMGenTxInputList(tx.decode_io_oldfmt(inputs))
|
|
|
|
|
|
-if tx.marked_signed(c):
|
|
|
+if tx.marked_signed():
|
|
|
msg('Transaction is signed')
|
|
|
|
|
|
-dec_tx = c.decoderawtransaction(tx.hex)
|
|
|
-tx.outputs = MMGenList(MMGenTX.MMGenTxOutput(addr=i['scriptPubKey']['addresses'][0],amt=i['value'])
|
|
|
- for i in dec_tx['vout'])
|
|
|
+dec_tx = g.rpch.decoderawtransaction(tx.hex)
|
|
|
+tx.outputs = tx.MMGenTxOutputList(
|
|
|
+ MMGenTX.MMGenTxOutput(addr=i['scriptPubKey']['addresses'][0],
|
|
|
+ amt=g.proto.coin_amt(i['value']))
|
|
|
+ for i in dec_tx['vout'])
|
|
|
for e in tx.outputs:
|
|
|
- if e.addr in b2m_map:
|
|
|
- f = b2m_map[e.addr]
|
|
|
+ if e.addr in outputs:
|
|
|
+ f = outputs[e.addr]
|
|
|
e.mmid = f[0]
|
|
|
if f[1]: e.label = f[1].decode('utf8')
|
|
|
else:
|
|
@@ -114,5 +128,5 @@ for e in tx.outputs:
|
|
|
e.mmid = f.mmid
|
|
|
if f.label: e.label = f.label.decode('utf8')
|
|
|
|
|
|
-tx.blockcount = find_block_by_time(c,tx.timestamp)
|
|
|
-tx.write_to_file(ask_tty=False)
|
|
|
+tx.blockcount = find_block_by_time(tx.timestamp)
|
|
|
+tx.write_to_file(ask_tty=False,ask_overwrite=not opt.quiet,ask_write=not opt.quiet)
|