Browse Source

Bugfix: MMGen -> BTC map for outputs not included in tx

philemon 10 years ago
parent
commit
a4998a9cbd
4 changed files with 71 additions and 49 deletions
  1. 5 3
      MANIFEST
  2. 37 8
      mmgen/addr.py
  3. 25 38
      mmgen/main_txcreate.py
  4. 4 0
      mmgen/util.py

+ 5 - 3
MANIFEST

@@ -11,7 +11,6 @@ mmgen-txsign
 mmgen-walletchk
 mmgen-walletchk
 mmgen-walletgen
 mmgen-walletgen
 setup.py
 setup.py
-mmgen/Opts.py
 mmgen/__init__.py
 mmgen/__init__.py
 mmgen/addr.py
 mmgen/addr.py
 mmgen/bitcoin.py
 mmgen/bitcoin.py
@@ -32,13 +31,13 @@ mmgen/main_walletgen.py
 mmgen/mn_electrum.py
 mmgen/mn_electrum.py
 mmgen/mn_tirosh.py
 mmgen/mn_tirosh.py
 mmgen/mnemonic.py
 mmgen/mnemonic.py
+mmgen/opt.py
+mmgen/opts.py
 mmgen/term.py
 mmgen/term.py
 mmgen/test.py
 mmgen/test.py
 mmgen/tool.py
 mmgen/tool.py
 mmgen/tx.py
 mmgen/tx.py
 mmgen/util.py
 mmgen/util.py
-mmgen/opt/Opts.py
-mmgen/opt/__init__.py
 mmgen/rpc/__init__.py
 mmgen/rpc/__init__.py
 mmgen/rpc/config.py
 mmgen/rpc/config.py
 mmgen/rpc/connection.py
 mmgen/rpc/connection.py
@@ -46,6 +45,9 @@ mmgen/rpc/data.py
 mmgen/rpc/exceptions.py
 mmgen/rpc/exceptions.py
 mmgen/rpc/proxy.py
 mmgen/rpc/proxy.py
 mmgen/rpc/util.py
 mmgen/rpc/util.py
+mmgen/share/Opts.py
+mmgen/share/__init__.py
 test/__init__.py
 test/__init__.py
+test/gentest.py
 test/test.py
 test/test.py
 test/tooltest.py
 test/tooltest.py

+ 37 - 8
mmgen/addr.py

@@ -208,8 +208,10 @@ def _parse_keyaddr_file(infile):
 
 
 class AddrInfoList(object):
 class AddrInfoList(object):
 
 
-	def __init__(self,addrinfo=None):
+	def __init__(self,addrinfo=None,bitcoind_connection=None):
 		self.data = {}
 		self.data = {}
+		if bitcoind_connection:
+			self.add_wallet_data(bitcoind_connection)
 
 
 	def seed_ids(self):
 	def seed_ids(self):
 		return self.data.keys()
 		return self.data.keys()
@@ -219,6 +221,28 @@ class AddrInfoList(object):
 		if sid in self.data:
 		if sid in self.data:
 			return self.data[sid]
 			return self.data[sid]
 
 
+	def add_wallet_data(self,c):
+		vmsg_r("Getting account data from wallet...")
+		data,accts,i = {},c.listaccounts(minconf=0,includeWatchonly=True),0
+		for acct in accts:
+			ma,comment = parse_mmgen_label(acct)
+			if ma:
+				i += 1
+				addrlist = c.getaddressesbyaccount(acct)
+				if len(addrlist) != 1:
+					msg(wmsg['too_many_acct_addresses'] % acct)
+					sys.exit(2)
+				seed_id,idx = ma.split(":")
+				if seed_id not in data:
+					data[seed_id] = []
+				a = AddrInfoEntry()
+				a.idx,a.addr,a.comment = \
+					int(idx),unicode(addrlist[0]),unicode(comment)
+				data[seed_id].append(a)
+		vmsg("%s %s addresses found, %s accounts total" % (i,g.proj_name,len(accts)))
+		for sid in data:
+			self.add(AddrInfo(sid=sid,adata=data[sid]))
+
 	def add(self,addrinfo):
 	def add(self,addrinfo):
 		if type(addrinfo) == AddrInfo:
 		if type(addrinfo) == AddrInfo:
 			self.data[addrinfo.seed_id] = addrinfo
 			self.data[addrinfo.seed_id] = addrinfo
@@ -235,17 +259,23 @@ class AddrInfoList(object):
 
 
 class AddrInfoEntry(object):
 class AddrInfoEntry(object):
 
 
-	def __init__(self):
-		pass
+	def __init__(self): pass
 
 
 class AddrInfo(object):
 class AddrInfo(object):
 
 
