Esempio n. 1
0
    def test_version_bytes(self):
        xprv_headers_b58 = {
            'standard':    'tprv',
            'p2wpkh-p2sh': 'uprv',
            'p2wsh-p2sh':  'Uprv',
            'p2wpkh':      'vprv',
            'p2wsh':       'Vprv',
        }
        xpub_headers_b58 = {
            'standard':    'tpub',
            'p2wpkh-p2sh': 'upub',
            'p2wsh-p2sh':  'Upub',
            'p2wpkh':      'vpub',
            'p2wsh':       'Vpub',
        }
        for xtype, xkey_header_bytes in constants.net.XPRV_HEADERS.items():
            xkey_header_bytes = bfh("%08x" % xkey_header_bytes)
            xkey_bytes = xkey_header_bytes + bytes([0] * 74)
            xkey_b58 = EncodeBase58Check(xkey_bytes)
            self.assertTrue(xkey_b58.startswith(xprv_headers_b58[xtype]))

            xkey_bytes = xkey_header_bytes + bytes([255] * 74)
            xkey_b58 = EncodeBase58Check(xkey_bytes)
            self.assertTrue(xkey_b58.startswith(xprv_headers_b58[xtype]))

        for xtype, xkey_header_bytes in constants.net.XPUB_HEADERS.items():
            xkey_header_bytes = bfh("%08x" % xkey_header_bytes)
            xkey_bytes = xkey_header_bytes + bytes([0] * 74)
            xkey_b58 = EncodeBase58Check(xkey_bytes)
            self.assertTrue(xkey_b58.startswith(xpub_headers_b58[xtype]))

            xkey_bytes = xkey_header_bytes + bytes([255] * 74)
            xkey_b58 = EncodeBase58Check(xkey_bytes)
            self.assertTrue(xkey_b58.startswith(xpub_headers_b58[xtype]))
Esempio n. 2
0
    def tx_inputs(self, tx, for_sig=False):
        inputs = []
        for txin in tx.inputs():
            txinputtype = self.types.TxInputType()
            if txin['type'] == 'coinbase':
                prev_hash = b"\x00"*32
                prev_index = 0xffffffff  # signed int -1
            else:
                if for_sig:
                    x_pubkeys = txin['x_pubkeys']
                    if len(x_pubkeys) == 1:
                        x_pubkey = x_pubkeys[0]
                        xpub, s = parse_xpubkey(x_pubkey)
                        xpub_n = self.client_class.expand_path(self.xpub_path[xpub])
                        txinputtype._extend_address_n(xpub_n + s)
                        txinputtype.script_type = self.get_safet_input_script_type(txin['type'])
                    else:
                        def f(x_pubkey):
                            xpub, s = parse_xpubkey(x_pubkey)
                            return self._make_node_path(xpub, s)
                        pubkeys = list(map(f, x_pubkeys))
                        multisig = self.types.MultisigRedeemScriptType(
                            pubkeys=pubkeys,
                            signatures=list(map(lambda x: bfh(x)[:-1] if x else b'', txin.get('signatures'))),
                            m=txin.get('num_sig'),
                        )
                        script_type = self.get_safet_input_script_type(txin['type'])
                        txinputtype = self.types.TxInputType(
                            script_type=script_type,
                            multisig=multisig
                        )
                        # find which key is mine
                        for x_pubkey in x_pubkeys:
                            if is_xpubkey(x_pubkey):
                                xpub, s = parse_xpubkey(x_pubkey)
                                if xpub in self.xpub_path:
                                    xpub_n = self.client_class.expand_path(self.xpub_path[xpub])
                                    txinputtype._extend_address_n(xpub_n + s)
                                    break

                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

            if txin.get('scriptSig') is not None:
                script_sig = bfh(txin['scriptSig'])
                txinputtype.script_sig = script_sig

            txinputtype.sequence = txin.get('sequence', 0xffffffff - 1)

            inputs.append(txinputtype)

        return inputs
Esempio n. 3
0
 def parse_script(self, x):
     script = ''
     for word in x.split():
         if word[0:3] == 'OP_':
             opcode_int = opcodes[word]
             assert opcode_int < 256  # opcode is single-byte
             script += bitcoin.int_to_hex(opcode_int)
         else:
             bfh(word)  # to test it is hex data
             script += push_script(word)
     return script
Esempio n. 4
0
 def parse_script(self, x):
     from electrum.transaction import opcodes, push_script
     script = ''
     for word in x.split():
         if word[0:3] == 'OP_':
             assert word in opcodes.lookup
             opcode_int = opcodes.lookup[word]
             assert opcode_int < 256  # opcode is single-byte
             script += bitcoin.int_to_hex(opcode_int)
         else:
             bfh(word)  # to test it is hex data
             script += push_script(word)
     return script
Esempio n. 5
0
    def on_receive(self, keyhash, message):
        self.print_error("signal arrived for", keyhash)
        for key, _hash, window in self.keys:
            if _hash == keyhash:
                break
        else:
            self.print_error("keyhash not found")
            return

        wallet = window.wallet
        if wallet.has_password():
            password = window.password_dialog('An encrypted transaction was retrieved from cosigning pool.\nPlease enter your password to decrypt it.')
            if not password:
                return
        else:
            password = None
            if not window.question(_("An encrypted transaction was retrieved from cosigning pool.\nDo you want to open it now?")):
                return

        xprv = wallet.keystore.get_master_private_key(password)
        if not xprv:
            return
        try:
            k = bh2u(bitcoin.deserialize_xprv(xprv)[-1])
            EC = bitcoin.EC_KEY(bfh(k))
            message = bh2u(EC.decrypt_message(message))
        except Exception as e:
            traceback.print_exc(file=sys.stdout)
            window.show_message(str(e))
            return

        self.listener.clear(keyhash)
        tx = transaction.Transaction(message)
        show_transaction(tx, window, prompt_if_unsaved=True)
Esempio n. 6
0
 def f(x_pubkey):
     if is_xpubkey(x_pubkey):
         xpub, s = parse_xpubkey(x_pubkey)
     else:
         xpub = xpub_from_pubkey(0, bfh(x_pubkey))
         s = []
     return self._make_node_path(xpub, s)
Esempio n. 7
0
 def get_noise_map(cls, versioned_seed: VersionedSeed) -> Dict[Tuple[int, int], int]:
     """Returns a map from (x,y) coordinate to pixel value 0/1, to be used as rawnoise."""
     w, h = cls.SIZE
     version  = versioned_seed.version
     hex_seed = versioned_seed.seed
     checksum = versioned_seed.checksum
     noise_map = {}
     if version == '0':
         random.seed(int(hex_seed, 16))
         for x in range(w):
             for y in range(h):
                 noise_map[(x, y)] = random.randint(0, 1)
     elif version == '1':
         prng_seed = bfh(hex_seed + version + checksum)
         drbg = DRBG(prng_seed)
         num_noise_bytes = 1929  # ~ w*h
         noise_array = bin(int.from_bytes(drbg.generate(num_noise_bytes), 'big'))[2:]
         # there's an approx 1/1024 chance that the generated number is 'too small'
         # and we would get IndexError below. easiest backwards compat fix:
         noise_array += '0' * (w * h - len(noise_array))
         i = 0
         for x in range(w):
             for y in range(h):
                 noise_map[(x, y)] = int(noise_array[i])
                 i += 1
     else:
         raise Exception(f"unexpected revealer version: {version}")
     return noise_map
Esempio n. 8
0
def xfp_from_xpub(xpub):
    # sometime we need to BIP32 fingerprint value: 4 bytes of ripemd(sha256(pubkey))
    # UNTESTED
    kk = bfh(Xpub.get_pubkey_from_xpub(xpub, []))
    assert len(kk) == 33
    xfp, = unpack('<I', hash_160(kk)[0:4])
    return xfp
Esempio n. 9
0
 def show_qr(self):
     text = bfh(str(self.tx))
     text = base_encode(text, base=43)
     try:
         self.main_window.show_qrcode(text, 'Transaction', parent=self)
     except Exception as e:
         self.show_message(str(e))
