Beispiel #1
0
    def add_label(self,
                  arg1,
                  label='',
                  addr=None,
                  silent=False,
                  on_fail='return'):
        from mmgen.tx import is_mmgen_id, is_coin_addr
        mmaddr, coinaddr = None, None
        if is_coin_addr(addr or arg1):
            coinaddr = CoinAddr(addr or arg1, on_fail='return')
        if is_mmgen_id(arg1):
            mmaddr = TwMMGenID(arg1)

        if mmaddr and not coinaddr:
            from mmgen.addr import AddrData
            coinaddr = AddrData(source='tw').mmaddr2coinaddr(mmaddr)

        try:
            if not is_mmgen_id(arg1):
                assert coinaddr, u"Invalid coin address for this chain: {}".format(
                    arg1)
            assert coinaddr, u"{pn} address '{ma}' not found in tracking wallet"
            assert self.is_in_wallet(
                coinaddr), u"Address '{ca}' not found in tracking wallet"
        except Exception as e:
            msg(e.message.format(pn=g.proj_name, ma=mmaddr, ca=coinaddr))
            return False

        # Allow for the possibility that BTC addr of MMGen addr was entered.
        # Do reverse lookup, so that MMGen addr will not be marked as non-MMGen.
        if not mmaddr:
            from mmgen.addr import AddrData
            mmaddr = AddrData(source='tw').coinaddr2mmaddr(coinaddr)

        if not mmaddr:
            mmaddr = '{}:{}'.format(g.proto.base_coin.lower(), coinaddr)

        mmaddr = TwMMGenID(mmaddr)

        cmt = TwComment(label, on_fail=on_fail)
        if cmt in (False, None): return False

        lbl = TwLabel(mmaddr + ('', ' ' + cmt)[bool(cmt)], on_fail=on_fail)

        ret = self.set_label(coinaddr, lbl)

        from mmgen.rpc import rpc_error, rpc_errmsg
        if rpc_error(ret):
            msg('From {}: {}'.format(g.proto.daemon_name, rpc_errmsg(ret)))
            if not silent:
                msg('Label could not be {}'.format(
                    ('removed', 'added')[bool(label)]))
            return False
        else:
            m = mmaddr.type.replace('mmg', 'MMG')
            a = mmaddr.replace(g.proto.base_coin.lower() + ':', '')
            s = '{} address {} in tracking wallet'.format(m, a)
            if label: msg(u"Added label '{}' to {}".format(label, s))
            else: msg(u'Removed label from {}'.format(s))
            return True
Beispiel #2
0
	def send(self,prompt_user=True,exit_on_fail=False):

		if not self.marked_signed():
			die(1,'Transaction is not signed!')

		self.check_correct_chain(on_fail='die')

		fee = self.fee_rel2abs(self.txobj['gasPrice'].toWei())

		if not self.disable_fee_check and (fee > g.proto.max_tx_fee):
			die(2,'Transaction fee ({}) greater than {} max_tx_fee ({} {})!'.format(
				fee,g.proto.name.capitalize(),g.proto.max_tx_fee,g.coin))

		self.get_status()

		if prompt_user: self.confirm_send()

		ret = None if g.bogus_send else g.rpch.eth_sendRawTransaction('0x'+self.hex,on_fail='return')

		from mmgen.rpc import rpc_error,rpc_errmsg
		if rpc_error(ret):
			msg(yellow(rpc_errmsg(ret)))
			msg(red('Send of MMGen transaction {} failed'.format(self.txid)))
			if exit_on_fail: sys.exit(1)
			return False
		else:
			m = 'BOGUS transaction NOT sent: {}' if g.bogus_send else 'Transaction sent: {}'
			if not g.bogus_send:
				assert ret == '0x'+self.coin_txid,'txid mismatch (after sending)'
			self.desc = 'sent transaction'
			msg(m.format(self.coin_txid.hl()))
			self.add_timestamp()
			self.add_blockcount()
			return True
