mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-06-25 09:22:33 +00:00
feat(core): support ownership proof anti-exfil protocol
This commit is contained in:
parent
cb7ac84d8a
commit
12ccfcd43c
@ -131,10 +131,6 @@ class EcdsaSigner:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def ecdsa_sign(node: bip32.HDNode, digest: bytes) -> bytes:
|
|
||||||
return EcdsaSigner(node, digest).sign()
|
|
||||||
|
|
||||||
|
|
||||||
def bip340_sign(node: bip32.HDNode, digest: bytes) -> bytes:
|
def bip340_sign(node: bip32.HDNode, digest: bytes) -> bytes:
|
||||||
internal_private_key = node.private_key()
|
internal_private_key = node.private_key()
|
||||||
output_private_key = bip340.tweak_secret_key(internal_private_key)
|
output_private_key = bip340.tweak_secret_key(internal_private_key)
|
||||||
|
@ -11,6 +11,17 @@ if TYPE_CHECKING:
|
|||||||
from .authorization import CoinJoinAuthorization
|
from .authorization import CoinJoinAuthorization
|
||||||
|
|
||||||
|
|
||||||
|
async def send_request_entropy(nonce_commitment: bytes) -> bytes:
|
||||||
|
from trezor.messages import OwnershipProofEntropy, OwnershipProofNonceCommitment
|
||||||
|
from trezor.wire.context import call
|
||||||
|
|
||||||
|
req = OwnershipProofNonceCommitment()
|
||||||
|
req.nonce_commitment = nonce_commitment
|
||||||
|
resp = await call(req, OwnershipProofEntropy)
|
||||||
|
assert resp.entropy is not None
|
||||||
|
return resp.entropy
|
||||||
|
|
||||||
|
|
||||||
@with_keychain
|
@with_keychain
|
||||||
async def get_ownership_proof(
|
async def get_ownership_proof(
|
||||||
msg: GetOwnershipProof,
|
msg: GetOwnershipProof,
|
||||||
@ -28,7 +39,7 @@ async def get_ownership_proof(
|
|||||||
|
|
||||||
from . import addresses, common, scripts
|
from . import addresses, common, scripts
|
||||||
from .keychain import validate_path_against_script_type
|
from .keychain import validate_path_against_script_type
|
||||||
from .ownership import generate_proof, get_identifier
|
from .ownership import ProofGenerator, get_identifier
|
||||||
|
|
||||||
script_type = msg.script_type # local_cache_attribute
|
script_type = msg.script_type # local_cache_attribute
|
||||||
ownership_ids = msg.ownership_ids # local_cache_attribute
|
ownership_ids = msg.ownership_ids # local_cache_attribute
|
||||||
@ -83,7 +94,7 @@ async def get_ownership_proof(
|
|||||||
TR.bitcoin__commitment_data,
|
TR.bitcoin__commitment_data,
|
||||||
)
|
)
|
||||||
|
|
||||||
ownership_proof, signature = generate_proof(
|
proof_generator = ProofGenerator(
|
||||||
node,
|
node,
|
||||||
script_type,
|
script_type,
|
||||||
msg.multisig,
|
msg.multisig,
|
||||||
@ -94,4 +105,13 @@ async def get_ownership_proof(
|
|||||||
msg.commitment_data,
|
msg.commitment_data,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if msg.entropy_commitment:
|
||||||
|
# use anti-exfil protocol
|
||||||
|
nonce_commitment = proof_generator.commit_nonce(msg.entropy_commitment)
|
||||||
|
entropy = await send_request_entropy(nonce_commitment)
|
||||||
|
_, signature = proof_generator.sign(entropy)
|
||||||
|
return OwnershipProof(ownership_proof=b"", signature=signature)
|
||||||
|
else:
|
||||||
|
ownership_proof, signature = proof_generator.sign()
|
||||||
|
assert ownership_proof is not None
|
||||||
return OwnershipProof(ownership_proof=ownership_proof, signature=signature)
|
return OwnershipProof(ownership_proof=ownership_proof, signature=signature)
|
||||||
|
@ -3,17 +3,18 @@ from typing import TYPE_CHECKING
|
|||||||
|
|
||||||
from trezor import utils
|
from trezor import utils
|
||||||
from trezor.crypto.hashlib import sha256
|
from trezor.crypto.hashlib import sha256
|
||||||
|
from trezor.enums import InputScriptType
|
||||||
from trezor.utils import HashWriter
|
from trezor.utils import HashWriter
|
||||||
from trezor.wire import DataError
|
from trezor.wire import DataError
|
||||||
|
|
||||||
from apps.bitcoin.writers import write_bytes_prefixed
|
from apps.bitcoin.writers import write_bytes_prefixed
|
||||||
from apps.common.readers import read_compact_size
|
from apps.common.readers import read_compact_size
|
||||||
|
|
||||||
|
from .common import EcdsaSigner
|
||||||
from .scripts import read_bip322_signature_proof
|
from .scripts import read_bip322_signature_proof
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from trezor.crypto import bip32
|
from trezor.crypto import bip32
|
||||||
from trezor.enums import InputScriptType
|
|
||||||
from trezor.messages import MultisigRedeemScriptType
|
from trezor.messages import MultisigRedeemScriptType
|
||||||
|
|
||||||
from apps.common.coininfo import CoinInfo
|
from apps.common.coininfo import CoinInfo
|
||||||
@ -29,28 +30,36 @@ _OWNERSHIP_ID_LEN = const(32)
|
|||||||
_OWNERSHIP_ID_KEY_PATH = [b"SLIP-0019", b"Ownership identification key"]
|
_OWNERSHIP_ID_KEY_PATH = [b"SLIP-0019", b"Ownership identification key"]
|
||||||
|
|
||||||
|
|
||||||
def generate_proof(
|
class ProofGenerator:
|
||||||
node: bip32.HDNode,
|
@staticmethod
|
||||||
script_type: InputScriptType,
|
def is_ecdsa_script_type(script_type: InputScriptType) -> bool:
|
||||||
multisig: MultisigRedeemScriptType | None,
|
return script_type in (
|
||||||
coin: CoinInfo,
|
InputScriptType.SPENDADDRESS,
|
||||||
|
InputScriptType.SPENDMULTISIG,
|
||||||
|
InputScriptType.SPENDWITNESS,
|
||||||
|
InputScriptType.SPENDP2SHWITNESS,
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_proof_body(
|
||||||
user_confirmed: bool,
|
user_confirmed: bool,
|
||||||
ownership_ids: list[bytes],
|
ownership_ids: list[bytes],
|
||||||
script_pubkey: bytes,
|
script_pubkey: bytes,
|
||||||
commitment_data: bytes,
|
commitment_data: bytes,
|
||||||
) -> tuple[bytes, bytes]:
|
) -> tuple[bytearray, bytes]:
|
||||||
from trezor.enums import InputScriptType
|
from apps.bitcoin.writers import (
|
||||||
|
write_bytes_fixed,
|
||||||
from apps.bitcoin.writers import write_bytes_fixed, write_compact_size, write_uint8
|
write_compact_size,
|
||||||
|
write_uint8,
|
||||||
from . import common
|
)
|
||||||
from .scripts import write_bip322_signature_proof
|
|
||||||
|
|
||||||
flags = 0
|
flags = 0
|
||||||
if user_confirmed:
|
if user_confirmed:
|
||||||
flags |= _FLAG_USER_CONFIRMED
|
flags |= _FLAG_USER_CONFIRMED
|
||||||
|
|
||||||
proof = utils.empty_bytearray(4 + 1 + 1 + len(ownership_ids) * _OWNERSHIP_ID_LEN)
|
proof = utils.empty_bytearray(
|
||||||
|
4 + 1 + 1 + len(ownership_ids) * _OWNERSHIP_ID_LEN
|
||||||
|
)
|
||||||
|
|
||||||
write_bytes_fixed(proof, _VERSION_MAGIC, 4)
|
write_bytes_fixed(proof, _VERSION_MAGIC, 4)
|
||||||
write_uint8(proof, flags)
|
write_uint8(proof, flags)
|
||||||
@ -61,23 +70,63 @@ def generate_proof(
|
|||||||
sighash = HashWriter(sha256(proof))
|
sighash = HashWriter(sha256(proof))
|
||||||
write_bytes_prefixed(sighash, script_pubkey)
|
write_bytes_prefixed(sighash, script_pubkey)
|
||||||
write_bytes_prefixed(sighash, commitment_data)
|
write_bytes_prefixed(sighash, commitment_data)
|
||||||
if script_type in (
|
digest = sighash.get_digest()
|
||||||
InputScriptType.SPENDADDRESS,
|
|
||||||
InputScriptType.SPENDMULTISIG,
|
return proof, digest
|
||||||
InputScriptType.SPENDWITNESS,
|
|
||||||
InputScriptType.SPENDP2SHWITNESS,
|
def __init__(
|
||||||
):
|
self,
|
||||||
signature = common.ecdsa_sign(node, sighash.get_digest())
|
node: bip32.HDNode,
|
||||||
elif script_type == InputScriptType.SPENDTAPROOT:
|
script_type: InputScriptType,
|
||||||
signature = common.bip340_sign(node, sighash.get_digest())
|
multisig: MultisigRedeemScriptType | None,
|
||||||
|
coin: CoinInfo,
|
||||||
|
user_confirmed: bool,
|
||||||
|
ownership_ids: list[bytes],
|
||||||
|
script_pubkey: bytes,
|
||||||
|
commitment_data: bytes,
|
||||||
|
) -> None:
|
||||||
|
self.proof_body, self.digest = self.get_proof_body(
|
||||||
|
user_confirmed, ownership_ids, script_pubkey, commitment_data
|
||||||
|
)
|
||||||
|
self.node = node
|
||||||
|
self.multisig = multisig
|
||||||
|
self.coin = coin
|
||||||
|
self.script_type = script_type
|
||||||
|
|
||||||
|
if self.is_ecdsa_script_type(script_type):
|
||||||
|
self.signer = EcdsaSigner(self.node, self.digest)
|
||||||
|
|
||||||
|
def commit_nonce(self, entropy_commitment: bytes) -> bytes:
|
||||||
|
if not self.is_ecdsa_script_type(self.script_type):
|
||||||
|
raise DataError("Unsupported script type.")
|
||||||
|
|
||||||
|
return self.signer.commit_nonce(entropy_commitment)
|
||||||
|
|
||||||
|
def sign(self, entropy: bytes | None = None) -> tuple[bytes | None, bytes]:
|
||||||
|
|
||||||
|
from . import common
|
||||||
|
from .scripts import write_bip322_signature_proof
|
||||||
|
|
||||||
|
if self.is_ecdsa_script_type(self.script_type):
|
||||||
|
signature = self.signer.sign(entropy)
|
||||||
|
elif self.script_type == InputScriptType.SPENDTAPROOT:
|
||||||
|
signature = common.bip340_sign(self.node, self.digest)
|
||||||
else:
|
else:
|
||||||
raise DataError("Unsupported script type.")
|
raise DataError("Unsupported script type.")
|
||||||
public_key = node.public_key()
|
|
||||||
write_bip322_signature_proof(
|
|
||||||
proof, script_type, multisig, coin, public_key, signature
|
|
||||||
)
|
|
||||||
|
|
||||||
return proof, signature
|
if entropy is None:
|
||||||
|
public_key = self.node.public_key()
|
||||||
|
write_bip322_signature_proof(
|
||||||
|
self.proof_body,
|
||||||
|
self.script_type,
|
||||||
|
self.multisig,
|
||||||
|
self.coin,
|
||||||
|
public_key,
|
||||||
|
signature,
|
||||||
|
)
|
||||||
|
return self.proof_body, signature
|
||||||
|
else:
|
||||||
|
return None, signature
|
||||||
|
|
||||||
|
|
||||||
def verify_nonownership(
|
def verify_nonownership(
|
||||||
|
@ -43,7 +43,7 @@ class TestOwnershipProof(unittest.TestCase):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
proof, signature = ownership.generate_proof(
|
proof, signature = ownership.ProofGenerator(
|
||||||
node=node,
|
node=node,
|
||||||
script_type=InputScriptType.SPENDWITNESS,
|
script_type=InputScriptType.SPENDWITNESS,
|
||||||
multisig=None,
|
multisig=None,
|
||||||
@ -52,7 +52,7 @@ class TestOwnershipProof(unittest.TestCase):
|
|||||||
ownership_ids=[ownership_id],
|
ownership_ids=[ownership_id],
|
||||||
script_pubkey=script_pubkey,
|
script_pubkey=script_pubkey,
|
||||||
commitment_data=commitment_data,
|
commitment_data=commitment_data,
|
||||||
)
|
).sign()
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
signature,
|
signature,
|
||||||
unhexlify(
|
unhexlify(
|
||||||
@ -95,7 +95,7 @@ class TestOwnershipProof(unittest.TestCase):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
proof, signature = ownership.generate_proof(
|
proof, signature = ownership.ProofGenerator(
|
||||||
node=node,
|
node=node,
|
||||||
script_type=InputScriptType.SPENDP2SHWITNESS,
|
script_type=InputScriptType.SPENDP2SHWITNESS,
|
||||||
multisig=None,
|
multisig=None,
|
||||||
@ -104,7 +104,7 @@ class TestOwnershipProof(unittest.TestCase):
|
|||||||
ownership_ids=[ownership_id],
|
ownership_ids=[ownership_id],
|
||||||
script_pubkey=script_pubkey,
|
script_pubkey=script_pubkey,
|
||||||
commitment_data=commitment_data,
|
commitment_data=commitment_data,
|
||||||
)
|
).sign()
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
signature,
|
signature,
|
||||||
unhexlify(
|
unhexlify(
|
||||||
@ -146,7 +146,7 @@ class TestOwnershipProof(unittest.TestCase):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
proof, signature = ownership.generate_proof(
|
proof, signature = ownership.ProofGenerator(
|
||||||
node=node,
|
node=node,
|
||||||
script_type=InputScriptType.SPENDTAPROOT,
|
script_type=InputScriptType.SPENDTAPROOT,
|
||||||
multisig=None,
|
multisig=None,
|
||||||
@ -155,7 +155,7 @@ class TestOwnershipProof(unittest.TestCase):
|
|||||||
ownership_ids=[ownership_id],
|
ownership_ids=[ownership_id],
|
||||||
script_pubkey=script_pubkey,
|
script_pubkey=script_pubkey,
|
||||||
commitment_data=commitment_data,
|
commitment_data=commitment_data,
|
||||||
)
|
).sign()
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
signature,
|
signature,
|
||||||
unhexlify(
|
unhexlify(
|
||||||
@ -197,7 +197,7 @@ class TestOwnershipProof(unittest.TestCase):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
proof, signature = ownership.generate_proof(
|
proof, signature = ownership.ProofGenerator(
|
||||||
node=node,
|
node=node,
|
||||||
script_type=InputScriptType.SPENDADDRESS,
|
script_type=InputScriptType.SPENDADDRESS,
|
||||||
multisig=None,
|
multisig=None,
|
||||||
@ -206,7 +206,7 @@ class TestOwnershipProof(unittest.TestCase):
|
|||||||
ownership_ids=[ownership_id],
|
ownership_ids=[ownership_id],
|
||||||
script_pubkey=script_pubkey,
|
script_pubkey=script_pubkey,
|
||||||
commitment_data=commitment_data,
|
commitment_data=commitment_data,
|
||||||
)
|
).sign()
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
signature,
|
signature,
|
||||||
unhexlify(
|
unhexlify(
|
||||||
@ -338,7 +338,7 @@ class TestOwnershipProof(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Sign with the first key.
|
# Sign with the first key.
|
||||||
_, signature = ownership.generate_proof(
|
_, signature = ownership.ProofGenerator(
|
||||||
node=keychains[0].derive([84 | HARDENED, 0 | HARDENED, 0 | HARDENED, 1, 0]),
|
node=keychains[0].derive([84 | HARDENED, 0 | HARDENED, 0 | HARDENED, 1, 0]),
|
||||||
script_type=InputScriptType.SPENDWITNESS,
|
script_type=InputScriptType.SPENDWITNESS,
|
||||||
multisig=multisig,
|
multisig=multisig,
|
||||||
@ -347,7 +347,7 @@ class TestOwnershipProof(unittest.TestCase):
|
|||||||
ownership_ids=ownership_ids,
|
ownership_ids=ownership_ids,
|
||||||
script_pubkey=script_pubkey,
|
script_pubkey=script_pubkey,
|
||||||
commitment_data=commitment_data,
|
commitment_data=commitment_data,
|
||||||
)
|
).sign()
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
signature,
|
signature,
|
||||||
unhexlify(
|
unhexlify(
|
||||||
@ -357,7 +357,7 @@ class TestOwnershipProof(unittest.TestCase):
|
|||||||
multisig.signatures[0] = signature
|
multisig.signatures[0] = signature
|
||||||
|
|
||||||
# Sign with the third key.
|
# Sign with the third key.
|
||||||
proof, signature = ownership.generate_proof(
|
proof, signature = ownership.ProofGenerator(
|
||||||
node=keychain.derive([84 | HARDENED, 0 | HARDENED, 0 | HARDENED, 1, 0]),
|
node=keychain.derive([84 | HARDENED, 0 | HARDENED, 0 | HARDENED, 1, 0]),
|
||||||
script_type=InputScriptType.SPENDWITNESS,
|
script_type=InputScriptType.SPENDWITNESS,
|
||||||
multisig=multisig,
|
multisig=multisig,
|
||||||
@ -366,7 +366,7 @@ class TestOwnershipProof(unittest.TestCase):
|
|||||||
ownership_ids=ownership_ids,
|
ownership_ids=ownership_ids,
|
||||||
script_pubkey=script_pubkey,
|
script_pubkey=script_pubkey,
|
||||||
commitment_data=commitment_data,
|
commitment_data=commitment_data,
|
||||||
)
|
).sign()
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
signature,
|
signature,
|
||||||
unhexlify(
|
unhexlify(
|
||||||
@ -429,7 +429,7 @@ class TestOwnershipProof(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Sign with the second key.
|
# Sign with the second key.
|
||||||
_, signature = ownership.generate_proof(
|
_, signature = ownership.ProofGenerator(
|
||||||
node=keychain.derive([49 | HARDENED, 0 | HARDENED, 2 | HARDENED, 0, 1]),
|
node=keychain.derive([49 | HARDENED, 0 | HARDENED, 2 | HARDENED, 0, 1]),
|
||||||
script_type=InputScriptType.SPENDP2SHWITNESS,
|
script_type=InputScriptType.SPENDP2SHWITNESS,
|
||||||
multisig=multisig,
|
multisig=multisig,
|
||||||
@ -438,7 +438,7 @@ class TestOwnershipProof(unittest.TestCase):
|
|||||||
ownership_ids=ownership_ids,
|
ownership_ids=ownership_ids,
|
||||||
script_pubkey=script_pubkey,
|
script_pubkey=script_pubkey,
|
||||||
commitment_data=commitment_data,
|
commitment_data=commitment_data,
|
||||||
)
|
).sign()
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
signature,
|
signature,
|
||||||
unhexlify(
|
unhexlify(
|
||||||
@ -448,7 +448,7 @@ class TestOwnershipProof(unittest.TestCase):
|
|||||||
multisig.signatures[1] = signature
|
multisig.signatures[1] = signature
|
||||||
|
|
||||||
# Sign with the fourth key.
|
# Sign with the fourth key.
|
||||||
proof, signature = ownership.generate_proof(
|
proof, signature = ownership.ProofGenerator(
|
||||||
node=keychain.derive([49 | HARDENED, 0 | HARDENED, 4 | HARDENED, 0, 1]),
|
node=keychain.derive([49 | HARDENED, 0 | HARDENED, 4 | HARDENED, 0, 1]),
|
||||||
script_type=InputScriptType.SPENDP2SHWITNESS,
|
script_type=InputScriptType.SPENDP2SHWITNESS,
|
||||||
multisig=multisig,
|
multisig=multisig,
|
||||||
@ -457,7 +457,7 @@ class TestOwnershipProof(unittest.TestCase):
|
|||||||
ownership_ids=ownership_ids,
|
ownership_ids=ownership_ids,
|
||||||
script_pubkey=script_pubkey,
|
script_pubkey=script_pubkey,
|
||||||
commitment_data=commitment_data,
|
commitment_data=commitment_data,
|
||||||
)
|
).sign()
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
signature,
|
signature,
|
||||||
unhexlify(
|
unhexlify(
|
||||||
@ -467,7 +467,7 @@ class TestOwnershipProof(unittest.TestCase):
|
|||||||
multisig.signatures[3] = signature
|
multisig.signatures[3] = signature
|
||||||
|
|
||||||
# Sign with the fifth key.
|
# Sign with the fifth key.
|
||||||
proof, signature = ownership.generate_proof(
|
proof, signature = ownership.ProofGenerator(
|
||||||
node=keychain.derive([49 | HARDENED, 0 | HARDENED, 5 | HARDENED, 0, 1]),
|
node=keychain.derive([49 | HARDENED, 0 | HARDENED, 5 | HARDENED, 0, 1]),
|
||||||
script_type=InputScriptType.SPENDP2SHWITNESS,
|
script_type=InputScriptType.SPENDP2SHWITNESS,
|
||||||
multisig=multisig,
|
multisig=multisig,
|
||||||
@ -476,7 +476,7 @@ class TestOwnershipProof(unittest.TestCase):
|
|||||||
ownership_ids=ownership_ids,
|
ownership_ids=ownership_ids,
|
||||||
script_pubkey=script_pubkey,
|
script_pubkey=script_pubkey,
|
||||||
commitment_data=commitment_data,
|
commitment_data=commitment_data,
|
||||||
)
|
).sign()
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
signature,
|
signature,
|
||||||
unhexlify(
|
unhexlify(
|
||||||
@ -539,7 +539,7 @@ class TestOwnershipProof(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Sign with the first key.
|
# Sign with the first key.
|
||||||
_, signature = ownership.generate_proof(
|
_, signature = ownership.ProofGenerator(
|
||||||
node=keychain.derive([48 | HARDENED, 0 | HARDENED, 1 | HARDENED, 0, 0]),
|
node=keychain.derive([48 | HARDENED, 0 | HARDENED, 1 | HARDENED, 0, 0]),
|
||||||
script_type=InputScriptType.SPENDMULTISIG,
|
script_type=InputScriptType.SPENDMULTISIG,
|
||||||
multisig=multisig,
|
multisig=multisig,
|
||||||
@ -548,7 +548,7 @@ class TestOwnershipProof(unittest.TestCase):
|
|||||||
ownership_ids=ownership_ids,
|
ownership_ids=ownership_ids,
|
||||||
script_pubkey=script_pubkey,
|
script_pubkey=script_pubkey,
|
||||||
commitment_data=commitment_data,
|
commitment_data=commitment_data,
|
||||||
)
|
).sign()
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
signature,
|
signature,
|
||||||
unhexlify(
|
unhexlify(
|
||||||
@ -558,7 +558,7 @@ class TestOwnershipProof(unittest.TestCase):
|
|||||||
multisig.signatures[0] = signature
|
multisig.signatures[0] = signature
|
||||||
|
|
||||||
# Sign with the third key.
|
# Sign with the third key.
|
||||||
proof, signature = ownership.generate_proof(
|
proof, signature = ownership.ProofGenerator(
|
||||||
node=keychain.derive([48 | HARDENED, 0 | HARDENED, 2 | HARDENED, 0, 0]),
|
node=keychain.derive([48 | HARDENED, 0 | HARDENED, 2 | HARDENED, 0, 0]),
|
||||||
script_type=InputScriptType.SPENDMULTISIG,
|
script_type=InputScriptType.SPENDMULTISIG,
|
||||||
multisig=multisig,
|
multisig=multisig,
|
||||||
@ -567,7 +567,7 @@ class TestOwnershipProof(unittest.TestCase):
|
|||||||
ownership_ids=ownership_ids,
|
ownership_ids=ownership_ids,
|
||||||
script_pubkey=script_pubkey,
|
script_pubkey=script_pubkey,
|
||||||
commitment_data=commitment_data,
|
commitment_data=commitment_data,
|
||||||
)
|
).sign()
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
signature,
|
signature,
|
||||||
unhexlify(
|
unhexlify(
|
||||||
|
Loading…
Reference in New Issue
Block a user