URI: 
       tMerge pull request #2760 from jhoenicke/trezorsegwit - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit b86619ee301cf6e2528439064328f2734adeee46
   DIR parent ad15c6a80e619d418c10b50d3fa8f3b583f8eecf
  HTML Author: ThomasV <thomasv@electrum.org>
       Date:   Wed, 30 Aug 2017 11:48:55 +0200
       
       Merge pull request #2760 from jhoenicke/trezorsegwit
       
       t[TREZOR] Added Segwit support.
       Diffstat:
         M lib/base_wizard.py                  |       2 +-
         M lib/keystore.py                     |       9 ++++-----
         M lib/transaction.py                  |      10 +++++++---
         M plugins/trezor/plugin.py            |      31 +++++++++++++++++++++----------
       
       4 files changed, 33 insertions(+), 19 deletions(-)
       ---
   DIR diff --git a/lib/base_wizard.py b/lib/base_wizard.py
       t@@ -227,7 +227,7 @@ class BaseWizard(object):
                    self.derivation_dialog(f)
        
            def derivation_dialog(self, f):
       -        default = bip44_derivation(0)
       +        default = bip44_derivation(0, self.config.get('segwit'))
                message = '\n'.join([
                    _('Enter your wallet derivation here.'),
                    _('If you are not sure what this is, leave this field unchanged.')
   DIR diff --git a/lib/keystore.py b/lib/keystore.py
       t@@ -684,11 +684,10 @@ is_private_key = lambda x: is_xprv(x) or is_private_key_list(x)
        is_bip32_key = lambda x: is_xprv(x) or is_xpub(x)
        
        
       -def bip44_derivation(account_id):
       -    if bitcoin.TESTNET:
       -        return "m/44'/1'/%d'"% int(account_id)
       -    else:
       -        return "m/44'/0'/%d'"% int(account_id)
       +def bip44_derivation(account_id, segwit=False):
       +    bip  = 49 if segwit else 44
       +    coin = 1 if bitcoin.TESTNET else 0
       +    return "m/%d'/%d'/%d'" % (bip, coin, int(account_id))
        
        def from_seed(seed, passphrase):
            t = seed_type(seed)
   DIR diff --git a/lib/transaction.py b/lib/transaction.py
       t@@ -421,8 +421,7 @@ def parse_input(vds):
        
        def parse_witness(vds):
            n = vds.read_compact_size()
       -    for i in range(n):
       -        x = vds.read_bytes(vds.read_compact_size())
       +    return list(vds.read_bytes(vds.read_compact_size()).encode('hex') for i in xrange(n))
        
        def parse_output(vds, i):
            d = {}
       t@@ -548,7 +547,12 @@ class Transaction:
                for i, txin in enumerate(self.inputs()):
                    pubkeys, x_pubkeys = self.get_sorted_pubkeys(txin)
                    sigs1 = txin.get('signatures')
       -            sigs2 = d['inputs'][i].get('signatures')
       +            if d.get('witness') is None:
       +                sigs2 = d['inputs'][i].get('signatures')
       +            else:
       +                # signatures are in the witnesses.  But the last item is
       +                # the pubkey or the multisig script, so skip that.
       +                sigs2 = d['witness'][i][:-1]
                    for sig in sigs2:
                        if sig in sigs1:
                            continue
   DIR diff --git a/plugins/trezor/plugin.py b/plugins/trezor/plugin.py
       t@@ -26,6 +26,9 @@ class TrezorCompatibleKeyStore(Hardware_KeyStore):
            def get_derivation(self):
                return self.derivation
        
       +    def is_segwit(self):
       +        return self.derivation.startswith("m/49'/")
       +
            def get_client(self, force_pair=True):
                return self.plugin.get_client(self, force_pair)
        
       t@@ -241,8 +244,8 @@ class TrezorCompatiblePlugin(HW_PluginBase):
                self.prev_tx = prev_tx
                self.xpub_path = xpub_path
                client = self.get_client(keystore)
       -        inputs = self.tx_inputs(tx, True)
       -        outputs = self.tx_outputs(keystore.get_derivation(), tx)
       +        inputs = self.tx_inputs(tx, True, keystore.is_segwit())
       +        outputs = self.tx_outputs(keystore.get_derivation(), tx, keystore.is_segwit())
                signed_tx = client.sign_tx(self.get_coin_name(), inputs, outputs, lock_time=tx.locktime)[1]
                raw = bh2u(signed_tx)
                tx.update_signatures(raw)
       t@@ -256,9 +259,11 @@ class TrezorCompatiblePlugin(HW_PluginBase):
                derivation = wallet.keystore.derivation
                address_path = "%s/%d/%d"%(derivation, change, index)
                address_n = client.expand_path(address_path)
       -        client.get_address(self.get_coin_name(), address_n, True)
       +        segwit = wallet.keystore.is_segwit()
       +        script_type = self.types.SPENDP2SHWITNESS if segwit else self.types.SPENDADDRESS
       +        client.get_address(self.get_coin_name(), address_n, True, script_type=script_type)
        
       -    def tx_inputs(self, tx, for_sig=False):
       +    def tx_inputs(self, tx, for_sig=False, segwit=False):
                inputs = []
                for txin in tx.inputs():
                    txinputtype = self.types.TxInputType()
       t@@ -273,6 +278,7 @@ class TrezorCompatiblePlugin(HW_PluginBase):
                                xpub, s = parse_xpubkey(x_pubkey)
                                xpub_n = self.client_class.expand_path(self.xpub_path[xpub])
                                txinputtype.address_n.extend(xpub_n + s)
       +                        txinputtype.script_type = self.types.SPENDP2SHWITNESS if segwit else self.types.SPENDADDRESS
                            else:
                                def f(x_pubkey):
                                    if is_xpubkey(x_pubkey):
       t@@ -288,8 +294,9 @@ class TrezorCompatiblePlugin(HW_PluginBase):
                                    signatures=map(lambda x: bfh(x)[:-1] if x else b'', txin.get('signatures')),
                                    m=txin.get('num_sig'),
                                )
       +                        script_type = self.types.SPENDP2SHWITNESS if segwit else self.types.SPENDMULTISIG
                                txinputtype = self.types.TxInputType(
       -                            script_type=self.types.SPENDMULTISIG,
       +                            script_type=script_type,
                                    multisig=multisig
                                )
                                # find which key is mine
       t@@ -304,6 +311,8 @@ class TrezorCompatiblePlugin(HW_PluginBase):
                        prev_hash = unhexlify(txin['prevout_hash'])
                        prev_index = txin['prevout_n']
        
       +            if 'value' in txin:
       +                txinputtype.amount = txin['value']
                    txinputtype.prev_hash = prev_hash
                    txinputtype.prev_index = prev_index
        
       t@@ -317,7 +326,7 @@ class TrezorCompatiblePlugin(HW_PluginBase):
        
                return inputs
        
       -    def tx_outputs(self, derivation, tx):
       +    def tx_outputs(self, derivation, tx, segwit=False):
                outputs = []
                has_change = False
        
       t@@ -327,14 +336,16 @@ class TrezorCompatiblePlugin(HW_PluginBase):
                        has_change = True # no more than one change address
                        addrtype, hash_160 = bc_address_to_hash_160(address)
                        index, xpubs, m = info
       -                if addrtype == ADDRTYPE_P2PKH:
       +                if len(xpubs) == 1:
       +                    script_type = self.types.PAYTOP2SHWITNESS if segwit else self.types.PAYTOADDRESS
                            address_n = self.client_class.expand_path(derivation + "/%d/%d"%index)
                            txoutputtype = self.types.TxOutputType(
                                amount = amount,
       -                        script_type = self.types.PAYTOADDRESS,
       +                        script_type = script_type,
                                address_n = address_n,
                            )
       -                elif addrtype == ADDRTYPE_P2SH:
       +                else:
       +                    script_type = self.types.PAYTOP2SHWITNESS if segwit else self.types.PAYTOMULTISIG
                            address_n = self.client_class.expand_path("/%d/%d"%index)
                            nodes = map(self.ckd_public.deserialize, xpubs)
                            pubkeys = [ self.types.HDNodePathType(node=node, address_n=address_n) for node in nodes]
       t@@ -346,7 +357,7 @@ class TrezorCompatiblePlugin(HW_PluginBase):
                                multisig = multisig,
                                amount = amount,
                                address_n = self.client_class.expand_path(derivation + "/%d/%d"%index),
       -                        script_type = self.types.PAYTOMULTISIG)
       +                        script_type = script_type)
                    else:
                        txoutputtype = self.types.TxOutputType()
                        txoutputtype.amount = amount