Beispiel #3
0
	def send(self,prompt_user=True,exit_on_fail=False):

		if not self.marked_signed():
			die(1,'Transaction is not signed!')

		self.die_if_incorrect_chain()

		self.check_hex_tx_matches_mmgen_tx(DeserializedTX(self.hex))

		bogus_send = os.getenv('MMGEN_BOGUS_SEND')

		if self.has_segwit_outputs() and not segwit_is_active() and not bogus_send:
			m = 'Transaction has MMGen Segwit outputs, but this blockchain does not support Segwit'
			die(2,m+' at the current height')

		if self.get_fee() > g.proto.max_tx_fee:
			die(2,'Transaction fee ({}) greater than {} max_tx_fee ({} {})!'.format(
				self.get_fee(),g.proto.name.capitalize(),g.proto.max_tx_fee,g.coin.upper()))

		self.get_status()

		if prompt_user:
			m1 = ("Once this transaction is sent, there's no taking it back!",'')[bool(opt.quiet)]
			m2 = 'broadcast this transaction to the {} network'.format(g.chain.upper())
			m3 = ('YES, I REALLY WANT TO DO THIS','YES')[bool(opt.quiet or opt.yes)]
			confirm_or_exit(m1,m2,m3)

		msg('Sending transaction')
		ret = None if bogus_send else g.rpch.sendrawtransaction(self.hex,on_fail='return')

		from mmgen.rpc import rpc_error,rpc_errmsg
		if rpc_error(ret):
			errmsg = rpc_errmsg(ret)
			if 'Signature must use SIGHASH_FORKID' in errmsg:
				m  = 'The Aug. 1 2017 UAHF has activated on this chain.'
				m += "\nRe-run the script with the --coin=bch option."
			elif 'Illegal use of SIGHASH_FORKID' in errmsg:
				m  = 'The Aug. 1 2017 UAHF is not yet active on this chain.'
				m += "\nRe-run the script without the --coin=bch option."
			elif '64: non-final' in errmsg:
				m2 = "Transaction with locktime '{}' can't be included in this block!"
				m = m2.format(strfmt_locktime(self.get_hex_locktime()))
			else:
				m = errmsg
			msg(yellow(m))
			msg(red('Send of MMGen transaction {} failed'.format(self.txid)))
			if exit_on_fail: sys.exit(1)
			return False
		else:
			if bogus_send:
				m = 'BOGUS transaction NOT sent: {}'
			else:
				assert ret == self.coin_txid, 'txid mismatch (after sending)'
				m = 'Transaction sent: {}'
			self.desc = 'sent transaction'
			msg(m.format(self.coin_txid.hl()))
			self.add_timestamp()
			self.add_blockcount()
			return True
Beispiel #4
0
	def sign(self,tx_num_str,keys):

		if self.marked_signed():
			die(1,'Transaction is already signed!')

		self.die_if_incorrect_chain()

		if (self.has_segwit_inputs() or self.has_segwit_outputs()) and not g.proto.cap('segwit'):
			die(2,yellow("TX has Segwit inputs or outputs, but {} doesn't support Segwit!".format(g.coin)))

		qmsg('Passing {} key{} to {}'.format(len(keys),suf(keys,'s'),g.proto.daemon_name))

		if self.has_segwit_inputs():
			from mmgen.addr import KeyGenerator,AddrGenerator
			kg = KeyGenerator('std')
			ag = AddrGenerator('segwit')
			keydict = MMGenDict([(d.addr,d.sec) for d in keys])

		sig_data = []
		for d in self.inputs:
			e = dict([(k,getattr(d,k)) for k in ('txid','vout','scriptPubKey','amt')])
			e['amount'] = e['amt']
			del e['amt']
			if d.mmid and d.mmid.mmtype == 'S':
				e['redeemScript'] = ag.to_segwit_redeem_script(kg.to_pubhex(keydict[d.addr]))
			sig_data.append(e)

		msg_r('Signing transaction{}...'.format(tx_num_str))
		wifs = [d.sec.wif for d in keys]
		ret = g.rpch.signrawtransaction(self.hex,sig_data,wifs,g.proto.sighash_type,on_fail='return')

		from mmgen.rpc import rpc_error,rpc_errmsg
		if rpc_error(ret):
			errmsg = rpc_errmsg(ret)
			if 'Invalid sighash param' in errmsg:
				m  = 'This is not the BCH chain.'
				m += "\nRe-run the script without the --coin=bch option."
			else:
				m = errmsg
			msg(yellow(m))
			return False
		else:
			if ret['complete']:
