def test_zip243(self): coin = coins.by_name("Zcash") for v in self.VECTORS: tx = SignTx( coin_name="Zcash", inputs_count=len(v["inputs"]), outputs_count=len(v["outputs"]), version=v["version"], lock_time=v["lock_time"], expiry=v["expiry"], version_group_id=v["version_group_id"], branch_id=v["branch_id"], ) zip243 = Zip243Hash() for i in v["inputs"]: txi = TxInput( amount=i["amount"], prev_hash=unhexlify(i["prevout"][0]), prev_index=i["prevout"][1], script_type=i["script_type"], sequence=i["sequence"], ) zip243.add_input(txi) for o in v["outputs"]: txo = PrevOutput( amount=o["amount"], script_pubkey=unhexlify(o["script_pubkey"]), ) zip243.add_output(txo, txo.script_pubkey) self.assertEqual(hexlify(get_tx_hash(zip243.h_prevouts)), v["prevouts_hash"]) self.assertEqual(hexlify(get_tx_hash(zip243.h_sequence)), v["sequence_hash"]) self.assertEqual(hexlify(get_tx_hash(zip243.h_outputs)), v["outputs_hash"]) self.assertEqual( hexlify( zip243.preimage_hash(txi, [unhexlify(i["pubkey"])], 1, tx, coin, SIGHASH_ALL)), v["preimage_hash"])
def test_paths_bch(self): incorrect_derivation_paths = [ ([H_(44)], InputScriptType.SPENDADDRESS), # invalid length ([H_(44), H_(145), H_(0), H_(0), H_(0)], InputScriptType.SPENDADDRESS), # too many HARDENED ([H_(49), H_(145), H_(0), 0, 0], InputScriptType.SPENDP2SHWITNESS ), # bch is not segwit coin so 49' is not allowed ([H_(84), H_(145), H_(1), 0, 1], InputScriptType.SPENDWITNESS), # and neither is 84' ([H_(44), H_(145)], InputScriptType.SPENDADDRESS), # invalid length ([H_(44), H_(145), H_(0), 0, 0, 0, 0], InputScriptType.SPENDADDRESS), # invalid length ([H_(44), H_(123), H_(0), 0, 0, 0], InputScriptType.SPENDADDRESS), # invalid slip44 ([H_(44), H_(145), H_(1000), 0, 0], InputScriptType.SPENDADDRESS), # account too high ([H_(44), H_(145), H_(1), 2, 0], InputScriptType.SPENDADDRESS), # invalid y ([H_(44), H_(145), H_(1), 0, 10000000], InputScriptType.SPENDADDRESS), # address index too high ([H_(84), H_(145), H_(1), 0, 10000000], InputScriptType.SPENDWITNESS), # address index too high ([H_(44), H_(145), H_(0), 0, 0], InputScriptType.SPENDWITNESS), # input type mismatch ] correct_derivation_paths = [ ([H_(44), H_(145), H_(0), 0, 0], InputScriptType.SPENDADDRESS), ([H_(44), H_(145), H_(0), 1, 0], InputScriptType.SPENDADDRESS), ([H_(44), H_(145), H_(0), 0, 1123], InputScriptType.SPENDADDRESS), ([H_(44), H_(145), H_(0), 1, 44444], InputScriptType.SPENDADDRESS), ([H_(44), H_(145), H_(5), 0, 0], InputScriptType.SPENDADDRESS), ([H_(48), H_(145), H_(0), H_(0), 0, 0], InputScriptType.SPENDMULTISIG), ([H_(48), H_(145), H_(5), H_(0), 0, 0], InputScriptType.SPENDMULTISIG), ([H_(48), H_(145), H_(5), H_(0), 0, 10], InputScriptType.SPENDMULTISIG), ] coin = coins.by_name('Bcash') # segwit is disabled for path, input_type in incorrect_derivation_paths: self.assertFalse(self.validate(path, coin, input_type)) for path, input_type in correct_derivation_paths: self.assertTrue(self.validate(path, coin, input_type))
async def verify_message(ctx, msg): message = msg.message address = msg.address signature = msg.signature coin_name = msg.coin_name or "Bitcoin" coin = coins.by_name(coin_name) digest = message_digest(coin, message) script_type = None recid = signature[0] if recid >= 27 and recid <= 34: script_type = SPENDADDRESS # p2pkh elif recid >= 35 and recid <= 38: script_type = SPENDP2SHWITNESS # segwit-in-p2sh signature = bytes([signature[0] - 4]) + signature[1:] elif recid >= 39 and recid <= 42: script_type = SPENDWITNESS # native segwit signature = bytes([signature[0] - 8]) + signature[1:] else: raise wire.ProcessError("Invalid signature") pubkey = secp256k1.verify_recover(signature, digest) if not pubkey: raise wire.ProcessError("Invalid signature") if script_type == SPENDADDRESS: addr = address_pkh(pubkey, coin) if coin.cashaddr_prefix is not None: addr = address_to_cashaddr(addr, coin) elif script_type == SPENDP2SHWITNESS: addr = address_p2wpkh_in_p2sh(pubkey, coin) elif script_type == SPENDWITNESS: addr = address_p2wpkh(pubkey, coin) else: raise wire.ProcessError("Invalid signature") if addr != address: raise wire.ProcessError("Invalid signature") await require_confirm_verify_message(ctx, address_short(coin, address), "Verify message", message) return Success(message="Message verified")
def test_bip143_preimage_testdata(self): seed = bip39.seed('alcohol woman abuse must during monitor noble actual mixed trade anger aisle', '') root = bip32.from_seed(seed, 'secp256k1') coin = coins.by_name(self.tx.coin_name) bip143 = Bip143() bip143.add_prevouts(self.inp1) bip143.add_sequence(self.inp1) for txo in [self.out1, self.out2]: txo_bin = TxOutputBinType() txo_bin.amount = txo.amount txo_bin.script_pubkey = output_derive_script(txo, coin, root) bip143.add_output(txo_bin) # test data public key hash result = bip143.preimage_hash(self.tx, self.inp1, unhexlify('79091972186c449eb1ded22b78e40d009bdf0089'), 0x01) self.assertEqual(hexlify(result), b'64f3b0f4dd2bb3aa1ce8566d220cc74dda9df97d8490cc81d89d735c92e59fb6')
def test_coins(self): ref = [ ('BTC', 'Bitcoin', 0), ('TEST', 'Testnet', 111), ('NMC', 'Namecoin', 52), ('LTC', 'Litecoin', 48), ('DOGE', 'Dogecoin', 30), ('DASH', 'Dash', 76), ('ZEC', 'Zcash', 7352), ('TAZ', 'Zcash Testnet', 7461), ] for s, n, a in ref: c1 = coins.by_shortcut(s) c2 = coins.by_name(n) c3 = coins.by_address_type(a) self.assertEqual(c1, c2) self.assertEqual(c1, c3) self.assertEqual(c2, c3)
async def get_address(ctx, msg): coin_name = msg.coin_name or 'Bitcoin' coin = coins.by_name(coin_name) node = await seed.derive_node(ctx, msg.address_n) address = addresses.get_address(msg.script_type, coin, node, msg.multisig) if msg.show_display: while True: if await _show_address(ctx, address): break if await _show_qr( ctx, address.upper() if msg.script_type == InputScriptType.SPENDWITNESS else address): break return Address(address=address)
def test_p2wpkh_verify_proof(self): # SLIP-0019 test vector 1 coin = coins.by_name('Bitcoin') seed = bip39.seed(' '.join(['all'] * 12), 'TREZOR') keychain = Keychain(seed, coin.curve_name, [AlwaysMatchingSchema], slip21_namespaces=[[b"SLIP-0019"]]) commitment_data = b"" # Proof for "all all ... all" seed without passphrase. script_pubkey = unhexlify( "0014b2f771c370ccf219cd3059cda92bdf7f00cf2103") proof = unhexlify( "534c00190001a122407efc198211c81af4450f40b235d54775efd934d16b9e31c6ce9bad57070002483045022100c0dc28bb563fc5fea76cacff75dba9cb4122412faae01937cdebccfb065f9a7002202e980bfbd8a434a7fc4cd2ca49da476ce98ca097437f8159b1a386b41fcdfac50121032ef68318c8f6aaa0adec0199c69901f0db7d3485eb38d9ad235221dc3d61154b" ) self.assertTrue( ownership.verify_nonownership(proof, script_pubkey, commitment_data, keychain, coin))
def test_preimage_testdata(self): seed = bip39.seed('alcohol woman abuse must during monitor noble actual mixed trade anger aisle', '') coin = coins.by_name(self.tx.coin_name) bip143 = Bitcoin(self.tx, None, coin) bip143.hash143_add_input(self.inp1) bip143.hash143_add_input(self.inp2) for txo in [self.out1, self.out2]: txo_bin = TxOutputBinType() txo_bin.amount = txo.amount script_pubkey = output_derive_script(txo, coin) bip143.hash143_add_output(txo_bin, script_pubkey) # test data public key hash # only for input 2 - input 1 is not segwit result = bip143.hash143_preimage_hash(self.inp2, unhexlify('1d0f172a0ecb48aee1be1f2687d2963ae33f71a1')) self.assertEqual(hexlify(result), b'c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670')
def test_p2wpkh_in_p2sh_gen_proof(self): # SLIP-0019 test vector 2 coin = coins.by_name('Bitcoin') seed = bip39.seed(' '.join(['all'] * 12), '') keychain = Keychain(seed, coin.curve_name, [AlwaysMatchingSchema], slip21_namespaces=[[b"SLIP-0019"]]) commitment_data = b"" node = keychain.derive( [49 | HARDENED, 0 | HARDENED, 0 | HARDENED, 1, 0]) address = address_p2wpkh_in_p2sh(node.public_key(), coin) script_pubkey = scripts.output_derive_script(address, coin) ownership_id = ownership.get_identifier(script_pubkey, keychain) self.assertEqual( ownership_id, unhexlify( "92caf0b8daf78f1d388dbbceaec34bd2dabc31b217e32343663667f6694a3f46" )) proof, signature = ownership.generate_proof( node=node, script_type=InputScriptType.SPENDP2SHWITNESS, multisig=None, coin=coin, user_confirmed=False, ownership_ids=[ownership_id], script_pubkey=script_pubkey, commitment_data=commitment_data, ) self.assertEqual( signature, unhexlify( "30440220484072ca317663dd685d372115a9d2ff43d9afc6d352c10445a94e555e12154602202d3ffee5f780dbc74e67fcc4bcbc75a9816ed00df1142d571014724af9959355" )) self.assertEqual( proof, unhexlify( "534c0019000192caf0b8daf78f1d388dbbceaec34bd2dabc31b217e32343663667f6694a3f4617160014e0cffbee1925a411844f44c3b8d81365ab51d036024730440220484072ca317663dd685d372115a9d2ff43d9afc6d352c10445a94e555e12154602202d3ffee5f780dbc74e67fcc4bcbc75a9816ed00df1142d571014724af9959355012103a961687895a78da9aef98eed8e1f2a3e91cfb69d2f3cf11cbd0bb1773d951928" )) self.assertFalse( ownership.verify_nonownership(proof, script_pubkey, commitment_data, keychain, coin))
async def sign_tx(ctx, msg): from apps.wallet.sign_tx import layout, progress, signing coin_name = msg.coin_name or "Bitcoin" coin = coins.by_name(coin_name) # TODO: rework this so we don't have to pass root to signing.sign_tx root = await seed.derive_node(ctx, [], curve_name=coin.curve_name) signer = signing.sign_tx(msg, root) res = None while True: try: req = signer.send(res) except signing.SigningError as e: raise wire.Error(*e.args) except signing.MultisigError as e: raise wire.Error(*e.args) except signing.AddressError as e: raise wire.Error(*e.args) except signing.ScriptsError as e: raise wire.Error(*e.args) except signing.Bip143Error as e: raise wire.Error(*e.args) if isinstance(req, TxRequest): if req.request_type == TXFINISHED: break res = await ctx.call(req, TxAck) elif isinstance(req, UiConfirmOutput): res = await layout.confirm_output(ctx, req.output, req.coin) progress.report_init() elif isinstance(req, UiConfirmTotal): res = await layout.confirm_total(ctx, req.spending, req.fee, req.coin) progress.report_init() elif isinstance(req, UiConfirmFeeOverThreshold): res = await layout.confirm_feeoverthreshold(ctx, req.fee, req.coin) progress.report_init() elif isinstance(req, UiConfirmForeignAddress): res = await layout.confirm_foreign_address(ctx, req.address_n, req.coin) else: raise TypeError("Invalid signing instruction") return req
def test_p2wpkh_in_p2sh_node_derive_address(self): coin = coins.by_name('Testnet') seed = bip39.seed(' '.join(['all'] * 12), '') root = bip32.from_seed(seed, 'secp256k1') node = node_derive(root, [H_(49), H_(1), H_(0), 1, 0]) address = address_p2wpkh_in_p2sh(node.public_key(), coin) self.assertEqual(address, '2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX') node = node_derive(root, [H_(49), H_(1), H_(0), 1, 1]) address = address_p2wpkh_in_p2sh(node.public_key(), coin) self.assertEqual(address, '2NFWLCJQBSpz1oUJwwLpX8ECifFWGznBVqs') node = node_derive(root, [H_(49), H_(1), H_(0), 0, 0]) address = address_p2wpkh_in_p2sh(node.public_key(), coin) self.assertEqual(address, '2N4Q5FhU2497BryFfUgbqkAJE87aKHUhXMp')
def test_p2wpkh_gen_proof(self): # SLIP-0019 test vector 1 coin = coins.by_name('Bitcoin') seed = bip39.seed(' '.join(['all'] * 12), '') keychain = Keychain(seed, coin.curve_name, [AlwaysMatchingSchema], slip21_namespaces=[[b"SLIP-0019"]]) commitment_data = b"" node = keychain.derive( [84 | HARDENED, 0 | HARDENED, 0 | HARDENED, 1, 0]) address = address_p2wpkh(node.public_key(), coin) script_pubkey = scripts.output_derive_script(address, coin) ownership_id = ownership.get_identifier(script_pubkey, keychain) self.assertEqual( ownership_id, unhexlify( "a122407efc198211c81af4450f40b235d54775efd934d16b9e31c6ce9bad5707" )) proof, signature = ownership.generate_proof( node=node, script_type=InputScriptType.SPENDWITNESS, multisig=None, coin=coin, user_confirmed=False, ownership_ids=[ownership_id], script_pubkey=script_pubkey, commitment_data=commitment_data, ) self.assertEqual( signature, unhexlify( "3045022100c0dc28bb563fc5fea76cacff75dba9cb4122412faae01937cdebccfb065f9a7002202e980bfbd8a434a7fc4cd2ca49da476ce98ca097437f8159b1a386b41fcdfac5" )) self.assertEqual( proof, unhexlify( "534c00190001a122407efc198211c81af4450f40b235d54775efd934d16b9e31c6ce9bad57070002483045022100c0dc28bb563fc5fea76cacff75dba9cb4122412faae01937cdebccfb065f9a7002202e980bfbd8a434a7fc4cd2ca49da476ce98ca097437f8159b1a386b41fcdfac50121032ef68318c8f6aaa0adec0199c69901f0db7d3485eb38d9ad235221dc3d61154b" )) self.assertFalse( ownership.verify_nonownership(proof, script_pubkey, commitment_data, keychain, coin))
def test_p2pkh_gen_proof(self): # SLIP-0019 test vector 3 coin = coins.by_name('Bitcoin') seed = bip39.seed(' '.join(['all'] * 12), 'TREZOR') keychain = Keychain(seed, coin.curve_name, [AlwaysMatchingSchema], slip21_namespaces=[[b"SLIP-0019"]]) commitment_data = b"" node = keychain.derive( [44 | HARDENED, 0 | HARDENED, 0 | HARDENED, 1, 0]) address = node.address(coin.address_type) script_pubkey = scripts.output_derive_script(address, coin) ownership_id = ownership.get_identifier(script_pubkey, keychain) self.assertEqual( ownership_id, unhexlify( "ccc49ac5fede0efc80725fbda8b763d4e62a221c51cc5425076cffa7722c0bda" )) proof, signature = ownership.generate_proof( node=node, script_type=InputScriptType.SPENDADDRESS, multisig=None, coin=coin, user_confirmed=False, ownership_ids=[ownership_id], script_pubkey=script_pubkey, commitment_data=commitment_data, ) self.assertEqual( signature, unhexlify( "3045022100e818002d0a85438a7f2140503a6aa0a6af6002fa956d0101fd3db24e776e546f0220430fd59dc1498bc96ab6e71a4829b60224828cf1fc35edc98e0973db203ca3f0" )) self.assertEqual( proof, unhexlify( "534c00190001ccc49ac5fede0efc80725fbda8b763d4e62a221c51cc5425076cffa7722c0bda6b483045022100e818002d0a85438a7f2140503a6aa0a6af6002fa956d0101fd3db24e776e546f0220430fd59dc1498bc96ab6e71a4829b60224828cf1fc35edc98e0973db203ca3f0012102f63159e21fbcb54221ec993def967ad2183a9c243c8bff6e7d60f4d5ed3b386500" )) self.assertFalse( ownership.verify_nonownership(proof, script_pubkey, commitment_data, keychain, coin))
def test_p2tr_gen_proof(self): # SLIP-0019 test vector 5 coin = coins.by_name('Bitcoin') seed = bip39.seed(' '.join(['all'] * 12), '') keychain = Keychain(seed, coin.curve_name, [AlwaysMatchingSchema], slip21_namespaces=[[b"SLIP-0019"]]) commitment_data = b"" node = keychain.derive( [86 | HARDENED, 0 | HARDENED, 0 | HARDENED, 1, 0]) address = address_p2tr(node.public_key(), coin) script_pubkey = scripts.output_derive_script(address, coin) ownership_id = ownership.get_identifier(script_pubkey, keychain) self.assertEqual( ownership_id, unhexlify( "dc18066224b9e30e306303436dc18ab881c7266c13790350a3fe415e438135ec" )) proof, signature = ownership.generate_proof( node=node, script_type=InputScriptType.SPENDTAPROOT, multisig=None, coin=coin, user_confirmed=False, ownership_ids=[ownership_id], script_pubkey=script_pubkey, commitment_data=commitment_data, ) self.assertEqual( signature, unhexlify( "1b553e5b9cc787b531bbc78417aea901272b4ea905136a2babc4d6ca471549743b5e0e39ddc14e620b254e42faa7f6d5bd953e97aa231d764d21bc5a58e8b7d9" )) self.assertEqual( proof, unhexlify( "534c00190001dc18066224b9e30e306303436dc18ab881c7266c13790350a3fe415e438135ec0001401b553e5b9cc787b531bbc78417aea901272b4ea905136a2babc4d6ca471549743b5e0e39ddc14e620b254e42faa7f6d5bd953e97aa231d764d21bc5a58e8b7d9" )) self.assertFalse( ownership.verify_nonownership(proof, script_pubkey, commitment_data, keychain, coin))
def test_bip143_outputs(self): seed = bip39.seed( 'alcohol woman abuse must during monitor noble actual mixed trade anger aisle', '') coin = coins.by_name(self.tx.coin_name) sig_hasher = BitcoinSigHasher() for txo in [self.out1, self.out2]: script_pubkey = output_derive_script(txo.address, coin) txo_bin = PrevOutput(amount=txo.amount, script_pubkey=script_pubkey) sig_hasher.add_output(txo_bin, script_pubkey) outputs_hash = get_tx_hash(sig_hasher.h_outputs, double=coin.sign_hash_double) self.assertEqual( hexlify(outputs_hash), b'de984f44532e2173ca0d64314fcefe6d30da6f8cf27bafa706da61df8a226c83' )
def test_p2wpkh_in_p2sh_gen_proof(self): coin = coins.by_name('Bitcoin') seed = bip39.seed(' '.join(['all'] * 12), '') keychain = Keychain(seed, coin.curve_name, [AlwaysMatchingSchema], slip21_namespaces=[[b"SLIP-0019"]]) commitment_data = b"" node = keychain.derive( [49 | HARDENED, 0 | HARDENED, 0 | HARDENED, 1, 0]) address = address_p2wpkh_in_p2sh(node.public_key(), coin) script_pubkey = scripts.output_derive_script(address, coin) ownership_id = ownership.get_identifier(script_pubkey, keychain) self.assertEqual( ownership_id, unhexlify( "92caf0b8daf78f1d388dbbceaec34bd2dabc31b217e32343663667f6694a3f46" )) proof, signature = ownership.generate_proof( node=node, script_type=InputScriptType.SPENDP2SHWITNESS, multisig=None, coin=coin, user_confirmed=False, ownership_ids=[ownership_id], script_pubkey=script_pubkey, commitment_data=commitment_data, ) self.assertEqual( signature, unhexlify( "3045022100a37330dca699725db613dd1b30059843d1248340642162a0adef114509c9849402201126c9044b998065d40b44fd2399b52c409794bbc3bfdd358cd5fb450c94316d" )) self.assertEqual( proof, unhexlify( "534c0019000192caf0b8daf78f1d388dbbceaec34bd2dabc31b217e32343663667f6694a3f4617160014e0cffbee1925a411844f44c3b8d81365ab51d03602483045022100a37330dca699725db613dd1b30059843d1248340642162a0adef114509c9849402201126c9044b998065d40b44fd2399b52c409794bbc3bfdd358cd5fb450c94316d012103a961687895a78da9aef98eed8e1f2a3e91cfb69d2f3cf11cbd0bb1773d951928" )) self.assertFalse( ownership.verify_nonownership(proof, script_pubkey, commitment_data, keychain, coin))
def test_p2tr_verify_proof(self): # SLIP-0019 test vector 5 coin = coins.by_name('Bitcoin') seed = bip39.seed(' '.join(['all'] * 12), 'TREZOR') keychain = Keychain(seed, coin.curve_name, [AlwaysMatchingSchema], slip21_namespaces=[[b"SLIP-0019"]]) commitment_data = b"" # Proof for "all all ... all" seed without passphrase. script_pubkey = unhexlify( "51204102897557de0cafea0a8401ea5b59668eccb753e4b100aebe6a19609f3cc79f" ) proof = unhexlify( "534c00190001dc18066224b9e30e306303436dc18ab881c7266c13790350a3fe415e438135ec0001401b553e5b9cc787b531bbc78417aea901272b4ea905136a2babc4d6ca471549743b5e0e39ddc14e620b254e42faa7f6d5bd953e97aa231d764d21bc5a58e8b7d9" ) self.assertTrue( ownership.verify_nonownership(proof, script_pubkey, commitment_data, keychain, coin))
def test_zip243(self): coin = coins.by_name("Zcash") for v in self.VECTORS: tx = SignTx( coin_name="Zcash", inputs_count=len(v["inputs"]), outputs_count=len(v["outputs"]), version=v["version"], lock_time=v["lock_time"], expiry=v["expiry"], overwintered=(v["version"] >= 3), version_group_id=v["version_group_id"], ) zip243 = Zip243() for i in v["inputs"]: txi = TxInputType() txi.amount = i["amount"] txi.prev_hash = unhexlify(i["prevout"][0]) txi.prev_index = i["prevout"][1] txi.script_type = i["script_type"] txi.sequence = i["sequence"] zip243.add_prevouts(txi) zip243.add_sequence(txi) for o in v["outputs"]: txo = TxOutputBinType() txo.amount = o["amount"] txo.script_pubkey = unhexlify(o["script_pubkey"]) zip243.add_output(txo) self.assertEqual(hexlify(zip243.get_prevouts_hash()), v["prevouts_hash"]) self.assertEqual(hexlify(zip243.get_sequence_hash()), v["sequence_hash"]) self.assertEqual(hexlify(zip243.get_outputs_hash()), v["outputs_hash"]) self.assertEqual( hexlify( zip243.preimage_hash(coin, tx, txi, unhexlify(i["pubkeyhash"]), v["hash_type"])), v["preimage_hash"], )
def test_bip143_outputs(self): seed = bip39.seed( 'alcohol woman abuse must during monitor noble actual mixed trade anger aisle', '') coin = coins.by_name(self.tx.coin_name) bip143 = Bitcoin(self.tx, None, coin) for txo in [self.out1, self.out2]: txo_bin = TxOutputBinType() txo_bin.amount = txo.amount script_pubkey = output_derive_script(txo, coin) bip143.hash143_add_output(txo_bin, script_pubkey) outputs_hash = get_tx_hash(bip143.h_outputs, double=coin.sign_hash_double) self.assertEqual( hexlify(outputs_hash), b'de984f44532e2173ca0d64314fcefe6d30da6f8cf27bafa706da61df8a226c83' )
def test_p2wpkh_in_p2sh_node_derive_address(self): coin = coins.by_name('Groestlcoin Testnet') seed = bip39.seed(' '.join(['all'] * 12), '') root = bip32.from_seed(seed, coin.curve_name) node = node_derive( root, [49 | 0x80000000, 1 | 0x80000000, 0 | 0x80000000, 1, 0]) address = address_p2wpkh_in_p2sh(node.public_key(), coin) self.assertEqual(address, '2N1LGaGg836mqSQqiuUBLfcyGBhyZYBtBZ7') node = node_derive( root, [49 | 0x80000000, 1 | 0x80000000, 0 | 0x80000000, 1, 1]) address = address_p2wpkh_in_p2sh(node.public_key(), coin) self.assertEqual(address, '2NFWLCJQBSpz1oUJwwLpX8ECifFWGxQyzGu') node = node_derive( root, [49 | 0x80000000, 1 | 0x80000000, 0 | 0x80000000, 0, 0]) address = address_p2wpkh_in_p2sh(node.public_key(), coin) self.assertEqual(address, '2N4Q5FhU2497BryFfUgbqkAJE87aKDv3V3e')
async def verify_message(ctx, msg): message = msg.message address = msg.address signature = msg.signature coin_name = msg.coin_name or 'Bitcoin' coin = coins.by_name(coin_name) digest = message_digest(coin, message) script_type = None recid = signature[0] if recid >= 27 and recid <= 34: script_type = SPENDADDRESS # p2pkh elif recid >= 35 and recid <= 38: script_type = SPENDP2SHWITNESS # segwit-in-p2sh signature = bytes([signature[0] - 4]) + signature[1:] elif recid >= 39 and recid <= 42: script_type = SPENDWITNESS # native segwit signature = bytes([signature[0] - 8]) + signature[1:] else: raise wire.FailureError(ProcessError, 'Invalid signature') pubkey = secp256k1.verify_recover(signature, digest) if not pubkey: raise wire.FailureError(ProcessError, 'Invalid signature') if script_type == SPENDADDRESS: addr = address_pkh(pubkey, coin.address_type) elif script_type == SPENDP2SHWITNESS: addr = address_p2wpkh_in_p2sh(pubkey, coin.address_type_p2sh) elif script_type == SPENDWITNESS: addr = address_p2wpkh(pubkey, coin.bech32_prefix) else: raise wire.FailureError(ProcessError, 'Invalid signature') if addr != address: raise wire.FailureError(ProcessError, 'Invalid signature') await require_confirm_verify_message(ctx, address, message) return Success(message='Message verified')
def test_p2pkh_gen_proof(self): coin = coins.by_name('Bitcoin') seed = bip39.seed(' '.join(['all'] * 12), 'TREZOR') keychain = Keychain(seed, coin.curve_name, [AlwaysMatchingSchema], slip21_namespaces=[[b"SLIP-0019"]]) commitment_data = b"" node = keychain.derive( [44 | HARDENED, 0 | HARDENED, 0 | HARDENED, 1, 0]) address = node.address(coin.address_type) script_pubkey = scripts.output_derive_script(address, coin) ownership_id = ownership.get_identifier(script_pubkey, keychain) self.assertEqual( ownership_id, unhexlify( "ccc49ac5fede0efc80725fbda8b763d4e62a221c51cc5425076cffa7722c0bda" )) proof, signature = ownership.generate_proof( node=node, script_type=InputScriptType.SPENDADDRESS, multisig=None, coin=coin, user_confirmed=False, ownership_ids=[ownership_id], script_pubkey=script_pubkey, commitment_data=commitment_data, ) self.assertEqual( signature, unhexlify( "304402206682f40a12f3609a308acb872888470a07760f2f4790ee4ff62665a39c02a5fc022026f3f38a7c2b2668c2eff9cc1e712c7f254926a482bae411ad18947eba9fd21c" )) self.assertEqual( proof, unhexlify( "534c00190001ccc49ac5fede0efc80725fbda8b763d4e62a221c51cc5425076cffa7722c0bda6a47304402206682f40a12f3609a308acb872888470a07760f2f4790ee4ff62665a39c02a5fc022026f3f38a7c2b2668c2eff9cc1e712c7f254926a482bae411ad18947eba9fd21c012102f63159e21fbcb54221ec993def967ad2183a9c243c8bff6e7d60f4d5ed3b386500" )) self.assertFalse( ownership.verify_nonownership(proof, script_pubkey, commitment_data, keychain, coin))
def test_p2wpkh_gen_proof(self): coin = coins.by_name('Bitcoin') seed = bip39.seed(' '.join(['all'] * 12), '') keychain = Keychain(seed, coin.curve_name, [AlwaysMatchingSchema], slip21_namespaces=[[b"SLIP-0019"]]) commitment_data = b"" node = keychain.derive( [84 | HARDENED, 0 | HARDENED, 0 | HARDENED, 1, 0]) address = address_p2wpkh(node.public_key(), coin) script_pubkey = scripts.output_derive_script(address, coin) ownership_id = ownership.get_identifier(script_pubkey, keychain) self.assertEqual( ownership_id, unhexlify( "a122407efc198211c81af4450f40b235d54775efd934d16b9e31c6ce9bad5707" )) proof, signature = ownership.generate_proof( node=node, script_type=InputScriptType.SPENDWITNESS, multisig=None, coin=coin, user_confirmed=False, ownership_ids=[ownership_id], script_pubkey=script_pubkey, commitment_data=commitment_data, ) self.assertEqual( signature, unhexlify( "3045022100e5eaf2cb0a473b4545115c7b85323809e75cb106175ace38129fd62323d73df30220363dbc7acb7afcda022b1f8d97acb8f47c42043cfe0595583aa26e30bc8b3bb5" )) self.assertEqual( proof, unhexlify( "534c00190001a122407efc198211c81af4450f40b235d54775efd934d16b9e31c6ce9bad57070002483045022100e5eaf2cb0a473b4545115c7b85323809e75cb106175ace38129fd62323d73df30220363dbc7acb7afcda022b1f8d97acb8f47c42043cfe0595583aa26e30bc8b3bb50121032ef68318c8f6aaa0adec0199c69901f0db7d3485eb38d9ad235221dc3d61154b" )) self.assertFalse( ownership.verify_nonownership(proof, script_pubkey, commitment_data, keychain, coin))
def test_zip143(self): coin = coins.by_name("Zcash") for v in self.VECTORS: tx = SignTx( coin_name="Zcash", inputs_count=len(v["inputs"]), outputs_count=len(v["outputs"]), version=v["version"], lock_time=v["lock_time"], expiry=v["expiry"], version_group_id=v["version_group_id"], ) zip143 = Overwintered(tx, None, coin) for i in v["inputs"]: txi = TxInputType() txi.amount = i["amount"] txi.prev_hash = unhexlify(i["prevout"][0]) txi.prev_index = i["prevout"][1] txi.script_type = i["script_type"] txi.sequence = i["sequence"] zip143.hash143_add_input(txi) for o in v["outputs"]: txo = TxOutputBinType() txo.amount = o["amount"] txo.script_pubkey = unhexlify(o["script_pubkey"]) zip143.hash143_add_output(txo, txo.script_pubkey) self.assertEqual(hexlify(get_tx_hash(zip143.h_prevouts)), v["prevouts_hash"]) self.assertEqual(hexlify(get_tx_hash(zip143.h_sequence)), v["sequence_hash"]) self.assertEqual(hexlify(get_tx_hash(zip143.h_outputs)), v["outputs_hash"]) self.assertEqual( hexlify( zip143.hash143_preimage_hash(txi, unhexlify(i["pubkeyhash"]))), v["preimage_hash"], )
def test_preimage_testdata(self): seed = bip39.seed('alcohol woman abuse must during monitor noble actual mixed trade anger aisle', '') coin = coins.by_name(self.tx.coin_name) sig_hasher = BitcoinSigHasher() sig_hasher.add_input(self.inp1, b"") sig_hasher.add_input(self.inp2, b"") for txo in [self.out1, self.out2]: script_pubkey = output_derive_script(txo.address, coin) txo_bin = PrevOutput(amount=txo.amount, script_pubkey=script_pubkey) sig_hasher.add_output(txo_bin, script_pubkey) keychain = Keychain(seed, coin.curve_name, [AlwaysMatchingSchema]) node = keychain.derive(self.inp2.address_n) # test data public key hash # only for input 2 - input 1 is not segwit result = sig_hasher.hash143(self.inp2, [node.public_key()], 1, self.tx, coin, SigHashType.SIGHASH_ALL) self.assertEqual(hexlify(result), b'2fa3f1351618b2532228d7182d3221d95c21fd3d496e7e22e9ded873cf022a8b')
def test_multisig_address_p2sh(self): # # test data from # # http://www.soroushjp.com/2014/12/20/bitcoin-multisig-the-hard-way-understanding-raw-multisignature-bitcoin-transactions/ # # commented out because uncompressed public keys are not supported # coin = coins.by_name('Bitcoin') # pubkeys = [ # unhexlify('04a882d414e478039cd5b52a92ffb13dd5e6bd4515497439dffd691a0f12af9575fa349b5694ed3155b136f09e63975a1700c9f4d4df849323dac06cf3bd6458cd'), # unhexlify('046ce31db9bdd543e72fe3039a1f1c047dab87037c36a669ff90e28da1848f640de68c2fe913d363a51154a0c62d7adea1b822d05035077418267b1a1379790187'), # unhexlify('0411ffd36c70776538d079fbae117dc38effafb33304af83ce4894589747aee1ef992f63280567f52f5ba870678b4ab4ff6c8ea600bd217870a8b4f1f09f3a8e83'), # ] # address = address_multisig_p2sh(pubkeys, 2, coin.address_type_p2sh) # self.assertEqual(address, '347N1Thc213QqfYCz3PZkjoJpNv5b14kBd') coin = coins.by_name('Bitcoin') pubkeys = [ unhexlify('02fe6f0a5a297eb38c391581c4413e084773ea23954d93f7753db7dc0adc188b2f'), unhexlify('02ff12471208c14bd580709cb2358d98975247d8765f92bc25eab3b2763ed605f8'), ] address = address_multisig_p2sh(pubkeys, 2, coin.address_type_p2sh) self.assertEqual(address, '39bgKC7RFbpoCRbtD5KEdkYKtNyhpsNa3Z')
def test_outputs(self): seed = bip39.seed( 'alcohol woman abuse must during monitor noble actual mixed trade anger aisle', '') coin = coins.by_name(self.tx.coin_name) bip143 = Bitcoin(self.tx, None, coin) for txo in [self.out1, self.out2]: txo_bin = TxOutputBinType() txo_bin.amount = txo.amount script_pubkey = output_derive_script(txo.address, coin) bip143.hash143_add_output(txo_bin, script_pubkey) outputs_hash = get_tx_hash(bip143.h_outputs, double=coin.sign_hash_double) self.assertEqual( hexlify(outputs_hash), b'863ef3e1a92afbfdb97f31ad0fc7683ee943e9abcf2501590ff8f6551f47e5e5' )
def test_bip143_outputs(self): seed = bip39.seed( 'alcohol woman abuse must during monitor noble actual mixed trade anger aisle', '') root = bip32.from_seed(seed, 'secp256k1') coin = coins.by_name(self.tx.coin_name) bip143 = Bip143() for txo in [self.out1, self.out2]: txo_bin = TxOutputBinType() txo_bin.amount = txo.amount txo_bin.script_pubkey = output_derive_script(txo, coin, root) bip143.add_output(txo_bin) self.assertEqual( hexlify(bip143.get_outputs_hash()), b'de984f44532e2173ca0d64314fcefe6d30da6f8cf27bafa706da61df8a226c83' )
def test_outputs(self): seed = bip39.seed( 'alcohol woman abuse must during monitor noble actual mixed trade anger aisle', '') root = bip32.from_seed(seed, 'secp256k1') coin = coins.by_name(self.tx.coin_name) bip143 = Bip143() for txo in [self.out1, self.out2]: txo_bin = TxOutputBinType() txo_bin.amount = txo.amount txo_bin.script_pubkey = output_derive_script(txo, coin, root) bip143.add_output(txo_bin) self.assertEqual( hexlify(bip143.get_outputs_hash()), b'863ef3e1a92afbfdb97f31ad0fc7683ee943e9abcf2501590ff8f6551f47e5e5' )
def test_preimage_testdata(self): seed = bip39.seed('alcohol woman abuse must during monitor noble actual mixed trade anger aisle', '') coin = coins.by_name(self.tx.coin_name) bip143 = Bitcoin(self.tx, None, coin, BasicApprover(self.tx, coin)) bip143.hash143_add_input(self.inp1) bip143.hash143_add_input(self.inp2) for txo in [self.out1, self.out2]: txo_bin = TxOutputBinType() txo_bin.amount = txo.amount script_pubkey = output_derive_script(txo.address, coin) bip143.hash143_add_output(txo_bin, script_pubkey) keychain = Keychain(seed, coin.curve_name, [[]]) node = keychain.derive(self.inp2.address_n) # test data public key hash # only for input 2 - input 1 is not segwit result = bip143.hash143_preimage_hash(self.inp2, [node.public_key()], 1) self.assertEqual(hexlify(result), b'2fa3f1351618b2532228d7182d3221d95c21fd3d496e7e22e9ded873cf022a8b')