You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
trezor-firmware/core/src/apps/bitcoin/get_ownership_proof.py

100 lines
3.5 KiB

from ubinascii import hexlify
from trezor import ui, wire
from trezor.messages.GetOwnershipProof import GetOwnershipProof
from trezor.messages.OwnershipProof import OwnershipProof
from trezor.ui.components.tt.text import Text
from apps.common.confirm import require_confirm
from apps.common.paths import validate_path
from . import addresses, common, scripts
from .keychain import validate_path_against_script_type, with_keychain
from .ownership import generate_proof, get_identifier
if False:
from typing import Optional
from apps.common.coininfo import CoinInfo
from apps.common.keychain import Keychain
from .authorization import CoinJoinAuthorization
# Maximum number of characters per line in monospace font.
_MAX_MONO_LINE = 18
@with_keychain
async def get_ownership_proof(
ctx: wire.Context,
msg: GetOwnershipProof,
keychain: Keychain,
coin: CoinInfo,
authorization: Optional[CoinJoinAuthorization] = None,
) -> OwnershipProof:
if authorization:
if not authorization.check_get_ownership_proof(msg):
raise wire.ProcessError("Unauthorized operation")
else:
await validate_path(
ctx,
keychain,
msg.address_n,
validate_path_against_script_type(coin, msg),
)
if msg.script_type not in common.INTERNAL_INPUT_SCRIPT_TYPES:
raise wire.DataError("Invalid script type")
if msg.script_type in common.SEGWIT_INPUT_SCRIPT_TYPES and not coin.segwit:
raise wire.DataError("Segwit not enabled on this coin")
node = keychain.derive(msg.address_n)
address = addresses.get_address(msg.script_type, coin, node, msg.multisig)
script_pubkey = scripts.output_derive_script(address, coin)
ownership_id = get_identifier(script_pubkey, keychain)
# If the scriptPubKey is multisig, then the caller has to provide
# ownership IDs, otherwise providing an ID is optional.
if msg.multisig:
if ownership_id not in msg.ownership_ids:
raise wire.DataError("Missing ownership identifier")
elif msg.ownership_ids:
if msg.ownership_ids != [ownership_id]:
raise wire.DataError("Invalid ownership identifier")
else:
msg.ownership_ids = [ownership_id]
# In order to set the "user confirmation" bit in the proof, the user must actually confirm.
if msg.user_confirmation and not authorization:
text = Text("Proof of ownership", ui.ICON_CONFIG)
text.normal("Do you want to create a")
if not msg.commitment_data:
text.normal("proof of ownership?")
else:
hex_data = hexlify(msg.commitment_data).decode()
text.normal("proof of ownership for:")
if len(hex_data) > 3 * _MAX_MONO_LINE:
text.mono(hex_data[0:_MAX_MONO_LINE])
text.mono(
hex_data[_MAX_MONO_LINE : 3 * _MAX_MONO_LINE // 2 - 1]
+ "..."
+ hex_data[-3 * _MAX_MONO_LINE // 2 + 2 : -_MAX_MONO_LINE]
)
text.mono(hex_data[-_MAX_MONO_LINE:])
else:
text.mono(hex_data)
await require_confirm(ctx, text)
ownership_proof, signature = generate_proof(
node,
msg.script_type,
msg.multisig,
coin,
msg.user_confirmation,
msg.ownership_ids,
script_pubkey,
msg.commitment_data,
)
return OwnershipProof(ownership_proof=ownership_proof, signature=signature)