#				Msg(pretty_hexdump(unhexlify(self.hex),cols=16)) # DEBUG
#				pmsg(make_chksum_6(unhexlify(self.hex)).upper())
				self.hex = ret['hex']
				self.compare_size_and_estimated_size()
				dt = DeserializedTX(self.hex)
				self.check_hex_tx_matches_mmgen_tx(dt)
				self.coin_txid = CoinTxID(dt['txid'],on_fail='return')
				self.check_sigs(dt)
				assert self.coin_txid == g.rpch.decoderawtransaction(self.hex)['txid'],(
											'txid mismatch (after signing)')
				msg('OK')
				return True
			else:
				msg('failed\n{} returned the following errors:'.format(g.proto.daemon_name.capitalize()))
				msg(repr(ret['errors']))
				return False
Beispiel #5
0
    def send(self, c, prompt_user=True):

        self.die_if_incorrect_chain()

        bogus_send = os.getenv('MMGEN_BOGUS_SEND')

        if self.has_segwit_outputs(
        ) and not segwit_is_active() and not bogus_send:
            m = 'Transaction has MMGen Segwit outputs, but this blockchain does not support Segwit'
            die(2, m + ' at the current height')

        if self.get_fee() > g.max_tx_fee:
            die(
                2, 'Transaction fee ({}) greater than max_tx_fee ({})!'.format(
                    self.get_fee(), g.max_tx_fee))

        self.get_status(c)

        if prompt_user:
            m1 = ("Once this transaction is sent, there's no taking it back!",
                  '')[bool(opt.quiet)]
            m2 = 'broadcast this transaction to the {} network'.format(
                g.chain.upper())
            m3 = ('YES, I REALLY WANT TO DO THIS', 'YES')[bool(opt.quiet
                                                               or opt.yes)]
            confirm_or_exit(m1, m2, m3)

        msg('Sending transaction')
        ret = None if bogus_send else c.sendrawtransaction(self.hex,
                                                           on_fail='return')

        from mmgen.rpc import rpc_error, rpc_errmsg
        if rpc_error(ret):
            errmsg = rpc_errmsg(ret)
            if 'Signature must use SIGHASH_FORKID' in errmsg:
                m = 'The Aug. 1 2017 UAHF has activated on this chain.'
                m += "\nRe-run the script with the --coin=bch option."
            elif 'Illegal use of SIGHASH_FORKID' in errmsg:
                m = 'The Aug. 1 2017 UAHF is not yet active on this chain.'
                m += "\nRe-run the script without the --aug1hf or --coin=bch option."
            else:
                m = errmsg
            msg(yellow(m))
            msg(red('Send of MMGen transaction {} failed'.format(self.txid)))
            return False
        else:
            if bogus_send:
                m = 'BOGUS transaction NOT sent: {}'
            else:
                assert ret == self.btc_txid, 'txid mismatch (after sending)'
                m = 'Transaction sent: {}'
            self.desc = 'sent transaction'
            msg(m.format(self.btc_txid.hl()))
            self.add_timestamp()
            self.add_blockcount(c)
            return True
