from micropython import const from trezor import ui from trezor.messages.AuthorizeCoinJoin import AuthorizeCoinJoin from trezor.messages.Success import Success from trezor.strings import format_amount from trezor.ui.text import Text from apps.base import set_authorization from apps.common.confirm import require_confirm, require_hold_to_confirm from apps.common.paths import validate_path from . import addresses from .authorization import FEE_PER_ANONYMITY_DECIMALS, CoinJoinAuthorization from .common import BIP32_WALLET_DEPTH from .keychain import get_keychain_for_coin if False: from trezor import wire _MAX_COORDINATOR_LEN = const(18) async def authorize_coinjoin(ctx: wire.Context, msg: AuthorizeCoinJoin) -> Success: # We cannot use the @with_keychain decorator here, because we need the keychain # to survive the function exit. The ownership of the keychain is transferred to # the CoinJoinAuthorization object, which takes care of its destruction. keychain, coin = await get_keychain_for_coin(ctx, msg.coin_name) try: if len(msg.coordinator) > _MAX_COORDINATOR_LEN or not all( 32 <= ord(x) <= 126 for x in msg.coordinator ): raise wire.DataError("Invalid coordinator name.") if not msg.address_n: raise wire.DataError("Empty path not allowed.") await validate_path( ctx, addresses.validate_full_path, keychain, msg.address_n + [0] * BIP32_WALLET_DEPTH, coin.curve_name, coin=coin, script_type=msg.script_type, ) text = Text("Authorize CoinJoin", ui.ICON_RECOVERY) text.normal("Do you really want to") text.normal("take part in a CoinJoin") text.normal("transaction at:") text.mono(msg.coordinator) await require_confirm(ctx, text) text = Text("Authorize CoinJoin", ui.ICON_RECOVERY) if msg.fee_per_anonymity is not None: text.normal("Fee per anonymity set:") text.bold( "{} %".format( format_amount(msg.fee_per_anonymity, FEE_PER_ANONYMITY_DECIMALS) ) ) text.normal("Maximum total fees:") text.bold( "{} {}".format( format_amount(msg.max_total_fee, coin.decimals), coin.coin_shortcut ) ) await require_hold_to_confirm(ctx, text) set_authorization(CoinJoinAuthorization(msg, keychain, coin)) except BaseException: keychain.__del__() raise return Success(message="CoinJoin authorized")