-	def __init__(self,addrfile="",has_keys=False):
+	def __init__(self,addrfile="",has_keys=False,sid="",adata=[]):
 		self.has_keys=has_keys
 		self.has_keys=has_keys
 		if addrfile:
 		if addrfile:
 			f = _parse_keyaddr_file if has_keys else _parse_addrfile
 			f = _parse_keyaddr_file if has_keys else _parse_addrfile
 			sid,adata = f(addrfile)
 			sid,adata = f(addrfile)
-			self.initialize(sid,adata)
+		elif sid and adata: # data from wallet
+			pass
+		elif sid or adata:
+			die(3,"Must specify address file, or seed_id + adata")
+		else:
+			return
+
+		self.initialize(sid,adata)
 
 
 	def initialize(self,seed_id,addrdata):
 	def initialize(self,seed_id,addrdata):
 		if seed_id in self.__dict__:
 		if seed_id in self.__dict__:
@@ -297,11 +327,10 @@ class AddrInfo(object):
 					sys.exit(2)
 					sys.exit(2)
 
 
 	def make_reverse_dict(self,btcaddrs):
 	def make_reverse_dict(self,btcaddrs):
-		d = {}
+		d,b = {},btcaddrs
 		for e in self.addrdata:
 		for e in self.addrdata:
 			try:
 			try:
-				i = btcaddrs.index(e.addr)
-				d[btcaddrs[i]] = ("%s:%s"%(self.seed_id,e.idx),e.comment)
+				d[b[b.index(e.addr)]] = ("%s:%s"%(self.seed_id,e.idx),e.comment)
 			except: pass
 			except: pass
 		return d
 		return d
 
 

+ 25 - 38
mmgen/main_txcreate.py

@@ -277,24 +277,6 @@ def select_outputs(unspent,prompt):
 		return selected
 		return selected
 
 
 
 
-def get_acct_data_from_wallet(c,acct_data):
-	# acct_data is global object initialized by caller
-	vmsg_r("Getting account data from wallet...")
-	accts,i = c.listaccounts(minconf=0,includeWatchonly=True),0
-	for acct in accts:
-		ma,comment = parse_mmgen_label(acct)
-		if ma:
-			i += 1
-			addrlist = c.getaddressesbyaccount(acct)
-			if len(addrlist) != 1:
-				msg(wmsg['too_many_acct_addresses'] % acct)
-				sys.exit(2)
-			seed_id,idx = ma.split(":")
-			if seed_id not in acct_data:
-				acct_data[seed_id] = {}
-			acct_data[seed_id][idx] = (addrlist[0],comment)
-	vmsg("%s %s addresses found, %s accounts total" % (i,g.proj_name,len(accts)))
-
 def mmaddr2btcaddr_unspent(unspent,mmaddr):
 def mmaddr2btcaddr_unspent(unspent,mmaddr):
 	vmsg_r("Searching for {g.proj_name} address {m} in wallet...".format(g=g,m=mmaddr))
 	vmsg_r("Searching for {g.proj_name} address {m} in wallet...".format(g=g,m=mmaddr))
 	m = [u for u in unspent if u.mmid == mmaddr]
 	m = [u for u in unspent if u.mmid == mmaddr]
@@ -309,15 +291,17 @@ def mmaddr2btcaddr_unspent(unspent,mmaddr):
 	sys.exit()
 	sys.exit()
 
 
 
 
-def mmaddr2btcaddr(c,mmaddr,acct_data,ail):
+def mmaddr2btcaddr(c,mmaddr,ail_w,ail_f):
 	# assume mmaddr has already been checked
 	# assume mmaddr has already been checked
-	if not acct_data: get_acct_data_from_wallet(c,acct_data)
-	btcaddr = mmaddr2btcaddr_addrdata(mmaddr,acct_data,"wallet")[0]
-#	btcaddr,comment = mmaddr2btcaddr_unspent(us,mmaddr)
+	sid,idx = mmaddr.split(":")
+	btcaddr = ""
+
+	if sid in ail_w.seed_ids():
+		btcaddr = ail_w.addrinfo(sid).btcaddr(int(idx))
+
 	if not btcaddr:
 	if not btcaddr:
-		if ail:
-			sid,idx = mmaddr.split(":")
-			btcaddr = ail.addrinfo(sid).btcaddr(int(idx))
+		if ail_f and sid in ail_f.seed_ids():
+			btcaddr = ail_f.addrinfo(sid).btcaddr(int(idx))
 			if btcaddr:
 			if btcaddr:
 				msg(wmsg['addr_in_addrfile_only'].format(mmgenaddr=mmaddr))
 				msg(wmsg['addr_in_addrfile_only'].format(mmgenaddr=mmaddr))
 				if not keypress_confirm("Continue anyway?"):
 				if not keypress_confirm("Continue anyway?"):
@@ -332,6 +316,13 @@ def mmaddr2btcaddr(c,mmaddr,acct_data,ail):
 	return btcaddr
 	return btcaddr
 
 
 
 
