예제 #1
0
    def __init__(self, d):
        Hardware_KeyStore.__init__(self, d)
        # Errors and other user interaction is done through the wallet's
        # handler.  The handler is per-window and preserved across
        # device reconnects
        self.force_watching_only = False
        self.ux_busy = False

        # for multisig I need to know what wallet this keystore is part of
        # will be set by link_wallet
        self.my_wallet = None

        # Seems like only the derivation path and resulting **derived** xpub is stored in
        # the wallet file... however, we need to know at least the fingerprint of the master
        # xpub to verify against MiTM, and also so we can put the right value into the subkey paths
        # of PSBT files that might be generated offline. 
        # - save the fingerprint of the master xpub, as "xfp"
        # - it's a LE32 int, but hex BE32 is more natural way to view it
        # - device reports these value during encryption setup process
        # - full xpub value now optional
        lab = d['label']
        if hasattr(lab, 'xfp'):
            # initial setup
            self.ckcc_xfp = lab.xfp
            self.ckcc_xpub = getattr(lab, 'xpub', None)
        else:
            # wallet load: fatal if missing, we need them!
            self.ckcc_xfp = d['ckcc_xfp']
            self.ckcc_xpub = d.get('ckcc_xpub', None)
예제 #2
0
 def __init__(self, d):
     Hardware_KeyStore.__init__(self, d)
     # Errors and other user interaction is done through the wallet's
     # handler.  The handler is per-window and preserved across
     # device reconnects
     self.force_watching_only = False
     self.signing = False
     self.cfg = d.get('cfg', {'mode':0,'pair':''})
예제 #3
0
 def __init__(self, d):
     Hardware_KeyStore.__init__(self, d)
     # Errors and other user interaction is done through the wallet's
     # handler.  The handler is per-window and preserved across
     # device reconnects
     self.force_watching_only = False
     self.signing = False
     self.cfg = d.get('cfg', {'mode': 0})
예제 #4
0
    def __init__(self, d):
        Hardware_KeyStore.__init__(self, d)
        # Errors and other user interaction is done through the wallet's
        # handler.  The handler is per-window and preserved across
        # device reconnects
        self.force_watching_only = False
        self.ux_busy = False

        # we need to know at least the fingerprint of the master xpub to verify against MiTM
        # - device reports these value during encryption setup process
        # - full xpub value now optional
        self.ckcc_xpub = d.get('ckcc_xpub', None)
예제 #5
0
    def dump(self):
        # our additions to the stored data about keystore -- only during creation?
        d = Hardware_KeyStore.dump(self)

        d['ckcc_xfp'] = self.ckcc_xfp
        d['ckcc_xpub'] = self.ckcc_xpub

        return d
예제 #6
0
    def dump(self):
        # our additions to the stored data about keystore -- only during creation?
        d = Hardware_KeyStore.dump(self)

        d['ckcc_xfp'] = self.ckcc_xfp
        d['ckcc_xpub'] = self.ckcc_xpub

        return d
예제 #7
0
    def __init__(self, d):
        Hardware_KeyStore.__init__(self, d)
        # Errors and other user interaction is done through the wallet's
        # handler.  The handler is per-window and preserved across
        # device reconnects
        self.force_watching_only = False
        self.ux_busy = False

        # Seems like only the derivation path and resulting **derived** xpub is stored in
        # the wallet file... however, we need to know at least the fingerprint of the master
        # xpub to verify against MiTM, and also so we can put the right value into the subkey paths
        # of PSBT files that might be generated offline. 
        # - save the fingerprint of the master xpub, as "xfp"
        # - it's a LE32 int, but hex more natural way to see it
        # - device reports these value during encryption setup process
        lab = d['label']
        if hasattr(lab, 'xfp'):
            # initial setup
            self.ckcc_xfp = lab.xfp
            self.ckcc_xpub = lab.xpub
        else:
            # wallet load: fatal if missing, we need them!
            self.ckcc_xfp = d['ckcc_xfp']
            self.ckcc_xpub = d['ckcc_xpub']
예제 #8
0
 def __init__(self, d):
     Hardware_KeyStore.__init__(self, d)
     self.force_watching_only = False
     self.maxInputs = 14  # maximum inputs per single sign command
예제 #9
0
 def dump(self):
     obj = Hardware_KeyStore.dump(self)
     obj['cfg'] = self.cfg
     return obj
예제 #10
0
 def dump(self):
     obj = Hardware_KeyStore.dump(self)
     obj['cfg'] = self.cfg
     return obj
