1
0
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:
Andrew Kozlik 2020-08-03 17:28:20 +02:00 committed by Andrew Kozlik
parent cd86f9f477
commit 791a74aeb2
3 changed files with 262 additions and 0 deletions

View File

@ -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:

View 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()

View 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()