Beispiel #6
0
Datei: tw.py Projekt: mmgen/mmgen
	def add_label(self,arg1,label='',addr=None,silent=False,on_fail='return'):
		from mmgen.tx import is_mmgen_id,is_coin_addr
		mmaddr,coinaddr = None,None
		if is_coin_addr(addr or arg1):
			coinaddr = CoinAddr(addr or arg1,on_fail='return')
		if is_mmgen_id(arg1):
			mmaddr = TwMMGenID(arg1)

		if mmaddr and not coinaddr:
			from mmgen.addr import AddrData
			coinaddr = AddrData(source='tw').mmaddr2coinaddr(mmaddr)

		try:
			if not is_mmgen_id(arg1):
				assert coinaddr,"Invalid coin address for this chain: {}".format(arg1)
			assert coinaddr,"{pn} address '{ma}' not found in tracking wallet"
			assert self.is_in_wallet(coinaddr),"Address '{ca}' not found in tracking wallet"
		except Exception as e:
			msg(e.args[0].format(pn=g.proj_name,ma=mmaddr,ca=coinaddr))
			return False

		# Allow for the possibility that BTC addr of MMGen addr was entered.
		# Do reverse lookup, so that MMGen addr will not be marked as non-MMGen.
		if not mmaddr:
			from mmgen.addr import AddrData
			mmaddr = AddrData(source='tw').coinaddr2mmaddr(coinaddr)

		if not mmaddr: mmaddr = '{}:{}'.format(g.proto.base_coin.lower(),coinaddr)

		mmaddr = TwMMGenID(mmaddr)

		cmt = TwComment(label,on_fail=on_fail)
		if cmt in (False,None): return False

		lbl = TwLabel(mmaddr + ('',' '+cmt)[bool(cmt)],on_fail=on_fail)

		ret = self.set_label(coinaddr,lbl)

		from mmgen.rpc import rpc_error,rpc_errmsg
		if rpc_error(ret):
			msg('From {}: {}'.format(g.proto.daemon_name,rpc_errmsg(ret)))
			if not silent:
				msg('Label could not be {}'.format(('removed','added')[bool(label)]))
			return False
		else:
			m = mmaddr.type.replace('mmg','MMG')
			a = mmaddr.replace(g.proto.base_coin.lower()+':','')
			s = '{} address {} in tracking wallet'.format(m,a)
			if label: msg("Added label '{}' to {}".format(label,s))
			else:     msg('Removed label from {}'.format(s))
			return True
Beispiel #7
0
    def add_label(cls, arg1, label='', addr=None, silent=False):
        from mmgen.tx import is_mmgen_id, is_btc_addr
        mmaddr, btcaddr = None, None
        if is_btc_addr(addr or arg1):
            btcaddr = BTCAddr(addr or arg1, on_fail='return')
        if is_mmgen_id(arg1):
            mmaddr = TwMMGenID(arg1)

        if not btcaddr and not mmaddr:
            msg("Address '{}' invalid or not found in tracking wallet".format(
                addr or arg1))
            return False

        if not btcaddr:
            from mmgen.addr import AddrData
            btcaddr = AddrData(source='tw').mmaddr2btcaddr(mmaddr)

        if not btcaddr:
            msg("{} address '{}' not found in tracking wallet".format(
                g.proj_name, mmaddr))
            return False

        # Checked that the user isn't importing a random address
        if not btcaddr.is_in_tracking_wallet():
            msg("Address '{}' not in tracking wallet".format(btcaddr))
            return False

        c = rpc_connection()
        if not btcaddr.is_for_current_chain():
            msg("Address '{}' not valid for chain {}".format(
                btcaddr, g.chain.upper()))
            return False

        # Allow for the possibility that BTC addr of MMGen addr was entered.
        # Do reverse lookup, so that MMGen addr will not be marked as non-MMGen.
        if not mmaddr:
            from mmgen.addr import AddrData
            ad = AddrData(source='tw')
            mmaddr = ad.btcaddr2mmaddr(btcaddr)

        if not mmaddr: mmaddr = 'btc:' + btcaddr

        mmaddr = TwMMGenID(mmaddr)

        cmt = TwComment(label, on_fail='return')
        if cmt in (False, None): return False

        lbl = TwLabel(mmaddr +
                      ('', ' ' + cmt)[bool(cmt)])  # label is ASCII for now

        # NOTE: this works because importaddress() removes the old account before
        # associating the new account with the address.
        # Will be replaced by setlabel() with new RPC label API
        # RPC args: addr,label,rescan[=true],p2sh[=none]
        ret = c.importaddress(btcaddr, lbl, False, on_fail='return')

        from mmgen.rpc import rpc_error, rpc_errmsg
        if rpc_error(ret):
            msg('From bitcoind: ' + rpc_errmsg(ret))
            if not silent:
                msg('Label could not be {}'.format(
                    ('removed', 'added')[bool(label)]))
            return False
        else:
            m = mmaddr.type.replace('mmg', 'MMG')
            a = mmaddr.replace('btc:', '')
            s = '{} address {} in tracking wallet'.format(m, a)
            if label: msg("Added label '{}' to {}".format(label, s))
            else: msg('Removed label from {}'.format(s))
            return True
