1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-18 04:18:10 +00:00

feat(core): Support ownership proofs for Taproot addresses.

This commit is contained in:
Andrew Kozlik 2021-12-01 14:19:04 +01:00 committed by Andrew Kozlik
parent b0f2d43884
commit ef5994d9f3
4 changed files with 44 additions and 2 deletions

View File

@ -0,0 +1 @@
Support ownership proofs for Taproot addresses.

View File

@ -56,6 +56,8 @@ def generate_proof(
InputScriptType.SPENDP2SHWITNESS,
):
signature = common.ecdsa_sign(node, sighash.digest())
elif script_type == InputScriptType.SPENDTAPROOT:
signature = common.bip340_sign(node, sighash.digest())
else:
raise wire.DataError("Unsupported script type.")
public_key = node.public_key()

View File

@ -609,7 +609,9 @@ def write_bip322_signature_proof(
w, script_type, multisig, coin, SigHashType.SIGHASH_ALL, public_key, signature
)
if script_type in common.SEGWIT_INPUT_SCRIPT_TYPES:
if script_type == InputScriptType.SPENDTAPROOT:
write_witness_p2tr(w, signature, SigHashType.SIGHASH_ALL_TAPROOT)
elif script_type in common.SEGWIT_INPUT_SCRIPT_TYPES:
if multisig:
# find the place of our signature based on the public key
signature_index = multisig_pubkey_index(multisig, public_key)

View File

@ -8,7 +8,7 @@ from apps.common import coins
from apps.common.keychain import Keychain
from apps.common.paths import HARDENED, AlwaysMatchingSchema
from apps.bitcoin import ownership, scripts
from apps.bitcoin.addresses import address_p2wpkh, address_p2wpkh_in_p2sh, address_multisig_p2wsh, address_multisig_p2wsh_in_p2sh, address_multisig_p2sh
from apps.bitcoin.addresses import address_p2tr, address_p2wpkh, address_p2wpkh_in_p2sh, address_multisig_p2wsh, address_multisig_p2wsh_in_p2sh, address_multisig_p2sh
from apps.bitcoin.multisig import multisig_get_pubkeys
@ -67,6 +67,32 @@ class TestOwnershipProof(unittest.TestCase):
self.assertEqual(proof, unhexlify("534c0019000192caf0b8daf78f1d388dbbceaec34bd2dabc31b217e32343663667f6694a3f4617160014e0cffbee1925a411844f44c3b8d81365ab51d03602483045022100a37330dca699725db613dd1b30059843d1248340642162a0adef114509c9849402201126c9044b998065d40b44fd2399b52c409794bbc3bfdd358cd5fb450c94316d012103a961687895a78da9aef98eed8e1f2a3e91cfb69d2f3cf11cbd0bb1773d951928"))
self.assertFalse(ownership.verify_nonownership(proof, script_pubkey, commitment_data, keychain, coin))
def test_p2tr_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([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("6cd08474ea019c9ab4b9b7b76ec03c4dd4db76abc3a460434a91cfc1b190174949eb7111c8e762407730a215421a0da0b5e01f48de62d7ccea0abea046e2a496"))
self.assertEqual(proof, unhexlify("534c00190001dc18066224b9e30e306303436dc18ab881c7266c13790350a3fe415e438135ec0001406cd08474ea019c9ab4b9b7b76ec03c4dd4db76abc3a460434a91cfc1b190174949eb7111c8e762407730a215421a0da0b5e01f48de62d7ccea0abea046e2a496"))
self.assertFalse(ownership.verify_nonownership(proof, script_pubkey, commitment_data, keychain, coin))
def test_p2pkh_gen_proof(self):
coin = coins.by_name('Bitcoin')
seed = bip39.seed(' '.join(['all'] * 12), 'TREZOR')
@ -104,6 +130,17 @@ class TestOwnershipProof(unittest.TestCase):
proof = unhexlify("534c00190001a122407efc198211c81af4450f40b235d54775efd934d16b9e31c6ce9bad57070002483045022100e5eaf2cb0a473b4545115c7b85323809e75cb106175ace38129fd62323d73df30220363dbc7acb7afcda022b1f8d97acb8f47c42043cfe0595583aa26e30bc8b3bb50121032ef68318c8f6aaa0adec0199c69901f0db7d3485eb38d9ad235221dc3d61154b")
self.assertTrue(ownership.verify_nonownership(proof, script_pubkey, commitment_data, keychain, coin))
def test_p2tr_verify_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""
# Proof for "all all ... all" seed without passphrase.
script_pubkey = unhexlify("51204102897557de0cafea0a8401ea5b59668eccb753e4b100aebe6a19609f3cc79f")
proof = unhexlify("534c00190001dc18066224b9e30e306303436dc18ab881c7266c13790350a3fe415e438135ec0001406cd08474ea019c9ab4b9b7b76ec03c4dd4db76abc3a460434a91cfc1b190174949eb7111c8e762407730a215421a0da0b5e01f48de62d7ccea0abea046e2a496")
self.assertTrue(ownership.verify_nonownership(proof, script_pubkey, commitment_data, keychain, coin))
def test_p2wsh_gen_proof(self):
coin = coins.by_name('Bitcoin')
seed = bip39.seed(' '.join(['all'] * 12), '')