Esempio n. 10
0
 def test_base43(self):
     tx_hex = "020000000001021cd0e96f9ca202e017ca3465e3c13373c0df3a4cdd91c1fd02ea42a1a65d2a410000000000fdffffff757da7cf8322e5063785e2d8ada74702d2648fa2add2d533ba83c52eb110df690200000000fdffffff02d07e010000000000160014b544c86eaf95e3bb3b6d2cabb12ab40fc59cad9ca086010000000000232102ce0d066fbfcf150a5a1bbc4f312cd2eb080e8d8a47e5f2ce1a63b23215e54fb5ac02483045022100a9856bf10a950810abceeabc9a86e6ba533e130686e3d7863971b9377e7c658a0220288a69ef2b958a7c2ecfa376841d4a13817ed24fa9a0e0a6b9cb48e6439794c701210324e291735f83ff8de47301b12034950b80fa4724926a34d67e413d8ff8817c53024830450221008f885978f7af746679200ed55fe2e86c1303620824721f95cc41eb7965a3dfcf02207872082ac4a3c433d41a203e6d685a459e70e551904904711626ac899238c20a0121023d4c9deae1aacf3f822dd97a28deaec7d4e4ff97be746d124a63d20e582f5b290a971600"
     tx_bytes = bfh(tx_hex)
     tx_base43 = base_encode(tx_bytes, 43)
     self.assertEqual("3E2DH7.J3PKVZJ3RCOXQVS3Y./6-WE.75DDU0K58-0N1FRL565N8ZH-DG1Z.1IGWTE5HK8F7PWH5P8+V3XGZZ6GQBPHNDE+RD8CAQVV1/6PQEMJIZTGPMIJ93B8P$QX+Y2R:TGT9QW8S89U4N2.+FUT8VG+34USI/N/JJ3CE*KLSW:REE8T5Y*9:U6515JIUR$6TODLYHSDE3B5DAF:5TF7V*VAL3G40WBOM0DO2+CFKTTM$G-SO:8U0EW:M8V:4*R9ZDX$B1IRBP9PLMDK8H801PNTFB4$HL1+/U3F61P$4N:UAO88:N5D+J:HI4YR8IM:3A7K1YZ9VMRC/47$6GGW5JEL1N690TDQ4XW+TWHD:V.1.630QK*JN/.EITVU80YS3.8LWKO:2STLWZAVHUXFHQ..NZ0:.J/FTZM.KYDXIE1VBY7/:PHZMQ$.JZQ2.XT32440X/HM+UY/7QP4I+HTD9.DUSY-8R6HDR-B8/PF2NP7I2-MRW9VPW3U9.S0LQ.*221F8KVMD5ANJXZJ8WV4UFZ4R.$-NXVE+-FAL:WFERGU+WHJTHAP",
                      tx_base43)
     self.assertEqual(tx_bytes,
                      base_decode(tx_base43, None, 43))
Esempio n. 11
0
 def f(x_pubkey):
     if is_xpubkey(x_pubkey):
         xpub, s = parse_xpubkey(x_pubkey)
     else:
         xpub = xpub_from_pubkey(0, bfh(x_pubkey))
         s = []
     node = self.ckd_public.deserialize(xpub)
     return self.types.HDNodePathType(node=node, address_n=s)
Esempio n. 12
0
 def test_base58(self):
     data_hex = '0cd394bef396200774544c58a5be0189f3ceb6a41c8da023b099ce547dd4d8071ed6ed647259fba8c26382edbf5165dfd2404e7a8885d88437db16947a116e451a5d1325e3fd075f9d370120d2ab537af69f32e74fc0ba53aaaa637752964b3ac95cfea7'
     data_bytes = bfh(data_hex)
     data_base58 = base_encode(data_bytes, 58)
     self.assertEqual("VuvZ2K5UEcXCVcogny7NH4Evd9UfeYipsTdWuU4jLDhyaESijKtrGWZTFzVZJPjaoC9jFBs3SFtarhDhQhAxkXosUD8PmUb5UXW1tafcoPiCp8jHy7Fe2CUPXAbYuMvAyrkocbe6",
                      data_base58)
     self.assertEqual(data_bytes,
                      base_decode(data_base58, None, 58))
Esempio n. 13
0
 def test_base58check(self):
     data_hex = '0cd394bef396200774544c58a5be0189f3ceb6a41c8da023b099ce547dd4d8071ed6ed647259fba8c26382edbf5165dfd2404e7a8885d88437db16947a116e451a5d1325e3fd075f9d370120d2ab537af69f32e74fc0ba53aaaa637752964b3ac95cfea7'
     data_bytes = bfh(data_hex)
     data_base58check = EncodeBase58Check(data_bytes)
     self.assertEqual("4GCCJsjHqFbHxWbFBvRg35cSeNLHKeNqkXqFHW87zRmz6iP1dJU9Tk2KHZkoKj45jzVsSV4ZbQ8GpPwko6V3Z7cRfux3zJhUw7TZB6Kpa8Vdya8cMuUtL5Ry3CLtMetaY42u52X7Ey6MAH",
                      data_base58check)
     self.assertEqual(data_bytes,
                      DecodeBase58Check(data_base58check))
Esempio n. 14
0
 def sign_transaction(self, keystore, tx, prev_tx, xpub_path):
     prev_tx = { bfh(txhash): self.electrum_tx_to_txtype(tx, xpub_path) for txhash, tx in prev_tx.items() }
     client = self.get_client(keystore)
     inputs = self.tx_inputs(tx, xpub_path, True)
     outputs = self.tx_outputs(keystore.get_derivation(), tx)
     details = SignTx(lock_time=tx.locktime, version=tx.version)
     signatures, _ = client.sign_tx(self.get_coin_name(), inputs, outputs, details=details, prev_txes=prev_tx)
     signatures = [(bh2u(x) + '01') for x in signatures]
     tx.update_signatures(signatures)
Esempio n. 15
0
        def write_kv(ktype, val, key=b''):
            # serialize helper: write w/ size and key byte
            out_fd.write(my_var_int(1 + len(key)))
            out_fd.write(bytes([ktype]) + key)

            if isinstance(val, str):
                val = bfh(val)

            out_fd.write(my_var_int(len(val)))
            out_fd.write(val)
Esempio n. 16
0
def trezor_validate_op_return_output_and_get_data(output: TxOutput) -> bytes:
    if output.type != TYPE_SCRIPT:
        raise Exception("Unexpected output type: {}".format(output.type))
    script = bfh(output.address)
    if not (script[0] == opcodes.OP_RETURN and
            script[1] == len(script) - 2 and script[1] <= 75):
        raise UserFacingException(_("Only OP_RETURN scripts, with one constant push, are supported."))
    if output.value != 0:
        raise UserFacingException(_("Amount for OP_RETURN output must be zero."))
    return script[2:]
Esempio n. 17
0
 def show_qr(self):
     text = bfh(str(self.tx))
     text = base_encode(text, base=43)
     try:
         self.main_window.show_qrcode(text, 'Transaction', parent=self)
     except qrcode.exceptions.DataOverflowError:
         self.show_error(_('Failed to display QR code.') + '\n' +
                         _('Transaction is too large in size.'))
     except Exception as e:
         self.show_error(_('Failed to display QR code.') + '\n' + str(e))
Esempio n. 18
0
 def electrum_tx_to_txtype(self, tx):
     t = self.types.TransactionType()
     d = deserialize(tx.raw)
     t.version = d['version']
     t.lock_time = d['lockTime']
     inputs = self.tx_inputs(tx)
     t.inputs.extend(inputs)
     for vout in d['outputs']:
         o = t.bin_outputs.add()
         o.amount = vout['value']
         o.script_pubkey = bfh(vout['scriptPubKey'])
     return t
Esempio n. 19
0
 def do_send(self, tx):
     for window, xpub, K, _hash in self.cosigner_list:
         if not self.cosigner_can_sign(tx, xpub):
             continue
         message = bitcoin.encrypt_message(bfh(tx.raw), bh2u(K)).decode('ascii')
         try:
             server.put(_hash, message)
         except Exception as e:
             traceback.print_exc(file=sys.stdout)
             window.show_message("Failed to send transaction to cosigning pool.")
             return
         window.show_message("Your transaction was sent to the cosigning pool.\nOpen your cosigner wallet to retrieve it.")