Beispiel #8
0
    def sign(self, c, tx_num_str, keys):

        self.die_if_incorrect_chain()

        if g.coin == 'BCH' and (self.has_segwit_inputs()
                                or self.has_segwit_outputs()):
            die(
                2,
                yellow(
                    "Segwit inputs cannot be spent or spent to on the BCH chain!"
                ))

        qmsg('Passing {} key{} to bitcoind'.format(len(keys), suf(keys, 's')))

        if self.has_segwit_inputs():
            from mmgen.addr import KeyGenerator, AddrGenerator
            kg = KeyGenerator()
            ag = AddrGenerator('segwit')
            keydict = MMGenDict([(d.addr, d.sec) for d in keys])

        sig_data = []
        for d in self.inputs:
            e = dict([(k, getattr(d, k))
                      for k in ('txid', 'vout', 'scriptPubKey', 'amt')])
            e['amount'] = e['amt']
            del e['amt']
            if d.mmid and d.mmid.mmtype == 'S':
                e['redeemScript'] = ag.to_segwit_redeem_script(
                    kg.to_pubhex(keydict[d.addr]))
            sig_data.append(e)

        msg_r('Signing transaction{}...'.format(tx_num_str))
        ht = ('ALL',
              'ALL|FORKID')[g.coin == 'BCH']  # sighashtype defaults to 'ALL'
        wifs = [d.sec.wif for d in keys]
        #		keys.pmsg()
        #		pmsg(wifs)
        ret = c.signrawtransaction(self.hex,
                                   sig_data,
                                   wifs,
                                   ht,
                                   on_fail='return')

        from mmgen.rpc import rpc_error, rpc_errmsg
        if rpc_error(ret):
            errmsg = rpc_errmsg(ret)
            if 'Invalid sighash param' in errmsg:
                m = 'This is not the BCH chain.'
                m += "\nRe-run the script without the --aug1hf or --coin=bch option."
            else:
                m = errmsg
            msg(yellow(m))
            return False
        else:
            if ret['complete']:
                self.hex = ret['hex']
                vmsg('Signed transaction size: {}'.format(len(self.hex) / 2))
                dt = DeserializedTX(self.hex)
                txid = dt['txid']
                self.check_sigs(dt)
                assert txid == c.decoderawtransaction(
                    self.hex)['txid'], 'txid mismatch (after signing)'
                self.btc_txid = BitcoinTxID(txid, on_fail='return')
                msg('OK')
                return True
            else:
                msg('failed\nBitcoind returned the following errors:')
                msg(repr(ret['errors']))
                return False
Beispiel #9
0
    def add_label(cls,
                  arg1,
                  label='',
                  addr=None,
                  silent=False,
                  on_fail='return'):
        from mmgen.tx import is_mmgen_id, is_coin_addr
        mmaddr, coinaddr = None, None
        if is_coin_addr(addr or arg1):
            coinaddr = CoinAddr(addr or arg1, on_fail='return')
        if is_mmgen_id(arg1):
            mmaddr = TwMMGenID(arg1)

        if mmaddr and not coinaddr:
            from mmgen.addr import AddrData
            coinaddr = AddrData(source='tw').mmaddr2coinaddr(mmaddr)

        try:
            if not is_mmgen_id(arg1):
                assert coinaddr, "Invalid coin address for this chain: {}".format(
                    arg1)
            assert coinaddr, "{pn} address '{ma}' not found in tracking wallet"
            assert coinaddr.is_in_tracking_wallet(
            ), "Address '{ca}' not found in tracking wallet"
        except Exception as e:
            msg(e[0].format(pn=g.proj_name, ma=mmaddr, ca=coinaddr))
            return False

        # Allow for the possibility that BTC addr of MMGen addr was entered.
        # Do reverse lookup, so that MMGen addr will not be marked as non-MMGen.
        if not mmaddr:
            from mmgen.addr import AddrData
            mmaddr = AddrData(source='tw').coinaddr2mmaddr(coinaddr)

        if not mmaddr:
            mmaddr = '{}:{}'.format(g.proto.base_coin.lower(), coinaddr)

        mmaddr = TwMMGenID(mmaddr)

        cmt = TwComment(label, on_fail=on_fail)
        if cmt in (False, None): return False

        lbl = TwLabel(mmaddr + ('', ' ' + cmt)[bool(cmt)], on_fail=on_fail)

        # NOTE: this works because importaddress() removes the old account before
        # associating the new account with the address.
        # Will be replaced by setlabel() with new RPC label API
        # RPC args: addr,label,rescan[=true],p2sh[=none]
        ret = g.rpch.importaddress(coinaddr, lbl, False, on_fail='return')

        from mmgen.rpc import rpc_error, rpc_errmsg
        if rpc_error(ret):
            msg('From {}: {}'.format(g.proto.daemon_name, rpc_errmsg(ret)))
            if not silent:
                msg('Label could not be {}'.format(
                    ('removed', 'added')[bool(label)]))
            return False
        else:
            m = mmaddr.type.replace('mmg', 'MMG')
            a = mmaddr.replace(g.proto.base_coin.lower() + ':', '')
            s = '{} address {} in tracking wallet'.format(m, a)
            if label: msg(u"Added label '{}' to {}".format(label, s))
            else: msg(u'Removed label from {}'.format(s))
            return True
