Browse Source

Support for the Aug 1 2017 UAHF ("Bitcoin Cash", "Bitcoin ABC")

Brief instructions for Linux (Windows users may adapt to fit):

    Make a copy of your Bitcoin data directory, including the blockchain and
    your tracking wallet (the blockchain must have been synced last BEFORE
    12:20 UTC Aug. 1).  This can be done as follows:

        $ mkdir ~/.bitcoin-abc
        $ rsync -av ~/.bitcoin/* ~/.bitcoin-abc

    If you messed up and synced your blockchain AFTER the HF, then do the
    following, after which you'll have to sync the ABC chain from scratch:

        $ mkdir ~/.bitcoin-abc
        $ cp ~/.bitcoin/{bitcoin.conf,*wallet*.dat} ~/.bitcoin-abc

    Download the Bitcoin ABC binary, but DON'T let it install automatically.
    Or alternatively, clone the source from Github and compile it yourself:

        Binary: https://download.bitcoinabc.org/0.14.6
        Source: git clone https://github.com/Bitcoin-ABC/bitcoin-abc

    Install the Bitcoin ABC daemon BY HAND into your exec path as 'bitcoind-abc':

        $ sudo cp bitcoind /usr/local/bin/bitcoind-abc

    Start the daemon and let it sync the ABC chain:

        $ bitcoind-abc -datadir=$HOME/.bitcoin-abc -daemon

    Don't forget to always start the ABC daemon with the -datadir argument.
    Otherwise you could trash your Core blockchain!

    Once the HF has activated, you sign or create-sign-send transactions on the
    ABC chain by invoking 'mmgen-txsign' or 'mmgen-txdo' with the --aug1hf
    switch.

    All other commands, including 'mmgen-txcreate' and 'mmgen-txsend', are
    invoked as usual, with no additional command-line switches.  Your address
    balances and unspent outputs will display correctly for whatever chain
    you're on at the moment.

    To switch back to the Core chain, just stop the ABC daemon and restart the
    Core daemon (WITHOUT the -datadir argument).

    After the Aug. 1 HF, Core transactions and ABC transactions will be
    incompatible, as they use an incompatible sighash type.  This prevents
    transactions from being broadcast (and hence replayed) on the wrong chain.
    So if you use the --aug1hf switch on the Core chain, or forget to use it on
    the ABC chain, nothing bad will happen; your sign or send operation will
    just fail with an error message.

    The main danger is forgetting which daemon is running at the moment and
    therefore which chain you're on.  This can be checked on Linux with the
    command `pgrep -a bitcoind` or on Windows by examining the task manager.

    In case you were wondering, all the --aug1hf switch does is perform a few
    sanity checks and call signrawtransaction with 'ALL|FORKID' as the
    'sighashtype' argument.  There's nothing more to it than that!
philemon 8 years ago
parent
commit
576d8036c7
6 changed files with 52 additions and 25 deletions
  1. 2 1
      mmgen/globalvars.py
  2. 1 1
      mmgen/main_txbump.py
  3. 1 0
      mmgen/main_txdo.py
  4. 1 0
      mmgen/main_txsign.py
  5. 46 22
      mmgen/tx.py
  6. 1 1
      mmgen/txsign.py

+ 2 - 1
mmgen/globalvars.py

@@ -38,7 +38,7 @@ class g(object):
 		sys.exit(ev)
 	# Variables - these might be altered at runtime:
 
-	version      = '0.9.2'
+	version      = '0.9.299'
 	release_date = 'July 2017'
 
 	proj_name = 'MMGen'
@@ -115,6 +115,7 @@ class g(object):
 		('label','keep_label'),
 		('tx_id','info'),
 		('tx_id','terse_info'),
+		('aug1hf','rbf'),
 		('batch','rescan')
 	)
 	cfg_file_opts = (

+ 1 - 1
mmgen/main_txbump.py

@@ -71,7 +71,7 @@ opts_data = {
 	'notes': '\n' + fee_notes + txsign_notes
 }
 
-cmd_args = opts.init(opts_data)
+cmd_args = opts.init(opts_data,add_opts=['aug1hf'])
 
 c = bitcoin_connection()
 

+ 1 - 0
mmgen/main_txdo.py

@@ -30,6 +30,7 @@ opts_data = {
 	'options': """
 -h, --help             Print this help message
 --, --longhelp         Print help message for long options (common options)
+-A, --aug1hf           Sign transaction for the Aug. 1 2017 UAHF chain
 -a, --tx-fee-adj=    f Adjust transaction fee by factor 'f' (see below)
 -b, --brain-params=l,p Use seed length 'l' and hash preset 'p' for
                        brainwallet input

+ 1 - 0
mmgen/main_txsign.py

@@ -30,6 +30,7 @@ opts_data = {
 	'options': """
 -h, --help            Print this help message
 --, --longhelp        Print help message for long options (common options)
+-A, --aug1hf          Sign transaction for the Aug. 1 2017 UAHF chain
 -b, --brain-params=l,p Use seed length 'l' and hash preset 'p' for
                       brainwallet input
 -d, --outdir=      d  Specify an alternate directory 'd' for output

+ 46 - 22
mmgen/tx.py

@@ -441,6 +441,9 @@ class MMGenTX(MMGenObject):
 
 		self.die_if_incorrect_chain()
 
+		if opt.aug1hf and self.has_segwit_inputs():
+			die(2,yellow("'--aug1hf' option is incompatible with Segwit transaction inputs!"))
+
 		if not keys:
 			msg('No keys. Cannot sign!')
 			return False
@@ -462,23 +465,34 @@ class MMGenTX(MMGenObject):
 
 		from mmgen.bitcoin import hash256
 		msg_r('Signing transaction{}...'.format(tx_num_str))
-		# sighashtype defaults to 'ALL'
-		sig_tx = c.signrawtransaction(self.hex,sig_data,keys.values())
-
-		if sig_tx['complete']:
-			self.hex = sig_tx['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(sig_tx['errors']))
+		ht = ('ALL','ALL|FORKID')[bool(opt.aug1hf)] # sighashtype defaults to 'ALL'
+		ret = c.signrawtransaction(self.hex,sig_data,keys.values(),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 chain does not support the Aug. 1 2017 UAHF.'
+				m += "\nRe-run 'mmgen-txsign' or 'mmgen-txdo' without the --aug1hf 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
 
 	def mark_raw(self):
 		self.desc = 'transaction'
@@ -567,10 +581,24 @@ class MMGenTX(MMGenObject):
 			ret = 'deadbeef' * 8
 			m = 'BOGUS transaction NOT sent: %s'
 		else:
-			ret = c.sendrawtransaction(self.hex) # exits on failure
+			ret = c.sendrawtransaction(self.hex,on_fail='return')
 			m = 'Transaction sent: %s'
 
-		if ret:
+		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 'mmgen-txsign' or 'mmgen-txdo' with the --aug1hf 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 'mmgen-txsign' or 'mmgen-txdo' without the --aug1hf option."
+			else:
+				m = errmsg
+			msg(yellow(m))
+			msg(red('Send of MMGen transaction {} failed'.format(self.txid)))
+			return False
+		else:
 			if not bogus_send:
 				assert ret == self.btc_txid, 'txid mismatch (after sending)'
 			self.desc = 'sent transaction'
@@ -579,10 +607,6 @@ class MMGenTX(MMGenObject):
 			self.add_blockcount(c)
 			return True
 
-		# rpc call exits on failure, so we won't get here
-		msg('Sending of transaction {} failed'.format(self.txid))
-		return False
-
 	def write_txid_to_file(self,ask_write=False,ask_write_default_yes=True):
 		fn = '%s[%s].%s' % (self.txid,self.send_amt,self.txid_ext)
 		write_data_to_file(fn,self.btc_txid+'\n','transaction ID',

+ 1 - 1
mmgen/txsign.py

@@ -185,4 +185,4 @@ def txsign(opt,c,tx,seed_files,kl,kal,tx_num_str=''):
 	if tx.sign(c,tx_num_str,dict(keys)):
 		return tx
 	else:
-		die(3,'failed\nSome keys were missing.  Transaction {}could not be signed.'.format(tx_num_str))
+		die(3,red('Transaction {}could not be signed.'.format(tx_num_str)))