Esempio n. 20
0
    def tx_inputs(self, tx, xpub_path, for_sig=False):
        inputs = []
        for txin in tx.inputs():
            txinputtype = TxInputType()
            if txin['type'] == 'coinbase':
                prev_hash = b"\x00"*32
                prev_index = 0xffffffff  # signed int -1
            else:
                if for_sig:
                    x_pubkeys = txin['x_pubkeys']
                    xpubs = [parse_xpubkey(x) for x in x_pubkeys]
                    multisig = self._make_multisig(txin.get('num_sig'), xpubs, txin.get('signatures'))
                    script_type = self.get_trezor_input_script_type(txin['type'])
                    txinputtype = TxInputType(
                        script_type=script_type,
                        multisig=multisig)
                    # find which key is mine
                    for xpub, deriv in xpubs:
                        if xpub in xpub_path:
                            xpub_n = parse_path(xpub_path[xpub])
                            txinputtype.address_n = xpub_n + deriv
                            break

                prev_hash = bfh(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

            if txin.get('scriptSig') is not None:
                script_sig = bfh(txin['scriptSig'])
                txinputtype.script_sig = script_sig

            txinputtype.sequence = txin.get('sequence', 0xffffffff - 1)

            inputs.append(txinputtype)

        return inputs
Esempio n. 21
0
    def test_sign_transaction(self):
        eckey1 = ecc.ECPrivkey(bfh('7e1255fddb52db1729fc3ceb21a46f95b8d9fe94cc83425e936a6c5223bb679d'))
        sig1 = eckey1.sign_transaction(bfh('5a548b12369a53faaa7e51b5081829474ebdd9c924b3a8230b69aa0be254cd94'))
        self.assertEqual(bfh('3045022100902a288b98392254cd23c0e9a49ac6d7920f171b8249a48e484b998f1874a2010220723d844826828f092cf400cb210c4fa0b8cd1b9d1a7f21590e78e022ff6476b9'), sig1)

        eckey2 = ecc.ECPrivkey(bfh('c7ce8c1462c311eec24dff9e2532ac6241e50ae57e7d1833af21942136972f23'))
        sig2 = eckey2.sign_transaction(bfh('642a2e66332f507c92bda910158dfe46fc10afbf72218764899d3af99a043fac'))
        self.assertEqual(bfh('30440220618513f4cfc87dde798ce5febae7634c23e7b9254a1eabf486be820f6a7c2c4702204fef459393a2b931f949e63ced06888f35e286e446dc46feb24b5b5f81c6ed52'), sig2)
Esempio n. 22
0
    def _do_test_bip32(self, seed: str, sequence):
        node = BIP32Node.from_rootseed(bfh(seed), xtype='standard')
        xprv, xpub = node.to_xprv(), node.to_xpub()
        self.assertEqual("m/", sequence[0:2])
        sequence = sequence[2:]
        for n in sequence.split('/'):
            if n[-1] != "'":
                xpub2 = BIP32Node.from_xkey(xpub).subkey_at_public_derivation(n).to_xpub()
            node = BIP32Node.from_xkey(xprv).subkey_at_private_derivation(n)
            xprv, xpub = node.to_xprv(), node.to_xpub()
            if n[-1] != "'":
                self.assertEqual(xpub, xpub2)

        return xpub, xprv
Esempio n. 23
0
 def electrum_tx_to_txtype(self, tx, xpub_path):
     t = TransactionType()
     if tx is None:
         # probably for segwit input and we don't need this prev txn
         return t
     d = deserialize(tx.raw)
     t.version = d['version']
     t.lock_time = d['lockTime']
     t.inputs = self.tx_inputs(tx, xpub_path)
     t.bin_outputs = [
         TxOutputBinType(amount=vout['value'], script_pubkey=bfh(vout['scriptPubKey']))
         for vout in d['outputs']
     ]
     return t
Esempio n. 24
0
    def deserialize_with_auxpow(data_hex: str, **kwargs):
        """Deserializes a block header given as hex string

        This makes sure that the data is always deserialised as full
        block header with AuxPoW.

        The keyword-arguments expect_trailing_data and start_position can be
        set and will be passed on to deserialize_full_header."""

        # We pass a height beyond the last checkpoint, because
        # deserialize_full_header expects checkpointed headers to be truncated
        # by ElectrumX (i.e. not contain an AuxPoW).
        return blockchain.deserialize_full_header(
            bfh(data_hex),
            constants.net.max_checkpoint() + 1, **kwargs)
Esempio n. 25
0
 def test_encode_decode_msg__init(self):
     # "init" is interesting because it has TLVs optionally
     self.assertEqual(
         bfh("00100000000220c2"),
         encode_msg(
             "init",
             gflen=0,
             flen=2,
             features=(LnFeatures.OPTION_STATIC_REMOTEKEY_OPT
                       | LnFeatures.GOSSIP_QUERIES_OPT
                       | LnFeatures.GOSSIP_QUERIES_REQ
                       | LnFeatures.OPTION_DATA_LOSS_PROTECT_OPT),
         ))
     self.assertEqual(
         bfh("00100000000220c2"),
         encode_msg("init", gflen=0, flen=2, features=bfh("20c2")))
     self.assertEqual(
         bfh("00100000000220c2012043497fd7f826957108f4a30fd9cec3aeba79972084e90ead01ea330900000000"
             ),
         encode_msg(
             "init",
             gflen=0,
             flen=2,
             features=(LnFeatures.OPTION_STATIC_REMOTEKEY_OPT
                       | LnFeatures.GOSSIP_QUERIES_OPT
                       | LnFeatures.GOSSIP_QUERIES_REQ
                       | LnFeatures.OPTION_DATA_LOSS_PROTECT_OPT),
             init_tlvs={
                 'networks': {
                     'chains':
                     b'CI\x7f\xd7\xf8&\x95q\x08\xf4\xa3\x0f\xd9\xce\xc3\xae\xbay\x97 \x84\xe9\x0e\xad\x01\xea3\t\x00\x00\x00\x00'
                 }
             }))
     self.assertEqual(('init', {
         'gflen': 2,
         'globalfeatures': b'"\x00',
         'flen': 3,
         'features': b'\x02\xa2\xa1',
         'init_tlvs': {}
     }), decode_msg(bfh("001000022200000302a2a1")))
     self.assertEqual(
         ('init', {
             'gflen': 2,
             'globalfeatures': b'"\x00',
             'flen': 3,
             'features': b'\x02\xaa\xa2',
             'init_tlvs': {
                 'networks': {
                     'chains':
                     b'CI\x7f\xd7\xf8&\x95q\x08\xf4\xa3\x0f\xd9\xce\xc3\xae\xbay\x97 \x84\xe9\x0e\xad\x01\xea3\t\x00\x00\x00\x00'
                 }
             }
         }),
         decode_msg(
             bfh("001000022200000302aaa2012043497fd7f826957108f4a30fd9cec3aeba79972084e90ead01ea330900000000"
                 )))
Esempio n. 26
0
 def electrum_tx_to_txtype(self, tx):
     t = self.types.TransactionType()
     if tx is None:
         # probably for segwit input and we don't need this prev txn
         return t
     d = deserialize(tx.raw)
     t.version = d['version']
     t.lock_time = d['lockTime']
     inputs = self.tx_inputs(tx)
     t._extend_inputs(inputs)
     for vout in d['outputs']:
         o = t._add_bin_outputs()
         o.amount = vout['value']
         o.script_pubkey = bfh(vout['scriptPubKey'])
     return t
Esempio n. 27
0
    def test_should_reject_very_long_merkle_branch(self):
        header_bytes = bfh(namecoin_header_37174)
        # We can't pass the real height because it's below a checkpoint, and
        # the deserializer expects ElectrumX to strip checkpointed AuxPoW.
        header = blockchain.deserialize_header(
            header_bytes,
            constants.net.max_checkpoint() + 1)

        header['auxpow']['chain_merkle_branch'] = list(
            [32 * '00' for i in range(32)])

        with self.assertRaises(auxpow.AuxPoWChainMerkleTooLongError):
            blockchain.Blockchain.verify_header(header,
                                                namecoin_prev_hash_37174,
                                                namecoin_target_37174)
Esempio n. 28
0
 def test_encode_decode_msg__ints_can_be_passed_as_bytes(self):
     self.assertEqual(bfh(frombtc("01020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000043497fd7f826957108f4a30fd9cec3aeba79972084e90ead01ea33090000000000d43100006f00025e6ed0830100009000000000000000c8000001f400000023000000003b9aca00")),
                      encode_msg(
                          "channel_update",
                          short_channel_id=ShortChannelID.from_components(54321, 111, 2),
                          channel_flags=b'\x00',
                          message_flags=b'\x01',
                          cltv_expiry_delta=int.to_bytes(144, length=2, byteorder="big", signed=False),
                          htlc_minimum_msat=int.to_bytes(200, length=8, byteorder="big", signed=False),
                          htlc_maximum_msat=int.to_bytes(1_000_000_000, length=8, byteorder="big", signed=False),
                          fee_base_msat=int.to_bytes(500, length=4, byteorder="big", signed=False),
                          fee_proportional_millionths=int.to_bytes(35, length=4, byteorder="big", signed=False),
                          chain_hash=constants.net.rev_genesis_bytes(),
                          timestamp=int.to_bytes(1584320643, length=4, byteorder="big", signed=False),
                      ))
Esempio n. 29
0
    def _do_test_bip32(self, seed, sequence):
        xprv, xpub = bip32_root(bfh(seed), 'standard')
        self.assertEqual("m/", sequence[0:2])
        path = 'm'
        sequence = sequence[2:]
        for n in sequence.split('/'):
            child_path = path + '/' + n
            if n[-1] != "'":
                xpub2 = bip32_public_derivation(xpub, path, child_path)
            xprv, xpub = bip32_private_derivation(xprv, path, child_path)
            if n[-1] != "'":
                self.assertEqual(xpub, xpub2)
            path = child_path

        return xpub, xprv
Esempio n. 30
0
 def electrum_tx_to_txtype(self, tx):
     t = self.types.TransactionType()
     if tx is None:
         # probably for segwit input and we don't need this prev txn
         return t
     d = deserialize(tx.raw)
     t.version = d['version']
     t.lock_time = d['lockTime']
     inputs = self.tx_inputs(tx)
     t._extend_inputs(inputs)
     for vout in d['outputs']:
         o = t._add_bin_outputs()
         o.amount = vout['value']
         o.script_pubkey = bfh(vout['scriptPubKey'])
     return t
Esempio n. 31
0
    def _make_multisig(self, m, xpubs, signatures=None):
        if len(xpubs) == 1:
            return None

        pubkeys = [self._make_node_path(xpub, deriv) for xpub, deriv in xpubs]
        if signatures is None:
            signatures = [b''] * len(pubkeys)
        elif len(signatures) != len(pubkeys):
            raise RuntimeError('Mismatched number of signatures')
        else:
            signatures = [bfh(x)[:-1] if x else b'' for x in signatures]

        return MultisigRedeemScriptType(pubkeys=pubkeys,
                                        signatures=signatures,
                                        m=m)
Esempio n. 32
0
 def electrum_tx_to_txtype(self, tx, xpub_path):
     t = TransactionType()
     if tx is None:
         # probably for segwit input and we don't need this prev txn
         return t
     d = deserialize(tx.raw)
     t.version = d['version']
     t.lock_time = d['lockTime']
     t.inputs = self.tx_inputs(tx, xpub_path)
     t.bin_outputs = [
         TxOutputBinType(amount=vout['value'],
                         script_pubkey=bfh(vout['scriptPubKey']))
         for vout in d['outputs']
     ]
     return t
Esempio n. 33
0
    def _do_test_bip32(self, seed: str, sequence):
        node = BIP32Node.from_rootseed(bfh(seed), xtype='standard')
        xprv, xpub = node.to_xprv(), node.to_xpub()
        self.assertEqual("m/", sequence[0:2])
        sequence = sequence[2:]
        for n in sequence.split('/'):
            if n[-1] != "'":
                xpub2 = BIP32Node.from_xkey(xpub).subkey_at_public_derivation(
                    n).to_xpub()
            node = BIP32Node.from_xkey(xprv).subkey_at_private_derivation(n)
            xprv, xpub = node.to_xprv(), node.to_xpub()
            if n[-1] != "'":
                self.assertEqual(xpub, xpub2)

        return xpub, xprv
Esempio n. 34
0
 def do_send(self, tx):
     for window, xpub, K, _hash in self.cosigner_list:
         if not self.cosigner_can_sign(tx, xpub):
             continue
         raw_tx_bytes = bfh(str(tx))
         public_key = ecc.ECPubkey(K)
         message = public_key.encrypt_message(raw_tx_bytes).decode('ascii')
         try:
             server.put(_hash, message)
         except Exception as e:
             traceback.print_exc(file=sys.stdout)
             window.show_error(_("Failed to send transaction to cosigning pool") + ':\n' + str(e))
             return
         window.show_message(_("Your transaction was sent to the cosigning pool.") + '\n' +
                             _("Open your cosigner wallet to retrieve it."))
Esempio n. 35
0
    def _do_test_bip32(self, seed, sequence):
        xprv, xpub = bip32_root(bfh(seed), 'standard')
        self.assertEqual("m/", sequence[0:2])
        path = 'm'
        sequence = sequence[2:]
        for n in sequence.split('/'):
            child_path = path + '/' + n
            if n[-1] != "'":
                xpub2 = bip32_public_derivation(xpub, path, child_path)
            xprv, xpub = bip32_private_derivation(xprv, path, child_path)
            if n[-1] != "'":
                self.assertEqual(xpub, xpub2)
            path = child_path

        return xpub, xprv
Esempio n. 36
0
    def test_deserialize_auxpow_header_explicit_coinbase(self):
        header = self.deserialize_with_auxpow(namecoin_header_37174)
        header_auxpow = header['auxpow']

        self.assertEqual(constants.net.AUXPOW_CHAIN_ID,
                         header_auxpow['chain_id'])

        coinbase_tx = header_auxpow['parent_coinbase_tx']
        expected_coinbase_txid = '8a3164be45a621f85318647d425fe9f45837b8e42ec4fdd902d7f64daf61ff4a'
        observed_coinbase_txid = auxpow.fast_txid(coinbase_tx)

        self.assertEqual(expected_coinbase_txid, observed_coinbase_txid)

        self.assertEqual(header_auxpow['coinbase_merkle_branch'], [
            "f8f27314022a5165ae122642babb28dd44191dd36f99dad80b4f16b75197dde0",
            "c8a9dc420e17dee7b04bc0174c7a37ed9e5bc3f0ea0fdfe0b5d24bfc19ecedb0",
            "0ce9c5b98e212527e4aa7b9298435dc4e8f4dfc4dc63b7c89c06300637c33620",
            "3b6d0c4122a5b047cb879a440461839f0446f6bd451f01c6f0b14b6624e84136",
            "458500be38a68b215112df5e52d9c08fdd52034fb2005ce15d2a42be28e436cb",
        ])

        coinbase_merkle_index = header_auxpow['coinbase_merkle_index']
        self.assertEqual(0, coinbase_merkle_index)

        self.assertEqual(header_auxpow['chain_merkle_branch'], [
            "000000000000000000000000000000000000000000000000000000000000000a",
            "65bd8eb2c7e3a3646507977e8659e5396b197f197fbb51e7158927a263798302",
            "5f961bb13289d705abb28376a01f7097535c95f87b9e719b9ec39d8eb20d72e9",
            "7cb5fdcc41120d6135a40a6753bddc0c9b675ba2936d2e0cd78cdcb02e6beb50",
        ])

        chain_merkle_index = header_auxpow['chain_merkle_index']
        self.assertEqual(11, chain_merkle_index)

        expected_parent_header = blockchain.deserialize_pure_header(
            bfh('0100000055a7bc918827dbe7d8027781d803f4b418589b7b9fc03e718a03000000000000625a3d6dc4dfb0ab25f450cd202ff3bdb074f2edde1ddb4af5217e10c9dbafb9639a0a4fd7690d1a25aeaa97'
                ), None)

        expected_parent_hash = blockchain.hash_header(expected_parent_header)
        observed_parent_hash = blockchain.hash_header(
            header_auxpow['parent_header'])
        self.assertEqual(expected_parent_hash, observed_parent_hash)

        expected_parent_merkle_root = expected_parent_header['merkle_root']
        observed_parent_merkle_root = header_auxpow['parent_header'][
            'merkle_root']
        self.assertEqual(expected_parent_merkle_root,
                         observed_parent_merkle_root)
Esempio n. 37
0
 def test_encode_decode_msg__missing_mandatory_field_gets_set_to_zeroes(self):
     # "channel_update": "signature" missing -> gets set to zeroes
     self.assertEqual(bfh(frombtc("01020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000043497fd7f826957108f4a30fd9cec3aeba79972084e90ead01ea33090000000000d43100006f00025e6ed0830100009000000000000000c8000001f400000023000000003b9aca00")),
                      encode_msg(
                          "channel_update",
                          short_channel_id=ShortChannelID.from_components(54321, 111, 2),
                          channel_flags=b'\x00',
                          message_flags=b'\x01',
                          cltv_expiry_delta=144,
                          htlc_minimum_msat=200,
                          htlc_maximum_msat=1_000_000_000,
                          fee_base_msat=500,
                          fee_proportional_millionths=35,
                          chain_hash=constants.net.rev_genesis_bytes(),
                          timestamp=1584320643,
                      ))
Esempio n. 38
0
    def _make_multisig(self, m, xpubs, signatures=None):
        if len(xpubs) == 1:
            return None

        pubkeys = [self._make_node_path(xpub, deriv) for xpub, deriv in xpubs]
        if signatures is None:
            signatures = [b''] * len(pubkeys)
        elif len(signatures) != len(pubkeys):
            raise RuntimeError('Mismatched number of signatures')
        else:
            signatures = [bfh(x)[:-1] if x else b'' for x in signatures]

        return MultisigRedeemScriptType(
            pubkeys=pubkeys,
            signatures=signatures,
            m=m)
Esempio n. 39
0
 def do_send(self, tx):
     for window, xpub, K, _hash in self.cosigner_list:
         if not self.cosigner_can_sign(tx, xpub):
             continue
         message = bitcoin.encrypt_message(bfh(tx.raw),
                                           bh2u(K)).decode('ascii')
         try:
             server.put(_hash, message)
         except Exception as e:
             traceback.print_exc(file=sys.stdout)
             window.show_message(
                 "Failed to send transaction to cosigning pool.")
             return
         window.show_message(
             "Your transaction was sent to the cosigning pool.\nOpen your cosigner wallet to retrieve it."
         )
Esempio n. 40
0
 def sign_transaction(self, keystore, tx, prev_tx, xpub_path):
     prev_tx = {
         bfh(txhash): self.electrum_tx_to_txtype(tx, xpub_path)
         for txhash, tx in prev_tx.items()
     }
     client = self.get_client(keystore)
     inputs = self.tx_inputs(tx, xpub_path, True)
     outputs = self.tx_outputs(keystore.get_derivation(), tx)
     details = SignTx(lock_time=tx.locktime, version=tx.version)
     signatures, _ = client.sign_tx(self.get_coin_name(),
                                    inputs,
                                    outputs,
                                    details=details,
                                    prev_txes=prev_tx)
     signatures = [(bh2u(x) + '01') for x in signatures]
     tx.update_signatures(signatures)
Esempio n. 41
0
 def test_scrypt(self):
     #0200000011f1fe21e0b66dc214be46366465cb95d29830e31ddd225a11349a836a993bf7b5db36b3e5593d039779bff204d132b65ee029a2e499ebeb5a4b19cbe862eee2b623cc5276676c1c000e1c60
     header = {
         'block_height': 12095,
         'nonce': 1612451328,
         'timestamp': 1389110198,
         'version': 2,
         'prev_block_hash':
         'f73b996a839a34115a22dd1de33098d295cb65643646be14c26db6e021fef111',
         'merkle_root':
         'e2ee62e8cb194b5aebeb99e4a229e05eb632d104f2bf7997033d59e5b336dbb5',
         'bits': 476866422
     }
     powhash = rev_hex(bh2u(scryptGetHash(bfh(serialize_header(header)))))
     self.assertEqual(
         powhash,
         '00000000335c88172421df73a1c1f22f4d7c23d8ef34c78d728c4eff3ba24a34')
Esempio n. 42
0
    def on_receive(self, keyhash, message):
        self.print_error("signal arrived for", keyhash)
        for key, _hash, window in self.keys:
            if _hash == keyhash:
                break
        else:
            self.print_error("keyhash not found")
            return

        wallet = window.wallet
        if isinstance(wallet.keystore, keystore.Hardware_KeyStore):
            window.show_warning(
                _('An encrypted transaction was retrieved from cosigning pool.'
                  ) + '\n' +
                _('However, hardware wallets do not support message decryption, '
                  'which makes them not compatible with the current design of cosigner pool.'
                  ))
            return
        elif wallet.has_keystore_encryption():
            password = window.password_dialog(
                _('An encrypted transaction was retrieved from cosigning pool.'
                  ) + '\n' + _('Please enter your password to decrypt it.'))
            if not password:
                return
        else:
            password = None
            if not window.question(
                    _("An encrypted transaction was retrieved from cosigning pool."
                      ) + '\n' + _("Do you want to open it now?")):
                return

        xprv = wallet.keystore.get_master_private_key(password)
        if not xprv:
            return
        try:
            k = bh2u(bitcoin.deserialize_xprv(xprv)[-1])
            EC = bitcoin.EC_KEY(bfh(k))
            message = bh2u(EC.decrypt_message(message))
        except Exception as e:
            traceback.print_exc(file=sys.stdout)
            window.show_message(str(e))
            return

        self.listener.clear(keyhash)
        tx = transaction.Transaction(message)
        show_transaction(tx, window, prompt_if_unsaved=True)
Esempio n. 43
0
    def test_decode_onion_error(self):
        orf = OnionRoutingFailure.from_bytes(
            bfh("400f0000000017d2d8b0001d9458"))
        self.assertEqual(('incorrect_or_unknown_payment_details', {
            'htlc_msat': 399694000,
            'height': 1938520
        }), OnionWireSerializer.decode_msg(orf.to_bytes()))
        self.assertEqual({
            'htlc_msat': 399694000,
            'height': 1938520
        }, orf.decode_data())

        orf2 = OnionRoutingFailure(26399,
                                   bytes.fromhex("0000000017d2d8b0001d9458"))
        with self.assertRaises(UnknownMsgType):
            OnionWireSerializer.decode_msg(orf2.to_bytes())
        self.assertEqual(None, orf2.decode_data())
Esempio n. 44
0
    def check_deserialization(self, fcn, hex_data):
        """
    Runs the deserialisation function fcn on the data given as hex, starting
    from position 80 (after the pure header).  This also verifies the expected
    error if we reach EOF, and returns the parsed dict.
    """

        data = bfh(hex_data)
        start = blockchain.PURE_HEADER_SIZE

        # A too-short auxpow raises an InvalidHeader exception rather than
        # our powdata one.  Just check for any error here.
        with self.assertRaises(Exception):
            fcn(data[:-1], expect_trailing_data=True, start_position=start)

        res, _ = fcn(data, start_position=start)
        return res
Esempio n. 45
0
    def test_get_address_from_output_script(self):
        # the inverse of this test is in test_bitcoin: test_address_to_script
        addr_from_script = lambda script: transaction.get_address_from_output_script(
            bfh(script))
        ADDR = transaction.TYPE_ADDRESS

        # bech32 native segwit
        # test vectors from BIP-0173
        self.assertEqual(
            (ADDR, 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4'),
            addr_from_script('0014751e76e8199196d454941c45d1b3a323f1433bd6'))
        self.assertEqual(
            (ADDR,
             'bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7k7grplx'
             ),
            addr_from_script(
                '5128751e76e8199196d454941c45d1b3a323f1433bd6751e76e8199196d454941c45d1b3a323f1433bd6'
            ))
        self.assertEqual((ADDR, 'bc1sw50qa3jx3s'),
                         addr_from_script('6002751e'))
        self.assertEqual(
            (ADDR, 'bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj'),
            addr_from_script('5210751e76e8199196d454941c45d1b3a323'))

        # base58 p2pkh
        self.assertEqual(
            (ADDR, '14gcRovpkCoGkCNBivQBvw7eso7eiNAbxG'),
            addr_from_script(
                '76a91428662c67561b95c79d2257d2a93d9d151c977e9188ac'))
        self.assertEqual(
            (ADDR, '1BEqfzh4Y3zzLosfGhw1AsqbEKVW6e1qHv'),
            addr_from_script(
                '76a914704f4b81cadb7bf7e68c08cd3657220f680f863c88ac'))
        self.assertEqual(
            (ADDR, '18u8VTYhogvwek9rUQRtHKn66Sf6a2RV5w'),
            addr_from_script(
                '76a91456a4c36cd1fdb71a493fec9941b69b4a7cec90ea88ac'))

        # base58 p2sh
        self.assertEqual(
            (ADDR, '35ZqQJcBQMZ1rsv8aSuJ2wkC7ohUCQMJbT'),
            addr_from_script('a9142a84cf00d47f699ee7bbc1dea5ec1bdecb4ac15487'))
        self.assertEqual(
            (ADDR, '3PyjzJ3im7f7bcV724GR57edKDqoZvH7Ji'),
            addr_from_script('a914f47c8954e421031ad04ecd8e7752c9479206b9d387'))
Esempio n. 46
0
 def sign_transaction(self, keystore, tx: PartialTransaction, prev_tx):
     prev_tx = {
         bfh(txhash): self.electrum_tx_to_txtype(tx)
         for txhash, tx in prev_tx.items()
     }
     client = self.get_client(keystore)
     inputs = self.tx_inputs(tx, for_sig=True, keystore=keystore)
     outputs = self.tx_outputs(tx, keystore=keystore)
     signatures, _ = client.sign_tx(
         self.get_coin_name(),
         inputs,
         outputs,
         lock_time=tx.locktime,
         version=tx.version,
         amount_unit=self.get_trezor_amount_unit(),
         prev_txes=prev_tx)
     signatures = [(bh2u(x) + '01') for x in signatures]
     tx.update_signatures(signatures)
Esempio n. 47
0
    def test_should_reject_coinbase_root_too_late(self):
        header = self.deserialize_with_auxpow(header_without_mm)

        input_script = header['powdata']['auxpow'][
            'parent_coinbase_tx'].inputs()[0].script_sig

        padded_script = bfh('00') * (
            auxpow.MAX_INDEX_PC_BACKWARDS_COMPATIBILITY + 4)
        padded_script += input_script

        header['powdata']['auxpow']['parent_coinbase_tx']._inputs[
            0].script_sig = padded_script

        self.clear_coinbase_outputs(header['powdata']['auxpow'])

        with self.assertRaises(auxpow.AuxPoWCoinbaseRootTooLate):
            blockchain.Blockchain.verify_header(header, prev_hash_without_mm,
                                                target_without_mm)
    def test_decode_onion_error(self):
        # test vector from bolt-04
        payment_path_pubkeys = [
            bfh('02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619'),
            bfh('0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c'),
            bfh('027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007'),
            bfh('032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991'),
            bfh('02edabbd16b41c8371b92ef2f04c1185b4f03b6dcd52ba9b78d9d7c89c8f221145'),
        ]
        session_key = bfh('4141414141414141414141414141414141414141414141414141414141414141')
        error_packet_for_node_0 = bfh('9c5add3963fc7f6ed7f148623c84134b5647e1306419dbe2174e523fa9e2fbed3a06a19f899145610741c83ad40b7712aefaddec8c6baf7325d92ea4ca4d1df8bce517f7e54554608bf2bd8071a4f52a7a2f7ffbb1413edad81eeea5785aa9d990f2865dc23b4bc3c301a94eec4eabebca66be5cf638f693ec256aec514620cc28ee4a94bd9565bc4d4962b9d3641d4278fb319ed2b84de5b665f307a2db0f7fbb757366067d88c50f7e829138fde4f78d39b5b5802f1b92a8a820865af5cc79f9f30bc3f461c66af95d13e5e1f0381c184572a91dee1c849048a647a1158cf884064deddbf1b0b88dfe2f791428d0ba0f6fb2f04e14081f69165ae66d9297c118f0907705c9c4954a199bae0bb96fad763d690e7daa6cfda59ba7f2c8d11448b604d12d')

        decoded_error, index_of_sender = _decode_onion_error(error_packet_for_node_0, payment_path_pubkeys, session_key)
        self.assertEqual(bfh('4c2fc8bc08510334b6833ad9c3e79cd1b52ae59dfe5c2a4b23ead50f09f7ee0b0002200200fe0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'),
                             decoded_error)
        self.assertEqual(4, index_of_sender)

        failure_msg, index_of_sender = decode_onion_error(error_packet_for_node_0, payment_path_pubkeys, session_key)
        self.assertEqual(4, index_of_sender)
        self.assertEqual(OnionFailureCode.TEMPORARY_NODE_FAILURE, failure_msg.code)
        self.assertEqual(b'', failure_msg.data)
Esempio n. 49
0
    def show_address(self,
                     wallet,
                     address,
                     keystore: 'Coldcard_KeyStore' = None):
        if keystore is None:
            keystore = wallet.get_keystore()
        if not self.show_address_helper(wallet, address, keystore):
            return

        txin_type = wallet.get_txin_type(address)

        # Standard_Wallet => not multisig, must be bip32
        if type(wallet) is Standard_Wallet:
            sequence = wallet.get_address_index(address)
            keystore.show_address(sequence, txin_type)
        elif type(wallet) is Multisig_Wallet:
            assert isinstance(
                wallet, Multisig_Wallet)  # only here for type-hints in IDE
            # More involved for P2SH/P2WSH addresses: need M, and all public keys, and their
            # derivation paths. Must construct script, and track fingerprints+paths for
            # all those keys

            pubkey_deriv_info = wallet.get_public_keys_with_deriv_info(address)
            pubkey_hexes = sorted([pk.hex() for pk in list(pubkey_deriv_info)])
            xfp_paths = []
            for pubkey_hex in pubkey_hexes:
                pubkey = bytes.fromhex(pubkey_hex)
                ks, der_suffix = pubkey_deriv_info[pubkey]
                fp_bytes, der_full = ks.get_fp_and_derivation_to_be_used_in_partial_tx(
                    der_suffix, only_der_suffix=False)
                xfp_int = xfp_int_from_xfp_bytes(fp_bytes)
                xfp_paths.append([xfp_int] + list(der_full))

            script = bfh(wallet.pubkeys_to_scriptcode(pubkey_hexes))

            keystore.show_p2sh_address(wallet.m, script, xfp_paths, txin_type)

        else:
            keystore.handler.show_error(
                _('This function is only available for standard wallets when using {}.'
                  ).format(self.device))
            return
Esempio n. 50
0
 def sign_transaction(self, keystore, tx: PartialTransaction, prev_tx):
     prev_tx = {
         bfh(txhash): self.electrum_tx_to_txtype(tx)
         for txhash, tx in prev_tx.items()
     }
     client = self.get_client(keystore)
     inputs = self.tx_inputs(tx, for_sig=True, keystore=keystore)
     outputs = self.tx_outputs(tx, keystore=keystore)
     details = SignTx(version=tx.version,
                      overwintered=tx.overwintered,
                      version_group_id=tx.versionGroupId,
                      lock_time=tx.locktime,
                      expiry=tx.expiryHeight)
     signatures, _ = client.sign_tx(self.get_coin_name(),
                                    inputs,
                                    outputs,
                                    details=details,
                                    prev_txes=prev_tx)
     signatures = [(bh2u(x) + '01') for x in signatures]
     tx.update_signatures(signatures)
Esempio n. 51
0
    def clear_coinbase_outputs(auxpow_header: dict, fix_merkle_root=True) -> None:
        """Clears the auxpow coinbase outputs

        Set the outputs of the auxpow coinbase to an empty list.  This is
        necessary when the coinbase has been modified and needs to be
        re-serialised, since present outputs are invalid due to the
        fast_tx_deserialize optimisation."""

        auxpow_header['parent_coinbase_tx']._outputs = []

        # Clear the cached raw serialization
        auxpow_header['parent_coinbase_tx'].invalidate_ser_cache()

        # Re-serialize.  Note that our AuxPoW library won't do this for us,
        # because it optimizes via fast_txid.
        auxpow_header['parent_coinbase_tx']._cached_network_ser_bytes = bfh(auxpow_header['parent_coinbase_tx'].serialize_to_network(force_legacy=True))

        # Correct the coinbase Merkle root.
        if fix_merkle_root:
            update_merkle_root_to_match_coinbase(auxpow_header)
Esempio n. 52
0
    def do_send(self, tx):
        def on_success(result):
            window.show_message(_("Your transaction was sent to the cosigning pool.") + '\n' +
                                _("Open your cosigner wallet to retrieve it."))
        def on_failure(exc_info):
            e = exc_info[1]
            try: traceback.print_exception(*exc_info)
            except OSError: pass
            window.show_error(_("Failed to send transaction to cosigning pool") + ':\n' + str(e))

        for window, xpub, K, _hash in self.cosigner_list:
            if not self.cosigner_can_sign(tx, xpub):
                continue
            # construct message
            raw_tx_bytes = bfh(str(tx))
            public_key = ecc.ECPubkey(K)
            message = public_key.encrypt_message(raw_tx_bytes).decode('ascii')
            # send message
            task = lambda: server.put(_hash, message)
            msg = _('Sending transaction to cosigning pool...')
            WaitingDialog(window, msg, task, on_success, on_failure)
Esempio n. 53
0
    def show_address(self, wallet, address, keystore=None):
        if keystore is None:
            keystore = wallet.get_keystore()
        if not self.show_address_helper(wallet, address, keystore):
            return

        txin_type = wallet.get_txin_type(address)

        # Standard_Wallet => not multisig, must be bip32
        if type(wallet) is Standard_Wallet:
            sequence = wallet.get_address_index(address)
            keystore.show_address(sequence, txin_type)
        elif type(wallet) is Multisig_Wallet:
            # More involved for P2SH/P2WSH addresses: need M, and all public keys, and their
            # derivation paths. Must construct script, and track fingerprints+paths for
            # all those keys

            pubkeys = wallet.get_public_keys(address)

            xfps = []
            for xp, ks in zip(wallet.get_master_public_keys(), wallet.get_keystores()):
                path = "%s/%d/%d" % (getattr(ks, 'derivation', 'm'),
                                        *wallet.get_address_index(address))

                # need master XFP for each co-signers
                ks_xfp = xfp_for_keystore(ks)
                xfps.append(unpacked_xfp_path(ks_xfp, path))

            # put into BIP45 (sorted) order
            pkx = list(sorted(zip(pubkeys, xfps)))

            script = bfh(multisig_script([pk for pk,xfp in pkx], wallet.m))

            keystore.show_p2sh_address(wallet.m, script, [xfp for pk,xfp in pkx], txin_type)

        else:
            keystore.handler.show_error(_('This function is only available for standard wallets when using {}.').format(self.device))
            return
Esempio n. 54
0
    def on_receive(self, keyhash, message):
        self.print_error("signal arrived for", keyhash)
        for key, _hash, window in self.keys:
            if _hash == keyhash:
                break
        else:
            self.print_error("keyhash not found")
            return

        wallet = window.wallet
        if wallet.has_keystore_encryption():
            password = window.password_dialog(
                'An encrypted transaction was retrieved from cosigning pool.\nPlease enter your password to decrypt it.'
            )
            if not password:
                return
        else:
            password = None
            if not window.question(
                    _("An encrypted transaction was retrieved from cosigning pool.\nDo you want to open it now?"
                      )):
                return

        xprv = wallet.keystore.get_master_private_key(password)
        if not xprv:
            return
        try:
            k = bh2u(bitcoin.deserialize_xprv(xprv)[-1])
            EC = bitcoin.EC_KEY(bfh(k))
            message = bh2u(EC.decrypt_message(message))
        except Exception as e:
            traceback.print_exc(file=sys.stdout)
            window.show_message(str(e))
            return

        self.listener.clear(keyhash)
        tx = transaction.Transaction(message)
        show_transaction(tx, window, prompt_if_unsaved=True)
Esempio n. 55
0
    def test_sign_transaction(self):
        eckey1 = ecc.ECPrivkey(
            bfh('7e1255fddb52db1729fc3ceb21a46f95b8d9fe94cc83425e936a6c5223bb679d'
                ))
        sig1 = eckey1.sign_transaction(
            bfh('5a548b12369a53faaa7e51b5081829474ebdd9c924b3a8230b69aa0be254cd94'
                ))
        self.assertEqual(
            bfh('3045022100902a288b98392254cd23c0e9a49ac6d7920f171b8249a48e484b998f1874a2010220723d844826828f092cf400cb210c4fa0b8cd1b9d1a7f21590e78e022ff6476b9'
                ), sig1)

        eckey2 = ecc.ECPrivkey(
            bfh('c7ce8c1462c311eec24dff9e2532ac6241e50ae57e7d1833af21942136972f23'
                ))
        sig2 = eckey2.sign_transaction(
            bfh('642a2e66332f507c92bda910158dfe46fc10afbf72218764899d3af99a043fac'
                ))
        self.assertEqual(
            bfh('30440220618513f4cfc87dde798ce5febae7634c23e7b9254a1eabf486be820f6a7c2c4702204fef459393a2b931f949e63ced06888f35e286e446dc46feb24b5b5f81c6ed52'
                ), sig2)
Esempio n. 56
0
 def test_add_number_to_script(self):
     # https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki#numbers
     self.assertEqual(add_number_to_script(0), bytes([opcodes.OP_0]))
     self.assertEqual(add_number_to_script(7), bytes([opcodes.OP_7]))
     self.assertEqual(add_number_to_script(16), bytes([opcodes.OP_16]))
     self.assertEqual(add_number_to_script(-1), bytes([opcodes.OP_1NEGATE]))
     self.assertEqual(add_number_to_script(-127), bfh('01ff'))
     self.assertEqual(add_number_to_script(-2), bfh('0182'))
     self.assertEqual(add_number_to_script(17), bfh('0111'))
     self.assertEqual(add_number_to_script(127), bfh('017f'))
     self.assertEqual(add_number_to_script(-32767), bfh('02ffff'))
     self.assertEqual(add_number_to_script(-128), bfh('028080'))
     self.assertEqual(add_number_to_script(128), bfh('028000'))
     self.assertEqual(add_number_to_script(32767), bfh('02ff7f'))
     self.assertEqual(add_number_to_script(-8388607), bfh('03ffffff'))
     self.assertEqual(add_number_to_script(-32768), bfh('03008080'))
     self.assertEqual(add_number_to_script(32768), bfh('03008000'))
     self.assertEqual(add_number_to_script(8388607), bfh('03ffff7f'))
     self.assertEqual(add_number_to_script(-2147483647), bfh('04ffffffff'))
     self.assertEqual(add_number_to_script(-8388608 ), bfh('0400008080'))
     self.assertEqual(add_number_to_script(8388608), bfh('0400008000'))
     self.assertEqual(add_number_to_script(2147483647), bfh('04ffffff7f'))
Esempio n. 57
0
    def sign_transaction(self, tx, password):
        if tx.is_complete():
            return
        client = self.get_client()
        inputs = []
        inputsPaths = []
        pubKeys = []
        chipInputs = []
        redeemScripts = []
        signatures = []
        preparedTrustedInputs = []
        changePath = ""
        changeAmount = None
        output = None
        outputAmount = None
        p2shTransaction = False
        segwitTransaction = False
        pin = ""
        self.get_client() # prompt for the PIN before displaying the dialog if necessary

        # Fetch inputs of the transaction to sign
        derivations = self.get_tx_derivations(tx)
        for txin in tx.inputs():
            if txin['type'] == 'coinbase':
                self.give_error("Coinbase not supported")     # should never happen

            if txin['type'] in ['p2sh']:
                p2shTransaction = True

            if txin['type'] in ['p2wpkh-p2sh', 'p2wsh-p2sh']:
                if not self.get_client_electrum().supports_segwit():
                    self.give_error(MSG_NEEDS_FW_UPDATE_SEGWIT)
                segwitTransaction = True

            if txin['type'] in ['p2wpkh', 'p2wsh']:
                if not self.get_client_electrum().supports_native_segwit():
                    self.give_error(MSG_NEEDS_FW_UPDATE_SEGWIT)
                segwitTransaction = True

            pubkeys, x_pubkeys = tx.get_sorted_pubkeys(txin)
            for i, x_pubkey in enumerate(x_pubkeys):
                if x_pubkey in derivations:
                    signingPos = i
                    s = derivations.get(x_pubkey)
                    hwAddress = "%s/%d/%d" % (self.get_derivation()[2:], s[0], s[1])
                    break
            else:
                self.give_error("No matching x_key for sign_transaction") # should never happen

            redeemScript = Transaction.get_preimage_script(txin)
            txin_prev_tx = txin.get('prev_tx')
            if txin_prev_tx is None and not Transaction.is_segwit_input(txin):
                raise Exception(_('Offline signing with {} is not supported for legacy inputs.').format(self.device))
            txin_prev_tx_raw = txin_prev_tx.raw if txin_prev_tx else None
            inputs.append([txin_prev_tx_raw,
                           txin['prevout_n'],
                           redeemScript,
                           txin['prevout_hash'],
                           signingPos,
                           txin.get('sequence', 0xffffffff - 1),
                           txin.get('value')])
            inputsPaths.append(hwAddress)
            pubKeys.append(pubkeys)

        # Sanity check
        if p2shTransaction:
            for txin in tx.inputs():
                if txin['type'] != 'p2sh':
                    self.give_error("P2SH / regular input mixed in same transaction not supported") # should never happen

        txOutput = var_int(len(tx.outputs()))
        for txout in tx.outputs():
            output_type, addr, amount = txout
            txOutput += int_to_hex(amount, 8)
            script = tx.pay_script(output_type, addr)
            txOutput += var_int(len(script)//2)
            txOutput += script
        txOutput = bfh(txOutput)

        # Recognize outputs - only one output and one change is authorized
        if not p2shTransaction:
            if not self.get_client_electrum().supports_multi_output():
                if len(tx.outputs()) > 2:
                    self.give_error("Transaction with more than 2 outputs not supported")
            for _type, address, amount in tx.outputs():
                assert _type == TYPE_ADDRESS
                info = tx.output_info.get(address)
                if (info is not None) and len(tx.outputs()) > 1 \
                        and info[0][0] == 1:  # "is on 'change' branch"
                    index, xpubs, m = info
                    changePath = self.get_derivation()[2:] + "/%d/%d"%index
                    changeAmount = amount
                else:
                    output = address
                    outputAmount = amount

        self.handler.show_message(_("Confirm Transaction on your Ledger device..."))
        try:
            # Get trusted inputs from the original transactions
            for utxo in inputs:
                sequence = int_to_hex(utxo[5], 4)
                if segwitTransaction:
                    tmp = bfh(utxo[3])[::-1]
                    tmp += bfh(int_to_hex(utxo[1], 4))
                    tmp += bfh(int_to_hex(utxo[6], 8))  # txin['value']
                    chipInputs.append({'value' : tmp, 'witness' : True, 'sequence' : sequence})
                    redeemScripts.append(bfh(utxo[2]))
                elif not p2shTransaction:
                    txtmp = bitcoinTransaction(bfh(utxo[0]))
                    trustedInput = self.get_client().getTrustedInput(txtmp, utxo[1])
                    trustedInput['sequence'] = sequence
                    chipInputs.append(trustedInput)
                    redeemScripts.append(txtmp.outputs[utxo[1]].script)
                else:
                    tmp = bfh(utxo[3])[::-1]
                    tmp += bfh(int_to_hex(utxo[1], 4))
                    chipInputs.append({'value' : tmp, 'sequence' : sequence})
                    redeemScripts.append(bfh(utxo[2]))

            # Sign all inputs
            firstTransaction = True
            inputIndex = 0
            rawTx = tx.serialize()
            self.get_client().enableAlternate2fa(False)
            if segwitTransaction:
                self.get_client().startUntrustedTransaction(True, inputIndex,
                                                            chipInputs, redeemScripts[inputIndex])
                if changePath:
                    # we don't set meaningful outputAddress, amount and fees
                    # as we only care about the alternateEncoding==True branch
                    outputData = self.get_client().finalizeInput(b'', 0, 0, changePath, bfh(rawTx))
                else:
                    outputData = self.get_client().finalizeInputFull(txOutput)
                outputData['outputData'] = txOutput
                transactionOutput = outputData['outputData']
                if outputData['confirmationNeeded']:
                    outputData['address'] = output
                    self.handler.finished()
                    pin = self.handler.get_auth( outputData ) # does the authenticate dialog and returns pin
                    if not pin:
                        raise UserWarning()
                    if pin != 'paired':
                        self.handler.show_message(_("Confirmed. Signing Transaction..."))
                while inputIndex < len(inputs):
                    singleInput = [ chipInputs[inputIndex] ]
                    self.get_client().startUntrustedTransaction(False, 0,
                                                            singleInput, redeemScripts[inputIndex])
                    inputSignature = self.get_client().untrustedHashSign(inputsPaths[inputIndex], pin, lockTime=tx.locktime)
                    inputSignature[0] = 0x30 # force for 1.4.9+
                    signatures.append(inputSignature)
                    inputIndex = inputIndex + 1
            else:
                while inputIndex < len(inputs):
                    self.get_client().startUntrustedTransaction(firstTransaction, inputIndex,
                                                            chipInputs, redeemScripts[inputIndex])
                    if changePath:
                        # we don't set meaningful outputAddress, amount and fees
                        # as we only care about the alternateEncoding==True branch
                        outputData = self.get_client().finalizeInput(b'', 0, 0, changePath, bfh(rawTx))
                    else:
                        outputData = self.get_client().finalizeInputFull(txOutput)
                    outputData['outputData'] = txOutput
                    if firstTransaction:
                        transactionOutput = outputData['outputData']
                    if outputData['confirmationNeeded']:
                        outputData['address'] = output
                        self.handler.finished()
                        pin = self.handler.get_auth( outputData ) # does the authenticate dialog and returns pin
                        if not pin:
                            raise UserWarning()
                        if pin != 'paired':
                            self.handler.show_message(_("Confirmed. Signing Transaction..."))
                    else:
                        # Sign input with the provided PIN
                        inputSignature = self.get_client().untrustedHashSign(inputsPaths[inputIndex], pin, lockTime=tx.locktime)
                        inputSignature[0] = 0x30 # force for 1.4.9+
                        signatures.append(inputSignature)
                        inputIndex = inputIndex + 1
                    if pin != 'paired':
                        firstTransaction = False
        except UserWarning:
            self.handler.show_error(_('Cancelled by user'))
            return
        except BTChipException as e:
            if e.sw == 0x6985:  # cancelled by user
                return
            elif e.sw == 0x6982:
                raise  # pin lock. decorator will catch it
            else:
                traceback.print_exc(file=sys.stderr)
                self.give_error(e, True)
        except BaseException as e:
            traceback.print_exc(file=sys.stdout)
            self.give_error(e, True)
        finally:
            self.handler.finished()

        for i, txin in enumerate(tx.inputs()):
            signingPos = inputs[i][4]
            Transaction.add_signature_to_txin(txin, signingPos, bh2u(signatures[i]))
        tx.raw = tx.serialize()
Esempio n. 58
0
    def tx_inputs(self, tx, for_sig=False, script_gen=SCRIPT_GEN_LEGACY):
        inputs = []
        for txin in tx.inputs():
            txinputtype = self.types.TxInputType()
            if txin['type'] == 'coinbase':
                prev_hash = "\0" * 32
                prev_index = 0xffffffff  # signed int -1
            else:
                if for_sig:
                    x_pubkeys = txin['x_pubkeys']
                    if len(x_pubkeys) == 1:
                        x_pubkey = x_pubkeys[0]
                        xpub, s = parse_xpubkey(x_pubkey)
                        xpub_n = self.client_class.expand_path(
                            self.xpub_path[xpub])
                        txinputtype._extend_address_n(xpub_n + s)
                        if script_gen == SCRIPT_GEN_NATIVE_SEGWIT:
                            txinputtype.script_type = self.types.InputScriptType.SPENDWITNESS
                        elif script_gen == SCRIPT_GEN_P2SH_SEGWIT:
                            txinputtype.script_type = self.types.InputScriptType.SPENDP2SHWITNESS
                        else:
                            txinputtype.script_type = self.types.InputScriptType.SPENDADDRESS
                    else:

                        def f(x_pubkey):
                            if is_xpubkey(x_pubkey):
                                xpub, s = parse_xpubkey(x_pubkey)
                            else:
                                xpub = xpub_from_pubkey(0, bfh(x_pubkey))
                                s = []
                            node = self.ckd_public.deserialize(xpub)
                            return self.types.HDNodePathType(node=node,
                                                             address_n=s)

                        pubkeys = list(map(f, x_pubkeys))
                        multisig = self.types.MultisigRedeemScriptType(
                            pubkeys=pubkeys,
                            signatures=list(
                                map(lambda x: bfh(x)[:-1] if x else b'',
                                    txin.get('signatures'))),
                            m=txin.get('num_sig'),
                        )
                        if script_gen == SCRIPT_GEN_NATIVE_SEGWIT:
                            script_type = self.types.InputScriptType.SPENDWITNESS
                        elif script_gen == SCRIPT_GEN_P2SH_SEGWIT:
                            script_type = self.types.InputScriptType.SPENDP2SHWITNESS
                        else:
                            script_type = self.types.InputScriptType.SPENDMULTISIG
                        txinputtype = self.types.TxInputType(
                            script_type=script_type, multisig=multisig)
                        # find which key is mine
                        for x_pubkey in x_pubkeys:
                            if is_xpubkey(x_pubkey):
                                xpub, s = parse_xpubkey(x_pubkey)
                                if xpub in self.xpub_path:
                                    xpub_n = self.client_class.expand_path(
                                        self.xpub_path[xpub])
                                    txinputtype._extend_address_n(xpub_n + s)
                                    break

                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

            if 'scriptSig' in txin:
                script_sig = bfh(txin['scriptSig'])
                txinputtype.script_sig = script_sig

            txinputtype.sequence = txin.get('sequence', 0xffffffff - 1)

            inputs.append(txinputtype)

        return inputs
Esempio n. 59
0
 def test_push_script(self):
     # https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki#push-operators
     self.assertEqual(push_script(''), bh2u(bytes([opcodes.OP_0])))
     self.assertEqual(push_script('07'), bh2u(bytes([opcodes.OP_7])))
     self.assertEqual(push_script('10'), bh2u(bytes([opcodes.OP_16])))
     self.assertEqual(push_script('81'), bh2u(bytes([opcodes.OP_1NEGATE])))
     self.assertEqual(push_script('11'), '0111')
     self.assertEqual(push_script(75 * '42'), '4b' + 75 * '42')
     self.assertEqual(push_script(76 * '42'), bh2u(bytes([opcodes.OP_PUSHDATA1]) + bfh('4c' + 76 * '42')))
     self.assertEqual(push_script(100 * '42'), bh2u(bytes([opcodes.OP_PUSHDATA1]) + bfh('64' + 100 * '42')))
     self.assertEqual(push_script(255 * '42'), bh2u(bytes([opcodes.OP_PUSHDATA1]) + bfh('ff' + 255 * '42')))
     self.assertEqual(push_script(256 * '42'), bh2u(bytes([opcodes.OP_PUSHDATA2]) + bfh('0001' + 256 * '42')))
     self.assertEqual(push_script(520 * '42'), bh2u(bytes([opcodes.OP_PUSHDATA2]) + bfh('0802' + 520 * '42')))