mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-17 21:22:10 +00:00
core/tests: Add unit tests for CoinJoinApprover and CoinJoinAuthorization.
This commit is contained in:
parent
cd86f9f477
commit
791a74aeb2
@ -7,6 +7,11 @@ from ubinascii import hexlify, unhexlify # noqa: F401
|
||||
import unittest # noqa: F401
|
||||
|
||||
from trezor import utils # noqa: F401
|
||||
from apps.common import HARDENED
|
||||
|
||||
|
||||
def H_(x: int) -> int:
|
||||
return x | HARDENED
|
||||
|
||||
|
||||
def await_result(task: Awaitable) -> Any:
|
||||
|
146
core/tests/test_apps.bitcoin.approver.py
Normal file
146
core/tests/test_apps.bitcoin.approver.py
Normal file
@ -0,0 +1,146 @@
|
||||
from common import unittest, await_result, H_
|
||||
|
||||
from trezor import wire
|
||||
from trezor.messages.AuthorizeCoinJoin import AuthorizeCoinJoin
|
||||
from trezor.messages.TxInputType import TxInputType
|
||||
from trezor.messages.TxOutputType import TxOutputType
|
||||
from trezor.messages.SignTx import SignTx
|
||||
from trezor.messages import InputScriptType, OutputScriptType
|
||||
|
||||
from apps.common import coins
|
||||
from apps.bitcoin.authorization import CoinJoinAuthorization
|
||||
from apps.bitcoin.sign_tx.approvers import CoinJoinApprover
|
||||
|
||||
|
||||
class TestApprover(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.coin = coins.by_name('Bitcoin')
|
||||
self.fee_per_anonymity_percent = 0.003
|
||||
|
||||
self.msg_auth = AuthorizeCoinJoin(
|
||||
coordinator="www.example.com",
|
||||
max_total_fee=40000,
|
||||
fee_per_anonymity=self.fee_per_anonymity_percent * 10**9,
|
||||
address_n=[H_(84), H_(0), H_(0)],
|
||||
coin_name=self.coin.coin_name,
|
||||
script_type=InputScriptType.SPENDWITNESS,
|
||||
)
|
||||
|
||||
def test_coinjoin_lots_of_inputs(self):
|
||||
denomination = 10000000
|
||||
|
||||
# Other's inputs.
|
||||
inputs = [
|
||||
TxInputType(
|
||||
amount=denomination + 1000000 * (i + 1),
|
||||
script_type=InputScriptType.EXTERNAL,
|
||||
) for i in range(99)
|
||||
]
|
||||
|
||||
# Our input.
|
||||
inputs.insert(
|
||||
30,
|
||||
TxInputType(
|
||||
address_n=[H_(84), H_(0), H_(0), 0, 1],
|
||||
amount=denomination + 1000000,
|
||||
script_type=InputScriptType.SPENDWITNESS,
|
||||
)
|
||||
)
|
||||
|
||||
# Other's CoinJoined outputs.
|
||||
outputs = [
|
||||
TxOutputType(
|
||||
amount=denomination,
|
||||
script_type=OutputScriptType.PAYTOWITNESS,
|
||||
) for i in range(99)
|
||||
]
|
||||
|
||||
# Our CoinJoined output.
|
||||
outputs.insert(
|
||||
40,
|
||||
TxOutputType(
|
||||
address_n=[H_(84), H_(0), H_(0), 0, 2],
|
||||
amount=denomination,
|
||||
script_type=OutputScriptType.PAYTOWITNESS,
|
||||
)
|
||||
)
|
||||
|
||||
coordinator_fee = 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(
|
||||
TxOutputType(
|
||||
amount=1000000 * (i + 1) - fees,
|
||||
script_type=OutputScriptType.PAYTOWITNESS,
|
||||
) for i in range(99)
|
||||
)
|
||||
|
||||
# Our change-output.
|
||||
outputs.append(
|
||||
TxOutputType(
|
||||
address_n=[H_(84), H_(0), H_(0), 1, 1],
|
||||
amount=1000000 - fees,
|
||||
script_type=OutputScriptType.PAYTOWITNESS,
|
||||
)
|
||||
)
|
||||
|
||||
# Coordinator's output.
|
||||
outputs.append(
|
||||
TxOutputType(
|
||||
amount=total_coordinator_fee,
|
||||
script_type=OutputScriptType.PAYTOWITNESS,
|
||||
)
|
||||
)
|
||||
|
||||
authorization = CoinJoinAuthorization(self.msg_auth, None, self.coin)
|
||||
tx = SignTx(outputs_count=len(outputs), inputs_count=len(inputs), coin_name=self.coin.coin_name, lock_time=0)
|
||||
approver = CoinJoinApprover(tx, self.coin, authorization)
|
||||
|
||||
for txi in inputs:
|
||||
if txi.script_type == InputScriptType.EXTERNAL:
|
||||
approver.add_external_input(txi)
|
||||
else:
|
||||
await_result(approver.add_internal_input(txi, txi.amount))
|
||||
|
||||
for txo in outputs:
|
||||
if txo.address_n:
|
||||
approver.add_change_output(txo, script_pubkey=bytes(22))
|
||||
else:
|
||||
await_result(approver.add_external_output(txo, script_pubkey=bytes(22)))
|
||||
|
||||
await_result(approver.approve_tx())
|
||||
|
||||
def test_coinjoin_input_account_depth_mismatch(self):
|
||||
authorization = CoinJoinAuthorization(self.msg_auth, None, self.coin)
|
||||
tx = SignTx(outputs_count=201, inputs_count=100, coin_name=self.coin.coin_name, lock_time=0)
|
||||
approver = CoinJoinApprover(tx, self.coin, authorization)
|
||||
|
||||
txi = TxInputType(
|
||||
address_n=[H_(49), H_(0), H_(0), 0],
|
||||
amount=10000000,
|
||||
script_type=InputScriptType.SPENDWITNESS
|
||||
)
|
||||
|
||||
with self.assertRaises(wire.ProcessError):
|
||||
await_result(approver.add_internal_input(txi, txi.amount))
|
||||
|
||||
def test_coinjoin_input_account_path_mismatch(self):
|
||||
authorization = CoinJoinAuthorization(self.msg_auth, None, self.coin)
|
||||
tx = SignTx(outputs_count=201, inputs_count=100, coin_name=self.coin.coin_name, lock_time=0)
|
||||
approver = CoinJoinApprover(tx, self.coin, authorization)
|
||||
|
||||
txi = TxInputType(
|
||||
address_n=[H_(49), H_(0), H_(0), 0, 2],
|
||||
amount=10000000,
|
||||
script_type=InputScriptType.SPENDWITNESS
|
||||
)
|
||||
|
||||
with self.assertRaises(wire.ProcessError):
|
||||
await_result(approver.add_internal_input(txi, txi.amount))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
111
core/tests/test_apps.bitcoin.authorization.py
Normal file
111
core/tests/test_apps.bitcoin.authorization.py
Normal file
@ -0,0 +1,111 @@
|
||||
from common import unittest, H_
|
||||
|
||||
from trezor.messages.AuthorizeCoinJoin import AuthorizeCoinJoin
|
||||
from trezor.messages.GetOwnershipProof import GetOwnershipProof
|
||||
from trezor.messages.SignTx import SignTx
|
||||
from trezor.messages import InputScriptType
|
||||
|
||||
from apps.common import coins
|
||||
from apps.bitcoin.authorization import CoinJoinAuthorization
|
||||
|
||||
_ROUND_ID_LEN = 32
|
||||
|
||||
|
||||
class TestAuthorization(unittest.TestCase):
|
||||
|
||||
coin = coins.by_name('Bitcoin')
|
||||
|
||||
def setUp(self):
|
||||
self.msg_auth = AuthorizeCoinJoin(
|
||||
coordinator="www.example.com",
|
||||
max_total_fee=40000,
|
||||
fee_per_anonymity=0.003 * 10**9,
|
||||
address_n=[H_(84), H_(0), H_(0)],
|
||||
coin_name=self.coin.coin_name,
|
||||
script_type=InputScriptType.SPENDWITNESS,
|
||||
)
|
||||
|
||||
self.authorization = CoinJoinAuthorization(self.msg_auth, None, self.coin)
|
||||
|
||||
def test_ownership_proof_account_depth_mismatch(self):
|
||||
# Account depth mismatch.
|
||||
msg = GetOwnershipProof(
|
||||
address_n=[H_(84), H_(0), H_(0), 1],
|
||||
coin_name=self.coin.coin_name,
|
||||
script_type=InputScriptType.SPENDWITNESS,
|
||||
user_confirmation=True,
|
||||
commitment_data=b"www.example.com" + int.to_bytes(1, _ROUND_ID_LEN, "big"),
|
||||
)
|
||||
|
||||
self.assertFalse(self.authorization.check_get_ownership_proof(msg))
|
||||
|
||||
def test_ownership_proof_account_path_mismatch(self):
|
||||
# Account path mismatch.
|
||||
msg = GetOwnershipProof(
|
||||
address_n=[H_(49), H_(0), H_(0), 1, 2],
|
||||
coin_name=self.coin.coin_name,
|
||||
script_type=InputScriptType.SPENDWITNESS,
|
||||
user_confirmation=True,
|
||||
commitment_data=b"www.example.com" + int.to_bytes(1, _ROUND_ID_LEN, "big"),
|
||||
)
|
||||
|
||||
self.assertFalse(self.authorization.check_get_ownership_proof(msg))
|
||||
|
||||
def test_ownership_proof_coordinator_mismatch(self):
|
||||
# Coordinator name mismatch.
|
||||
msg = GetOwnershipProof(
|
||||
address_n=[H_(84), H_(0), H_(0), 1, 2],
|
||||
coin_name=self.coin.coin_name,
|
||||
script_type=InputScriptType.SPENDWITNESS,
|
||||
user_confirmation=True,
|
||||
commitment_data=b"www.example.org" + int.to_bytes(1, _ROUND_ID_LEN, "big"),
|
||||
)
|
||||
|
||||
self.assertFalse(self.authorization.check_get_ownership_proof(msg))
|
||||
|
||||
def test_ownership_proof_wrong_round_id(self):
|
||||
# Wrong round ID length.
|
||||
msg = GetOwnershipProof(
|
||||
address_n=[H_(84), H_(0), H_(0), 1, 2],
|
||||
coin_name=self.coin.coin_name,
|
||||
script_type=InputScriptType.SPENDWITNESS,
|
||||
user_confirmation=True,
|
||||
commitment_data=b"www.example.com" + int.to_bytes(1, _ROUND_ID_LEN - 1, "big"),
|
||||
)
|
||||
|
||||
self.assertFalse(self.authorization.check_get_ownership_proof(msg))
|
||||
|
||||
msg = GetOwnershipProof(
|
||||
address_n=[H_(84), H_(0), H_(0), 1, 2],
|
||||
coin_name=self.coin.coin_name,
|
||||
script_type=InputScriptType.SPENDWITNESS,
|
||||
user_confirmation=True,
|
||||
commitment_data=b"www.example.com" + int.to_bytes(1, _ROUND_ID_LEN + 1, "big"),
|
||||
)
|
||||
|
||||
self.assertFalse(self.authorization.check_get_ownership_proof(msg))
|
||||
|
||||
def test_authorize_ownership_proof(self):
|
||||
|
||||
msg = GetOwnershipProof(
|
||||
address_n=[H_(84), H_(0), H_(0), 1, 2],
|
||||
coin_name=self.coin.coin_name,
|
||||
script_type=InputScriptType.SPENDWITNESS,
|
||||
user_confirmation=True,
|
||||
commitment_data=b"www.example.com" + int.to_bytes(1, _ROUND_ID_LEN, "big"),
|
||||
)
|
||||
|
||||
self.assertTrue(self.authorization.check_get_ownership_proof(msg))
|
||||
|
||||
def test_approve_sign_tx(self):
|
||||
|
||||
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))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
Loading…
Reference in New Issue
Block a user