URI: 
       tfix incorrect txid for partial segwit txns - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit e8b5bcf31e33900aa574867eb4722c014d687a42
   DIR parent 12c5474cf126f8bcb01a5cf90b582189f1297cb0
  HTML Author: SomberNight <somber.night@protonmail.com>
       Date:   Wed, 13 Jun 2018 15:54:45 +0200
       
       fix incorrect txid for partial segwit txns
       
       follow-up #4405
       
       Diffstat:
         M lib/tests/test_transaction.py       |      32 ++++++++++++++++++++++++++++++-
         M lib/tests/test_wallet_vertical.py   |       6 ++++++
         M lib/transaction.py                  |      10 ++++------
       
       3 files changed, 41 insertions(+), 7 deletions(-)
       ---
   DIR diff --git a/lib/tests/test_transaction.py b/lib/tests/test_transaction.py
       t@@ -5,7 +5,7 @@ from lib.bitcoin import TYPE_ADDRESS
        from lib.keystore import xpubkey_to_address
        from lib.util import bh2u, bfh
        
       -from . import SequentialTestCase
       +from . import SequentialTestCase, TestCaseForTestnet
        from .test_bitcoin import needs_test_with_all_ecc_implementations
        
        unsigned_blob = '45505446ff0001000000012a5c9a94fcde98f5581cd00162c60a13936ceb75389ea65bf38633b424eb4031000000005701ff4c53ff0488b21e03ef2afea18000000089689bff23e1e7fb2f161daa37270a97a3d8c2e537584b2d304ecb47b86d21fc021b010d3bd425f8cf2e04824bfdf1f1f5ff1d51fadd9a41f9e3fb8dd3403b1bfe00000000ffffffff0140420f00000000001976a914230ac37834073a42146f11ef8414ae929feaafc388ac00000000'
       t@@ -768,6 +768,36 @@ class TestTransaction(SequentialTestCase):
        # txns from Bitcoin Core ends <---
        
        
       +class TestTransactionTestnet(TestCaseForTestnet):
       +
       +    def _run_naive_tests_on_tx(self, raw_tx, txid):
       +        tx = transaction.Transaction(raw_tx)
       +        self.assertEqual(txid, tx.txid())
       +        self.assertEqual(raw_tx, tx.serialize())
       +        self.assertTrue(tx.estimated_size() >= 0)
       +
       +# partial txns using our partial format --->
       +    # NOTE: our partial format contains xpubs, and xpubs have version bytes,
       +    # and version bytes encode the network as well; so these are network-sensitive!
       +
       +    def test_txid_partial_segwit_p2wpkh(self):
       +        raw_tx = '45505446ff000100000000010115a847356cbb44be67f345965bb3f2589e2fec1c9a0ada21fd28225dcc602e8f0100000000fdffffff02f6fd1200000000001600149c756aa33f4f89418b33872a973274b5445c727b80969800000000001600140f9de573bc679d040e763d13f0250bd03e625f6ffeffffffff9095ab000000000000000201ff53ff045f1cf6014af5fa07800000002fa3f450ba41799b9b62642979505817783a9b6c656dc11cd0bb4fa362096808026adc616c25a4d0a877d1741eb1db9cef65c15118bd7d5f31bf65f319edda81840100c8000f391400'
       +        txid = '63ff7e99d85d8e33f683e6ec84574bdf8f5111078a5fe900893e019f9a7f95c3'
       +        self._run_naive_tests_on_tx(raw_tx, txid)
       +
       +    def test_txid_partial_segwit_p2wpkh_p2sh_simple(self):
       +        raw_tx = '45505446ff0001000000000101d0d23a6fbddb21cc664cb81cca96715baa4d6dbe5b7b9bcc6632f1005a7b0b840100000017160014a78a91261e71a681b6312cd184b14503a21f856afdffffff0134410f000000000017a914d6514ca17ecc31952c990daf96e307fbc58529cd87feffffffff40420f000000000000000201ff53ff044a5262033601222e800000001618aa51e49a961f63fd111f64cd4a7e792c1d7168be7a07703de505ebed2cf70286ebbe755767adaa5835f4d78dec1ee30849d69eacfe80b7ee6b1585279536c30000020011391400'
       +        txid = '2739f2e7fde9b8ec73fce4aee53722cc7683312d1321ded073284c51fadf44df'
       +        self._run_naive_tests_on_tx(raw_tx, txid)
       +
       +    def test_txid_partial_segwit_p2wpkh_p2sh_mixed_outputs(self):
       +        raw_tx = '45505446ff00010000000001011dcac788f24b84d771b60c44e1f9b6b83429e50f06e1472d47241922164013b00100000017160014801d28ca6e2bde551112031b6cb75de34f10851ffdffffff0440420f00000000001600140f9de573bc679d040e763d13f0250bd03e625f6fc0c62d000000000017a9142899f6484e477233ce60072fc185ef4c1f2c654487809698000000000017a914d40f85ba3c8fa0f3615bcfa5d6603e36dfc613ef87712d19040000000017a914e38c0cffde769cb65e72cda1c234052ae8d2254187feffffffff6ad1ee040000000000000201ff53ff044a5262033601222e800000001618aa51e49a961f63fd111f64cd4a7e792c1d7168be7a07703de505ebed2cf70286ebbe755767adaa5835f4d78dec1ee30849d69eacfe80b7ee6b1585279536c301000c000f391400'
       +        txid = 'ba5c88e07a4025a39ad3b85247cbd4f556a70d6312b18e04513c7cec9d45d6ac'
       +        self._run_naive_tests_on_tx(raw_tx, txid)
       +
       +# end partial txns <---
       +
       +
        class NetworkMock(object):
        
            def __init__(self, unspent):
   DIR diff --git a/lib/tests/test_wallet_vertical.py b/lib/tests/test_wallet_vertical.py
       t@@ -646,7 +646,9 @@ class TestWalletSending(TestCaseForTestnet):
                # wallet1 -> wallet2
                outputs = [(bitcoin.TYPE_ADDRESS, wallet2a.get_receiving_address(), 165000)]
                tx = wallet1a.mktx(outputs=outputs, password=None, config=self.config, fee=5000)
       +        txid = tx.txid()
                tx = Transaction(tx.serialize())  # simulates moving partial txn between cosigners
       +        self.assertEqual(txid, tx.txid())
                self.assertFalse(tx.is_complete())
                wallet1b.sign_transaction(tx, password=None)
        
       t@@ -662,6 +664,7 @@ class TestWalletSending(TestCaseForTestnet):
                self.assertEqual('6e9c3cd8788bdb970a124ea06136d52bc01cec4f9b1e217627d5e90ebe77d049', tx_copy.txid())
                self.assertEqual('c58650fb77d04577fccb3e201deecbf691ab52ffb61cd2e57996c4d51f7e980b', tx_copy.wtxid())
                self.assertEqual(tx.wtxid(), tx_copy.wtxid())
       +        self.assertEqual(txid, tx_copy.txid())
        
                wallet1a.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)
                wallet2a.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)
       t@@ -669,7 +672,9 @@ class TestWalletSending(TestCaseForTestnet):
                # wallet2 -> wallet1
                outputs = [(bitcoin.TYPE_ADDRESS, wallet1a.get_receiving_address(), 100000)]
                tx = wallet2a.mktx(outputs=outputs, password=None, config=self.config, fee=5000)
       +        txid = tx.txid()
                tx = Transaction(tx.serialize())  # simulates moving partial txn between cosigners
       +        self.assertEqual(txid, tx.txid())
                self.assertFalse(tx.is_complete())
                wallet2b.sign_transaction(tx, password=None)
        
       t@@ -685,6 +690,7 @@ class TestWalletSending(TestCaseForTestnet):
                self.assertEqual('84b0dcb43022385f7a10e2710e5625a2be3cd6e390387b6100b55500d5eea8f6', tx_copy.txid())
                self.assertEqual('7e561e25da843326e61fd20a40b72fcaeb8690176fc7c3fcbadb3a0146c8396c', tx_copy.wtxid())
                self.assertEqual(tx.wtxid(), tx_copy.wtxid())
       +        self.assertEqual(txid, tx_copy.txid())
        
                wallet1a.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)
                wallet2a.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)
   DIR diff --git a/lib/transaction.py b/lib/transaction.py
       t@@ -978,19 +978,17 @@ class Transaction:
                else:
                    return nVersion + txins + txouts + nLocktime
        
       -    def hash(self):
       -        print("warning: deprecated tx.hash()")
       -        return self.txid()
       -
            def txid(self):
       +        self.deserialize()
                all_segwit = all(self.is_segwit_input(x) for x in self.inputs())
                if not all_segwit and not self.is_complete():
                    return None
       -        ser = self.serialize(witness=False)
       +        ser = self.serialize_to_network(witness=False)
                return bh2u(Hash(bfh(ser))[::-1])
        
            def wtxid(self):
       -        ser = self.serialize(witness=True)
       +        self.deserialize()
       +        ser = self.serialize_to_network(witness=True)
                return bh2u(Hash(bfh(ser))[::-1])
        
            def add_inputs(self, inputs):