Beispiel #10
0
	def add_label(cls,arg1,label='',addr=None,silent=False):
		from mmgen.tx import is_mmgen_id,is_coin_addr
		mmaddr,coinaddr = None,None
		if is_coin_addr(addr or arg1):
			coinaddr = CoinAddr(addr or arg1,on_fail='return')
		if is_mmgen_id(arg1):
			mmaddr = TwMMGenID(arg1)

		if not coinaddr and not mmaddr:
			msg("Address '{}' invalid or not found in tracking wallet".format(addr or arg1))
			return False

		if not coinaddr:
			from mmgen.addr import AddrData
			coinaddr = AddrData(source='tw').mmaddr2coinaddr(mmaddr)

		if not coinaddr:
			msg("{} address '{}' not found in tracking wallet".format(g.proj_name,mmaddr))
			return False

		# Checked that the user isn't importing a random address
		if not coinaddr.is_in_tracking_wallet():
			msg("Address '{}' not in tracking wallet".format(coinaddr))
			return False

		if not coinaddr.is_for_chain(g.chain):
			msg("Address '{}' not valid for chain {}".format(coinaddr,g.chain.upper()))
			return False

		# Allow for the possibility that BTC addr of MMGen addr was entered.
		# Do reverse lookup, so that MMGen addr will not be marked as non-MMGen.
		if not mmaddr:
			from mmgen.addr import AddrData
			ad = AddrData(source='tw')
			mmaddr = ad.coinaddr2mmaddr(coinaddr)

		if not mmaddr: mmaddr = '{}:{}'.format(g.proto.base_coin.lower(),coinaddr)

		mmaddr = TwMMGenID(mmaddr)

		cmt = TwComment(label,on_fail='return')
		if cmt in (False,None): return False

		lbl = TwLabel(mmaddr + ('',' '+cmt)[bool(cmt)]) # label is ASCII for now

		# NOTE: this works because importaddress() removes the old account before
		# associating the new account with the address.
		# Will be replaced by setlabel() with new RPC label API
		# RPC args: addr,label,rescan[=true],p2sh[=none]
		ret = g.rpch.importaddress(coinaddr,lbl,False,on_fail='return')

		from mmgen.rpc import rpc_error,rpc_errmsg
		if rpc_error(ret):
			msg('From {}: {}'.format(g.proto.daemon_name,rpc_errmsg(ret)))
			if not silent:
				msg('Label could not be {}'.format(('removed','added')[bool(label)]))
			return False
		else:
			m = mmaddr.type.replace('mmg','MMG')
			a = mmaddr.replace(g.proto.base_coin.lower()+':','')
			s = '{} address {} in tracking wallet'.format(m,a)
			if label: msg("Added label '{}' to {}".format(label,s))
			else:     msg('Removed label from {}'.format(s))
			return True