def test_get_public_key(self): with self.client: self.setup_mnemonic_pin_passphrase() self.client.set_expected_responses( [proto.PinMatrixRequest(), proto.PassphraseRequest(), proto.PublicKey()] ) btc.get_public_node(self.client, [])
def test_clear_session(client): if client.features.model == "1": init_responses = [ messages.PinMatrixRequest(), messages.PassphraseRequest() ] else: init_responses = [messages.PassphraseRequest()] cached_responses = [messages.PublicKey()] with client: client.set_expected_responses(init_responses + cached_responses) assert get_public_node(client, ADDRESS_N).xpub == XPUB with client: # pin and passphrase are cached client.set_expected_responses(cached_responses) assert get_public_node(client, ADDRESS_N).xpub == XPUB client.clear_session() # session cache is cleared with client: client.set_expected_responses(init_responses + cached_responses) assert get_public_node(client, ADDRESS_N).xpub == XPUB with client: # pin and passphrase are cached client.set_expected_responses(cached_responses) assert get_public_node(client, ADDRESS_N).xpub == XPUB
def test_clear_session(client): is_trezor1 = client.features.model == "1" init_responses = [ messages.PinMatrixRequest if is_trezor1 else messages.ButtonRequest, messages.PassphraseRequest, ] cached_responses = [messages.PublicKey] with client: client.use_pin_sequence([PIN4]) client.set_expected_responses(init_responses + cached_responses) assert get_public_node(client, ADDRESS_N).xpub == XPUB with client: # pin and passphrase are cached client.set_expected_responses(cached_responses) assert get_public_node(client, ADDRESS_N).xpub == XPUB client.clear_session() # session cache is cleared with client: client.use_pin_sequence([PIN4]) client.set_expected_responses(init_responses + cached_responses) assert get_public_node(client, ADDRESS_N).xpub == XPUB with client: # pin and passphrase are cached client.set_expected_responses(cached_responses) assert get_public_node(client, ADDRESS_N).xpub == XPUB
def test_coin_and_curve(client): with pytest.raises( TrezorFailure, match="Cannot use coin_name or script_type with ecdsa_curve_name" ): btc.get_public_node( client, PATH_PRIVATE, coin_name="Bitcoin", ecdsa_curve_name="ed25519" )
def test_multisig_missing(self, client, show_display): # Multisig with global suffix specification. # Use account numbers 1, 2 and 3 to create a valid multisig, # but not containing the keys from account 0 used below. nodes = [ btc.get_public_node(client, parse_path(f"44'/0'/{i}'")).node for i in range(1, 4) ] multisig1 = messages.MultisigRedeemScriptType( nodes=nodes, address_n=[0, 0], signatures=[b"", b"", b""], m=2) # Multisig with per-node suffix specification. node = btc.get_public_node(client, parse_path("44h/0h/0h/0"), coin_name="Bitcoin").node multisig2 = messages.MultisigRedeemScriptType( pubkeys=[ messages.HDNodePathType(node=node, address_n=[1]), messages.HDNodePathType(node=node, address_n=[2]), messages.HDNodePathType(node=node, address_n=[3]), ], signatures=[b"", b"", b""], m=2, ) for multisig in (multisig1, multisig2): with pytest.raises(TrezorFailure): btc.get_address( client, "Bitcoin", parse_path("44'/0'/0'/0/0"), show_display=show_display, multisig=multisig, )
def test_attack_ownership_id(client: Client): # Multisig with global suffix specification. # Use account numbers 1, 2 and 3 to create a valid multisig, # but not containing the keys from account 0 used below. nodes = [ btc.get_public_node(client, parse_path(f"m/84h/0h/{i}h")).node for i in range(1, 4) ] multisig1 = messages.MultisigRedeemScriptType( nodes=nodes, address_n=[0, 0], signatures=[b"", b"", b""], m=2 ) # Multisig with per-node suffix specification. node = btc.get_public_node( client, parse_path("m/84h/0h/0h/0"), coin_name="Bitcoin" ).node multisig2 = messages.MultisigRedeemScriptType( pubkeys=[ messages.HDNodePathType(node=node, address_n=[1]), messages.HDNodePathType(node=node, address_n=[2]), messages.HDNodePathType(node=node, address_n=[3]), ], signatures=[b"", b"", b""], m=2, ) for multisig in (multisig1, multisig2): with pytest.raises(TrezorFailure): btc.get_ownership_id( client, "Bitcoin", parse_path("m/84h/0h/0h/0/0"), multisig=multisig, script_type=messages.InputScriptType.SPENDWITNESS, )
def test_get_public_key(self, client): with client: client.use_pin_sequence([PIN4]) client.set_expected_responses( [proto.PinMatrixRequest(), proto.PassphraseRequest(), proto.PublicKey()] ) btc.get_public_node(client, [])
def test_script_type(self): self.setup_mnemonic_nopin_nopassphrase() assert ( btc.get_public_node(self.client, [], coin_name="Bitcoin").xpub == "xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy" ) assert ( btc.get_public_node( self.client, [], coin_name="Bitcoin", script_type=proto.InputScriptType.SPENDADDRESS, ).xpub == "xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy" ) assert ( btc.get_public_node( self.client, [], coin_name="Bitcoin", script_type=proto.InputScriptType.SPENDP2SHWITNESS, ).xpub == "ypub6QqdH2c5z7966KBPZ5yDEQCTKWrkLK4dsw8RRjpMLMtyvvZmJ3nNv7pKdQw6fnQkUrLm6XEeheSCGVSpoJCQGm6fofpt9RoHVJYH72ecmVm" ) assert ( btc.get_public_node( self.client, [], coin_name="Bitcoin", script_type=proto.InputScriptType.SPENDWITNESS, ).xpub == "zpub6jftahH18ngZwcNWPSkqSVHxVV1CGw48o3eeD8iEiNGrz2NzYhwwYBUTectgfh4ftVTZqzqDAJnk9n4PWzcR4znGg1XJjLcmm2bvVc3Honv" )
def test_script_type(self, client): assert ( btc.get_public_node(client, [], coin_name="Bitcoin").xpub == "xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy" ) assert ( btc.get_public_node( client, [], coin_name="Bitcoin", script_type=proto.InputScriptType.SPENDADDRESS, ).xpub == "xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy" ) assert ( btc.get_public_node( client, [], coin_name="Bitcoin", script_type=proto.InputScriptType.SPENDP2SHWITNESS, ).xpub == "ypub6QqdH2c5z7966KBPZ5yDEQCTKWrkLK4dsw8RRjpMLMtyvvZmJ3nNv7pKdQw6fnQkUrLm6XEeheSCGVSpoJCQGm6fofpt9RoHVJYH72ecmVm" ) assert ( btc.get_public_node( client, [], coin_name="Bitcoin", script_type=proto.InputScriptType.SPENDWITNESS, ).xpub == "zpub6jftahH18ngZwcNWPSkqSVHxVV1CGw48o3eeD8iEiNGrz2NzYhwwYBUTectgfh4ftVTZqzqDAJnk9n4PWzcR4znGg1XJjLcmm2bvVc3Honv" )
def test_get_public_key(self): with self.client: self.setup_mnemonic_pin_passphrase() self.client.set_expected_responses([ proto.PinMatrixRequest(), proto.PassphraseRequest(), proto.PublicKey() ]) btc.get_public_node(self.client, [])
def test_default_curve(self, client): assert ( btc.get_public_node(client, [H_(111), 42]).node.public_key.hex() == "02e7fcec053f0df94d88c86447970743e8a1979d242d09338dcf8687a9966f7fbc" ) assert ( btc.get_public_node(client, [H_(111), H_(42)]).node.public_key.hex() == "03ce7b690969d773ba9ed212464eb2b534b87b9b8a9383300bddabe1f093f79220" )
def test_tbtc(self, client): assert ( bip32.serialize( btc.get_public_node(client, [111, 42]).node, 0x043587CF) == "tpubDAgixSyai5PWbc8N1mBkHDR5nLgAnHFtY7r4y5EzxqAxrt9YUDpZL3kaRoHVvCfrcwNo31c2isBP2uTHcZxEosuKbyJhCAbrvGoPuLUZ7Mz" ) assert ( btc.get_public_node(client, [111, 42], coin_name="Testnet").xpub == "tpubDAgixSyai5PWbc8N1mBkHDR5nLgAnHFtY7r4y5EzxqAxrt9YUDpZL3kaRoHVvCfrcwNo31c2isBP2uTHcZxEosuKbyJhCAbrvGoPuLUZ7Mz" )
def test_get_public_key(client): _assert_protection(client) with client: client.use_pin_sequence([PIN4]) client.set_expected_responses([ _pin_request(client), messages.PassphraseRequest, messages.PublicKey, ]) btc.get_public_node(client, [])
def test_default_curve(self): self.setup_mnemonic_nopin_nopassphrase() assert ( btc.get_public_node(self.client, [H_(111), 42]).node.public_key.hex() == "02e7fcec053f0df94d88c86447970743e8a1979d242d09338dcf8687a9966f7fbc" ) assert ( btc.get_public_node(self.client, [H_(111), H_(42)]).node.public_key.hex() == "03ce7b690969d773ba9ed212464eb2b534b87b9b8a9383300bddabe1f093f79220" )
def test_btc(self): self.setup_mnemonic_nopin_nopassphrase() assert ( bip32.serialize( btc.get_public_node(self.client, []).node, 0x0488B21E) == "xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy" ) assert ( btc.get_public_node(self.client, [], coin_name="Bitcoin").xpub == "xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy" ) assert ( bip32.serialize( btc.get_public_node(self.client, [1]).node, 0x0488B21E) == "xpub68zNxjsTrV8y9AadThLW7dTAqEpZ7xBLFSyJ3X9pjTv6Njg6kxgjXJkzxq8u3ttnjBw1jupQHMP3gpGZzZqd1eh5S4GjkaMhPR18vMyUi8N" ) assert ( btc.get_public_node(self.client, [1], coin_name="Bitcoin").xpub == "xpub68zNxjsTrV8y9AadThLW7dTAqEpZ7xBLFSyJ3X9pjTv6Njg6kxgjXJkzxq8u3ttnjBw1jupQHMP3gpGZzZqd1eh5S4GjkaMhPR18vMyUi8N" ) assert ( bip32.serialize( btc.get_public_node(self.client, [0, H_(1)]).node, 0x0488B21E) == "xpub6A3FoZqYXj1AbW4thRwBh26YwZWbmoyjTaZwwxJjY1oKUpefLepL3RFS9DHKQrjAfxDrzDepYMDZPqXN6upQm3bHQ9xaXD5a3mqni3goF4v" ) assert ( btc.get_public_node(self.client, [0, H_(1)], coin_name="Bitcoin").xpub == "xpub6A3FoZqYXj1AbW4thRwBh26YwZWbmoyjTaZwwxJjY1oKUpefLepL3RFS9DHKQrjAfxDrzDepYMDZPqXN6upQm3bHQ9xaXD5a3mqni3goF4v" ) assert ( bip32.serialize( btc.get_public_node(self.client, [H_(9), 0]).node, 0x0488B21E) == "xpub6A2h5mzLDfYginoD7q7wCWbq18wTbN9gducRr2w5NRTwdLeoT3cJSwefFqW7uXTpVFGtpUyDMBNYs3DNvvXx6NPjF9YEbUQrtxFSWnPtVrv" ) assert ( btc.get_public_node(self.client, [H_(9), 0], coin_name="Bitcoin").xpub == "xpub6A2h5mzLDfYginoD7q7wCWbq18wTbN9gducRr2w5NRTwdLeoT3cJSwefFqW7uXTpVFGtpUyDMBNYs3DNvvXx6NPjF9YEbUQrtxFSWnPtVrv" ) assert ( bip32.serialize( btc.get_public_node(self.client, [0, 9999999]).node, 0x0488B21E) == "xpub6A3FoZqQEK6iwLZ4HFkqSo5fb35BH4bpjC4SPZ63prfLdGYPwYxEuC6o91bUvFFdMzKWe5rs3axHRUjxJaSvBnKKFtnfLwDACRxPxabsv2r" ) assert ( btc.get_public_node(self.client, [0, 9999999], coin_name="Bitcoin").xpub == "xpub6A3FoZqQEK6iwLZ4HFkqSo5fb35BH4bpjC4SPZ63prfLdGYPwYxEuC6o91bUvFFdMzKWe5rs3axHRUjxJaSvBnKKFtnfLwDACRxPxabsv2r" )
def test_tbtc(self): self.setup_mnemonic_nopin_nopassphrase() assert ( bip32.serialize( btc.get_public_node(self.client, [111, 42]).node, 0x043587CF ) == "tpubDAgixSyai5PWbc8N1mBkHDR5nLgAnHFtY7r4y5EzxqAxrt9YUDpZL3kaRoHVvCfrcwNo31c2isBP2uTHcZxEosuKbyJhCAbrvGoPuLUZ7Mz" ) assert ( btc.get_public_node(self.client, [111, 42], coin_name="Testnet").xpub == "tpubDAgixSyai5PWbc8N1mBkHDR5nLgAnHFtY7r4y5EzxqAxrt9YUDpZL3kaRoHVvCfrcwNo31c2isBP2uTHcZxEosuKbyJhCAbrvGoPuLUZ7Mz" )
def test_ltc(self): self.setup_mnemonic_nopin_nopassphrase() assert ( bip32.serialize( btc.get_public_node(self.client, []).node, 0x019DA462) == "Ltub2SSUS19CirucVPGDKDBatBDBEM2s9UbH66pBURfaKrMocCPLhQ7Z7hecy5VYLHA5fRdXwB2e61j2VJCNzVsqKTCVEU1vECjqi5EyczFX9xp" ) assert ( btc.get_public_node(self.client, [], coin_name="Litecoin").xpub == "Ltub2SSUS19CirucVPGDKDBatBDBEM2s9UbH66pBURfaKrMocCPLhQ7Z7hecy5VYLHA5fRdXwB2e61j2VJCNzVsqKTCVEU1vECjqi5EyczFX9xp" ) assert ( bip32.serialize( btc.get_public_node(self.client, [1]).node, 0x019DA462) == "Ltub2VRVRP5VjvSyPXra4BLVyVZPv397sjhUNjBGsbtw6xko77JuQyBULxFSKheviJJ3KQLbL3Cx8P2RnudguTw4raUVjCACRG7jsumUptYx55C" ) assert ( btc.get_public_node(self.client, [1], coin_name="Litecoin").xpub == "Ltub2VRVRP5VjvSyPXra4BLVyVZPv397sjhUNjBGsbtw6xko77JuQyBULxFSKheviJJ3KQLbL3Cx8P2RnudguTw4raUVjCACRG7jsumUptYx55C" ) assert ( bip32.serialize( btc.get_public_node(self.client, [0, H_(1)]).node, 0x019DA462) == "Ltub2WUNGD3aRAKAqsLqHuwBYtCn2MqAXbVsarmvn33quWe2DCHTzfK4s4jsW5oM5G8RGAdSaM3NPNrwVvtV1ourbyNhhHr3BtqcYGc8caf5GoT" ) assert ( btc.get_public_node(self.client, [0, H_(1)], coin_name="Litecoin").xpub == "Ltub2WUNGD3aRAKAqsLqHuwBYtCn2MqAXbVsarmvn33quWe2DCHTzfK4s4jsW5oM5G8RGAdSaM3NPNrwVvtV1ourbyNhhHr3BtqcYGc8caf5GoT" ) assert ( bip32.serialize( btc.get_public_node(self.client, [H_(9), 0]).node, 0x019DA462) == "Ltub2WToYRCN76rgyA59iK7w4Ni45wG2M9fpmBpQg7gBjvJeMiHc7473Gb96ci29Zvs55TgUQcMmCD1vy8aVqpdPwJB9YHRhGAAuPT1nRLLXmFu" ) assert ( btc.get_public_node(self.client, [H_(9), 0], coin_name="Litecoin").xpub == "Ltub2WToYRCN76rgyA59iK7w4Ni45wG2M9fpmBpQg7gBjvJeMiHc7473Gb96ci29Zvs55TgUQcMmCD1vy8aVqpdPwJB9YHRhGAAuPT1nRLLXmFu" ) assert ( bip32.serialize( btc.get_public_node(self.client, [0, 9999999]).node, 0x019DA462) == "Ltub2WUNGD3S7kQjBhpzsjkqJfBtfqPk2r7xrUGRDdqACMW3MeBCbZSyiqbEVt7WaeesxCj6EDFQtcbfXa75DUYN2i6jZ2g81cyCgvijs9J2u2n" ) assert ( btc.get_public_node(self.client, [0, 9999999], coin_name="Litecoin").xpub == "Ltub2WUNGD3S7kQjBhpzsjkqJfBtfqPk2r7xrUGRDdqACMW3MeBCbZSyiqbEVt7WaeesxCj6EDFQtcbfXa75DUYN2i6jZ2g81cyCgvijs9J2u2n" )
def test_public_ckd(self, client): node = btc.get_public_node(client, []).node node_sub1 = btc.get_public_node(client, [1]).node node_sub2 = bip32.public_ckd(node, [1]) assert node_sub1.chain_code == node_sub2.chain_code assert node_sub1.public_key == node_sub2.public_key address1 = btc.get_address(client, "Bitcoin", [1]) address2 = bip32.get_address(node_sub2, 0) assert address2 == "1CK7SJdcb8z9HuvVft3D91HLpLC6KSsGb" assert address1 == address2
def test_public_ckd(client): node = btc.get_public_node(client, parse_path("m/44'/0'/0'")).node node_sub1 = btc.get_public_node(client, parse_path("m/44'/0'/0'/1/0")).node node_sub2 = bip32.public_ckd(node, [1, 0]) assert node_sub1.chain_code == node_sub2.chain_code assert node_sub1.public_key == node_sub2.public_key address1 = btc.get_address(client, "Bitcoin", parse_path("m/44'/0'/0'/1/0")) address2 = bip32.get_address(node_sub2, 0) assert address2 == "1DyHzbQUoQEsLxJn6M7fMD8Xdt1XvNiwNE" assert address1 == address2
def test_nist256p1_curve(self, client): assert ( btc.get_public_node( client, [H_(111), 42], ecdsa_curve_name="nist256p1").node.public_key.hex() == "02a9ce59b32bd64a70bc52aca96e5d09af65c6b9593ba2a60af8fccfe1437f2129" ) assert ( btc.get_public_node( client, [H_(111), H_(42)], ecdsa_curve_name="nist256p1").node.public_key.hex() == "026fe35d8afed67dbf0561a1d32922e8ad0cd0d86effbc82be970cbed7d9bab2c2" )
def test_secp256k1_curve(self): self.setup_mnemonic_nopin_nopassphrase() assert ( btc.get_public_node( self.client, [H_(111), 42], ecdsa_curve_name="secp256k1").node.public_key.hex() == "02e7fcec053f0df94d88c86447970743e8a1979d242d09338dcf8687a9966f7fbc" ) assert ( btc.get_public_node( self.client, [H_(111), H_(42)], ecdsa_curve_name="secp256k1").node.public_key.hex() == "03ce7b690969d773ba9ed212464eb2b534b87b9b8a9383300bddabe1f093f79220" )
def test_default_curve(self): self.setup_mnemonic_nopin_nopassphrase() assert ( hexlify( btc.get_public_node(self.client, [H_(111), 42]).node.public_key) == b"02e7fcec053f0df94d88c86447970743e8a1979d242d09338dcf8687a9966f7fbc" ) assert ( hexlify( btc.get_public_node(self.client, [H_(111), H_(42)]).node.public_key) == b"03ce7b690969d773ba9ed212464eb2b534b87b9b8a9383300bddabe1f093f79220" )
def test_nist256p1_curve(self): self.setup_mnemonic_nopin_nopassphrase() assert ( btc.get_public_node( self.client, [H_(111), 42], ecdsa_curve_name="nist256p1" ).node.public_key.hex() == "02a9ce59b32bd64a70bc52aca96e5d09af65c6b9593ba2a60af8fccfe1437f2129" ) assert ( btc.get_public_node( self.client, [H_(111), H_(42)], ecdsa_curve_name="nist256p1" ).node.public_key.hex() == "026fe35d8afed67dbf0561a1d32922e8ad0cd0d86effbc82be970cbed7d9bab2c2" )
def test_script_type(client, script_type, xpub, xpub_ignored_magic): path = parse_path("m/44h/0h/0") res = btc.get_public_node(client, path, coin_name="Bitcoin", script_type=script_type) assert res.xpub == xpub res = btc.get_public_node( client, path, coin_name="Bitcoin", script_type=script_type, ignore_xpub_magic=True, ) assert res.xpub == xpub_ignored_magic
def test_public_ckd(self): self.setup_mnemonic_nopin_nopassphrase() node = btc.get_public_node(self.client, []).node node_sub1 = btc.get_public_node(self.client, [1]).node node_sub2 = bip32.public_ckd(node, [1]) assert node_sub1.chain_code == node_sub2.chain_code assert node_sub1.public_key == node_sub2.public_key address1 = btc.get_address(self.client, "Bitcoin", [1]) address2 = bip32.get_address(node_sub2, 0) assert address2 == "1CK7SJdcb8z9HuvVft3D91HLpLC6KSsGb" assert address1 == address2
def test_ltc(self): self.setup_mnemonic_nopin_nopassphrase() assert ( bip32.serialize(btc.get_public_node(self.client, []).node, 0x019DA462) == "Ltub2SSUS19CirucVPGDKDBatBDBEM2s9UbH66pBURfaKrMocCPLhQ7Z7hecy5VYLHA5fRdXwB2e61j2VJCNzVsqKTCVEU1vECjqi5EyczFX9xp" ) assert ( btc.get_public_node(self.client, [], coin_name="Litecoin").xpub == "Ltub2SSUS19CirucVPGDKDBatBDBEM2s9UbH66pBURfaKrMocCPLhQ7Z7hecy5VYLHA5fRdXwB2e61j2VJCNzVsqKTCVEU1vECjqi5EyczFX9xp" ) assert ( bip32.serialize(btc.get_public_node(self.client, [1]).node, 0x019DA462) == "Ltub2VRVRP5VjvSyPXra4BLVyVZPv397sjhUNjBGsbtw6xko77JuQyBULxFSKheviJJ3KQLbL3Cx8P2RnudguTw4raUVjCACRG7jsumUptYx55C" ) assert ( btc.get_public_node(self.client, [1], coin_name="Litecoin").xpub == "Ltub2VRVRP5VjvSyPXra4BLVyVZPv397sjhUNjBGsbtw6xko77JuQyBULxFSKheviJJ3KQLbL3Cx8P2RnudguTw4raUVjCACRG7jsumUptYx55C" ) assert ( bip32.serialize( btc.get_public_node(self.client, [0, H_(1)]).node, 0x019DA462 ) == "Ltub2WUNGD3aRAKAqsLqHuwBYtCn2MqAXbVsarmvn33quWe2DCHTzfK4s4jsW5oM5G8RGAdSaM3NPNrwVvtV1ourbyNhhHr3BtqcYGc8caf5GoT" ) assert ( btc.get_public_node(self.client, [0, H_(1)], coin_name="Litecoin").xpub == "Ltub2WUNGD3aRAKAqsLqHuwBYtCn2MqAXbVsarmvn33quWe2DCHTzfK4s4jsW5oM5G8RGAdSaM3NPNrwVvtV1ourbyNhhHr3BtqcYGc8caf5GoT" ) assert ( bip32.serialize( btc.get_public_node(self.client, [H_(9), 0]).node, 0x019DA462 ) == "Ltub2WToYRCN76rgyA59iK7w4Ni45wG2M9fpmBpQg7gBjvJeMiHc7473Gb96ci29Zvs55TgUQcMmCD1vy8aVqpdPwJB9YHRhGAAuPT1nRLLXmFu" ) assert ( btc.get_public_node(self.client, [H_(9), 0], coin_name="Litecoin").xpub == "Ltub2WToYRCN76rgyA59iK7w4Ni45wG2M9fpmBpQg7gBjvJeMiHc7473Gb96ci29Zvs55TgUQcMmCD1vy8aVqpdPwJB9YHRhGAAuPT1nRLLXmFu" ) assert ( bip32.serialize( btc.get_public_node(self.client, [0, 9999999]).node, 0x019DA462 ) == "Ltub2WUNGD3S7kQjBhpzsjkqJfBtfqPk2r7xrUGRDdqACMW3MeBCbZSyiqbEVt7WaeesxCj6EDFQtcbfXa75DUYN2i6jZ2g81cyCgvijs9J2u2n" ) assert ( btc.get_public_node(self.client, [0, 9999999], coin_name="Litecoin").xpub == "Ltub2WUNGD3S7kQjBhpzsjkqJfBtfqPk2r7xrUGRDdqACMW3MeBCbZSyiqbEVt7WaeesxCj6EDFQtcbfXa75DUYN2i6jZ2g81cyCgvijs9J2u2n" )
def test_btc(self): self.setup_mnemonic_nopin_nopassphrase() assert ( bip32.serialize(btc.get_public_node(self.client, []).node, 0x0488B21E) == "xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy" ) assert ( btc.get_public_node(self.client, [], coin_name="Bitcoin").xpub == "xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy" ) assert ( bip32.serialize(btc.get_public_node(self.client, [1]).node, 0x0488B21E) == "xpub68zNxjsTrV8y9AadThLW7dTAqEpZ7xBLFSyJ3X9pjTv6Njg6kxgjXJkzxq8u3ttnjBw1jupQHMP3gpGZzZqd1eh5S4GjkaMhPR18vMyUi8N" ) assert ( btc.get_public_node(self.client, [1], coin_name="Bitcoin").xpub == "xpub68zNxjsTrV8y9AadThLW7dTAqEpZ7xBLFSyJ3X9pjTv6Njg6kxgjXJkzxq8u3ttnjBw1jupQHMP3gpGZzZqd1eh5S4GjkaMhPR18vMyUi8N" ) assert ( bip32.serialize( btc.get_public_node(self.client, [0, H_(1)]).node, 0x0488B21E ) == "xpub6A3FoZqYXj1AbW4thRwBh26YwZWbmoyjTaZwwxJjY1oKUpefLepL3RFS9DHKQrjAfxDrzDepYMDZPqXN6upQm3bHQ9xaXD5a3mqni3goF4v" ) assert ( btc.get_public_node(self.client, [0, H_(1)], coin_name="Bitcoin").xpub == "xpub6A3FoZqYXj1AbW4thRwBh26YwZWbmoyjTaZwwxJjY1oKUpefLepL3RFS9DHKQrjAfxDrzDepYMDZPqXN6upQm3bHQ9xaXD5a3mqni3goF4v" ) assert ( bip32.serialize( btc.get_public_node(self.client, [H_(9), 0]).node, 0x0488B21E ) == "xpub6A2h5mzLDfYginoD7q7wCWbq18wTbN9gducRr2w5NRTwdLeoT3cJSwefFqW7uXTpVFGtpUyDMBNYs3DNvvXx6NPjF9YEbUQrtxFSWnPtVrv" ) assert ( btc.get_public_node(self.client, [H_(9), 0], coin_name="Bitcoin").xpub == "xpub6A2h5mzLDfYginoD7q7wCWbq18wTbN9gducRr2w5NRTwdLeoT3cJSwefFqW7uXTpVFGtpUyDMBNYs3DNvvXx6NPjF9YEbUQrtxFSWnPtVrv" ) assert ( bip32.serialize( btc.get_public_node(self.client, [0, 9999999]).node, 0x0488B21E ) == "xpub6A3FoZqQEK6iwLZ4HFkqSo5fb35BH4bpjC4SPZ63prfLdGYPwYxEuC6o91bUvFFdMzKWe5rs3axHRUjxJaSvBnKKFtnfLwDACRxPxabsv2r" ) assert ( btc.get_public_node(self.client, [0, 9999999], coin_name="Bitcoin").xpub == "xpub6A3FoZqQEK6iwLZ4HFkqSo5fb35BH4bpjC4SPZ63prfLdGYPwYxEuC6o91bUvFFdMzKWe5rs3axHRUjxJaSvBnKKFtnfLwDACRxPxabsv2r" )
def test_show_multisig_3(self): self.setup_mnemonic_allallall() nodes = map( lambda index: btc.get_public_node( self.client, parse_path("999'/1'/%d'" % index)), range(1, 4), ) multisig1 = proto.MultisigRedeemScriptType( nodes=[bip32.deserialize(n.xpub) for n in nodes], address_n=[2, 0], signatures=[b"", b"", b""], m=2, ) # multisig2 = proto.MultisigRedeemScriptType( # pubkeys=map(lambda n: proto.HDNodePathType(node=bip32.deserialize(n.xpub), address_n=[2, 1]), nodes), # signatures=[b'', b'', b''], # m=2, # ) for i in [1, 2, 3]: assert (btc.get_address( self.client, "Testnet", parse_path("999'/1'/%d'/2/0" % i), False, multisig1, script_type=proto.InputScriptType.SPENDP2SHWITNESS, ) == "2N2MxyAfifVhb3AMagisxaj3uij8bfXqf4Y")
def get_pubkey_at_path(self, path): expanded_path = tools.parse_path(path) output = btc.get_public_node(self.client, expanded_path) if self.is_testnet: return {'xpub': xpub_main_2_test(output.xpub)} else: return {'xpub': output.xpub}
def get_tz_priv(coin, path): session_id = bytes.fromhex(environ.get('TZ_SESSIONID', '')) if trezor and len(session_id) == 32: device = get_transport() client = TrezorClient(transport=device, ui=ClickUI(), session_id=session_id) n_path = parse_path( "m/10065'/0'") # Logical path for BIP0065 operation info = get_public_node(client, n_path, coin_name=coin) side, pubkey = (info.node.public_key[0], info.node.public_key[1:]) left = True if side == 2 else False print("seed", b2x(pubkey), side) priv = encrypt_keyvalue(client, n_path, path, pubkey, ask_on_decrypt=side, ask_on_encrypt=False) client.close() print("priv", b2x(priv), left) is_valid(priv) return CBitcoinSecret.from_secret_bytes(priv) else: print("trezorlib must be available") print("see: https://pypi.org/project/trezor/") print("TZ_SESSIONID enviroinment variable required") print("See: trezorctl get-session --help") sys.exit(2)
def test_bch_multisig(self): self.setup_mnemonic_allallall() xpubs = [] for n in range(1, 4): node = btc.get_public_node(self.client, parse_path("44'/145'/%d'" % n)) xpubs.append(node.xpub) for nr in range(1, 4): assert ( btc.get_address( self.client, "Bcash", parse_path("44'/145'/%d'/0/0" % nr), show_display=(nr == 1), multisig=getmultisig(0, 0, xpubs=xpubs), ) == "bitcoincash:pqguz4nqq64jhr5v3kvpq4dsjrkda75hwy86gq0qzw" ) assert ( btc.get_address( self.client, "Bcash", parse_path("44'/145'/%d'/1/0" % nr), show_display=(nr == 1), multisig=getmultisig(1, 0, xpubs=xpubs), ) == "bitcoincash:pp6kcpkhua7789g2vyj0qfkcux3yvje7euhyhltn0a" )
def test_missing_pubkey(self, client): node = btc.get_public_node( client, parse_path("48h/0h/1h/0h/0"), coin_name="Bitcoin" ).node multisig = proto.MultisigRedeemScriptType( pubkeys=[ proto.HDNodePathType(node=node, address_n=[1]), proto.HDNodePathType(node=node, address_n=[2]), proto.HDNodePathType(node=node, address_n=[3]), ], signatures=[b"", b"", b""], m=2, ) # Let's go to sign with key 10, which is NOT in pubkeys inp1 = proto.TxInputType( address_n=parse_path("48h/0h/1h/0h/0/10"), amount=100000, prev_hash=TXHASH_c6091a, prev_index=1, script_type=proto.InputScriptType.SPENDMULTISIG, multisig=multisig, ) out1 = proto.TxOutputType( address="12iyMbUb4R2K3gre4dHSrbu5azG5KaqVss", amount=100000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) with pytest.raises(TrezorFailure, match="Pubkey not found in multisig script"): btc.sign_tx(client, "Bitcoin", [inp1], [out1], prev_txes=TX_API)
def test_multisig(client): xpubs = [] for n in range(1, 4): node = btc.get_public_node(client, parse_path(f"44'/0'/{n}'")) xpubs.append(node.xpub) for nr in range(1, 4): assert ( btc.get_address( client, "Bitcoin", parse_path(f"44'/0'/{nr}'/0/0"), show_display=(nr == 1), multisig=getmultisig(0, 0, xpubs=xpubs), ) == "3Pdz86KtfJBuHLcSv4DysJo4aQfanTqCzG" ) assert ( btc.get_address( client, "Bitcoin", parse_path(f"44'/0'/{nr}'/1/0"), show_display=(nr == 1), multisig=getmultisig(1, 0, xpubs=xpubs), ) == "36gP3KVx1ooStZ9quZDXbAF3GCr42b2zzd" )
def test_bch_multisig(client): xpubs = [] for n in range(1, 4): node = btc.get_public_node( client, parse_path(f"44'/145'/{n}'"), coin_name="Bcash" ) xpubs.append(node.xpub) for nr in range(1, 4): assert ( btc.get_address( client, "Bcash", parse_path(f"44'/145'/{nr}'/0/0"), show_display=(nr == 1), multisig=getmultisig(0, 0, xpubs=xpubs), ) == "bitcoincash:pqguz4nqq64jhr5v3kvpq4dsjrkda75hwy86gq0qzw" ) assert ( btc.get_address( client, "Bcash", parse_path(f"44'/145'/{nr}'/1/0"), show_display=(nr == 1), multisig=getmultisig(1, 0, xpubs=xpubs), ) == "bitcoincash:pp6kcpkhua7789g2vyj0qfkcux3yvje7euhyhltn0a" )
def test_multisig_missing(self, client): xpubs = [] for n in range(1, 4): # shift account numbers by 10 to create valid multisig, # but not containing the keys used below n = n + 10 node = btc.get_public_node(client, parse_path("44'/0'/%d'" % n)) xpubs.append(node.xpub) for nr in range(1, 4): with pytest.raises(CallException): btc.get_address( client, "Bitcoin", parse_path("44'/0'/%d'/0/0" % nr), show_display=(nr == 1), multisig=getmultisig(0, 0, xpubs=xpubs), ) with pytest.raises(CallException): btc.get_address( client, "Bitcoin", parse_path("44'/0'/%d'/1/0" % nr), show_display=(nr == 1), multisig=getmultisig(1, 0, xpubs=xpubs), )
def test_show_multisig_3(self): self.setup_mnemonic_allallall() nodes = map( lambda index: btc.get_public_node( self.client, parse_path("999'/1'/%d'" % index) ), range(1, 4), ) multisig1 = proto.MultisigRedeemScriptType( nodes=[bip32.deserialize(n.xpub) for n in nodes], address_n=[2, 0], signatures=[b"", b"", b""], m=2, ) # multisig2 = proto.MultisigRedeemScriptType( # pubkeys=map(lambda n: proto.HDNodePathType(node=bip32.deserialize(n.xpub), address_n=[2, 1]), nodes), # signatures=[b'', b'', b''], # m=2, # ) for i in [1, 2, 3]: assert ( btc.get_address( self.client, "Testnet", parse_path("999'/1'/%d'/2/0" % i), False, multisig1, script_type=proto.InputScriptType.SPENDP2SHWITNESS, ) == "2N2MxyAfifVhb3AMagisxaj3uij8bfXqf4Y" )
def test_multisig_missing(self): self.setup_mnemonic_allallall() xpubs = [] for n in range(1, 4): # shift account numbers by 10 to create valid multisig, # but not containing the keys used below n = n + 10 node = btc.get_public_node(self.client, parse_path("44'/0'/%d'" % n)) xpubs.append(node.xpub) for nr in range(1, 4): with pytest.raises(CallException): btc.get_address( self.client, "Bitcoin", parse_path("44'/0'/%d'/0/0" % nr), show_display=(nr == 1), multisig=getmultisig(0, 0, xpubs=xpubs), ) with pytest.raises(CallException): btc.get_address( self.client, "Bitcoin", parse_path("44'/0'/%d'/1/0" % nr), show_display=(nr == 1), multisig=getmultisig(1, 0, xpubs=xpubs), )
def test_multisig(self): self.setup_mnemonic_allallall() xpubs = [] for n in range(1, 4): node = btc.get_public_node(self.client, parse_path("44'/0'/%d'" % n)) xpubs.append(node.xpub) for nr in range(1, 4): assert ( btc.get_address( self.client, "Bitcoin", parse_path("44'/0'/%d'/0/0" % nr), show_display=(nr == 1), multisig=getmultisig(0, 0, xpubs=xpubs), ) == "3Pdz86KtfJBuHLcSv4DysJo4aQfanTqCzG" ) assert ( btc.get_address( self.client, "Bitcoin", parse_path("44'/0'/%d'/1/0" % nr), show_display=(nr == 1), multisig=getmultisig(1, 0, xpubs=xpubs), ) == "36gP3KVx1ooStZ9quZDXbAF3GCr42b2zzd" )
def test_show_multisig_3(self, client): nodes = [ btc.get_public_node( client, parse_path(f"49'/1'/{i}'"), coin_name="Testnet" ).node for i in range(1, 4) ] multisig1 = proto.MultisigRedeemScriptType( nodes=nodes, address_n=[0, 7], signatures=[b"", b"", b""], m=2 ) # multisig2 = proto.MultisigRedeemScriptType( # pubkeys=map(lambda n: proto.HDNodePathType(node=bip32.deserialize(n.xpub), address_n=[2, 1]), nodes), # signatures=[b'', b'', b''], # m=2, # ) for i in [1, 2, 3]: assert ( btc.get_address( client, "Testnet", parse_path(f"49'/1'/{i}'/0/7"), False, multisig1, script_type=proto.InputScriptType.SPENDP2SHWITNESS, ) == "2MwuUwUzPG17wiKQpfXmzfxJEoe7RXZDRad" )
def test_ed25519_curve(self): self.setup_mnemonic_nopin_nopassphrase() # ed25519 curve does not support public derivation, so test only private derivation paths assert ( btc.get_public_node( self.client, [H_(111), H_(42)], ecdsa_curve_name="ed25519" ).node.public_key.hex() == "0069a14b478e508eab6e93303f4e6f5c50b8136627830f2ed5c3a835fc6c0ea2b7" ) assert ( btc.get_public_node( self.client, [H_(111), H_(65535)], ecdsa_curve_name="ed25519" ).node.public_key.hex() == "00514f73a05184458611b14c348fee4fd988d36cf3aee7207737861bac611de991" ) # test failure when using public derivation with pytest.raises(CallException): btc.get_public_node(self.client, [H_(111), 42], ecdsa_curve_name="ed25519")
def test_show_multisig_3(self): self.setup_mnemonic_allallall() nodes = [ btc.get_public_node(self.client, parse_path("999'/1'/%d'" % index)) for index in range(1, 4) ] multisig1 = proto.MultisigRedeemScriptType( nodes=[bip32.deserialize(n.xpub) for n in nodes], address_n=[2, 0], signatures=[b"", b"", b""], m=2, ) multisig2 = proto.MultisigRedeemScriptType( nodes=[bip32.deserialize(n.xpub) for n in nodes], address_n=[2, 1], signatures=[b"", b"", b""], m=2, ) for i in [1, 2, 3]: assert ( btc.get_address( self.client, "Testnet", parse_path("999'/1'/%d'/2/1" % i), False, multisig2, script_type=proto.InputScriptType.SPENDWITNESS, ) == "tb1qch62pf820spe9mlq49ns5uexfnl6jzcezp7d328fw58lj0rhlhasge9hzy" ) assert ( btc.get_address( self.client, "Testnet", parse_path("999'/1'/%d'/2/0" % i), False, multisig1, script_type=proto.InputScriptType.SPENDWITNESS, ) == "tb1qr6xa5v60zyt3ry9nmfew2fk5g9y3gerkjeu6xxdz7qga5kknz2ssld9z2z" )
def test_send_multisig_1(self): self.setup_mnemonic_allallall() nodes = map( lambda index: btc.get_public_node( self.client, parse_path("49'/156'/%d'" % index) ), range(1, 4), ) multisig = proto.MultisigRedeemScriptType( nodes=[deserialize(n.xpub) for n in nodes], address_n=[1, 0], signatures=[b"", b"", b""], m=2, ) inp1 = proto.TxInputType( address_n=parse_path("49'/156'/1'/1/0"), prev_hash=bytes.fromhex( "25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985" ), prev_index=1, script_type=proto.InputScriptType.SPENDP2SHWITNESS, multisig=multisig, amount=1610436, ) out1 = proto.TxOutputType( address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe", amount=1605000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) with self.client: self.client.set_expected_responses( [ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ] ) signatures, _ = btc.sign_tx( self.client, "Bgold", [inp1], [out1], prev_txes=TX_API ) # store signature inp1.multisig.signatures[0] = signatures[0] # sign with third key inp1.address_n[2] = H_(3) self.client.set_expected_responses( [ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ] ) _, serialized_tx = btc.sign_tx( self.client, "Bgold", [inp1], [out1], prev_txes=TX_API ) assert ( serialized_tx.hex() == "0100000000010185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b52250100000023220020ea9ec48498c451286c2ebaf9e19255e2873b0fb517d67b2f2005298c7e437829ffffffff01887d1800000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac0400473044022077cb8b2a534f79328810ca8c330539ae9ffa086c359ddb7da11026557b04eef202201d95be0dd1da0aa01720953e52d5dabffd19a998d1490c13a21b8e52e4ead2e041483045022100e41cbd6a501ba8fe6f65554420e23e950d35af0da9b052da54a087463b0717ca02206c695c8d1f74f9535b5d89a2fd1f9326a0ef20e5400137f1e1daeee992b62b594169522103279aea0b253b144d1b2bb8532280001a996dcddd04f86e5e13df1355032cbc1321032c6465c956c0879663fa8be974c912d229c179a5cdedeb29611a1bec1f951eb22103494480a4b72101cbd2eadac8e18c7a3a7589a7f576bf46b8971c38c51e5eceeb53ae00000000" )
def test_send_btg_multisig_change(self): self.setup_mnemonic_allallall() xpubs = [] for n in map( lambda index: btc.get_public_node( self.client, parse_path("48'/156'/%d'" % index) ), range(1, 4), ): xpubs.append(n.xpub) def getmultisig(chain, nr, signatures=[b"", b"", b""], xpubs=xpubs): return proto.MultisigRedeemScriptType( nodes=[deserialize(xpub) for xpub in xpubs], address_n=[chain, nr], signatures=signatures, m=2, ) inp1 = proto.TxInputType( address_n=parse_path("48'/156'/3'/0/0"), multisig=getmultisig(0, 0), # 33Ju286QvonBz5N1V754ZekQv4GLJqcc5R amount=48490, prev_hash=bytes.fromhex( "25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985" ), prev_index=0, script_type=proto.InputScriptType.SPENDMULTISIG, ) out1 = proto.TxOutputType( address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe", amount=24000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) out2 = proto.TxOutputType( address_n=parse_path("48'/156'/3'/1/0"), multisig=getmultisig(1, 0), script_type=proto.OutputScriptType.PAYTOMULTISIG, amount=24000, ) with self.client: self.client.set_expected_responses( [ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ] ) signatures, serialized_tx = btc.sign_tx( self.client, "Bgold", [inp1], [out1, out2], prev_txes=TX_API ) assert ( signatures[0].hex() == "3045022100d954f341ddd3ec96e4bc6cdb90f2df9b2032723f85e4a0187346dd743130bfca0220105ce08b795c70dc09a55569d7874bff684a877219ec2fc37c88cdffe12f332c" ) inp1 = proto.TxInputType( address_n=parse_path("48'/156'/1'/0/0"), multisig=getmultisig(0, 0, [b"", b"", signatures[0]]), amount=48490, prev_hash=bytes.fromhex( "25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985" ), prev_index=0, script_type=proto.InputScriptType.SPENDMULTISIG, ) out2.address_n[2] = H_(1) with self.client: self.client.set_expected_responses( [ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ] ) signatures, serialized_tx = btc.sign_tx( self.client, "Bgold", [inp1], [out1, out2], prev_txes=TX_API ) assert ( signatures[0].hex() == "30440220614f9a18695365a2edba0d930404a77cae970d3430ad86c5b5239a96fd54bf84022030bc76a322e3b2b1c987622b5eb6da23ac1e6c905ee9b3b6405a4e4edd5bbb87" ) assert ( serialized_tx.hex() == "010000000185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b522500000000fdfd00004730440220614f9a18695365a2edba0d930404a77cae970d3430ad86c5b5239a96fd54bf84022030bc76a322e3b2b1c987622b5eb6da23ac1e6c905ee9b3b6405a4e4edd5bbb8741483045022100d954f341ddd3ec96e4bc6cdb90f2df9b2032723f85e4a0187346dd743130bfca0220105ce08b795c70dc09a55569d7874bff684a877219ec2fc37c88cdffe12f332c414c695221035a8db79c0ef57a202664a3da60ca41e8865c6d86ed0aafc03f8e75173341b58021037fba152d8fca660cc49973d8bc9421ff49a75b44ea200873d70d3990f763ed4c210348cbcbd93e069416e0d5db93e86b5698852d9fd54502ad0bed9722fa83f90e4b53aeffffffff02c05d0000000000001976a914ea5f904d195079a350b534db4446433b3cec222e88acc05d00000000000017a914623c803f7fb654dac8dda7786fbf9bc38cd867f48700000000" )
def test_2_of_3(self): self.setup_mnemonic_allallall() nodes = [ btc.get_public_node(self.client, parse_path("48'/0'/%d'" % index)) for index in range(1, 4) ] multisig = proto.MultisigRedeemScriptType( nodes=[deserialize(n.xpub) for n in nodes], address_n=[0, 0], signatures=[b"", b"", b""], m=2, ) # Let's go to sign with key 1 inp1 = proto.TxInputType( address_n=parse_path("48'/0'/1'/0/0"), prev_hash=TXHASH_c6091a, prev_index=1, script_type=proto.InputScriptType.SPENDMULTISIG, multisig=multisig, ) out1 = proto.TxOutputType( address="12iyMbUb4R2K3gre4dHSrbu5azG5KaqVss", amount=100000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) with self.client: self.client.set_expected_responses( [ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_c6091a), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType( request_index=0, tx_hash=TXHASH_c6091a ), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType( request_index=0, tx_hash=TXHASH_c6091a ), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType( request_index=1, tx_hash=TXHASH_c6091a ), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ] ) # Now we have first signature signatures1, _ = btc.sign_tx( self.client, "Bitcoin", [inp1], [out1], prev_txes=TX_API ) assert ( signatures1[0].hex() == "3044022052f4a3dc5ca3e86ed66abb1e2b4d9b9ace7d96f5615944beea19e58280847c2902201bd3ff32a38366a4eed0373e27da26ebc0d2a4c2bbeffd83e8a60e313d95b9e3" ) # --------------------------------------- # Let's do second signature using 3rd key multisig = proto.MultisigRedeemScriptType( nodes=[deserialize(n.xpub) for n in nodes], address_n=[0, 0], signatures=[ signatures1[0], b"", b"", ], # Fill signature from previous signing process m=2, ) # Let's do a second signature with key 3 inp3 = proto.TxInputType( address_n=parse_path("48'/0'/3'/0/0"), prev_hash=TXHASH_c6091a, prev_index=1, script_type=proto.InputScriptType.SPENDMULTISIG, multisig=multisig, ) with self.client: self.client.set_expected_responses( [ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_c6091a), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType( request_index=0, tx_hash=TXHASH_c6091a ), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType( request_index=0, tx_hash=TXHASH_c6091a ), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType( request_index=1, tx_hash=TXHASH_c6091a ), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ] ) signatures2, serialized_tx = btc.sign_tx( self.client, "Bitcoin", [inp3], [out1], prev_txes=TX_API ) assert ( signatures2[0].hex() == "304402203828fd48540811be6a1b12967e7012587c46e6f05c78d42471e7b25c06bc7afc0220749274bc1aa698335b00400c5ba946a70b6b46c711324fbc4989279737a57f49" ) assert ( serialized_tx.hex() == "010000000152ba4dfcde9c4bed88f55479cdea03e711ae586e9a89352a98230c4cdf1a09c601000000fc00473044022052f4a3dc5ca3e86ed66abb1e2b4d9b9ace7d96f5615944beea19e58280847c2902201bd3ff32a38366a4eed0373e27da26ebc0d2a4c2bbeffd83e8a60e313d95b9e30147304402203828fd48540811be6a1b12967e7012587c46e6f05c78d42471e7b25c06bc7afc0220749274bc1aa698335b00400c5ba946a70b6b46c711324fbc4989279737a57f49014c6952210203ed6187880ae932660086e55d4561a57952dd200aa3ed2aa66b73e5723a0ce7210360e7f32fd3c8dee27a166f6614c598929699ee66acdcbda5fb24571bf2ae1ca021037c4c7e5d3293ab0f97771dcfdf83caadab341f427f54713da8b2c590a834f03b53aeffffffff01a0860100000000001976a91412e8391ad256dcdc023365978418d658dfecba1c88ac00000000" )
def test_send_multisig_4_change(self): self.setup_mnemonic_allallall() nodes = [ btc.get_public_node(self.client, parse_path("49'/1'/%d'" % index)) for index in range(1, 4) ] multisig = proto.MultisigRedeemScriptType( nodes=[deserialize(n.xpub) for n in nodes], address_n=[1, 1], signatures=[b"", b"", b""], m=2, ) multisig2 = proto.MultisigRedeemScriptType( nodes=[deserialize(n.xpub) for n in nodes], address_n=[1, 2], signatures=[b"", b"", b""], m=2, ) inp1 = proto.TxInputType( address_n=parse_path("49'/1'/1'/1/1"), prev_hash=bytes.fromhex( "31bc1c88ce6ae337a6b3057a16d5bad0b561ad1dfc047d0a7fbb8814668f91e5" ), prev_index=0, script_type=proto.InputScriptType.SPENDP2SHWITNESS, multisig=multisig, amount=1603000, ) out1 = proto.TxOutputType( address_n=parse_path("49'/1'/1'/1/2"), amount=1602000, multisig=multisig2, script_type=proto.OutputScriptType.PAYTOWITNESS, ) with self.client: self.client.set_expected_responses( [ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ] ) signatures, _ = btc.sign_tx( self.client, "Testnet", [inp1], [out1], prev_txes=TX_API ) # store signature inp1.multisig.signatures[0] = signatures[0] # sign with third key inp1.address_n[2] = H_(3) out1.address_n[2] = H_(3) self.client.set_expected_responses( [ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ] ) _, serialized_tx = btc.sign_tx( self.client, "Testnet", [inp1], [out1], prev_txes=TX_API ) assert ( serialized_tx.hex() == "01000000000101e5918f661488bb7f0a7d04fc1dad61b5d0bad5167a05b3a637e36ace881cbc310000000023220020fa6c73de618ec134eeec0c16f6dd04d46d4347e9a4fd0a95fd7938403a4949f9ffffffff01d071180000000000220020bcea2324dacbcde5a9db90cc26b8df9cbc72010e05cb68cf034df6f0e05239a2040047304402206bbddb45f12e31e77610fd85b50a83bad4426433b1c4860b1c5ddc0a69f803720220087b0607daab14830f4b4941f16b953b38e606ad70029bac24af7267f93c4242014730440220551a0cb6b0d5b3fa0cfd0b07bb5d751494b827b1c6a08702186696cfbc18278302204f37c382876c4117cca656654599b508f2d55fc3b083dc938e3cd8491b29719601695221036a5ec3abd10501409092246fe59c6d7a15fff1a933479483c3ba98b866c5b9742103559be875179d44e438db2c74de26e0bc9842cbdefd16018eae8a2ed989e474722103067b56aad037cd8b5f569b21f9025b76470a72dc69457813d2b76e98dc0cd01a53ae00000000" )
def test_send_multisig_2(self): self.setup_mnemonic_allallall() nodes = [ btc.get_public_node(self.client, parse_path("84'/1'/%d'" % index)) for index in range(1, 4) ] multisig = proto.MultisigRedeemScriptType( nodes=[deserialize(n.xpub) for n in nodes], address_n=[0, 1], signatures=[b"", b"", b""], m=2, ) inp1 = proto.TxInputType( address_n=parse_path("84'/1'/2'/0/1"), prev_hash=bytes.fromhex( "f41cbedd8becee05a830f418d13aa665125464547db5c7a6cd28f21639fe1228" ), prev_index=0, script_type=proto.InputScriptType.SPENDWITNESS, multisig=multisig, amount=1605000, ) out1 = proto.TxOutputType( address="tb1qr6xa5v60zyt3ry9nmfew2fk5g9y3gerkjeu6xxdz7qga5kknz2ssld9z2z", amount=1604000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) with self.client: self.client.set_expected_responses( [ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ] ) signatures, _ = btc.sign_tx( self.client, "Testnet", [inp1], [out1], prev_txes=TX_API ) # store signature inp1.multisig.signatures[1] = signatures[0] # sign with first key inp1.address_n[2] = H_(1) self.client.set_expected_responses( [ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ] ) _, serialized_tx = btc.sign_tx( self.client, "Testnet", [inp1], [out1], prev_txes=TX_API ) assert ( serialized_tx.hex() == "010000000001012812fe3916f228cda6c7b57d5464541265a63ad118f430a805eeec8bddbe1cf40000000000ffffffff01a0791800000000002200201e8dda334f11171190b3da72e526d441491464769679a319a2f011da5ad312a10400473044022001b7f4f21a8ddcd5e0faaaee3b95515bf8b84f2a7cbfdf66996c64123617a5cf02202fc6a776a7225420dbca759ad4ac83a61d15bf8d2883b6bf1aa31de7437f9b6e0147304402206c4125c1189a3b3e93a77cdf54c60c0538b80e5a03ec74e6ac776dfa77706ee4022035be14de76259b9d8a24863131a06a65b95df02f7d3ace90d52b37e8d94b167f0169522103bab8ecdd9ae2c51a0dc858f4c751b27533143bf6013ba1725ba8a4ecebe7de8c21027d5e55696c875308b03f2ca3d8637f51d3e35da9456a5187aa14b3de8a89534f2103b78eabaea8b3a4868be4f4bb96d6f66973f7081faa7f1cafba321444611c241e53ae00000000" )
def test_send_bch_multisig_wrongchange(self): self.setup_mnemonic_allallall() xpubs = [] for n in map( lambda index: btc.get_public_node( self.client, parse_path("48'/145'/%d'" % index) ), range(1, 4), ): xpubs.append(n.xpub) def getmultisig(chain, nr, signatures=[b"", b"", b""], xpubs=xpubs): return proto.MultisigRedeemScriptType( nodes=[deserialize(xpub) for xpub in xpubs], address_n=[chain, nr], signatures=signatures, m=2, ) correcthorse = proto.HDNodeType( depth=1, fingerprint=0, child_num=0, chain_code=bytes.fromhex( "0000000000000000000000000000000000000000000000000000000000000000" ), public_key=bytes.fromhex( "0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71" ), ) sig = bytes.fromhex( "304402207274b5a4d15e75f3df7319a375557b0efba9b27bc63f9f183a17da95a6125c94022000efac57629f1522e2d3958430e2ef073b0706cfac06cce492651b79858f09ae" ) inp1 = proto.TxInputType( address_n=parse_path("48'/145'/1'/1/0"), multisig=getmultisig(1, 0, [b"", sig, b""]), # bitcoincash:pp6kcpkhua7789g2vyj0qfkcux3yvje7euhyhltn0a amount=24000, prev_hash=bytes.fromhex( "f68caf10df12d5b07a34601d88fa6856c6edcbf4d05ebef3486510ae1c293d5f" ), prev_index=1, script_type=proto.InputScriptType.SPENDMULTISIG, ) out1 = proto.TxOutputType( address_n=parse_path("48'/145'/1'/1/1"), multisig=proto.MultisigRedeemScriptType( pubkeys=[ proto.HDNodePathType(node=deserialize(xpubs[0]), address_n=[1, 1]), proto.HDNodePathType(node=correcthorse, address_n=[]), proto.HDNodePathType(node=correcthorse, address_n=[]), ], signatures=[b"", b"", b""], m=2, ), script_type=proto.OutputScriptType.PAYTOMULTISIG, amount=23000, ) with self.client: self.client.set_expected_responses( [ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ] ) (signatures1, serialized_tx) = btc.sign_tx( self.client, "Bcash", [inp1], [out1], prev_txes=TX_API ) assert ( signatures1[0].hex() == "304402201badcdcafef4855ed58621f95935efcbc72068510472140f4ec5e252faa0af93022003310a43488288f70aedee96a5af2643a255268a6858cda9ae3001ea5e3c7557" ) assert ( serialized_tx.hex() == "01000000015f3d291cae106548f3be5ed0f4cbedc65668fa881d60347ab0d512df10af8cf601000000fc0047304402201badcdcafef4855ed58621f95935efcbc72068510472140f4ec5e252faa0af93022003310a43488288f70aedee96a5af2643a255268a6858cda9ae3001ea5e3c75574147304402207274b5a4d15e75f3df7319a375557b0efba9b27bc63f9f183a17da95a6125c94022000efac57629f1522e2d3958430e2ef073b0706cfac06cce492651b79858f09ae414c69522102245739b55787a27228a4fe78b3a324366cc645fbaa708cad45da351a334341192102debbdcb0b6970d5ade84a50fdbda1c701cdde5c9925d9b6cd8e05a9a15dbef352102ffe5fa04547b2b0c3cfbc21c08a1ddfb147025fee10274cdcd5c1bdeee88eae253aeffffffff01d85900000000000017a914a23eb2a1ed4003d357770120f5c370e199ee55468700000000" )
def test_send_multisig_1(self): self.setup_mnemonic_allallall() nodes = [ btc.get_public_node(self.client, parse_path("49'/1'/%d'" % index)) for index in range(1, 4) ] multisig = proto.MultisigRedeemScriptType( nodes=[deserialize(n.xpub) for n in nodes], address_n=[0, 0], signatures=[b"", b"", b""], m=2, ) inp1 = proto.TxInputType( address_n=parse_path("49'/1'/1'/0/0"), prev_hash=bytes.fromhex( "9c31922be756c06d02167656465c8dc83bb553bf386a3f478ae65b5c021002be" ), prev_index=1, script_type=proto.InputScriptType.SPENDP2SHWITNESS, multisig=multisig, amount=1610436, ) out1 = proto.TxOutputType( address="tb1qch62pf820spe9mlq49ns5uexfnl6jzcezp7d328fw58lj0rhlhasge9hzy", amount=1605000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) with self.client: self.client.set_expected_responses( [ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ] ) signatures, _ = btc.sign_tx( self.client, "Testnet", [inp1], [out1], prev_txes=TX_API ) # store signature inp1.multisig.signatures[0] = signatures[0] # sign with third key inp1.address_n[2] = H_(3) self.client.set_expected_responses( [ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ] ) _, serialized_tx = btc.sign_tx( self.client, "Testnet", [inp1], [out1], prev_txes=TX_API ) assert ( serialized_tx.hex() == "01000000000101be0210025c5be68a473f6a38bf53b53bc88d5c46567616026dc056e72b92319c01000000232200208d398cfb58a1d9cdb59ccbce81559c095e8c6f4a3e64966ca385078d9879f95effffffff01887d180000000000220020c5f4a0a4ea7c0392efe0a9670a73264cffa90b19107cd8a8e9750ff93c77fdfb0400483045022100dd6342c65197af27d7894d8b8b88b16b568ee3b5ebfdc55fdfb7caa9650e3b4c02200c7074a5bcb0068f63d9014c7cd2b0490aba75822d315d41aad444e9b86adf5201483045022100e7e6c2d21109512ba0609e93903e84bfb7731ac3962ee2c1cad54a7a30ff99a20220421497930226c39fc3834e8d6da3fc876516239518b0e82e2dc1e3c46271a17c01695221021630971f20fa349ba940a6ba3706884c41579cd760c89901374358db5dd545b92102f2ff4b353702d2bb03d4c494be19d77d0ab53d16161b53fbcaf1afeef4ad0cb52103e9b6b1c691a12ce448f1aedbbd588e064869c79fbd760eae3b8cd8a5f1a224db53ae00000000" )
def test_send_bch_multisig_change(self): self.setup_mnemonic_allallall() xpubs = [] for n in map( lambda index: btc.get_public_node( self.client, parse_path("48'/145'/%d'" % index) ), range(1, 4), ): xpubs.append(n.xpub) def getmultisig(chain, nr, signatures=[b"", b"", b""], xpubs=xpubs): return proto.MultisigRedeemScriptType( nodes=[deserialize(xpub) for xpub in xpubs], address_n=[chain, nr], signatures=signatures, m=2, ) inp1 = proto.TxInputType( address_n=parse_path("48'/145'/3'/0/0"), multisig=getmultisig(0, 0), amount=48490, prev_hash=bytes.fromhex( "8b6db9b8ba24235d86b053ea2ccb484fc32b96f89c3c39f98d86f90db16076a0" ), prev_index=0, script_type=proto.InputScriptType.SPENDMULTISIG, ) out1 = proto.TxOutputType( address="bitcoincash:qqq8gx2j76nw4dfefumxmdwvtf2tpsjznusgsmzex9", amount=24000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) out2 = proto.TxOutputType( address_n=parse_path("48'/145'/3'/1/0"), multisig=getmultisig(1, 0), script_type=proto.OutputScriptType.PAYTOMULTISIG, amount=24000, ) with self.client: self.client.set_expected_responses( [ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ] ) (signatures1, serialized_tx) = btc.sign_tx( self.client, "Bcash", [inp1], [out1, out2], prev_txes=TX_API ) assert ( signatures1[0].hex() == "3045022100a05f77bb39515c21c43e6c4ba401f39ed5d409dc3cfcd90f9a8345a08cc4bc8202205faf8f3b0775748278495324fdd60f370460452e4995e546450209ec4804a0f3" ) inp1 = proto.TxInputType( address_n=parse_path("48'/145'/1'/0/0"), multisig=getmultisig(0, 0, [b"", b"", signatures1[0]]), # bitcoincash:pqguz4nqq64jhr5v3kvpq4dsjrkda75hwy86gq0qzw amount=48490, prev_hash=bytes.fromhex( "8b6db9b8ba24235d86b053ea2ccb484fc32b96f89c3c39f98d86f90db16076a0" ), prev_index=0, script_type=proto.InputScriptType.SPENDMULTISIG, ) out2.address_n[2] = H_(1) with self.client: self.client.set_expected_responses( [ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ] ) (signatures1, serialized_tx) = btc.sign_tx( self.client, "Bcash", [inp1], [out1, out2], prev_txes=TX_API ) assert ( signatures1[0].hex() == "3044022006f239ef1f065a70873ab9d2c81a623a04ec7a37a0ec5299d3c585668f441f49022032b2f9ef13bc61230d14f6d79b9ad1bbebdf47b95e4757e9af1b1dcdf520d3ab" ) assert ( serialized_tx.hex() == "0100000001a07660b10df9868df9393c9cf8962bc34f48cb2cea53b0865d2324bab8b96d8b00000000fdfd0000473044022006f239ef1f065a70873ab9d2c81a623a04ec7a37a0ec5299d3c585668f441f49022032b2f9ef13bc61230d14f6d79b9ad1bbebdf47b95e4757e9af1b1dcdf520d3ab41483045022100a05f77bb39515c21c43e6c4ba401f39ed5d409dc3cfcd90f9a8345a08cc4bc8202205faf8f3b0775748278495324fdd60f370460452e4995e546450209ec4804a0f3414c69522102f8ca0d9665af03de32a7c19a167a4f6e97e4e0ed9505f75d11f7a45ab60b1f4d2103263d87cefd687bc15b4ef7801f9f538267b66d46f18e9fccc41d54071cfdd1ce210388568bf42f02298308eb6fa2fa4b446d544600253b4409be27e2c0c1a71c424853aeffffffff02c05d0000000000001976a91400741952f6a6eab5394f366db5cc5a54b0c2429f88acc05d00000000000017a91478574751407449b97f8054be2e40e684ad07d3738700000000" )
def test_send_multisig_3_change(self): self.setup_mnemonic_allallall() nodes = [ btc.get_public_node(self.client, parse_path("84'/1'/%d'" % index)) for index in range(1, 4) ] multisig = proto.MultisigRedeemScriptType( nodes=[deserialize(n.xpub) for n in nodes], address_n=[1, 0], signatures=[b"", b"", b""], m=2, ) multisig2 = proto.MultisigRedeemScriptType( nodes=[deserialize(n.xpub) for n in nodes], address_n=[1, 1], signatures=[b"", b"", b""], m=2, ) inp1 = proto.TxInputType( address_n=parse_path("84'/1'/1'/1/0"), prev_hash=bytes.fromhex( "c9348040bbc2024e12dcb4a0b4806b0398646b91acf314da028c3f03dd0179fc" ), prev_index=0, script_type=proto.InputScriptType.SPENDWITNESS, multisig=multisig, amount=1604000, ) out1 = proto.TxOutputType( address_n=parse_path("84'/1'/1'/1/1"), amount=1603000, multisig=multisig2, script_type=proto.OutputScriptType.PAYTOP2SHWITNESS, ) with self.client: self.client.set_expected_responses( [ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ] ) signatures, _ = btc.sign_tx( self.client, "Testnet", [inp1], [out1], prev_txes=TX_API ) # store signature inp1.multisig.signatures[0] = signatures[0] # sign with third key inp1.address_n[2] = H_(3) out1.address_n[2] = H_(3) self.client.set_expected_responses( [ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ] ) _, serialized_tx = btc.sign_tx( self.client, "Testnet", [inp1], [out1], prev_txes=TX_API ) assert ( serialized_tx.hex() == "01000000000101fc7901dd033f8c02da14f3ac916b6498036b80b4a0b4dc124e02c2bb408034c90000000000ffffffff01b87518000000000017a914536250d41937e5b641082447580ff6a8e46c122a870400473044022003c26107a5a47f1f900ef8aa758977530cd13ea37a33971abae8d75cac2f9f34022039e2b8c2c1d0c24ff4fc026652e1f27ad8e3ed6c9bf485f61d9aa691cb57830801483045022100963b0dc0ab46e963a66ab6e69e5e41bac6c4fedc127cac12c560b029d54fe87402205b3bcdcf313dccd78e5dce0540e7d3c8cc1bf83f13c1f9f01811eb791fd35c8101695221039dba3a72f5dc3cad17aa924b5a03c34561465f997d0cb15993f2ca2c0be771c42103cd39f3f08bbd508dce4d307d57d0c70c258c285878bfda579fa260acc738c25d2102cd631ba95beca1d64766f5540885092d0bb384a3c13b6c3a5334d0ebacf51b9553ae00000000" )