def test_version_bytes(self): xprv_headers_b58 = { 'standard': 'tprv', } xpub_headers_b58 = { 'standard': 'tpub', } 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]))
def test_cadex_tx_sub_tx_reset_key(self): tx = transaction.Transaction(SUB_TX_RESET_KEY) deser = tx.deserialize() assert deser['version'] == 3 assert deser['tx_type'] == 10 extra = deser['extra_payload'] assert (str(extra)) assert extra.version == 1 assert len(extra.regTxHash) == 32 assert extra.regTxHash == bfh( 'd384e42374e8abfeffffff01570b000000a40100b67ffbbd095de31ea3844675') assert len(extra.hashPrevSubTx) == 32 assert extra.hashPrevSubTx == bfh( 'af3e98e9601210293360bf2a2e810673412bc6e8e0e358f3fb7bdbe9a667b3d0') assert extra.creditFee == 1000 assert len(extra.newPubKey) == 48 assert extra.newPubKey == bfh( '601210293360bf2a2e810673412bc6e8e0e358f3fb7bdbe9a667b3d0103f7' '61caf3e98e9601210293360bf2a2e810673') assert len(extra.payloadSig) == 96 assert extra.payloadSig == bfh( '412bc6e8e0e358f3fb7bdbe9a667b3d0103f761caf3e98e9601210293360b' 'f2a2e810673412bc6e8e0e358f3fb7bdbe9a667b3d0103f761caf3e98e960' '1210293360bf2a2e810673412bc6e8e0e358f3fb7bdbe9a667b3d0103f761' 'cabcdefab') ser = tx.serialize() assert ser == SUB_TX_RESET_KEY
def test_cadex_tx_pro_up_serv_tx(self): tx = transaction.Transaction(PRO_UP_SERV_TX) deser = tx.deserialize() assert deser['version'] == 3 assert deser['tx_type'] == 2 extra = deser['extra_payload'] assert (str(extra)) assert extra.version == 1 assert len(extra.proTxHash) == 32 assert extra.proTxHash == bfh( '3c6dca244f49f19d3f09889753ffff1fec5bb8f9f5bd5bc09dabd999da21198f') assert extra.ipAddress == '95.183.53.128' assert extra.port == 10001 assert extra.scriptOperatorPayout == bfh( '76a91421851058431a7d722e8e8dd9509e7f2b8e7042ec88ac') assert len(extra.inputsHash) == 32 assert extra.inputsHash == bfh( 'efcfe3d578914bb48c6bd71b3459d384e4237446d521c9e2c6' 'b6fcf019b5aafc') assert len(extra.payloadSig) == 96 assert extra.payloadSig == bfh( '99443fe14f644cfa47086e8897cf7b546a67723d4a8ec5353a82f962a96e' 'c3cea328343b647aace2897d6eddd0b8c8ee0f2e56f6733aed2e9f0006ca' 'afa6fc21c18a013c619d6e37af8d2f0985e3b769abc38ffa60e46c365a38' 'd9fa0d44fd62') ser = tx.serialize() assert ser == PRO_UP_SERV_TX
def parse_script(self, x): from electrum_cadex.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
def test_serialize_protocol_version_70210(self): announce = MasternodeAnnounce.deserialize(raw_announce_70210) msg = announce.serialize_for_sig() expected = to_bytes(''.join([ '178.151.192.107:19999', '1530021571', bitcoin.hash_encode(bitcoin.hash_160(bfh('0221088c51bef8c9c891b385fa1e8a78b016f01db41741aea7e43e67a7415ab7be'))), bitcoin.hash_encode(bitcoin.hash_160(bfh('042379a871a10ae6bf06e756262f69d7f0ce9b8b562f223bde964db573fb7d0f1e219c246a4b3a6133c5cec136d83f4049df51321ba2cb01d676cc3982c7e24d1f'))), '70210', ])) print('7'*50, expected) print('8'*50, msg) self.assertEqual(expected, msg)
def test_verify(self): announce = MasternodeAnnounce.deserialize(raw_announce) message = announce.serialize_for_sig() pk = bitcoin.public_key_to_p2pkh(bfh(announce.collateral_key)) self.assertTrue(announce.verify()) raw = '7ca6564432d0e0920b811887e1f9077a92924c83564e6ea8ea874fc8843ccd2b0000000000ffffffff00000000000000000000ffffc0a801014e1f410411e2638aeb4584ff2e027b6ee20e05655ff05583185b1d87188185d6955534fe02ad35caabb5e6e9ce8747ba73fdccccd2369feb9a6f2b0bdee93378e7c8f1c0410411e2638aeb4584ff2e027b6ee20e05655ff05583185b1d87188185d6955534fe02ad35caabb5e6e9ce8747ba73fdccccd2369feb9a6f2b0bdee93378e7c8f1c0411bab132617d8e6a0e3b5434c91a5a64ff13a9cfadc6c178a47b87691f13a26e7440c08660e488ddf927bba1bf04c1ec196370452a30fd3381ea8ba27d627f9d4468be80e5700000000d71101007ca6564432d0e0920b811887e1f9077a92924c83564e6ea8ea874fc8843ccd2b0000000000ffffffffd75eb4fa0cb71dd2e99d7b242784a5601c5c86d7c1cf0362a3391575070000008be80e5700000000411b6d5985008e0821c936fafc192f31963141ae2fab837e84bb9f12422711c1952d5750f9a781c89117a6f4576edc1149a1bf211e7151c5c88cf3252e2d83cb154a0000000000000000' announce = MasternodeAnnounce.deserialize(raw) msg = announce.serialize_for_sig() pk = bitcoin.public_key_to_p2pkh(bfh(announce.collateral_key)) self.assertTrue(announce.verify(pk))
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)
def test_create_and_sign(self): collateral_pub = '038ae57bd0fa5b45640e771614ec571c7326a2266c78bb444f1971c85188411ba1' # XahPxwmCuKjPq69hzVxP18V1eASwDWbUrn delegate_pub = '02526201c87c1b4630aabbd04572eec3e2545e442503e57e60880fafcc1f684dbc' # Xx2nSdhaT7c9SREKBPAgzpkhu518XFgkgh protocol_version = 70103 ip = '0.0.0.0' port = 20000 addr = NetworkAddress(ip=ip, port=port) vin = {'prevout_hash': '00'*32, 'prevout_n': 0, 'scriptSig': '', 'sequence':0xffffffff} last_ping = MasternodePing(vin=vin, block_hash='ff'*32) announce = MasternodeAnnounce(vin=vin, addr=addr, collateral_key=collateral_pub, delegate_key=delegate_pub, protocol_version=protocol_version, last_ping=last_ping) collateral_wif = 'XJqCcyfnLYK4Y7ZDVjLrgPnsrq2cWMF6MX9cyhKgfMajwqrCwZaS' delegate_wif = 'XCbhXBc2N9q8kxqBF41rSuLWVpVVbDm7P1oPv9GxcrS9QXYBWZkB' announce.last_ping.sign(delegate_wif, bfh(delegate_pub), 1461858375) sig = announce.sign(collateral_wif, 1461858375) address = 'XahPxwmCuKjPq69hzVxP18V1eASwDWbUrn' self.assertTrue(announce.verify(address)) self.assertTrue(ecc.verify_message_with_address (address, sig, announce.serialize_for_sig()))
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)
def test_serialize_protocol_version_70201(self): raw = '08108933d948aed6a107cd01e7862ed61ef9bf14e87da0a14e8d17791e9f9c570100000000ffffffff00000000000000000000ffff7f0000014e1f210269e1abb1ffe231ea045068272a06f0fae231d11b11a54225867d89267faa4e23210269e1abb1ffe231ea045068272a06f0fae231d11b11a54225867d89267faa4e234120b8bc547ce2471125eddfdfd5af30ea1e892e750acfe2896b241097b7f21442a61da073d47c885535769bf215eb3e97eca692d868db1bfb9dee469a1ece5acb92a1945457000000003912010008108933d948aed6a107cd01e7862ed61ef9bf14e87da0a14e8d17791e9f9c570100000000ffffffffefc894d8431c1774a19aeb732ea7fc56925b740ed80486f30424109a05000000a1945457000000004120818f17742e6644359c8b9a91e56b595615bd2c593de713304435dcfd07ceb6a815559fd3b2f05f531d9b9918b22b8748491c3f36cb25e8397ff950f74030444f0000000000000000' announce = MasternodeAnnounce.deserialize(raw) announce.sig_time = 1465161129 msg = announce.serialize_for_sig() expected = to_bytes(''.join([ '127.0.0.1:19999', '1465161129', bitcoin.hash_encode(bitcoin.hash_160(bfh('0269e1abb1ffe231ea045068272a06f0fae231d11b11a54225867d89267faa4e23'))), bitcoin.hash_encode(bitcoin.hash_160(bfh('0269e1abb1ffe231ea045068272a06f0fae231d11b11a54225867d89267faa4e23'))), '70201', ])) print('7'*50, expected) print('8'*50, msg) self.assertEqual(expected, msg)
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)
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))
def test_cadex_tx_sub_tx_register(self): tx = transaction.Transaction(SUB_TX_REGISTER) deser = tx.deserialize() assert deser['version'] == 3 assert deser['tx_type'] == 8 extra = deser['extra_payload'] assert (str(extra)) assert extra.version == 1 assert extra.userName == b'abc' assert len(extra.pubKey) == 48 assert extra.pubKey == bfh( '8e7042ec88acefcfe3d578914bb48c6bd71b3459d384e42374e8abfeffff' 'ff01570b0000000000001976a91490c5ce9d') assert len(extra.payloadSig) == 96 assert extra.payloadSig == bfh( '8bc992a88ac00000000a40100b67ffbbd095de31ea38446754e8abfeffff' 'ff01570b0000000000001976a91490c5ce9d8bc992a88ac00000000a4010' '0b67ffbbd095de31ea38446754e8abfeffffff01570b0000000000001976' 'a91490c5ce9d') ser = tx.serialize() assert ser == SUB_TX_REGISTER
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 Exception( _("Only OP_RETURN scripts, with one constant push, are supported.") ) if output.value != 0: raise Exception(_("Amount for OP_RETURN output must be zero.")) return script[2:]
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
def test_cadex_tx_pro_up_reg_tx(self): tx = transaction.Transaction(PRO_UP_REG_TX) deser = tx.deserialize() assert deser['version'] == 3 assert deser['tx_type'] == 3 extra = deser['extra_payload'] assert (str(extra)) assert extra.version == 1 assert len(extra.proTxHash) == 32 assert extra.proTxHash == bfh( 'aeb817f94b8e699b58130a53d2fbe98d5519c2abe3b15e6f36c9abeb32e4dcce') assert extra.mode == 0 assert len(extra.PubKeyOperator) == 48 assert extra.PubKeyOperator == bfh( '1061eb559a64427ad239830742ef59591cdbbdffda7d3f5e7a2d95b9607a' 'd80e389191e44c59ea5987b85e6d0e3eb527') assert len(extra.KeyIdVoting) == 20 assert extra.KeyIdVoting == bfh( 'b9e198fa7a745913c9278ec993d4472a95dac425') assert extra.scriptPayout == bfh( '76a914eebbacffff3a55437803e0efb68a7d591e0409d188ac') assert len(extra.inputsHash) == 32 assert extra.inputsHash == bfh( '0eb0067e6ccdd2acb96e7279113702218f3f0ab6f2287e14c11c5be6f2051d5a') assert extra.payloadSig == bfh( '20cb00124d838b02207097048cb668244cd79df825eb2d4d211fd2c4604c1' '8b30e1ae9bb654787144d16856676efff180889f05b5c9121a483b4ae3f0e' 'a0ff3faf') ser = tx.serialize() assert ser == PRO_UP_REG_TX
def test_cadex_tx_sub_tx_topup(self): tx = transaction.Transaction(SUB_TX_TOPUP) deser = tx.deserialize() assert deser['version'] == 3 assert deser['tx_type'] == 9 extra = deser['extra_payload'] assert (str(extra)) assert extra.version == 1 assert len(extra.regTxHash) == 32 assert extra.regTxHash == bfh( 'd384e42374e8abfeffffff01570b000000a40100b67ffbbd095de31ea3844675') ser = tx.serialize() assert ser == SUB_TX_TOPUP
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')))
def test_cadex_tx_pro_up_rev_tx(self): tx = transaction.Transaction(PRO_UP_REV_TX) deser = tx.deserialize() assert deser['version'] == 3 assert deser['tx_type'] == 4 extra = deser['extra_payload'] assert (str(extra)) assert extra.version == 1 assert len(extra.proTxHash) == 32 assert extra.proTxHash == bfh( 'b67ffbbd095de31ea38446754b6bf251287936d2881d58b7c4efae0b54c75e9f') assert extra.reason == 0 assert len(extra.inputsHash) == 32 assert extra.inputsHash == bfh( 'eb073521b60306717f1d4feb3e9022f886b97bf981137684716a7d3d7e45b7fe') assert len(extra.payloadSig) == 96 assert extra.payloadSig == bfh( '83f4bb5530f7c5954e8b1ad50a74a9e1d65dcdcbe4acb8cbe3671abc7911' 'e8c3954856c4da7e5fd242f2e4f5546f08d90849245bc593d1605654e1a9' '9cd0a79e9729799742c48d4920044666ad25a85fd093559c43e4900e634c' '371b9b8d89ba') ser = tx.serialize() assert ser == PRO_UP_REV_TX
def test_cadex_tx_cb_tx(self): tx = transaction.Transaction(CB_TX) deser = tx.deserialize() assert deser['version'] == 3 assert deser['tx_type'] == 5 extra = deser['extra_payload'] assert (str(extra)) assert extra.version == 1 assert extra.height == 264132 assert len(extra.merkleRootMNList) == 32 assert extra.merkleRootMNList == bfh( '76629a6e42fb519188f65889fd3ac0201be87aa227462b5643e8bb2ec1d7a82a') ser = tx.serialize() assert ser == CB_TX
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
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
def test_cadex_tx_unknown_spec_tx(self): tx = transaction.Transaction(UNKNOWN_SPEC_TX) deser = tx.deserialize() assert deser['version'] == 3 assert deser['tx_type'] == 187 extra = deser['extra_payload'] assert extra == bfh( '0100d384e42374e8abfeffffff01570b000000a40100b67ffbbd095de31e' 'a3844675af3e98e9601210293360bf2a2e810673412bc6e8e0e358f3fb7b' 'dbe9a12bc6e8e0e358f3fb7bdbe9a62bc6e8e0e358f3fb7bdbe9a667b3d0' '103f761caf3e98e9601210293360bf2a2e810673412bc6e8e0e358f3fb7b' 'dbe9a667b3d0103f761caf3e98e9601210293360bf2a2e810673412bc6e8' 'e0e358f3fb7bdbe9a667b3d0103f761cabcdefab') ser = tx.serialize() assert ser == UNKNOWN_SPEC_TX
def test_cadex_tx_pro_reg_tx(self): tx = transaction.Transaction(PRO_REG_TX) deser = tx.deserialize() assert deser['version'] == 3 assert deser['tx_type'] == 1 extra = deser['extra_payload'] assert (str(extra)) assert extra.version == 1 assert extra.type == 0 assert extra.mode == 0 assert len(extra.collateralOutpoint.hash) == 32 assert extra.collateralOutpoint.hash == bfh( '4de1afa0a321bc88c34978d4eeba739256b86f8d8cdf47651b6f60e451f0a3de') assert extra.collateralOutpoint.index == 1 assert extra.ipAddress == '18.202.52.170' assert extra.port == 29999 assert len(extra.KeyIdOwner) == 20 assert extra.KeyIdOwner == bfh( '2b3edeed6842db1f59cf35de1ab5721094f049d0') assert len(extra.PubKeyOperator) == 48 assert extra.PubKeyOperator == bfh( '00ab986c589053b3f3bd720724e75e18581afdca54bce80d14750b1bcf920215' '8fe6c596ce8391815265747bd4a2009e') assert len(extra.KeyIdVoting) == 20 assert extra.KeyIdVoting == bfh( '2b3edeed6842db1f59cf35de1ab5721094f049d0') assert extra.operatorReward == 0 assert extra.scriptPayout == bfh( '76a9149bf5948b901a1e3e54e42c6e10496a17cd4067e088ac') assert len(extra.inputsHash) == 32 assert extra.inputsHash == bfh( '54d046585434668b4ee664c597864248b8a6aac33a7b2f4fcd1cc1b5da474a8a') assert extra.payloadSig == bfh( '1fc1617ae83406c92a9132f14f9fff1487f2890f401e776fdddd639bc505' '5c456268cf7497400d3196109c8cd31b94732caf6937d63de81d9a5be4db' '5beb83f9aa') ser = tx.serialize() assert ser == PRO_REG_TX
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)
def data(self, index, role=Qt.DisplayRole): data = None if not index.isValid(): return QVariant(data) if role not in [ Qt.DisplayRole, Qt.EditRole, Qt.ToolTipRole, Qt.FontRole, Qt.BackgroundRole ]: return None mn = self.masternodes[index.row()] i = index.column() if i == self.ALIAS: data = mn.alias elif i == self.STATUS: status = self.manager.masternode_statuses.get( mn.get_collateral_str()) data = masternode_status(status) if role == Qt.BackgroundRole: data = QBrush( QColor(ENABLED_MASTERNODE_BG)) if data[0] else None # Return the long description for data widget mappers. elif role == Qt.EditRole: data = data[2] else: data = data[1] elif i == self.VIN: txid = mn.vin.get('prevout_hash', '') out_n = str(mn.vin.get('prevout_n', '')) addr = mn.vin.get('address', '') value = str(mn.vin.get('value', '')) scriptsig = mn.vin.get('scriptSig', '') if role == Qt.EditRole: data = ':'.join([txid, out_n, addr, value, scriptsig]) elif role == Qt.FontRole: data = util.MONOSPACE_FONT else: if all(attr for attr in [txid, out_n, addr]): data = '%s:%s' % (txid, out_n) else: data = '' elif i == self.COLLATERAL: data = mn.collateral_key if role in [Qt.EditRole, Qt.DisplayRole, Qt.ToolTipRole] and data: data = bitcoin.public_key_to_p2pkh(bfh(data)) elif role == Qt.FontRole: data = util.MONOSPACE_FONT elif i == self.DELEGATE: data = mn.delegate_key if role in [Qt.EditRole, Qt.DisplayRole, Qt.ToolTipRole] and data: data = self.manager.get_delegate_privkey(data) elif role == Qt.FontRole: data = util.MONOSPACE_FONT elif i == self.ADDR: data = '' if mn.addr.ip: data = str(mn.addr) elif i == self.PROTOCOL_VERSION: data = mn.protocol_version return QVariant(data)
from typing import Sequence from electrum_cadex import storage, bitcoin, keystore, constants from electrum_cadex.transaction import Transaction from electrum_cadex.simple_config import SimpleConfig from electrum_cadex.address_synchronizer import TX_HEIGHT_UNCONFIRMED, TX_HEIGHT_UNCONF_PARENT from electrum_cadex.wallet import sweep, Multisig_Wallet, Standard_Wallet, Imported_Wallet from electrum_cadex.util import bfh, bh2u from electrum_cadex.transaction import TxOutput from . import TestCaseForTestnet from . import SequentialTestCase from .test_bitcoin import needs_test_with_all_ecc_implementations _UNICODE_HORROR_HEX = 'e282bf20f09f988020f09f98882020202020e3818620e38191e3819fe381be20e3828fe3828b2077cda2cda2cd9d68cda16fcda2cda120ccb8cda26bccb5cd9f6eccb4cd98c7ab77ccb8cc9b73cd9820cc80cc8177cd98cda2e1b8a9ccb561d289cca1cda27420cca7cc9568cc816fccb572cd8fccb5726f7273cca120ccb6cda1cda06cc4afccb665cd9fcd9f20ccb6cd9d696ecda220cd8f74cc9568ccb7cca1cd9f6520cd9fcd9f64cc9b61cd9c72cc95cda16bcca2cca820cda168ccb465cd8f61ccb7cca2cca17274cc81cd8f20ccb4ccb7cda0c3b2ccb5ccb666ccb82075cca7cd986ec3adcc9bcd9c63cda2cd8f6fccb7cd8f64ccb8cda265cca1cd9d3fcd9e' UNICODE_HORROR = bfh(_UNICODE_HORROR_HEX).decode('utf-8') # '₿ 😀 😈 う けたま わる w͢͢͝h͡o͢͡ ̸͢k̵͟n̴͘ǫw̸̛s͘ ̀́w͘͢ḩ̵a҉̡͢t ̧̕h́o̵r͏̵rors̡ ̶͡͠lį̶e͟͟ ̶͝in͢ ͏t̕h̷̡͟e ͟͟d̛a͜r̕͡k̢̨ ͡h̴e͏a̷̢̡rt́͏ ̴̷͠ò̵̶f̸ u̧͘ní̛͜c͢͏o̷͏d̸͢e̡͝?͞' class WalletIntegrityHelper: gap_limit = 1 # make tests run faster @classmethod def check_seeded_keystore_sanity(cls, test_obj, ks): test_obj.assertTrue(ks.is_deterministic()) test_obj.assertFalse(ks.is_watching_only()) test_obj.assertFalse(ks.can_import()) test_obj.assertTrue(ks.has_seed()) @classmethod
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.address_n.extend(xpub_n + s) txinputtype.script_type = self.types.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 = map(f, x_pubkeys) multisig = self.types.MultisigRedeemScriptType( pubkeys=pubkeys, signatures=map(lambda x: bfh(x)[:-1] if x else b'', txin.get('signatures')), m=txin.get('num_sig'), ) script_type = self.types.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.address_n.extend(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
def sign_transaction(self, tx, password): if tx.is_complete(): return client = self.get_client() inputs = [] inputsPaths = [] pubKeys = [] chipInputs = [] redeemScripts = [] signatures = [] preparedTrustedInputs = [] changePath = "" output = None p2shTransaction = 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 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: 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 (for hw.1 and nano) # - at most one output can bypass confirmation (~change) (for all) 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") has_change = False any_output_on_change_branch = is_any_tx_output_on_change_branch(tx) for o in tx.outputs(): assert o.type == TYPE_ADDRESS info = tx.output_info.get(o.address) if (info is not None) and len(tx.outputs()) > 1 \ and not has_change: index = info.address_index on_change_branch = index[0] == 1 # prioritise hiding outputs on the 'change' branch from user # because no more than one change address allowed if on_change_branch == any_output_on_change_branch: changePath = self.get_derivation()[2:] + "/%d/%d"%index has_change = True else: output = o.address else: output = o.address if not self.get_client_electrum().canAlternateCoinVersions: v, h = b58_address_to_hash160(address) if v == constants.net.ADDRTYPE_P2PKH: output = hash160_to_b58_address(h, 0) 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 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_to_network() self.get_client().enableAlternate2fa(False) 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] tx.add_signature_to_txin(i, signingPos, bh2u(signatures[i])) tx.raw = tx.serialize()
def test_verify(self): announce = MasternodeAnnounce.deserialize(raw_announce_70210) message = announce.serialize_for_sig() pk = bitcoin.public_key_to_p2pkh(bfh(announce.collateral_key)) self.assertTrue(announce.verify())