예제 #11
0
    def sign_transaction(
        self,
        keystore: Hardware_KeyStore,
        tx: PartialTransaction,
        wallet: Deterministic_Wallet,
    ):
        if tx.is_complete():
            return

        if self.bitbox02_device is None:
            raise Exception(
                "Need to setup communication first before attempting any BitBox02 calls"
            )

        coin = bitbox02.btc.LTC
        if constants.net.TESTNET:
            coin = bitbox02.btc.TLTC

        tx_script_type = None

        # Build BTCInputType list
        inputs = []
        for txin in tx.inputs():
            _, full_path = keystore.find_my_pubkey_in_txinout(txin)

            if full_path is None:
                raise Exception(
                    "A wallet owned pubkey was not found in the transaction input to be signed"
                )

            inputs.append(
                {
                    "prev_out_hash": txin.prevout.txid[::-1],
                    "prev_out_index": txin.prevout.out_idx,
                    "prev_out_value": txin.value_sats(),
                    "sequence": txin.nsequence,
                    "keypath": full_path,
                }
            )

            if tx_script_type == None:
                tx_script_type = txin.script_type
            elif tx_script_type != txin.script_type:
                raise Exception("Cannot mix different input script types")

        if tx_script_type == "p2wpkh":
            tx_script_type = bitbox02.btc.BTCScriptConfig(
                simple_type=bitbox02.btc.BTCScriptConfig.P2WPKH
            )
        elif tx_script_type == "p2wpkh-p2sh":
            tx_script_type = bitbox02.btc.BTCScriptConfig(
                simple_type=bitbox02.btc.BTCScriptConfig.P2WPKH_P2SH
            )
        elif tx_script_type == "p2wsh":
            if type(wallet) is Multisig_Wallet:
                tx_script_type = self.btc_multisig_config(coin, full_path, wallet)
            else:
                raise Exception("Can only use p2wsh with multisig wallets")
        else:
            raise UserFacingException(
                "invalid input script type: {} is not supported by the BitBox02".format(
                    tx_script_type
                )
            )

        # Build BTCOutputType list
        outputs = []
        for txout in tx.outputs():
            assert txout.address
            # check for change
            if txout.is_change:
                _, change_pubkey_path = keystore.find_my_pubkey_in_txinout(txout)
                outputs.append(
                    bitbox02.BTCOutputInternal(
                        keypath=change_pubkey_path, value=txout.value,
                    )
                )
            else:
                addrtype, pubkey_hash = bitcoin.address_to_hash(txout.address)
                if addrtype == OnchainOutputType.P2PKH:
                    output_type = bitbox02.btc.P2PKH
                elif addrtype == OnchainOutputType.P2SH:
                    output_type = bitbox02.btc.P2SH
                elif addrtype == OnchainOutputType.WITVER0_P2WPKH:
                    output_type = bitbox02.btc.P2WPKH
                elif addrtype == OnchainOutputType.WITVER0_P2WSH:
                    output_type = bitbox02.btc.P2WSH
                else:
                    raise UserFacingException(
                        "Received unsupported output type during transaction signing: {} is not supported by the BitBox02".format(
                            addrtype
                        )
                    )
                outputs.append(
                    bitbox02.BTCOutputExternal(
                        output_type=output_type,
                        output_hash=pubkey_hash,
                        value=txout.value,
                    )
                )

        if type(wallet) is Standard_Wallet:
            keypath_account = full_path[:3]
        elif type(wallet) is Multisig_Wallet:
            keypath_account = full_path[:4]
        else:
            raise Exception(
                "BitBox02 does not support this wallet type: {}".format(type(wallet))
            )

        sigs = self.bitbox02_device.btc_sign(
            coin,
            tx_script_type,
            keypath_account=keypath_account,
            inputs=inputs,
            outputs=outputs,
            locktime=tx.locktime,
            version=tx.version,
        )

        # Fill signatures
        if len(sigs) != len(tx.inputs()):
            raise Exception("Incorrect number of inputs signed.")  # Should never occur
        signatures = [bh2u(ecc.der_sig_from_sig_string(x[1])) + "01" for x in sigs]
        tx.update_signatures(signatures)
예제 #12
0
 def dump(self):
     # our additions to the stored data about keystore -- only during creation?
     d = Hardware_KeyStore.dump(self)
     return d
예제 #13
0
 def __init__(self, d):
     Hardware_KeyStore.__init__(self, d)
     #_logger.info(f"[Satochip_KeyStore] __init__(): xpub:{str(d.get('xpub'))}")#debugSatochip
     #_logger.info(f"[Satochip_KeyStore] __init__(): derivation:{str(d.get('derivation'))}")#debugSatochip
     self.force_watching_only = False
     self.ux_busy = False
예제 #14
0
 def __init__(self, d):
     Hardware_KeyStore.__init__(self, d)
     self.force_watching_only = False
     self.maxInputs = 14 # maximum inputs per single sign command