diff --git a/core/src/apps/bitcoin/authorization.py b/core/src/apps/bitcoin/authorization.py index 581319ebf..b1b0fb365 100644 --- a/core/src/apps/bitcoin/authorization.py +++ b/core/src/apps/bitcoin/authorization.py @@ -19,7 +19,7 @@ if TYPE_CHECKING: from apps.common.coininfo import CoinInfo -FEE_PER_ANONYMITY_DECIMALS = const(9) +FEE_RATE_DECIMALS = const(8) class CoinJoinAuthorization: @@ -47,11 +47,11 @@ class CoinJoinAuthorization: and txi.script_type == self.params.script_type ) - def approve_sign_tx(self, msg: SignTx, fee: int) -> bool: - if self.params.max_total_fee < fee or msg.coin_name != self.params.coin_name: + def approve_sign_tx(self, msg: SignTx) -> bool: + if self.params.max_rounds < 1 or msg.coin_name != self.params.coin_name: return False - self.params.max_total_fee -= fee + self.params.max_rounds -= 1 authorization.set(self.params) return True diff --git a/core/src/apps/bitcoin/authorize_coinjoin.py b/core/src/apps/bitcoin/authorize_coinjoin.py index 4289653b8..fb50a07f5 100644 --- a/core/src/apps/bitcoin/authorize_coinjoin.py +++ b/core/src/apps/bitcoin/authorize_coinjoin.py @@ -2,23 +2,25 @@ from micropython import const from typing import TYPE_CHECKING from trezor import ui, wire +from trezor.enums import ButtonRequestType from trezor.messages import AuthorizeCoinJoin, Success from trezor.strings import format_amount -from trezor.ui.layouts import confirm_action, confirm_coinjoin +from trezor.ui.layouts import confirm_action, confirm_coinjoin, confirm_metadata -from apps.common import authorization +from apps.common import authorization, safety_checks from apps.common.paths import validate_path -from .authorization import FEE_PER_ANONYMITY_DECIMALS +from .authorization import FEE_RATE_DECIMALS from .common import BIP32_WALLET_DEPTH from .keychain import validate_path_against_script_type, with_keychain -from .sign_tx.layout import format_coin_amount if TYPE_CHECKING: from apps.common.coininfo import CoinInfo from apps.common.keychain import Keychain _MAX_COORDINATOR_LEN = const(36) +_MAX_ROUNDS = const(500) +_MAX_COORDINATOR_FEE_RATE = 5 * pow(10, FEE_RATE_DECIMALS) # 5 % @with_keychain @@ -30,19 +32,21 @@ async def authorize_coinjoin( ): raise wire.DataError("Invalid coordinator name.") + if msg.max_rounds > _MAX_ROUNDS and safety_checks.is_strict(): + raise wire.DataError("The number of rounds is unexpectedly large.") + + if ( + msg.max_coordinator_fee_rate > _MAX_COORDINATOR_FEE_RATE + and safety_checks.is_strict() + ): + raise wire.DataError("The coordination fee rate is unexpectedly large.") + + if msg.max_fee_per_kvbyte > 10 * coin.maxfee_kb and safety_checks.is_strict(): + raise wire.DataError("The fee per vbyte is unexpectedly large.") + if not msg.address_n: raise wire.DataError("Empty path not allowed.") - validation_path = msg.address_n + [0] * BIP32_WALLET_DEPTH - await validate_path( - ctx, - keychain, - validation_path, - validate_path_against_script_type( - coin, address_n=validation_path, script_type=msg.script_type - ), - ) - await confirm_action( ctx, "coinjoin_coordinator", @@ -53,19 +57,29 @@ async def authorize_coinjoin( icon=ui.ICON_RECOVERY, ) - if msg.fee_per_anonymity: - fee_per_anonymity: str | None = format_amount( - msg.fee_per_anonymity, FEE_PER_ANONYMITY_DECIMALS - ) - else: - fee_per_anonymity = None + max_fee_per_vbyte = format_amount(msg.max_fee_per_kvbyte, 3) + await confirm_coinjoin(ctx, coin.coin_name, msg.max_rounds, max_fee_per_vbyte) - await confirm_coinjoin( + validation_path = msg.address_n + [0] * BIP32_WALLET_DEPTH + await validate_path( ctx, - fee_per_anonymity, - format_coin_amount(msg.max_total_fee, coin, msg.amount_unit), + keychain, + validation_path, + validate_path_against_script_type( + coin, address_n=validation_path, script_type=msg.script_type + ), ) + if msg.max_fee_per_kvbyte > coin.maxfee_kb: + await confirm_metadata( + ctx, + "fee_over_threshold", + "High mining fee", + "The mining fee of\n{} sats/vbyte\nis unexpectedly high.", + max_fee_per_vbyte, + ButtonRequestType.FeeOverThreshold, + ) + authorization.set(msg) return Success(message="CoinJoin authorized") diff --git a/core/src/apps/bitcoin/sign_tx/approvers.py b/core/src/apps/bitcoin/sign_tx/approvers.py index 0882a6e99..bfff96377 100644 --- a/core/src/apps/bitcoin/sign_tx/approvers.py +++ b/core/src/apps/bitcoin/sign_tx/approvers.py @@ -7,7 +7,7 @@ from trezor.ui.components.common.confirm import INFO from apps.common import safety_checks -from ..authorization import FEE_PER_ANONYMITY_DECIMALS +from ..authorization import FEE_RATE_DECIMALS from ..common import input_is_external_unverified from ..keychain import validate_path_against_script_type from . import helpers, tx_weight @@ -335,18 +335,6 @@ class CoinJoinApprover(Approver): # Upper bound on the user's contribution to the weight of the transaction. self.our_weight = tx_weight.TxWeightCalculator() - # base for coordinator fee to be multiplied by fee_per_anonymity - self.coordinator_fee_base = 0 - - # size of the current group of outputs - self.group_size = 0 - - # number of our change outputs in the current group - self.group_our_count = 0 - - # amount of each output in the current group - self.group_amount = 0 - async def add_internal_input(self, txi: TxInput) -> None: self.our_weight.add_input(txi) if not self.authorization.check_sign_tx_input(txi, self.coin): @@ -374,7 +362,6 @@ class CoinJoinApprover(Approver): def add_change_output(self, txo: TxOutput, script_pubkey: bytes) -> None: super().add_change_output(txo, script_pubkey) self.our_weight.add_output(script_pubkey) - self.group_our_count += 1 async def add_payment_request( self, msg: TxAckPaymentRequest, keychain: Keychain @@ -395,11 +382,16 @@ class CoinJoinApprover(Approver): async def approve_tx(self, tx_info: TxInfo, orig_txs: list[OriginalTxInfo]) -> None: await super().approve_tx(tx_info, orig_txs) + max_fee_per_vbyte = self.authorization.params.max_fee_per_kvbyte / 1000 + max_coordinator_fee_rate = ( + self.authorization.params.max_coordinator_fee_rate + / pow(10, FEE_RATE_DECIMALS + 2) + ) + # The mining fee of the transaction as a whole. mining_fee = self.total_in - self.total_out - # mining_fee > (coin.maxfee per byte * tx size) - if mining_fee > (self.coin.maxfee_kb / 1000) * (self.weight.get_total() / 4): + if mining_fee > max_fee_per_vbyte * self.weight.get_total() / 4: raise wire.ProcessError("Mining fee over threshold") # The maximum mining fee that the user should be paying assuming that participants share @@ -410,30 +402,19 @@ class CoinJoinApprover(Approver): / (self.weight.get_total() - self.MAX_OUTPUT_WEIGHT) ) - # The coordinator fee for the user's outputs. - our_coordinator_fee = self._get_coordinator_fee() + # The maximum coordination fee for the user's inputs. + our_max_coordinator_fee = max_coordinator_fee_rate * ( + self.total_in - self.external_in + ) # Total fees that the user is paying. our_fees = self.total_in - self.external_in - self.change_out - if our_fees > our_coordinator_fee + our_max_mining_fee: - raise wire.ProcessError("Total fee over threshold") + if our_fees > our_max_coordinator_fee + our_max_mining_fee: + raise wire.ProcessError("Total fee over threshold.") - if not self.authorization.approve_sign_tx(tx_info.tx, our_fees): - raise wire.ProcessError("Fees exceed authorized limit") - - # Coordinator fee calculation. - - def _get_coordinator_fee(self) -> float: - # Add the coordinator fee for the last group of outputs. - self._new_group(0) - - decimal_divisor: float = pow(10, FEE_PER_ANONYMITY_DECIMALS + 2) - return ( - self.coordinator_fee_base - * self.authorization.params.fee_per_anonymity - / decimal_divisor - ) + if not self.authorization.approve_sign_tx(tx_info.tx): + raise wire.ProcessError("Exceeded number of CoinJoin rounds.") def _add_output(self, txo: TxOutput, script_pubkey: bytes) -> None: super()._add_output(txo, script_pubkey) @@ -441,27 +422,3 @@ class CoinJoinApprover(Approver): # All CoinJoin outputs must be accompanied by a signed payment request. if txo.payment_req_index is None: raise wire.DataError("Missing payment request.") - - # Assumption: CoinJoin outputs are grouped by amount. (If this assumption is - # not satisfied, then we will compute a lower coordinator fee, which may lead - # us to wrongfully decline the transaction.) - if self.group_amount != txo.amount: - self._new_group(txo.amount) - - self.group_size += 1 - - def _new_group(self, amount: int) -> None: - # Add the base coordinator fee for the previous group of outputs. - # Skip groups of size 1, because those must be change-outputs. - if self.group_size > 1: - self.coordinator_fee_base += ( - self.group_our_count * self.group_size * self.group_amount - ) - - # Check whether our outputs gained any anonymity. - if self.group_our_count and self.group_size > self.group_our_count: - self.anonymity = True - - self.group_size = 0 - self.group_our_count = 0 - self.group_amount = amount diff --git a/core/src/trezor/ui/layouts/tt/__init__.py b/core/src/trezor/ui/layouts/tt/__init__.py index 12643939a..29bf3bd1d 100644 --- a/core/src/trezor/ui/layouts/tt/__init__.py +++ b/core/src/trezor/ui/layouts/tt/__init__.py @@ -988,14 +988,17 @@ async def confirm_modify_fee( async def confirm_coinjoin( - ctx: wire.GenericContext, fee_per_anonymity: str | None, total_fee: str + ctx: wire.GenericContext, coin_name: str, max_rounds: int, max_fee_per_vbyte: str ) -> None: text = Text("Authorize CoinJoin", ui.ICON_RECOVERY, new_lines=False) - if fee_per_anonymity is not None: - text.normal("Fee per anonymity set:\n") - text.bold(f"{fee_per_anonymity} %\n") - text.normal("Maximum total fees:\n") - text.bold(total_fee) + text.normal("Coin name: ") + text.bold(f"{coin_name}\n") + text.br_half() + text.normal("Maximum rounds: ") + text.bold(f"{max_rounds}\n") + text.br_half() + text.normal("Maximum mining fee:\n") + text.bold(f"{max_fee_per_vbyte} sats/vbyte") await raise_if_cancelled( interact(ctx, HoldToConfirm(text), "coinjoin_final", ButtonRequestType.Other) ) diff --git a/core/src/trezor/ui/layouts/tt_v2/__init__.py b/core/src/trezor/ui/layouts/tt_v2/__init__.py index db64946c0..63ea8d8c4 100644 --- a/core/src/trezor/ui/layouts/tt_v2/__init__.py +++ b/core/src/trezor/ui/layouts/tt_v2/__init__.py @@ -409,7 +409,7 @@ async def confirm_modify_fee( async def confirm_coinjoin( - ctx: wire.GenericContext, fee_per_anonymity: str | None, total_fee: str + ctx: wire.GenericContext, coin_name: str, max_rounds: int, max_fee_per_vbyte: str ) -> None: raise NotImplementedError diff --git a/core/tests/test_apps.bitcoin.approver.py b/core/tests/test_apps.bitcoin.approver.py index 10e7c7a0f..7a3413353 100644 --- a/core/tests/test_apps.bitcoin.approver.py +++ b/core/tests/test_apps.bitcoin.approver.py @@ -24,13 +24,14 @@ class TestApprover(unittest.TestCase): def setUp(self): self.coin = coins.by_name('Bitcoin') - self.fee_per_anonymity_percent = 0.003 + self.max_fee_rate_percent = 0.3 self.coordinator_name = "www.example.com" self.msg_auth = AuthorizeCoinJoin( coordinator=self.coordinator_name, - max_total_fee=40000, - fee_per_anonymity=int(self.fee_per_anonymity_percent * 10**9), + max_rounds=10, + max_coordinator_fee_rate=int(self.max_fee_rate_percent * 10**8), + max_fee_per_kvbyte=7000, address_n=[H_(84), H_(0), H_(0)], coin_name=self.coin.coin_name, script_type=InputScriptType.SPENDWITNESS, @@ -39,13 +40,15 @@ class TestApprover(unittest.TestCase): def test_coinjoin_lots_of_inputs(self): denomination = 10000000 + coordinator_fee = int(self.max_fee_rate_percent / 100 * denomination) + fees = coordinator_fee + 500 # Other's inputs. inputs = [ TxInput( prev_hash=b"", prev_index=0, - amount=denomination + 1000000 * (i + 1), + amount=denomination, script_pubkey=bytes(22), script_type=InputScriptType.EXTERNAL, sequence=0xffffffff, @@ -54,13 +57,12 @@ class TestApprover(unittest.TestCase): ] # Our input. - inputs.insert( - 30, + inputs.insert(30, TxInput( prev_hash=b"", prev_index=0, address_n=[H_(84), H_(0), H_(0), 0, 1], - amount=denomination + 1000000, + amount=denomination, script_type=InputScriptType.SPENDWITNESS, sequence=0xffffffff, ) @@ -70,7 +72,7 @@ class TestApprover(unittest.TestCase): outputs = [ TxOutput( address="", - amount=denomination, + amount=denomination-fees, script_type=OutputScriptType.PAYTOWITNESS, payment_req_index=0, ) for i in range(99) @@ -82,32 +84,7 @@ class TestApprover(unittest.TestCase): TxOutput( address="", address_n=[H_(84), H_(0), H_(0), 0, 2], - amount=denomination, - script_type=OutputScriptType.PAYTOWITNESS, - payment_req_index=0, - ) - ) - - coordinator_fee = int(self.fee_per_anonymity_percent / 100 * len(outputs) * denomination) - fees = coordinator_fee + 10000 - total_coordinator_fee = coordinator_fee * len(outputs) - - # Other's change-outputs. - outputs.extend( - TxOutput( - address="", - amount=1000000 * (i + 1) - fees, - script_type=OutputScriptType.PAYTOWITNESS, - payment_req_index=0, - ) for i in range(99) - ) - - # Our change-output. - outputs.append( - TxOutput( - address="", - address_n=[H_(84), H_(0), H_(0), 1, 1], - amount=1000000 - fees, + amount=denomination-fees, script_type=OutputScriptType.PAYTOWITNESS, payment_req_index=0, ) @@ -117,7 +94,7 @@ class TestApprover(unittest.TestCase): outputs.append( TxOutput( address="", - amount=total_coordinator_fee, + amount=coordinator_fee * len(outputs), script_type=OutputScriptType.PAYTOWITNESS, payment_req_index=0, ) diff --git a/core/tests/test_apps.bitcoin.authorization.py b/core/tests/test_apps.bitcoin.authorization.py index ab55ee1e9..367882142 100644 --- a/core/tests/test_apps.bitcoin.authorization.py +++ b/core/tests/test_apps.bitcoin.authorization.py @@ -19,8 +19,9 @@ class TestAuthorization(unittest.TestCase): def setUp(self): self.msg_auth = AuthorizeCoinJoin( coordinator="www.example.com", - max_total_fee=40000, - fee_per_anonymity=int(0.003 * 10**9), + max_rounds=3, + max_coordinator_fee_rate=int(0.3 * 10**8), + max_fee_per_kvbyte=7000, address_n=[H_(84), H_(0), H_(0)], coin_name=self.coin.coin_name, script_type=InputScriptType.SPENDWITNESS, @@ -102,10 +103,10 @@ class TestAuthorization(unittest.TestCase): msg = SignTx(outputs_count=10, inputs_count=21, coin_name=self.coin.coin_name, lock_time=0) - self.assertTrue(self.authorization.approve_sign_tx(msg, 10000)) - self.assertTrue(self.authorization.approve_sign_tx(msg, 20000)) - self.assertFalse(self.authorization.approve_sign_tx(msg, 10001)) - self.assertTrue(self.authorization.approve_sign_tx(msg, 10000)) + self.assertTrue(self.authorization.approve_sign_tx(msg)) + self.assertTrue(self.authorization.approve_sign_tx(msg)) + self.assertTrue(self.authorization.approve_sign_tx(msg)) + self.assertFalse(self.authorization.approve_sign_tx(msg)) if __name__ == '__main__': diff --git a/tests/device_tests/bitcoin/test_authorize_coinjoin.py b/tests/device_tests/bitcoin/test_authorize_coinjoin.py index b730d1496..b1f804bbe 100644 --- a/tests/device_tests/bitcoin/test_authorize_coinjoin.py +++ b/tests/device_tests/bitcoin/test_authorize_coinjoin.py @@ -60,8 +60,9 @@ def test_sign_tx(client: Client): btc.authorize_coinjoin( client, coordinator="www.example.com", - max_total_fee=10_010, - fee_per_anonymity=5_000_000, # 0.005 % + max_rounds=2, + max_coordinator_fee_rate=50_000_000, # 0.5 % + max_fee_per_kvbyte=3500, n=parse_path("m/84h/1h/0h"), coin_name="Testnet", script_type=messages.InputScriptType.SPENDWITNESS, @@ -141,21 +142,21 @@ def test_sign_tx(client: Client): messages.TxOutputType( # tb1qr5p6f5sk09sms57ket074vywfymuthlgud7xyx address_n=parse_path("m/84h/1h/0h/1/2"), - amount=7_289_000 - 50_000 - 5 - 5_000, + amount=7_289_000 - 50_000 - 36_445 - 490, script_type=messages.OutputScriptType.PAYTOWITNESS, payment_req_index=0, ), # Other's change output. messages.TxOutputType( address="tb1q9cqhdr9ydetjzrct6tyeuccws9505hl96azwxk", - amount=100_000 - 50_000 - 5 - 5_000, + amount=100_000 - 50_000 - 500 - 490, script_type=messages.OutputScriptType.PAYTOWITNESS, payment_req_index=0, ), # Coordinator's output. messages.TxOutputType( address="mvbu1Gdy8SUjTenqerxUaZyYjmveZvt33q", - amount=10, + amount=36_945, script_type=messages.OutputScriptType.PAYTOWITNESS, payment_req_index=0, ), @@ -217,7 +218,7 @@ def test_sign_tx(client: Client): assert ( serialized_tx.hex() - == "010000000001028abbd1cf69e00fbf60fa3ba475dccdbdba4a859ffa6bfd1ee820a75b1be2b7e50000000000ffffffff0ab6ad3ba09261cfb4fa1d3680cb19332a8fe4d9de9ea89aa565bd83a2c082f90100000000ffffffff0550c3000000000000160014b7a51ede0a66ae36558a3ab097ad86bbd800786150c3000000000000160014167dae080bca35c9ea49c0c8335dcc4b252a1d70cb616e00000000001600141d03a4d2167961b853d6cadfeab08e4937c5dfe8c3af0000000000001600142e01768ca46e57210f0bd2c99e630e8168fa5fe50a000000000000001976a914a579388225827d9f2fe9014add644487808c695d88ac0002473044022010bcbb2ae63db4bfdfdce298bcf3e302e2b1923d02ff57a2155eaae65fdb2949022026289b6d04d7615bf53b7aa0030b25619c465d639b233297b10d0da9ce1a6ca4012103505647c017ff2156eb6da20fae72173d3b681a1d0a629f95f49e884db300689f00000000" + == "010000000001028abbd1cf69e00fbf60fa3ba475dccdbdba4a859ffa6bfd1ee820a75b1be2b7e50000000000ffffffff0ab6ad3ba09261cfb4fa1d3680cb19332a8fe4d9de9ea89aa565bd83a2c082f90100000000ffffffff0550c3000000000000160014b7a51ede0a66ae36558a3ab097ad86bbd800786150c3000000000000160014167dae080bca35c9ea49c0c8335dcc4b252a1d7011e56d00000000001600141d03a4d2167961b853d6cadfeab08e4937c5dfe872bf0000000000001600142e01768ca46e57210f0bd2c99e630e8168fa5fe551900000000000001976a914a579388225827d9f2fe9014add644487808c695d88ac000247304402204df07c5baacca264696cc4270665cb759be05387dead8942bd41f20309ceb29002203e685b8e9483435d9b70006bb424b5fef7249415a0f212abdf202b5d62859698012103505647c017ff2156eb6da20fae72173d3b681a1d0a629f95f49e884db300689f00000000" ) # Test for a second time. @@ -231,8 +232,8 @@ def test_sign_tx(client: Client): preauthorized=True, ) - # Test for a third time, fees should exceed max_total_fee. - with pytest.raises(TrezorFailure, match="Fees exceed authorized limit"): + # Test for a third time, number of rounds should be exceeded. + with pytest.raises(TrezorFailure, match="Exceeded number of CoinJoin rounds"): btc.sign_tx( client, "Testnet", @@ -251,8 +252,9 @@ def test_unfair_fee(client: Client): btc.authorize_coinjoin( client, coordinator="www.example.com", - max_total_fee=10_000, - fee_per_anonymity=5_000_000, # 0.005 % + max_rounds=1, + max_fee_rate=50_000_000, # 0.5 % + max_fee_per_kvbyte=3500, n=parse_path("m/84h/1h/0h"), coin_name="Testnet", script_type=messages.InputScriptType.SPENDWITNESS, @@ -302,21 +304,21 @@ def test_unfair_fee(client: Client): messages.TxOutputType( # tb1qr5p6f5sk09sms57ket074vywfymuthlgud7xyx address_n=parse_path("m/84h/1h/0h/1/2"), - amount=7_289_000 - 50_000 - 5 - 6_000, # unfair mining fee + amount=7_289_000 - 50_000 - 36_445 - 600, # unfair mining fee script_type=messages.OutputScriptType.PAYTOWITNESS, payment_req_index=0, ), # Other's change output. messages.TxOutputType( address="tb1q9cqhdr9ydetjzrct6tyeuccws9505hl96azwxk", - amount=100_000 - 50_000 - 5 - 4_000, + amount=100_000 - 50_000 - 500 - 400, script_type=messages.OutputScriptType.PAYTOWITNESS, payment_req_index=0, ), # Coordinator's output. messages.TxOutputType( address="mvbu1Gdy8SUjTenqerxUaZyYjmveZvt33q", - amount=10, + amount=36_945, script_type=messages.OutputScriptType.PAYTOWITNESS, payment_req_index=0, ), @@ -350,8 +352,10 @@ def test_wrong_coordinator(client: Client): btc.authorize_coinjoin( client, - max_total_fee=50_000, coordinator="www.example.com", + max_rounds=10, + max_coordinator_fee_rate=50_000_000, # 0.5 % + max_fee_per_kvbyte=3500, n=parse_path("m/84h/1h/0h"), coin_name="Testnet", script_type=messages.InputScriptType.SPENDWITNESS, @@ -374,8 +378,10 @@ def test_cancel_authorization(client: Client): btc.authorize_coinjoin( client, - max_total_fee=50_000, coordinator="www.example.com", + max_rounds=10, + max_coordinator_fee_rate=50_000_000, # 0.5 % + max_fee_per_kvbyte=3500, n=parse_path("m/84h/1h/0h"), coin_name="Testnet", script_type=messages.InputScriptType.SPENDWITNESS, @@ -399,8 +405,10 @@ def test_multisession_authorization(client: Client): # Authorize CoinJoin with www.example1.com in session 1. btc.authorize_coinjoin( client, - max_total_fee=50_000, coordinator="www.example1.com", + max_rounds=10, + max_coordinator_fee_rate=50_000_000, # 0.5 % + max_fee_per_kvbyte=3500, n=parse_path("m/84h/1h/0h"), coin_name="Testnet", script_type=messages.InputScriptType.SPENDWITNESS, @@ -413,8 +421,10 @@ def test_multisession_authorization(client: Client): # Authorize CoinJoin with www.example2.com in session 2. btc.authorize_coinjoin( client, - max_total_fee=50_000, coordinator="www.example2.com", + max_rounds=10, + max_coordinator_fee_rate=50_000_000, # 0.5 % + max_fee_per_kvbyte=3500, n=parse_path("m/84h/1h/0h"), coin_name="Testnet", script_type=messages.InputScriptType.SPENDWITNESS, diff --git a/tests/device_tests/test_msg_applysettings.py b/tests/device_tests/test_msg_applysettings.py index 984690868..4769f112c 100644 --- a/tests/device_tests/test_msg_applysettings.py +++ b/tests/device_tests/test_msg_applysettings.py @@ -229,8 +229,9 @@ def test_experimental_features(client: Client): btc.authorize_coinjoin( client, coordinator="www.example.com", - max_total_fee=10_010, - fee_per_anonymity=5_000_000, # 0.005 % + max_rounds=10, + max_coordinator_fee_rate=50_000_000, # 0.5 % + max_fee_per_kvbyte=3500, n=parse_path("m/84h/1h/0h"), coin_name="Testnet", script_type=messages.InputScriptType.SPENDWITNESS, diff --git a/tests/ui_tests/fixtures.json b/tests/ui_tests/fixtures.json index e5c885452..1b99d31d2 100644 --- a/tests/ui_tests/fixtures.json +++ b/tests/ui_tests/fixtures.json @@ -600,11 +600,11 @@ "TT_binance-test_sign_tx.py::test_binance_sign_message[message0-expected_response0]": "fab7b62cab76ae2e4370d9ce113569b3aa2d089a5dbc365c8920731f756a4f37", "TT_binance-test_sign_tx.py::test_binance_sign_message[message1-expected_response1]": "805fc5ef8074c3f5cfee5f7128c2cd068fef42f4f01f9450578f50e791ff811f", "TT_binance-test_sign_tx.py::test_binance_sign_message[message2-expected_response2]": "323e0a474e71ede187ee1332e42952aeca501b42da95f88b2bad5445a3db858c", -"TT_bitcoin-test_authorize_coinjoin.py::test_cancel_authorization": "9887e0f4da5c7800f832396e50391beb03229c8edcb5b0e078433703cac6e0d3", -"TT_bitcoin-test_authorize_coinjoin.py::test_multisession_authorization": "fd412d086cf4ff677f6ae266e88de725549505d9a2abc1c2ba36f8f854461694", -"TT_bitcoin-test_authorize_coinjoin.py::test_sign_tx": "c48bbbaf032eacb42567e49f5b4b82ed51fe97bb613e165dca2c51207199f236", +"TT_bitcoin-test_authorize_coinjoin.py::test_cancel_authorization": "2e5cffe7bd0dc6034852d21612fba8cf1ee3c45a14e76140a4c2786f360f54f0", +"TT_bitcoin-test_authorize_coinjoin.py::test_multisession_authorization": "65c9435e10e3dede19169a9b02d373bd5acb22eba0ba3b31324271025d65d5a7", +"TT_bitcoin-test_authorize_coinjoin.py::test_sign_tx": "87b81a29fe6e27fdfedfdbb1953b3d0178786749eadbb0fe01509c1af8075de5", "TT_bitcoin-test_authorize_coinjoin.py::test_unfair_fee": "ab1aa516510b627b8ffc65391c1c113922ab08f48baf295861a9b597f27f8ea1", -"TT_bitcoin-test_authorize_coinjoin.py::test_wrong_coordinator": "9887e0f4da5c7800f832396e50391beb03229c8edcb5b0e078433703cac6e0d3", +"TT_bitcoin-test_authorize_coinjoin.py::test_wrong_coordinator": "2e5cffe7bd0dc6034852d21612fba8cf1ee3c45a14e76140a4c2786f360f54f0", "TT_bitcoin-test_bcash.py::test_attack_change_input": "b824d3eb233f6ba2567dd052fa4b52e9a1f170fe4a39af55c1cc262683f188b9", "TT_bitcoin-test_bcash.py::test_send_bch_change": "b824d3eb233f6ba2567dd052fa4b52e9a1f170fe4a39af55c1cc262683f188b9", "TT_bitcoin-test_bcash.py::test_send_bch_external_presigned": "4ea82258a094d49829ab7240465de9cb06198d7b0bb1a56b66bfbda5ccc676c1", @@ -1452,7 +1452,7 @@ "TT_test_msg_applysettings.py::test_apply_settings_passphrase": "b7af5acc4678edc97c6cab669554b20ec63560d8bd36c40f9c292b40992b590c", "TT_test_msg_applysettings.py::test_apply_settings_passphrase_on_device": "ec6ae42f5d061e40d6c4512a743bc2ac1564455a50a838b6f42fd4c7225d8079", "TT_test_msg_applysettings.py::test_apply_settings_rotation": "1f6da326281b5e4ddff444f96403683badae200f1d4b5cc6b044aeab99141d16", -"TT_test_msg_applysettings.py::test_experimental_features": "d06a7f434a7a76a996ef0a9b1c2dc44b508bb9c361551f65f171fd762c0f4d77", +"TT_test_msg_applysettings.py::test_experimental_features": "0908b33f42fc4a3405dcfa919e2e00171999a589897d2eac04a720227a7a4bb5", "TT_test_msg_applysettings.py::test_label_too_long": "c09de07fbbf1e047442180e2facb5482d06a1a428891b875b7dd93c9e4704ae1", "TT_test_msg_applysettings.py::test_safety_checks": "71ac970ca0d87f1ef70a8605dcc4db478a9190333307ff37ee90dd3d3e97e0fa", "TT_test_msg_backup_device.py::test_backup_bip39": "9b572b12da20b516222ecb0a76fba6d6de5193647405b67625140ed3ed45049c",