+def make_b2m_map(inputs_data,tx_out,ail_w,ail_f):
+	d = dict([(d['address'], (d['mmid'],d['comment']))
+				for d in inputs_data if d['mmid']])
+	d.update(ail_w.make_reverse_dict(tx_out.keys()))
+	d.update(ail_f.make_reverse_dict(tx_out.keys()))
+	return d
+
 cmd_args = opt.opts.init(opts_data)
 cmd_args = opt.opts.init(opts_data)
 
 
 if opt.comment_file:
 if opt.comment_file:
@@ -342,16 +333,18 @@ c = connect_to_bitcoind()
 if not opt.info:
 if not opt.info:
 	do_license_msg(immed=True)
 	do_license_msg(immed=True)
 
 
-	tx_out,acct_data,change_addr = {},{},""
-	from mmgen.addr import AddrInfo,AddrInfoList
-	ail = AddrInfoList()
+	tx_out,change_addr = {},""
 
 
 	addrfiles = [a for a in cmd_args if get_extension(a) == g.addrfile_ext]
 	addrfiles = [a for a in cmd_args if get_extension(a) == g.addrfile_ext]
 	cmd_args = set(cmd_args) - set(addrfiles)
 	cmd_args = set(cmd_args) - set(addrfiles)
 
 
+	from mmgen.addr import AddrInfo,AddrInfoList
+	ail_f = AddrInfoList()
 	for a in addrfiles:
 	for a in addrfiles:
 		check_infile(a)
 		check_infile(a)
-		ail.add(AddrInfo(a))
+		ail_f.add(AddrInfo(a))
+
+	ail_w = AddrInfoList(bitcoind_connection=c)
 
 
 	for a in cmd_args:
 	for a in cmd_args:
 		if "," in a:
 		if "," in a:
@@ -359,7 +352,7 @@ if not opt.info:
 			if is_btc_addr(a1):
 			if is_btc_addr(a1):
 				btcaddr = a1
 				btcaddr = a1
 			elif is_mmgen_addr(a1):
 			elif is_mmgen_addr(a1):
-				btcaddr = mmaddr2btcaddr(c,a1,acct_data,ail)
+				btcaddr = mmaddr2btcaddr(c,a1,ail_w,ail_f)
 			else:
 			else:
 				msg("%s: unrecognized subargument in argument '%s'" % (a1,a))
 				msg("%s: unrecognized subargument in argument '%s'" % (a1,a))
 				sys.exit(2)
 				sys.exit(2)
@@ -376,7 +369,7 @@ if not opt.info:
 						(change_addr, a))
 						(change_addr, a))
 				sys.exit(2)
 				sys.exit(2)
 			change_addr = a if is_btc_addr(a) else \
 			change_addr = a if is_btc_addr(a) else \
-							mmaddr2btcaddr(c,a,acct_data,ail)
+							mmaddr2btcaddr(c,a,ail_w,ail_f)
 			tx_out[change_addr] = 0
 			tx_out[change_addr] = 0
 		else:
 		else:
 			msg("%s: unrecognized argument" % a)
 			msg("%s: unrecognized argument" % a)
@@ -474,13 +467,7 @@ tx_id = make_chksum_6(unhexlify(tx_hex)).upper()
 metadata = tx_id, amt, make_timestamp()
 metadata = tx_id, amt, make_timestamp()
 sel_unspent = [i.__dict__ for i in sel_unspent]
 sel_unspent = [i.__dict__ for i in sel_unspent]
 
 
-def make_b2m_map(inputs_data,tx_out):
-	m = [(d['address'],(d['mmid'],d['comment'])) for d in inputs_data if d['mmid']]
-	d = ail.make_reverse_dict(tx_out.keys())
-	d.update(m)
-	return d
-
-b2m_map = make_b2m_map(sel_unspent,tx_out)
+b2m_map = make_b2m_map(sel_unspent,tx_out,ail_w,ail_f)
 
 
 prompt_and_view_tx_data(c,"View decoded transaction?",
 prompt_and_view_tx_data(c,"View decoded transaction?",
 		sel_unspent,tx_hex,b2m_map,comment,metadata)
 		sel_unspent,tx_hex,b2m_map,comment,metadata)

+ 4 - 0
mmgen/util.py

@@ -58,6 +58,10 @@ def Vmsg(s):
 def Vmsg_r(s):
 def Vmsg_r(s):
 	if opt.verbose: sys.stdout.write(s)
 	if opt.verbose: sys.stdout.write(s)
 
 
+def die(ev,s):
+	sys.stderr.write(s+"\n"); sys.exit(ev)
+def Die(ev,s):
+	sys.stdout.write(s+"\n"); sys.exit(ev)
 
 
 def msgrepr(*args):
 def msgrepr(*args):
 	for d in args:
 	for d in args: