From 9cd600f79ea4f2c1f68f3c40f8841200cf54c1b1 Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Wed, 17 Jun 2020 13:41:38 +0200 Subject: [PATCH] core/bitcoin: Add special confirmation screen for transactions with external inputs. --- core/src/apps/bitcoin/sign_tx/__init__.py | 7 +++++++ core/src/apps/bitcoin/sign_tx/bitcoin.py | 10 +++++++--- core/src/apps/bitcoin/sign_tx/helpers.py | 13 +++++++++++++ core/src/apps/bitcoin/sign_tx/layout.py | 14 ++++++++++++++ 4 files changed, 41 insertions(+), 3 deletions(-) diff --git a/core/src/apps/bitcoin/sign_tx/__init__.py b/core/src/apps/bitcoin/sign_tx/__init__.py index c49d2dd02..e39c349e2 100644 --- a/core/src/apps/bitcoin/sign_tx/__init__.py +++ b/core/src/apps/bitcoin/sign_tx/__init__.py @@ -55,6 +55,13 @@ async def sign_tx( res = await layout.confirm_total(ctx, req.spending, req.fee, req.coin) utils.unimport_end(mods) progress.report_init() + elif isinstance(req, helpers.UiConfirmJointTotal): + mods = utils.unimport_begin() + res = await layout.confirm_joint_total( + ctx, req.spending, req.total, req.coin + ) + utils.unimport_end(mods) + progress.report_init() elif isinstance(req, helpers.UiConfirmFeeOverThreshold): mods = utils.unimport_begin() res = await layout.confirm_feeoverthreshold(ctx, req.fee, req.coin) diff --git a/core/src/apps/bitcoin/sign_tx/bitcoin.py b/core/src/apps/bitcoin/sign_tx/bitcoin.py index e3a86f71b..d7e0de03f 100644 --- a/core/src/apps/bitcoin/sign_tx/bitcoin.py +++ b/core/src/apps/bitcoin/sign_tx/bitcoin.py @@ -148,14 +148,18 @@ class Bitcoin: if fee < 0: self.on_negative_fee() + total = self.total_in - self.change_out + spending = total - self.external_in + # fee > (coin.maxfee per byte * tx size) if fee > (self.coin.maxfee_kb / 1000) * (self.weight.get_total() / 4): await helpers.confirm_feeoverthreshold(fee, self.coin) if self.tx.lock_time > 0: await helpers.confirm_nondefault_locktime(self.tx.lock_time) - await helpers.confirm_total( - self.total_in - self.external_in - self.change_out, fee, self.coin - ) + if not self.external: + await helpers.confirm_total(total, fee, self.coin) + else: + await helpers.confirm_joint_total(spending, total, self.coin) async def step4_verify_external_inputs(self) -> None: # should come out the same as h_external, checked before continuing diff --git a/core/src/apps/bitcoin/sign_tx/helpers.py b/core/src/apps/bitcoin/sign_tx/helpers.py index 6258c133b..d6987d342 100644 --- a/core/src/apps/bitcoin/sign_tx/helpers.py +++ b/core/src/apps/bitcoin/sign_tx/helpers.py @@ -46,6 +46,15 @@ class UiConfirmTotal: __eq__ = utils.obj_eq +class UiConfirmJointTotal: + def __init__(self, spending: int, total: int, coin: CoinInfo): + self.spending = spending + self.total = total + self.coin = coin + + __eq__ = utils.obj_eq + + class UiConfirmFeeOverThreshold: def __init__(self, fee: int, coin: CoinInfo): self.fee = fee @@ -76,6 +85,10 @@ def confirm_total(spending: int, fee: int, coin: CoinInfo) -> Awaitable[Any]: # return (yield UiConfirmTotal(spending, fee, coin)) +def confirm_joint_total(spending: int, total: int, coin: CoinInfo) -> Awaitable[Any]: # type: ignore + return (yield UiConfirmJointTotal(spending, total, coin)) + + def confirm_feeoverthreshold(fee: int, coin: CoinInfo) -> Awaitable[Any]: # type: ignore return (yield UiConfirmFeeOverThreshold(fee, coin)) diff --git a/core/src/apps/bitcoin/sign_tx/layout.py b/core/src/apps/bitcoin/sign_tx/layout.py index fdfd8ea7b..ffb9c1d6f 100644 --- a/core/src/apps/bitcoin/sign_tx/layout.py +++ b/core/src/apps/bitcoin/sign_tx/layout.py @@ -58,6 +58,20 @@ async def confirm_output( await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) +async def confirm_joint_total( + ctx: wire.Context, spending: int, total: int, coin: coininfo.CoinInfo +) -> None: + from trezor.ui.text import Text + from apps.common.confirm import require_hold_to_confirm + + text = Text("Joint transaction", ui.ICON_SEND, ui.GREEN) + text.normal("You are contributing:") + text.bold(format_coin_amount(spending, coin)) + text.normal("to the total amount:") + text.bold(format_coin_amount(total, coin)) + await require_hold_to_confirm(ctx, text, ButtonRequestType.SignTx) + + async def confirm_total( ctx: wire.Context, spending: int, fee: int, coin: coininfo.CoinInfo ) -> None: