core/tests: Add unit tests for CoinJoinApprover and CoinJoinAuthorization.

pull/1168/head
Andrew Kozlik 4 years ago committed by Andrew Kozlik
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:

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

@ -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…
Cancel
Save