diff --git a/test/unit/conftest.py b/test/unit/conftest.py index a8a764c..2c0bdea 100644 --- a/test/unit/conftest.py +++ b/test/unit/conftest.py @@ -1,14 +1,15 @@ import pytest +import requests from time import sleep from threading import Thread from pisa.api import start_api -from test2.simulator.bitcoind_sim import run_simulator +from test.simulator.bitcoind_sim import run_simulator, HOST, PORT @pytest.fixture(scope='session') def run_bitcoind(): - bitcoind_thread = Thread(target=run_simulator) + bitcoind_thread = Thread(target=run_simulator, kwargs={"mode": "event"}) bitcoind_thread.daemon = True bitcoind_thread.start() @@ -24,3 +25,10 @@ def run_api(): # It takes a little bit of time to start the API (otherwise the requests are sent too early and they fail) sleep(0.1) + + +def generate_block(): + requests.post(url="http://{}:{}/generate".format(HOST, PORT), timeout=5) + sleep(0.5) + + diff --git a/test/unit/test_api.py b/test/unit/test_api.py index fd293de..ba052e5 100644 --- a/test/unit/test_api.py +++ b/test/unit/test_api.py @@ -1,37 +1,42 @@ -import os import json import pytest -import time import requests from hashlib import sha256 from binascii import unhexlify from apps.cli.blob import Blob from pisa import HOST, PORT, logging +from test.simulator.utils import sha256d +from test.simulator.transaction import TX +from test.unit.conftest import generate_block from pisa.utils.auth_proxy import AuthServiceProxy -from test2.simulator.bitcoind_sim import TIME_BETWEEN_BLOCKS, create_dummy_transaction from pisa.conf import BTC_RPC_USER, BTC_RPC_PASSWD, BTC_RPC_HOST, BTC_RPC_PORT, MAX_APPOINTMENTS logging.getLogger().disabled = True + PISA_API = "http://{}:{}".format(HOST, PORT) MULTIPLE_APPOINTMENTS = 10 appointments = [] -locator_dispute_txid_map = {} +locator_dispute_tx_map = {} -def generate_dummy_appointment(dispute_txid): +def generate_dummy_appointment(): r = requests.get(url=PISA_API + '/get_block_count', timeout=5) current_height = r.json().get("block_count") - dummy_appointment_data = {"tx": create_dummy_transaction(), "tx_id": dispute_txid, "start_time": current_height + 5, + dispute_tx = TX.create_dummy_transaction() + dispute_txid = sha256d(dispute_tx) + justice_tx = TX.create_dummy_transaction(dispute_txid) + + dummy_appointment_data = {"tx": justice_tx, "tx_id": dispute_txid, "start_time": current_height + 5, "end_time": current_height + 30, "dispute_delta": 20} cipher = "AES-GCM-128" hash_function = "SHA256" - locator = sha256(unhexlify(dummy_appointment_data.get("tx_id"))).hexdigest() + locator = sha256(unhexlify(dispute_txid)).hexdigest() blob = Blob(dummy_appointment_data.get("tx"), cipher, hash_function) encrypted_blob = blob.encrypt((dummy_appointment_data.get("tx_id"))) @@ -41,22 +46,13 @@ def generate_dummy_appointment(dispute_txid): "dispute_delta": dummy_appointment_data.get("dispute_delta"), "encrypted_blob": encrypted_blob, "cipher": cipher, "hash_function": hash_function} - return appointment + return appointment, dispute_tx @pytest.fixture -def new_appointment(dispute_txid=None): - appointment = create_appointment(dispute_txid) - - return appointment - - -def create_appointment(dispute_txid=None): - if dispute_txid is None: - dispute_txid = os.urandom(32).hex() - - appointment = generate_dummy_appointment(dispute_txid) - locator_dispute_txid_map[appointment["locator"]] = dispute_txid +def new_appointment(): + appointment, dispute_tx = generate_dummy_appointment() + locator_dispute_tx_map[appointment["locator"]] = dispute_tx return appointment @@ -147,12 +143,12 @@ def test_get_all_appointments_responder(): bitcoin_cli = AuthServiceProxy("http://%s:%s@%s:%d" % (BTC_RPC_USER, BTC_RPC_PASSWD, BTC_RPC_HOST, BTC_RPC_PORT)) locators = [appointment["locator"] for appointment in appointments] - for locator, dispute_txid in locator_dispute_txid_map.items(): + for locator, dispute_tx in locator_dispute_tx_map.items(): if locator in locators: - bitcoin_cli.sendrawtransaction(dispute_txid) + bitcoin_cli.sendrawtransaction(dispute_tx) # Wait a bit for them to get confirmed - time.sleep(TIME_BETWEEN_BLOCKS) + generate_block() # Get all appointments r = requests.get(url=PISA_API + "/get_all_appointments") diff --git a/test/unit/test_carrier.py b/test/unit/test_carrier.py index 92db193..d73c749 100644 --- a/test/unit/test_carrier.py +++ b/test/unit/test_carrier.py @@ -1,11 +1,13 @@ import pytest import logging from os import urandom -from time import sleep + from pisa.carrier import Carrier +from test.simulator.utils import sha256d +from test.simulator.transaction import TX +from test.unit.conftest import generate_block from pisa.rpc_errors import RPC_VERIFY_ALREADY_IN_CHAIN, RPC_DESERIALIZATION_ERROR -from test2.simulator.bitcoind_sim import TIME_BETWEEN_BLOCKS logging.getLogger().disabled = True @@ -24,23 +26,28 @@ def carrier(): def test_send_transaction(run_bitcoind, carrier): # We are mocking bitcoind and in our simulator txid == tx - tx = urandom(32).hex() - receipt = carrier.send_transaction(tx, tx) + tx = TX.create_dummy_transaction() + txid = sha256d(tx) + + receipt = carrier.send_transaction(tx, txid) assert(receipt.delivered is True) def test_send_double_spending_transaction(carrier): # We can test what happens if the same transaction is sent twice - tx = urandom(32).hex() - receipt = carrier.send_transaction(tx, tx) - sent_txs.append(tx) + tx = TX.create_dummy_transaction() + txid = sha256d(tx) + + receipt = carrier.send_transaction(tx, txid) + sent_txs.append(txid) # Wait for a block to be mined - sleep(2*TIME_BETWEEN_BLOCKS) + for _ in range(2): + generate_block() # Try to send it again - receipt2 = carrier.send_transaction(tx, tx) + receipt2 = carrier.send_transaction(tx, txid) # The carrier should report delivered True for both, but in the second case the transaction was already delivered # (either by himself or someone else) @@ -51,8 +58,9 @@ def test_send_double_spending_transaction(carrier): def test_send_transaction_invalid_format(carrier): # Test sending a transaction that does not fits the format - tx = urandom(31).hex() - receipt = carrier.send_transaction(tx, tx) + tx = TX.create_dummy_transaction() + txid = sha256d(tx) + receipt = carrier.send_transaction(txid, txid) assert (receipt.delivered is False and receipt.reason == RPC_DESERIALIZATION_ERROR) diff --git a/test/unit/test_encrypted_blob.py b/test/unit/test_encrypted_blob.py index 26e1d9e..25dc78f 100644 --- a/test/unit/test_encrypted_blob.py +++ b/test/unit/test_encrypted_blob.py @@ -1,5 +1,4 @@ from os import urandom -from cryptography.exceptions import InvalidTag from pisa import logging from pisa.encrypted_blob import EncryptedBlob diff --git a/test/unit/test_tools.py b/test/unit/test_tools.py index e3bce92..251663e 100644 --- a/test/unit/test_tools.py +++ b/test/unit/test_tools.py @@ -1,4 +1,4 @@ -from pisa import logging, bitcoin_cli +from pisa import logging from pisa.tools import check_txid_format from pisa.tools import can_connect_to_bitcoind, in_correct_network diff --git a/test/unit/test_watcher.py b/test/unit/test_watcher.py index bc0f5e7..90c2ae7 100644 --- a/test/unit/test_watcher.py +++ b/test/unit/test_watcher.py @@ -1,22 +1,25 @@ import pytest import logging -from os import urandom -from time import sleep from uuid import uuid4 from hashlib import sha256 from threading import Thread +from binascii import unhexlify from queue import Queue, Empty +from apps.cli.blob import Blob from pisa.watcher import Watcher from pisa.responder import Responder from pisa.conf import MAX_APPOINTMENTS from pisa.appointment import Appointment from pisa.tools import check_txid_format +from test.simulator.utils import sha256d +from test.simulator.transaction import TX +from test.unit.conftest import generate_block from pisa.utils.auth_proxy import AuthServiceProxy -from test2.simulator.bitcoind_sim import TIME_BETWEEN_BLOCKS from pisa.conf import EXPIRY_DELTA, BTC_RPC_USER, BTC_RPC_PASSWD, BTC_RPC_HOST, BTC_RPC_PORT logging.getLogger().disabled = True + APPOINTMENTS = 5 START_TIME_OFFSET = 1 END_TIME_OFFSET = 1 @@ -27,37 +30,44 @@ def watcher(): return Watcher() -def create_appointment(locator=None): +def generate_dummy_appointment(): bitcoin_cli = AuthServiceProxy("http://%s:%s@%s:%d" % (BTC_RPC_USER, BTC_RPC_PASSWD, BTC_RPC_HOST, BTC_RPC_PORT)) - if locator is None: - locator = urandom(32).hex() + dispute_tx = TX.create_dummy_transaction() + dispute_txid = sha256d(dispute_tx) + justice_tx = TX.create_dummy_transaction(dispute_txid) start_time = bitcoin_cli.getblockcount() + 1 end_time = start_time + 1 dispute_delta = 20 - encrypted_blob_data = urandom(100).hex() + cipher = "AES-GCM-128" hash_function = "SHA256" - return Appointment(locator, start_time, end_time, dispute_delta, encrypted_blob_data, cipher, hash_function) + locator = sha256(unhexlify(dispute_txid)).hexdigest() + blob = Blob(justice_tx, cipher, hash_function) + + encrypted_blob = blob.encrypt(dispute_txid) + + appointment = Appointment(locator, start_time, end_time, dispute_delta, encrypted_blob, cipher, hash_function) + + return appointment, dispute_tx def create_appointments(n): locator_uuid_map = dict() appointments = dict() - txids = [] + dispute_txs = [] for i in range(n): - txid = urandom(32) + appointment, dispute_tx = generate_dummy_appointment() uuid = uuid4().hex - locator = sha256(txid).hexdigest() - appointments[uuid] = create_appointment(locator) - locator_uuid_map[locator] = [uuid] - txids.append(txid.hex()) + appointments[uuid] = appointment + locator_uuid_map[appointment.locator] = [uuid] + dispute_txs.append(dispute_tx) - return appointments, locator_uuid_map, txids + return appointments, locator_uuid_map, dispute_txs def test_init(watcher): @@ -71,13 +81,14 @@ def test_init(watcher): def test_add_appointment(run_bitcoind, watcher): - # The watcher automatically fire do_watch and do_subscribe on adding an appointment if it is asleep (initial state). + # The watcher automatically fires do_watch and do_subscribe on adding an appointment if it is asleep (initial state) # Avoid this by setting the state to awake. watcher.asleep = False # We should be able to add appointments up to the limit for _ in range(10): - added_appointment = watcher.add_appointment(create_appointment()) + appointment, dispute_tx = generate_dummy_appointment() + added_appointment = watcher.add_appointment(appointment) assert added_appointment is True @@ -87,11 +98,13 @@ def test_add_too_many_appointments(watcher): watcher.appointments = dict() for _ in range(MAX_APPOINTMENTS): - added_appointment = watcher.add_appointment(create_appointment()) + appointment, dispute_tx = generate_dummy_appointment() + added_appointment = watcher.add_appointment(appointment) assert added_appointment is True - added_appointment = watcher.add_appointment(create_appointment()) + appointment, dispute_tx = generate_dummy_appointment() + added_appointment = watcher.add_appointment(appointment) assert added_appointment is False @@ -104,7 +117,8 @@ def test_do_subscribe(watcher): zmq_thread.start() try: - block_hash = watcher.block_queue.get(timeout=MAX_APPOINTMENTS) + generate_block() + block_hash = watcher.block_queue.get() assert check_txid_format(block_hash) except Empty: @@ -115,25 +129,28 @@ def test_do_watch(watcher): bitcoin_cli = AuthServiceProxy("http://%s:%s@%s:%d" % (BTC_RPC_USER, BTC_RPC_PASSWD, BTC_RPC_HOST, BTC_RPC_PORT)) # We will wipe all the previous data and add 5 appointments - watcher.appointments, watcher.locator_uuid_map, txids = create_appointments(APPOINTMENTS) + watcher.appointments, watcher.locator_uuid_map, dispute_txs = create_appointments(APPOINTMENTS) watch_thread = Thread(target=watcher.do_watch) watch_thread.daemon = True watch_thread.start() # Broadcast the first two - for txid in txids[:2]: - bitcoin_cli.sendrawtransaction(txid) + for dispute_tx in dispute_txs[:2]: + r = bitcoin_cli.sendrawtransaction(dispute_tx) # After leaving some time for the block to be mined and processed, the number of appointments should have reduced # by two - sleep(TIME_BETWEEN_BLOCKS*(START_TIME_OFFSET+END_TIME_OFFSET + 1)) + for _ in range(START_TIME_OFFSET + END_TIME_OFFSET): + generate_block() + assert len(watcher.appointments) == APPOINTMENTS - 2 # The rest of appointments will timeout after the end (2) + EXPIRY_DELTA # Wait for an additional block to be safe - sleep((EXPIRY_DELTA + 2 + 1) * TIME_BETWEEN_BLOCKS) + for _ in range(EXPIRY_DELTA + START_TIME_OFFSET + END_TIME_OFFSET): + generate_block() assert len(watcher.appointments) == 0 assert watcher.asleep is True