mirror of
https://github.com/aljazceru/python-teos.git
synced 2025-12-17 14:14:22 +01:00
Refactors the tests to match the new class definitions and config formats
This commit is contained in:
@@ -12,7 +12,7 @@ from common.tools import (
|
|||||||
check_locator_format,
|
check_locator_format,
|
||||||
compute_locator,
|
compute_locator,
|
||||||
setup_data_folder,
|
setup_data_folder,
|
||||||
check_conf_fields,
|
create_config_dict,
|
||||||
extend_paths,
|
extend_paths,
|
||||||
setup_logging,
|
setup_logging,
|
||||||
)
|
)
|
||||||
@@ -77,7 +77,7 @@ def test_setup_data_folder():
|
|||||||
|
|
||||||
def test_check_conf_fields():
|
def test_check_conf_fields():
|
||||||
# The test should work with a valid config_fields (obtained from a valid conf.py)
|
# The test should work with a valid config_fields (obtained from a valid conf.py)
|
||||||
assert type(check_conf_fields(conf_fields_copy)) == dict
|
assert type(create_config_dict(conf_fields_copy)) == dict
|
||||||
|
|
||||||
|
|
||||||
def test_bad_check_conf_fields():
|
def test_bad_check_conf_fields():
|
||||||
@@ -88,7 +88,7 @@ def test_bad_check_conf_fields():
|
|||||||
|
|
||||||
# We should get a ValueError here.
|
# We should get a ValueError here.
|
||||||
with pytest.raises(Exception):
|
with pytest.raises(Exception):
|
||||||
check_conf_fields(conf_fields_copy)
|
create_config_dict(conf_fields_copy)
|
||||||
|
|
||||||
|
|
||||||
def test_extend_paths():
|
def test_extend_paths():
|
||||||
|
|||||||
@@ -1,32 +1,40 @@
|
|||||||
import os
|
|
||||||
import pytest
|
import pytest
|
||||||
import random
|
import random
|
||||||
import requests
|
import requests
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from shutil import rmtree
|
from shutil import rmtree
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
from coincurve import PrivateKey
|
from coincurve import PrivateKey
|
||||||
|
|
||||||
from common.blob import Blob
|
|
||||||
from teos.responder import TransactionTracker
|
|
||||||
from teos.tools import bitcoin_cli
|
|
||||||
from teos.db_manager import DBManager
|
|
||||||
from common.appointment import Appointment
|
|
||||||
from common.tools import compute_locator
|
|
||||||
|
|
||||||
from bitcoind_mock.transaction import create_dummy_transaction
|
|
||||||
from bitcoind_mock.bitcoind import BitcoindMock
|
from bitcoind_mock.bitcoind import BitcoindMock
|
||||||
from bitcoind_mock.conf import BTC_RPC_HOST, BTC_RPC_PORT
|
from bitcoind_mock.conf import BTC_RPC_HOST, BTC_RPC_PORT
|
||||||
|
from bitcoind_mock.transaction import create_dummy_transaction
|
||||||
|
|
||||||
|
from teos.carrier import Carrier
|
||||||
|
from teos.tools import bitcoin_cli
|
||||||
|
from teos.db_manager import DBManager
|
||||||
|
from teos import LOG_PREFIX, DEFAULT_CONF
|
||||||
|
from teos.responder import TransactionTracker
|
||||||
|
from teos.block_processor import BlockProcessor
|
||||||
|
|
||||||
from teos import LOG_PREFIX
|
|
||||||
import common.cryptographer
|
import common.cryptographer
|
||||||
|
from common.blob import Blob
|
||||||
from common.logger import Logger
|
from common.logger import Logger
|
||||||
|
from common.tools import compute_locator
|
||||||
|
from common.appointment import Appointment
|
||||||
from common.constants import LOCATOR_LEN_HEX
|
from common.constants import LOCATOR_LEN_HEX
|
||||||
|
from common.config_loader import ConfigLoader
|
||||||
from common.cryptographer import Cryptographer
|
from common.cryptographer import Cryptographer
|
||||||
|
|
||||||
common.cryptographer.logger = Logger(actor="Cryptographer", log_name_prefix=LOG_PREFIX)
|
common.cryptographer.logger = Logger(actor="Cryptographer", log_name_prefix=LOG_PREFIX)
|
||||||
|
|
||||||
|
# Set params to connect to regtest for testing
|
||||||
|
DEFAULT_CONF["BTC_RPC_PORT"]["value"] = 18443
|
||||||
|
DEFAULT_CONF["BTC_NETWORK"]["value"] = "regtest"
|
||||||
|
|
||||||
|
bitcoind_connect_params = {k: v["value"] for k, v in DEFAULT_CONF.items() if k.startswith("BTC")}
|
||||||
|
bitcoind_feed_params = {k: v["value"] for k, v in DEFAULT_CONF.items() if k.startswith("FEED")}
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
def run_bitcoind():
|
def run_bitcoind():
|
||||||
@@ -54,6 +62,16 @@ def db_manager():
|
|||||||
rmtree("test_db")
|
rmtree("test_db")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
def carrier():
|
||||||
|
return Carrier(bitcoind_connect_params)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
def block_processor():
|
||||||
|
return BlockProcessor(bitcoind_connect_params)
|
||||||
|
|
||||||
|
|
||||||
def generate_keypair():
|
def generate_keypair():
|
||||||
sk = PrivateKey()
|
sk = PrivateKey()
|
||||||
pk = sk.public_key
|
pk = sk.public_key
|
||||||
@@ -84,7 +102,7 @@ def fork(block_hash):
|
|||||||
|
|
||||||
def generate_dummy_appointment_data(real_height=True, start_time_offset=5, end_time_offset=30):
|
def generate_dummy_appointment_data(real_height=True, start_time_offset=5, end_time_offset=30):
|
||||||
if real_height:
|
if real_height:
|
||||||
current_height = bitcoin_cli().getblockcount()
|
current_height = bitcoin_cli(bitcoind_connect_params).getblockcount()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
current_height = 10
|
current_height = 10
|
||||||
@@ -151,23 +169,7 @@ def generate_dummy_tracker():
|
|||||||
|
|
||||||
|
|
||||||
def get_config():
|
def get_config():
|
||||||
data_folder = os.path.expanduser("~/.teos")
|
config_loader = ConfigLoader(".", DEFAULT_CONF, {})
|
||||||
config = {
|
config = config_loader.build_config()
|
||||||
"BTC_RPC_USER": "username",
|
|
||||||
"BTC_RPC_PASSWD": "password",
|
|
||||||
"BTC_RPC_HOST": "localhost",
|
|
||||||
"BTC_RPC_PORT": 8332,
|
|
||||||
"BTC_NETWORK": "regtest",
|
|
||||||
"FEED_PROTOCOL": "tcp",
|
|
||||||
"FEED_ADDR": "127.0.0.1",
|
|
||||||
"FEED_PORT": 28332,
|
|
||||||
"DATA_FOLDER": data_folder,
|
|
||||||
"MAX_APPOINTMENTS": 100,
|
|
||||||
"EXPIRY_DELTA": 6,
|
|
||||||
"MIN_TO_SELF_DELAY": 20,
|
|
||||||
"SERVER_LOG_FILE": data_folder + "teos.log",
|
|
||||||
"TEOS_SECRET_KEY": data_folder + "teos_sk.der",
|
|
||||||
"DB_PATH": "appointments",
|
|
||||||
}
|
|
||||||
|
|
||||||
return config
|
return config
|
||||||
|
|||||||
@@ -5,10 +5,11 @@ from time import sleep
|
|||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
from teos.api import API
|
from teos.api import API
|
||||||
from teos.watcher import Watcher
|
|
||||||
from teos.responder import Responder
|
|
||||||
from teos.tools import bitcoin_cli
|
|
||||||
from teos import HOST, PORT
|
from teos import HOST, PORT
|
||||||
|
from teos.watcher import Watcher
|
||||||
|
from teos.tools import bitcoin_cli
|
||||||
|
from teos.inspector import Inspector
|
||||||
|
from teos.responder import Responder
|
||||||
from teos.chain_monitor import ChainMonitor
|
from teos.chain_monitor import ChainMonitor
|
||||||
|
|
||||||
from test.teos.unit.conftest import (
|
from test.teos.unit.conftest import (
|
||||||
@@ -18,8 +19,11 @@ from test.teos.unit.conftest import (
|
|||||||
generate_dummy_appointment_data,
|
generate_dummy_appointment_data,
|
||||||
generate_keypair,
|
generate_keypair,
|
||||||
get_config,
|
get_config,
|
||||||
|
bitcoind_connect_params,
|
||||||
|
bitcoind_feed_params,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
from common.constants import LOCATOR_LEN_BYTES
|
from common.constants import LOCATOR_LEN_BYTES
|
||||||
|
|
||||||
|
|
||||||
@@ -33,15 +37,21 @@ config = get_config()
|
|||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def run_api(db_manager):
|
def run_api(db_manager, carrier, block_processor):
|
||||||
sk, pk = generate_keypair()
|
sk, pk = generate_keypair()
|
||||||
|
|
||||||
watcher = Watcher(db_manager, Responder(db_manager), sk.to_der(), get_config())
|
responder = Responder(db_manager, carrier, block_processor)
|
||||||
chain_monitor = ChainMonitor(watcher.block_queue, watcher.responder.block_queue)
|
watcher = Watcher(
|
||||||
|
db_manager, block_processor, responder, sk.to_der(), config.get("MAX_APPOINTMENTS"), config.get("EXPIRY_DELTA")
|
||||||
|
)
|
||||||
|
|
||||||
|
chain_monitor = ChainMonitor(
|
||||||
|
watcher.block_queue, watcher.responder.block_queue, block_processor, bitcoind_feed_params
|
||||||
|
)
|
||||||
watcher.awake()
|
watcher.awake()
|
||||||
chain_monitor.monitor_chain()
|
chain_monitor.monitor_chain()
|
||||||
|
|
||||||
api_thread = Thread(target=API(watcher, config).start)
|
api_thread = Thread(target=API(Inspector(block_processor, config.get("MIN_TO_SELF_DELAY")), watcher).start)
|
||||||
api_thread.daemon = True
|
api_thread.daemon = True
|
||||||
api_thread.start()
|
api_thread.start()
|
||||||
|
|
||||||
@@ -131,7 +141,7 @@ def test_get_all_appointments_responder():
|
|||||||
locators = [appointment["locator"] for appointment in appointments]
|
locators = [appointment["locator"] for appointment in appointments]
|
||||||
for locator, dispute_tx in locator_dispute_tx_map.items():
|
for locator, dispute_tx in locator_dispute_tx_map.items():
|
||||||
if locator in locators:
|
if locator in locators:
|
||||||
bitcoin_cli().sendrawtransaction(dispute_tx)
|
bitcoin_cli(bitcoind_connect_params).sendrawtransaction(dispute_tx)
|
||||||
|
|
||||||
# Confirm transactions
|
# Confirm transactions
|
||||||
generate_blocks(6)
|
generate_blocks(6)
|
||||||
@@ -173,7 +183,7 @@ def test_request_appointment_watcher(new_appt_data):
|
|||||||
def test_request_appointment_responder(new_appt_data):
|
def test_request_appointment_responder(new_appt_data):
|
||||||
# Let's do something similar to what we did with the watcher but now we'll send the dispute tx to the network
|
# Let's do something similar to what we did with the watcher but now we'll send the dispute tx to the network
|
||||||
dispute_tx = locator_dispute_tx_map[new_appt_data["appointment"]["locator"]]
|
dispute_tx = locator_dispute_tx_map[new_appt_data["appointment"]["locator"]]
|
||||||
bitcoin_cli().sendrawtransaction(dispute_tx)
|
bitcoin_cli(bitcoind_connect_params).sendrawtransaction(dispute_tx)
|
||||||
|
|
||||||
r = add_appointment(new_appt_data)
|
r = add_appointment(new_appt_data)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from teos.block_processor import BlockProcessor
|
from test.teos.unit.conftest import get_random_value_hex, generate_block, generate_blocks, fork, bitcoind_connect_params
|
||||||
from test.teos.unit.conftest import get_random_value_hex, generate_block, generate_blocks, fork
|
|
||||||
|
|
||||||
|
|
||||||
hex_tx = (
|
hex_tx = (
|
||||||
@@ -14,19 +13,16 @@ hex_tx = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
def test_get_best_block_hash(run_bitcoind, block_processor):
|
||||||
def best_block_hash():
|
best_block_hash = block_processor.get_best_block_hash()
|
||||||
return BlockProcessor.get_best_block_hash()
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_best_block_hash(run_bitcoind, best_block_hash):
|
|
||||||
# As long as bitcoind is running (or mocked in this case) we should always a block hash
|
# As long as bitcoind is running (or mocked in this case) we should always a block hash
|
||||||
assert best_block_hash is not None and isinstance(best_block_hash, str)
|
assert best_block_hash is not None and isinstance(best_block_hash, str)
|
||||||
|
|
||||||
|
|
||||||
def test_get_block(best_block_hash):
|
def test_get_block(block_processor):
|
||||||
|
best_block_hash = block_processor.get_best_block_hash()
|
||||||
# Getting a block from a block hash we are aware of should return data
|
# Getting a block from a block hash we are aware of should return data
|
||||||
block = BlockProcessor.get_block(best_block_hash)
|
block = block_processor.get_block(best_block_hash)
|
||||||
|
|
||||||
# Checking that the received block has at least the fields we need
|
# Checking that the received block has at least the fields we need
|
||||||
# FIXME: We could be more strict here, but we'll need to add those restrictions to bitcoind_sim too
|
# FIXME: We could be more strict here, but we'll need to add those restrictions to bitcoind_sim too
|
||||||
@@ -34,75 +30,75 @@ def test_get_block(best_block_hash):
|
|||||||
assert block.get("hash") == best_block_hash and "height" in block and "previousblockhash" in block and "tx" in block
|
assert block.get("hash") == best_block_hash and "height" in block and "previousblockhash" in block and "tx" in block
|
||||||
|
|
||||||
|
|
||||||
def test_get_random_block():
|
def test_get_random_block(block_processor):
|
||||||
block = BlockProcessor.get_block(get_random_value_hex(32))
|
block = block_processor.get_block(get_random_value_hex(32))
|
||||||
|
|
||||||
assert block is None
|
assert block is None
|
||||||
|
|
||||||
|
|
||||||
def test_get_block_count():
|
def test_get_block_count(block_processor):
|
||||||
block_count = BlockProcessor.get_block_count()
|
block_count = block_processor.get_block_count()
|
||||||
assert isinstance(block_count, int) and block_count >= 0
|
assert isinstance(block_count, int) and block_count >= 0
|
||||||
|
|
||||||
|
|
||||||
def test_decode_raw_transaction():
|
def test_decode_raw_transaction(block_processor):
|
||||||
# We cannot exhaustively test this (we rely on bitcoind for this) but we can try to decode a correct transaction
|
# We cannot exhaustively test this (we rely on bitcoind for this) but we can try to decode a correct transaction
|
||||||
assert BlockProcessor.decode_raw_transaction(hex_tx) is not None
|
assert block_processor.decode_raw_transaction(hex_tx) is not None
|
||||||
|
|
||||||
|
|
||||||
def test_decode_raw_transaction_invalid():
|
def test_decode_raw_transaction_invalid(block_processor):
|
||||||
# Same but with an invalid one
|
# Same but with an invalid one
|
||||||
assert BlockProcessor.decode_raw_transaction(hex_tx[::-1]) is None
|
assert block_processor.decode_raw_transaction(hex_tx[::-1]) is None
|
||||||
|
|
||||||
|
|
||||||
def test_get_missed_blocks():
|
def test_get_missed_blocks(block_processor):
|
||||||
target_block = BlockProcessor.get_best_block_hash()
|
target_block = block_processor.get_best_block_hash()
|
||||||
|
|
||||||
# Generate some blocks and store the hash in a list
|
# Generate some blocks and store the hash in a list
|
||||||
missed_blocks = []
|
missed_blocks = []
|
||||||
for _ in range(5):
|
for _ in range(5):
|
||||||
generate_block()
|
generate_block()
|
||||||
missed_blocks.append(BlockProcessor.get_best_block_hash())
|
missed_blocks.append(block_processor.get_best_block_hash())
|
||||||
|
|
||||||
# Check what we've missed
|
# Check what we've missed
|
||||||
assert BlockProcessor.get_missed_blocks(target_block) == missed_blocks
|
assert block_processor.get_missed_blocks(target_block) == missed_blocks
|
||||||
|
|
||||||
# We can see how it does not work if we replace the target by the first element in the list
|
# We can see how it does not work if we replace the target by the first element in the list
|
||||||
block_tip = missed_blocks[0]
|
block_tip = missed_blocks[0]
|
||||||
assert BlockProcessor.get_missed_blocks(block_tip) != missed_blocks
|
assert block_processor.get_missed_blocks(block_tip) != missed_blocks
|
||||||
|
|
||||||
# But it does again if we skip that block
|
# But it does again if we skip that block
|
||||||
assert BlockProcessor.get_missed_blocks(block_tip) == missed_blocks[1:]
|
assert block_processor.get_missed_blocks(block_tip) == missed_blocks[1:]
|
||||||
|
|
||||||
|
|
||||||
def test_get_distance_to_tip():
|
def test_get_distance_to_tip(block_processor):
|
||||||
target_distance = 5
|
target_distance = 5
|
||||||
|
|
||||||
target_block = BlockProcessor.get_best_block_hash()
|
target_block = block_processor.get_best_block_hash()
|
||||||
|
|
||||||
# Mine some blocks up to the target distance
|
# Mine some blocks up to the target distance
|
||||||
generate_blocks(target_distance)
|
generate_blocks(target_distance)
|
||||||
|
|
||||||
# Check if the distance is properly computed
|
# Check if the distance is properly computed
|
||||||
assert BlockProcessor.get_distance_to_tip(target_block) == target_distance
|
assert block_processor.get_distance_to_tip(target_block) == target_distance
|
||||||
|
|
||||||
|
|
||||||
def test_is_block_in_best_chain():
|
def test_is_block_in_best_chain(block_processor):
|
||||||
best_block_hash = BlockProcessor.get_best_block_hash()
|
best_block_hash = block_processor.get_best_block_hash()
|
||||||
best_block = BlockProcessor.get_block(best_block_hash)
|
best_block = block_processor.get_block(best_block_hash)
|
||||||
|
|
||||||
assert BlockProcessor.is_block_in_best_chain(best_block_hash)
|
assert block_processor.is_block_in_best_chain(best_block_hash)
|
||||||
|
|
||||||
fork(best_block.get("previousblockhash"))
|
fork(best_block.get("previousblockhash"))
|
||||||
generate_blocks(2)
|
generate_blocks(2)
|
||||||
|
|
||||||
assert not BlockProcessor.is_block_in_best_chain(best_block_hash)
|
assert not block_processor.is_block_in_best_chain(best_block_hash)
|
||||||
|
|
||||||
|
|
||||||
def test_find_last_common_ancestor():
|
def test_find_last_common_ancestor(block_processor):
|
||||||
ancestor = BlockProcessor.get_best_block_hash()
|
ancestor = block_processor.get_best_block_hash()
|
||||||
generate_blocks(3)
|
generate_blocks(3)
|
||||||
best_block_hash = BlockProcessor.get_best_block_hash()
|
best_block_hash = block_processor.get_best_block_hash()
|
||||||
|
|
||||||
# Create a fork (forking creates a block if the mock is set by events)
|
# Create a fork (forking creates a block if the mock is set by events)
|
||||||
fork(ancestor)
|
fork(ancestor)
|
||||||
@@ -111,6 +107,6 @@ def test_find_last_common_ancestor():
|
|||||||
generate_blocks(5)
|
generate_blocks(5)
|
||||||
|
|
||||||
# The last common ancestor between the old best and the new best should be the "ancestor"
|
# The last common ancestor between the old best and the new best should be the "ancestor"
|
||||||
last_common_ancestor, dropped_txs = BlockProcessor.find_last_common_ancestor(best_block_hash)
|
last_common_ancestor, dropped_txs = block_processor.find_last_common_ancestor(best_block_hash)
|
||||||
assert last_common_ancestor == ancestor
|
assert last_common_ancestor == ancestor
|
||||||
assert len(dropped_txs) == 3
|
assert len(dropped_txs) == 3
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ from queue import Queue
|
|||||||
from teos.builder import Builder
|
from teos.builder import Builder
|
||||||
from teos.watcher import Watcher
|
from teos.watcher import Watcher
|
||||||
from teos.responder import Responder
|
from teos.responder import Responder
|
||||||
|
|
||||||
from test.teos.unit.conftest import (
|
from test.teos.unit.conftest import (
|
||||||
get_random_value_hex,
|
get_random_value_hex,
|
||||||
generate_dummy_appointment,
|
generate_dummy_appointment,
|
||||||
@@ -12,8 +13,11 @@ from test.teos.unit.conftest import (
|
|||||||
generate_block,
|
generate_block,
|
||||||
bitcoin_cli,
|
bitcoin_cli,
|
||||||
get_config,
|
get_config,
|
||||||
|
bitcoind_connect_params,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
config = get_config()
|
||||||
|
|
||||||
|
|
||||||
def test_build_appointments():
|
def test_build_appointments():
|
||||||
appointments_data = {}
|
appointments_data = {}
|
||||||
@@ -89,8 +93,15 @@ def test_populate_block_queue():
|
|||||||
assert len(blocks) == 0
|
assert len(blocks) == 0
|
||||||
|
|
||||||
|
|
||||||
def test_update_states_empty_list(db_manager):
|
def test_update_states_empty_list(db_manager, carrier, block_processor):
|
||||||
w = Watcher(db_manager=db_manager, responder=Responder(db_manager), sk_der=None, config=None)
|
w = Watcher(
|
||||||
|
db_manager=db_manager,
|
||||||
|
block_processor=block_processor,
|
||||||
|
responder=Responder(db_manager, carrier, block_processor),
|
||||||
|
sk_der=None,
|
||||||
|
max_appointments=config.get("MAX_APPOINTMENTS"),
|
||||||
|
expiry_delta=config.get("EXPIRY_DELTA"),
|
||||||
|
)
|
||||||
|
|
||||||
missed_blocks_watcher = []
|
missed_blocks_watcher = []
|
||||||
missed_blocks_responder = [get_random_value_hex(32)]
|
missed_blocks_responder = [get_random_value_hex(32)]
|
||||||
@@ -103,13 +114,20 @@ def test_update_states_empty_list(db_manager):
|
|||||||
Builder.update_states(w, missed_blocks_responder, missed_blocks_watcher)
|
Builder.update_states(w, missed_blocks_responder, missed_blocks_watcher)
|
||||||
|
|
||||||
|
|
||||||
def test_update_states_responder_misses_more(run_bitcoind, db_manager):
|
def test_update_states_responder_misses_more(run_bitcoind, db_manager, carrier, block_processor):
|
||||||
w = Watcher(db_manager=db_manager, responder=Responder(db_manager), sk_der=None, config=get_config())
|
w = Watcher(
|
||||||
|
db_manager=db_manager,
|
||||||
|
block_processor=block_processor,
|
||||||
|
responder=Responder(db_manager, carrier, block_processor),
|
||||||
|
sk_der=None,
|
||||||
|
max_appointments=config.get("MAX_APPOINTMENTS"),
|
||||||
|
expiry_delta=config.get("EXPIRY_DELTA"),
|
||||||
|
)
|
||||||
|
|
||||||
blocks = []
|
blocks = []
|
||||||
for _ in range(5):
|
for _ in range(5):
|
||||||
generate_block()
|
generate_block()
|
||||||
blocks.append(bitcoin_cli().getbestblockhash())
|
blocks.append(bitcoin_cli(bitcoind_connect_params).getbestblockhash())
|
||||||
|
|
||||||
# Updating the states should bring both to the same last known block.
|
# Updating the states should bring both to the same last known block.
|
||||||
w.awake()
|
w.awake()
|
||||||
@@ -120,14 +138,21 @@ def test_update_states_responder_misses_more(run_bitcoind, db_manager):
|
|||||||
assert w.responder.last_known_block == blocks[-1]
|
assert w.responder.last_known_block == blocks[-1]
|
||||||
|
|
||||||
|
|
||||||
def test_update_states_watcher_misses_more(run_bitcoind, db_manager):
|
def test_update_states_watcher_misses_more(db_manager, carrier, block_processor):
|
||||||
# Same as before, but data is now in the Responder
|
# Same as before, but data is now in the Responder
|
||||||
w = Watcher(db_manager=db_manager, responder=Responder(db_manager), sk_der=None, config=get_config())
|
w = Watcher(
|
||||||
|
db_manager=db_manager,
|
||||||
|
block_processor=block_processor,
|
||||||
|
responder=Responder(db_manager, carrier, block_processor),
|
||||||
|
sk_der=None,
|
||||||
|
max_appointments=config.get("MAX_APPOINTMENTS"),
|
||||||
|
expiry_delta=config.get("EXPIRY_DELTA"),
|
||||||
|
)
|
||||||
|
|
||||||
blocks = []
|
blocks = []
|
||||||
for _ in range(5):
|
for _ in range(5):
|
||||||
generate_block()
|
generate_block()
|
||||||
blocks.append(bitcoin_cli().getbestblockhash())
|
blocks.append(bitcoin_cli(bitcoind_connect_params).getbestblockhash())
|
||||||
|
|
||||||
w.awake()
|
w.awake()
|
||||||
w.responder.awake()
|
w.responder.awake()
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
import pytest
|
|
||||||
|
|
||||||
from teos.carrier import Carrier
|
|
||||||
from bitcoind_mock.transaction import create_dummy_transaction
|
from bitcoind_mock.transaction import create_dummy_transaction
|
||||||
from test.teos.unit.conftest import generate_blocks, get_random_value_hex
|
from test.teos.unit.conftest import generate_blocks, get_random_value_hex
|
||||||
from teos.rpc_errors import RPC_VERIFY_ALREADY_IN_CHAIN, RPC_DESERIALIZATION_ERROR
|
from teos.rpc_errors import RPC_VERIFY_ALREADY_IN_CHAIN, RPC_DESERIALIZATION_ERROR
|
||||||
@@ -14,11 +11,6 @@ from teos.rpc_errors import RPC_VERIFY_ALREADY_IN_CHAIN, RPC_DESERIALIZATION_ERR
|
|||||||
sent_txs = []
|
sent_txs = []
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
|
||||||
def carrier():
|
|
||||||
return Carrier()
|
|
||||||
|
|
||||||
|
|
||||||
def test_send_transaction(run_bitcoind, carrier):
|
def test_send_transaction(run_bitcoind, carrier):
|
||||||
tx = create_dummy_transaction()
|
tx = create_dummy_transaction()
|
||||||
|
|
||||||
@@ -56,15 +48,15 @@ def test_send_transaction_invalid_format(carrier):
|
|||||||
assert receipt.delivered is False and receipt.reason == RPC_DESERIALIZATION_ERROR
|
assert receipt.delivered is False and receipt.reason == RPC_DESERIALIZATION_ERROR
|
||||||
|
|
||||||
|
|
||||||
def test_get_transaction():
|
def test_get_transaction(carrier):
|
||||||
# We should be able to get back every transaction we've sent
|
# We should be able to get back every transaction we've sent
|
||||||
for tx in sent_txs:
|
for tx in sent_txs:
|
||||||
tx_info = Carrier.get_transaction(tx)
|
tx_info = carrier.get_transaction(tx)
|
||||||
|
|
||||||
assert tx_info is not None
|
assert tx_info is not None
|
||||||
|
|
||||||
|
|
||||||
def test_get_non_existing_transaction():
|
def test_get_non_existing_transaction(carrier):
|
||||||
tx_info = Carrier.get_transaction(get_random_value_hex(32))
|
tx_info = carrier.get_transaction(get_random_value_hex(32))
|
||||||
|
|
||||||
assert tx_info is None
|
assert tx_info is None
|
||||||
|
|||||||
@@ -3,17 +3,16 @@ import time
|
|||||||
from queue import Queue
|
from queue import Queue
|
||||||
from threading import Thread, Event, Condition
|
from threading import Thread, Event, Condition
|
||||||
|
|
||||||
from teos.block_processor import BlockProcessor
|
|
||||||
from teos.chain_monitor import ChainMonitor
|
from teos.chain_monitor import ChainMonitor
|
||||||
|
|
||||||
from test.teos.unit.conftest import get_random_value_hex, generate_block
|
from test.teos.unit.conftest import get_random_value_hex, generate_block, bitcoind_connect_params, bitcoind_feed_params
|
||||||
|
|
||||||
|
|
||||||
def test_init(run_bitcoind):
|
def test_init(run_bitcoind, block_processor):
|
||||||
# run_bitcoind is started here instead of later on to avoid race conditions while it initializes
|
# run_bitcoind is started here instead of later on to avoid race conditions while it initializes
|
||||||
|
|
||||||
# Not much to test here, just sanity checks to make sure nothing goes south in the future
|
# Not much to test here, just sanity checks to make sure nothing goes south in the future
|
||||||
chain_monitor = ChainMonitor(Queue(), Queue())
|
chain_monitor = ChainMonitor(Queue(), Queue(), block_processor, bitcoind_feed_params)
|
||||||
|
|
||||||
assert chain_monitor.best_tip is None
|
assert chain_monitor.best_tip is None
|
||||||
assert isinstance(chain_monitor.last_tips, list) and len(chain_monitor.last_tips) == 0
|
assert isinstance(chain_monitor.last_tips, list) and len(chain_monitor.last_tips) == 0
|
||||||
@@ -27,8 +26,8 @@ def test_init(run_bitcoind):
|
|||||||
assert isinstance(chain_monitor.responder_queue, Queue)
|
assert isinstance(chain_monitor.responder_queue, Queue)
|
||||||
|
|
||||||
|
|
||||||
def test_notify_subscribers():
|
def test_notify_subscribers(block_processor):
|
||||||
chain_monitor = ChainMonitor(Queue(), Queue())
|
chain_monitor = ChainMonitor(Queue(), Queue(), block_processor, bitcoind_feed_params)
|
||||||
# Subscribers are only notified as long as they are awake
|
# Subscribers are only notified as long as they are awake
|
||||||
new_block = get_random_value_hex(32)
|
new_block = get_random_value_hex(32)
|
||||||
|
|
||||||
@@ -42,11 +41,11 @@ def test_notify_subscribers():
|
|||||||
assert chain_monitor.responder_queue.get() == new_block
|
assert chain_monitor.responder_queue.get() == new_block
|
||||||
|
|
||||||
|
|
||||||
def test_update_state():
|
def test_update_state(block_processor):
|
||||||
# The state is updated after receiving a new block (and only if the block is not already known).
|
# The state is updated after receiving a new block (and only if the block is not already known).
|
||||||
# Let's start by setting a best_tip and a couple of old tips
|
# Let's start by setting a best_tip and a couple of old tips
|
||||||
new_block_hash = get_random_value_hex(32)
|
new_block_hash = get_random_value_hex(32)
|
||||||
chain_monitor = ChainMonitor(Queue(), Queue())
|
chain_monitor = ChainMonitor(Queue(), Queue(), block_processor, bitcoind_feed_params)
|
||||||
chain_monitor.best_tip = new_block_hash
|
chain_monitor.best_tip = new_block_hash
|
||||||
chain_monitor.last_tips = [get_random_value_hex(32) for _ in range(5)]
|
chain_monitor.last_tips = [get_random_value_hex(32) for _ in range(5)]
|
||||||
|
|
||||||
@@ -63,14 +62,15 @@ def test_update_state():
|
|||||||
assert chain_monitor.best_tip == another_block_hash and new_block_hash == chain_monitor.last_tips[-1]
|
assert chain_monitor.best_tip == another_block_hash and new_block_hash == chain_monitor.last_tips[-1]
|
||||||
|
|
||||||
|
|
||||||
def test_monitor_chain_polling(db_manager):
|
def test_monitor_chain_polling(db_manager, block_processor):
|
||||||
# Try polling with the Watcher
|
# Try polling with the Watcher
|
||||||
wq = Queue()
|
wq = Queue()
|
||||||
chain_monitor = ChainMonitor(wq, Queue())
|
chain_monitor = ChainMonitor(Queue(), Queue(), block_processor, bitcoind_feed_params)
|
||||||
chain_monitor.best_tip = BlockProcessor.get_best_block_hash()
|
chain_monitor.best_tip = block_processor.get_best_block_hash()
|
||||||
|
chain_monitor.polling_delta = 0.1
|
||||||
|
|
||||||
# monitor_chain_polling runs until terminate if set
|
# monitor_chain_polling runs until terminate if set
|
||||||
polling_thread = Thread(target=chain_monitor.monitor_chain_polling, kwargs={"polling_delta": 0.1}, daemon=True)
|
polling_thread = Thread(target=chain_monitor.monitor_chain_polling, daemon=True)
|
||||||
polling_thread.start()
|
polling_thread.start()
|
||||||
|
|
||||||
# Check that nothing changes as long as a block is not generated
|
# Check that nothing changes as long as a block is not generated
|
||||||
@@ -88,10 +88,10 @@ def test_monitor_chain_polling(db_manager):
|
|||||||
polling_thread.join()
|
polling_thread.join()
|
||||||
|
|
||||||
|
|
||||||
def test_monitor_chain_zmq(db_manager):
|
def test_monitor_chain_zmq(db_manager, block_processor):
|
||||||
rq = Queue()
|
responder_queue = Queue()
|
||||||
chain_monitor = ChainMonitor(Queue(), rq)
|
chain_monitor = ChainMonitor(Queue(), responder_queue, block_processor, bitcoind_feed_params)
|
||||||
chain_monitor.best_tip = BlockProcessor.get_best_block_hash()
|
chain_monitor.best_tip = block_processor.get_best_block_hash()
|
||||||
|
|
||||||
zmq_thread = Thread(target=chain_monitor.monitor_chain_zmq, daemon=True)
|
zmq_thread = Thread(target=chain_monitor.monitor_chain_zmq, daemon=True)
|
||||||
zmq_thread.start()
|
zmq_thread.start()
|
||||||
@@ -106,9 +106,9 @@ def test_monitor_chain_zmq(db_manager):
|
|||||||
assert chain_monitor.responder_queue.empty()
|
assert chain_monitor.responder_queue.empty()
|
||||||
|
|
||||||
|
|
||||||
def test_monitor_chain(db_manager):
|
def test_monitor_chain(db_manager, block_processor):
|
||||||
# Not much to test here, this should launch two threads (one per monitor approach) and finish on terminate
|
# Not much to test here, this should launch two threads (one per monitor approach) and finish on terminate
|
||||||
chain_monitor = ChainMonitor(Queue(), Queue())
|
chain_monitor = ChainMonitor(Queue(), Queue(), block_processor, bitcoind_feed_params)
|
||||||
|
|
||||||
chain_monitor.best_tip = None
|
chain_monitor.best_tip = None
|
||||||
chain_monitor.monitor_chain()
|
chain_monitor.monitor_chain()
|
||||||
@@ -131,15 +131,16 @@ def test_monitor_chain(db_manager):
|
|||||||
generate_block()
|
generate_block()
|
||||||
|
|
||||||
|
|
||||||
def test_monitor_chain_single_update(db_manager):
|
def test_monitor_chain_single_update(db_manager, block_processor):
|
||||||
# This test tests that if both threads try to add the same block to the queue, only the first one will make it
|
# This test tests that if both threads try to add the same block to the queue, only the first one will make it
|
||||||
chain_monitor = ChainMonitor(Queue(), Queue())
|
chain_monitor = ChainMonitor(Queue(), Queue(), block_processor, bitcoind_feed_params)
|
||||||
|
|
||||||
chain_monitor.best_tip = None
|
chain_monitor.best_tip = None
|
||||||
|
chain_monitor.polling_delta = 2
|
||||||
|
|
||||||
# We will create a block and wait for the polling thread. Then check the queues to see that the block hash has only
|
# We will create a block and wait for the polling thread. Then check the queues to see that the block hash has only
|
||||||
# been added once.
|
# been added once.
|
||||||
chain_monitor.monitor_chain(polling_delta=2)
|
chain_monitor.monitor_chain()
|
||||||
generate_block()
|
generate_block()
|
||||||
|
|
||||||
watcher_block = chain_monitor.watcher_queue.get()
|
watcher_block = chain_monitor.watcher_queue.get()
|
||||||
|
|||||||
@@ -1,26 +1,27 @@
|
|||||||
from binascii import unhexlify
|
from binascii import unhexlify
|
||||||
|
|
||||||
from teos.errors import *
|
from teos.errors import *
|
||||||
from teos.inspector import Inspector
|
|
||||||
from common.appointment import Appointment
|
|
||||||
from teos.block_processor import BlockProcessor
|
|
||||||
from teos.conf import MIN_TO_SELF_DELAY
|
|
||||||
|
|
||||||
from test.teos.unit.conftest import get_random_value_hex, generate_dummy_appointment_data, generate_keypair, get_config
|
|
||||||
|
|
||||||
from common.constants import LOCATOR_LEN_BYTES, LOCATOR_LEN_HEX
|
|
||||||
from common.cryptographer import Cryptographer
|
|
||||||
from common.logger import Logger
|
|
||||||
|
|
||||||
from teos import LOG_PREFIX
|
from teos import LOG_PREFIX
|
||||||
|
from teos.inspector import Inspector
|
||||||
|
from teos.block_processor import BlockProcessor
|
||||||
|
|
||||||
import common.cryptographer
|
import common.cryptographer
|
||||||
|
from common.logger import Logger
|
||||||
|
from common.appointment import Appointment
|
||||||
|
from common.cryptographer import Cryptographer
|
||||||
|
from common.constants import LOCATOR_LEN_BYTES, LOCATOR_LEN_HEX
|
||||||
|
|
||||||
|
from test.teos.unit.conftest import (
|
||||||
|
get_random_value_hex,
|
||||||
|
generate_dummy_appointment_data,
|
||||||
|
generate_keypair,
|
||||||
|
bitcoind_connect_params,
|
||||||
|
get_config,
|
||||||
|
)
|
||||||
|
|
||||||
common.cryptographer.logger = Logger(actor="Cryptographer", log_name_prefix=LOG_PREFIX)
|
common.cryptographer.logger = Logger(actor="Cryptographer", log_name_prefix=LOG_PREFIX)
|
||||||
|
|
||||||
|
|
||||||
inspector = Inspector(get_config())
|
|
||||||
APPOINTMENT_OK = (0, None)
|
APPOINTMENT_OK = (0, None)
|
||||||
|
|
||||||
NO_HEX_STRINGS = [
|
NO_HEX_STRINGS = [
|
||||||
"R" * LOCATOR_LEN_HEX,
|
"R" * LOCATOR_LEN_HEX,
|
||||||
get_random_value_hex(LOCATOR_LEN_BYTES - 1) + "PP",
|
get_random_value_hex(LOCATOR_LEN_BYTES - 1) + "PP",
|
||||||
@@ -41,6 +42,11 @@ WRONG_TYPES = [
|
|||||||
]
|
]
|
||||||
WRONG_TYPES_NO_STR = [[], unhexlify(get_random_value_hex(LOCATOR_LEN_BYTES)), 3.2, 2.0, (), object, {}, object()]
|
WRONG_TYPES_NO_STR = [[], unhexlify(get_random_value_hex(LOCATOR_LEN_BYTES)), 3.2, 2.0, (), object, {}, object()]
|
||||||
|
|
||||||
|
config = get_config()
|
||||||
|
MIN_TO_SELF_DELAY = config.get("MIN_TO_SELF_DELAY")
|
||||||
|
block_processor = BlockProcessor(bitcoind_connect_params)
|
||||||
|
inspector = Inspector(block_processor, MIN_TO_SELF_DELAY)
|
||||||
|
|
||||||
|
|
||||||
def test_check_locator():
|
def test_check_locator():
|
||||||
# Right appointment type, size and format
|
# Right appointment type, size and format
|
||||||
@@ -200,7 +206,7 @@ def test_inspect(run_bitcoind):
|
|||||||
|
|
||||||
# Valid appointment
|
# Valid appointment
|
||||||
locator = get_random_value_hex(LOCATOR_LEN_BYTES)
|
locator = get_random_value_hex(LOCATOR_LEN_BYTES)
|
||||||
start_time = BlockProcessor.get_block_count() + 5
|
start_time = block_processor.get_block_count() + 5
|
||||||
end_time = start_time + 20
|
end_time = start_time + 20
|
||||||
to_self_delay = MIN_TO_SELF_DELAY
|
to_self_delay = MIN_TO_SELF_DELAY
|
||||||
encrypted_blob = get_random_value_hex(64)
|
encrypted_blob = get_random_value_hex(64)
|
||||||
|
|||||||
@@ -1,27 +1,33 @@
|
|||||||
import json
|
import json
|
||||||
import pytest
|
import pytest
|
||||||
import random
|
import random
|
||||||
from queue import Queue
|
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
from queue import Queue
|
||||||
from shutil import rmtree
|
from shutil import rmtree
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
from teos.db_manager import DBManager
|
from teos.carrier import Carrier
|
||||||
from teos.responder import Responder, TransactionTracker
|
|
||||||
from teos.block_processor import BlockProcessor
|
|
||||||
from teos.chain_monitor import ChainMonitor
|
|
||||||
from teos.tools import bitcoin_cli
|
from teos.tools import bitcoin_cli
|
||||||
|
from teos.db_manager import DBManager
|
||||||
|
from teos.chain_monitor import ChainMonitor
|
||||||
|
from teos.responder import Responder, TransactionTracker
|
||||||
|
|
||||||
from common.constants import LOCATOR_LEN_HEX
|
from common.constants import LOCATOR_LEN_HEX
|
||||||
from bitcoind_mock.transaction import create_dummy_transaction, create_tx_from_hex
|
from bitcoind_mock.transaction import create_dummy_transaction, create_tx_from_hex
|
||||||
from test.teos.unit.conftest import generate_block, generate_blocks, get_random_value_hex
|
from test.teos.unit.conftest import (
|
||||||
|
generate_block,
|
||||||
|
generate_blocks,
|
||||||
|
get_random_value_hex,
|
||||||
|
bitcoind_connect_params,
|
||||||
|
bitcoind_feed_params,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def responder(db_manager):
|
def responder(db_manager, carrier, block_processor):
|
||||||
responder = Responder(db_manager)
|
responder = Responder(db_manager, carrier, block_processor)
|
||||||
chain_monitor = ChainMonitor(Queue(), responder.block_queue)
|
chain_monitor = ChainMonitor(Queue(), responder.block_queue, block_processor, bitcoind_feed_params)
|
||||||
chain_monitor.monitor_chain()
|
chain_monitor.monitor_chain()
|
||||||
|
|
||||||
return responder
|
return responder
|
||||||
@@ -61,7 +67,7 @@ def create_dummy_tracker_data(random_txid=False, penalty_rawtx=None):
|
|||||||
if random_txid is True:
|
if random_txid is True:
|
||||||
penalty_txid = get_random_value_hex(32)
|
penalty_txid = get_random_value_hex(32)
|
||||||
|
|
||||||
appointment_end = bitcoin_cli().getblockcount() + 2
|
appointment_end = bitcoin_cli(bitcoind_connect_params).getblockcount() + 2
|
||||||
locator = dispute_txid[:LOCATOR_LEN_HEX]
|
locator = dispute_txid[:LOCATOR_LEN_HEX]
|
||||||
|
|
||||||
return locator, dispute_txid, penalty_txid, penalty_rawtx, appointment_end
|
return locator, dispute_txid, penalty_txid, penalty_rawtx, appointment_end
|
||||||
@@ -86,21 +92,21 @@ def test_tracker_init(run_bitcoind):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_on_sync(run_bitcoind, responder):
|
def test_on_sync(run_bitcoind, responder, block_processor):
|
||||||
# We're on sync if we're 1 or less blocks behind the tip
|
# We're on sync if we're 1 or less blocks behind the tip
|
||||||
chain_tip = BlockProcessor.get_best_block_hash()
|
chain_tip = block_processor.get_best_block_hash()
|
||||||
assert Responder.on_sync(chain_tip) is True
|
assert responder.on_sync(chain_tip) is True
|
||||||
|
|
||||||
generate_block()
|
generate_block()
|
||||||
assert Responder.on_sync(chain_tip) is True
|
assert responder.on_sync(chain_tip) is True
|
||||||
|
|
||||||
|
|
||||||
def test_on_sync_fail(responder):
|
def test_on_sync_fail(responder, block_processor):
|
||||||
# This should fail if we're more than 1 block behind the tip
|
# This should fail if we're more than 1 block behind the tip
|
||||||
chain_tip = BlockProcessor.get_best_block_hash()
|
chain_tip = block_processor.get_best_block_hash()
|
||||||
generate_blocks(2)
|
generate_blocks(2)
|
||||||
|
|
||||||
assert Responder.on_sync(chain_tip) is False
|
assert responder.on_sync(chain_tip) is False
|
||||||
|
|
||||||
|
|
||||||
def test_tracker_to_dict():
|
def test_tracker_to_dict():
|
||||||
@@ -147,8 +153,8 @@ def test_tracker_from_dict_invalid_data():
|
|||||||
assert True
|
assert True
|
||||||
|
|
||||||
|
|
||||||
def test_init_responder(temp_db_manager):
|
def test_init_responder(temp_db_manager, carrier, block_processor):
|
||||||
responder = Responder(temp_db_manager)
|
responder = Responder(temp_db_manager, carrier, block_processor)
|
||||||
assert isinstance(responder.trackers, dict) and len(responder.trackers) == 0
|
assert isinstance(responder.trackers, dict) and len(responder.trackers) == 0
|
||||||
assert isinstance(responder.tx_tracker_map, dict) and len(responder.tx_tracker_map) == 0
|
assert isinstance(responder.tx_tracker_map, dict) and len(responder.tx_tracker_map) == 0
|
||||||
assert isinstance(responder.unconfirmed_txs, list) and len(responder.unconfirmed_txs) == 0
|
assert isinstance(responder.unconfirmed_txs, list) and len(responder.unconfirmed_txs) == 0
|
||||||
@@ -156,8 +162,8 @@ def test_init_responder(temp_db_manager):
|
|||||||
assert responder.block_queue.empty()
|
assert responder.block_queue.empty()
|
||||||
|
|
||||||
|
|
||||||
def test_handle_breach(db_manager):
|
def test_handle_breach(db_manager, carrier, block_processor):
|
||||||
responder = Responder(db_manager)
|
responder = Responder(db_manager, carrier, block_processor)
|
||||||
|
|
||||||
uuid = uuid4().hex
|
uuid = uuid4().hex
|
||||||
tracker = create_dummy_tracker()
|
tracker = create_dummy_tracker()
|
||||||
@@ -176,7 +182,11 @@ def test_handle_breach(db_manager):
|
|||||||
assert receipt.delivered is True
|
assert receipt.delivered is True
|
||||||
|
|
||||||
|
|
||||||
def test_handle_breach_bad_response(responder):
|
def test_handle_breach_bad_response(db_manager, block_processor):
|
||||||
|
# We need a new carrier here, otherwise the transaction will be flagged as previously sent and receipt.delivered
|
||||||
|
# will be True
|
||||||
|
responder = Responder(db_manager, Carrier(bitcoind_connect_params), block_processor)
|
||||||
|
|
||||||
uuid = uuid4().hex
|
uuid = uuid4().hex
|
||||||
tracker = create_dummy_tracker()
|
tracker = create_dummy_tracker()
|
||||||
|
|
||||||
@@ -262,10 +272,10 @@ def test_add_tracker_already_confirmed(responder):
|
|||||||
assert penalty_txid not in responder.unconfirmed_txs
|
assert penalty_txid not in responder.unconfirmed_txs
|
||||||
|
|
||||||
|
|
||||||
def test_do_watch(temp_db_manager):
|
def test_do_watch(temp_db_manager, carrier, block_processor):
|
||||||
# Create a fresh responder to simplify the test
|
# Create a fresh responder to simplify the test
|
||||||
responder = Responder(temp_db_manager)
|
responder = Responder(temp_db_manager, carrier, block_processor)
|
||||||
chain_monitor = ChainMonitor(Queue(), responder.block_queue)
|
chain_monitor = ChainMonitor(Queue(), responder.block_queue, block_processor, bitcoind_feed_params)
|
||||||
chain_monitor.monitor_chain()
|
chain_monitor.monitor_chain()
|
||||||
|
|
||||||
trackers = [create_dummy_tracker(penalty_rawtx=create_dummy_transaction().hex()) for _ in range(20)]
|
trackers = [create_dummy_tracker(penalty_rawtx=create_dummy_transaction().hex()) for _ in range(20)]
|
||||||
@@ -293,7 +303,7 @@ def test_do_watch(temp_db_manager):
|
|||||||
# And broadcast some of the transactions
|
# And broadcast some of the transactions
|
||||||
broadcast_txs = []
|
broadcast_txs = []
|
||||||
for tracker in trackers[:5]:
|
for tracker in trackers[:5]:
|
||||||
bitcoin_cli().sendrawtransaction(tracker.penalty_rawtx)
|
bitcoin_cli(bitcoind_connect_params).sendrawtransaction(tracker.penalty_rawtx)
|
||||||
broadcast_txs.append(tracker.penalty_txid)
|
broadcast_txs.append(tracker.penalty_txid)
|
||||||
|
|
||||||
# Mine a block
|
# Mine a block
|
||||||
@@ -312,7 +322,7 @@ def test_do_watch(temp_db_manager):
|
|||||||
# Do the rest
|
# Do the rest
|
||||||
broadcast_txs = []
|
broadcast_txs = []
|
||||||
for tracker in trackers[5:]:
|
for tracker in trackers[5:]:
|
||||||
bitcoin_cli().sendrawtransaction(tracker.penalty_rawtx)
|
bitcoin_cli(bitcoind_connect_params).sendrawtransaction(tracker.penalty_rawtx)
|
||||||
broadcast_txs.append(tracker.penalty_txid)
|
broadcast_txs.append(tracker.penalty_txid)
|
||||||
|
|
||||||
# Mine a block
|
# Mine a block
|
||||||
@@ -321,9 +331,9 @@ def test_do_watch(temp_db_manager):
|
|||||||
assert len(responder.tx_tracker_map) == 0
|
assert len(responder.tx_tracker_map) == 0
|
||||||
|
|
||||||
|
|
||||||
def test_check_confirmations(db_manager):
|
def test_check_confirmations(db_manager, carrier, block_processor):
|
||||||
responder = Responder(db_manager)
|
responder = Responder(db_manager, carrier, block_processor)
|
||||||
chain_monitor = ChainMonitor(Queue(), responder.block_queue)
|
chain_monitor = ChainMonitor(Queue(), responder.block_queue, block_processor, bitcoind_feed_params)
|
||||||
chain_monitor.monitor_chain()
|
chain_monitor.monitor_chain()
|
||||||
|
|
||||||
# check_confirmations checks, given a list of transaction for a block, what of the known penalty transaction have
|
# check_confirmations checks, given a list of transaction for a block, what of the known penalty transaction have
|
||||||
@@ -378,11 +388,11 @@ def test_get_txs_to_rebroadcast(responder):
|
|||||||
assert txs_to_rebroadcast == list(txs_missing_too_many_conf.keys())
|
assert txs_to_rebroadcast == list(txs_missing_too_many_conf.keys())
|
||||||
|
|
||||||
|
|
||||||
def test_get_completed_trackers(db_manager):
|
def test_get_completed_trackers(db_manager, carrier, block_processor):
|
||||||
initial_height = bitcoin_cli().getblockcount()
|
initial_height = bitcoin_cli(bitcoind_connect_params).getblockcount()
|
||||||
|
|
||||||
responder = Responder(db_manager)
|
responder = Responder(db_manager, carrier, block_processor)
|
||||||
chain_monitor = ChainMonitor(Queue(), responder.block_queue)
|
chain_monitor = ChainMonitor(Queue(), responder.block_queue, block_processor, bitcoind_feed_params)
|
||||||
chain_monitor.monitor_chain()
|
chain_monitor.monitor_chain()
|
||||||
|
|
||||||
# A complete tracker is a tracker that has reached the appointment end with enough confs (> MIN_CONFIRMATIONS)
|
# A complete tracker is a tracker that has reached the appointment end with enough confs (> MIN_CONFIRMATIONS)
|
||||||
@@ -417,7 +427,7 @@ def test_get_completed_trackers(db_manager):
|
|||||||
}
|
}
|
||||||
|
|
||||||
for uuid, tracker in all_trackers.items():
|
for uuid, tracker in all_trackers.items():
|
||||||
bitcoin_cli().sendrawtransaction(tracker.penalty_rawtx)
|
bitcoin_cli(bitcoind_connect_params).sendrawtransaction(tracker.penalty_rawtx)
|
||||||
|
|
||||||
# The dummy appointments have a end_appointment time of current + 2, but trackers need at least 6 confs by default
|
# The dummy appointments have a end_appointment time of current + 2, but trackers need at least 6 confs by default
|
||||||
generate_blocks(6)
|
generate_blocks(6)
|
||||||
@@ -438,9 +448,9 @@ def test_get_completed_trackers(db_manager):
|
|||||||
assert set(completed_trackers_ids) == set(ended_trackers_keys)
|
assert set(completed_trackers_ids) == set(ended_trackers_keys)
|
||||||
|
|
||||||
|
|
||||||
def test_rebroadcast(db_manager):
|
def test_rebroadcast(db_manager, carrier, block_processor):
|
||||||
responder = Responder(db_manager)
|
responder = Responder(db_manager, carrier, block_processor)
|
||||||
chain_monitor = ChainMonitor(Queue(), responder.block_queue)
|
chain_monitor = ChainMonitor(Queue(), responder.block_queue, block_processor, bitcoind_feed_params)
|
||||||
chain_monitor.monitor_chain()
|
chain_monitor.monitor_chain()
|
||||||
|
|
||||||
txs_to_rebroadcast = []
|
txs_to_rebroadcast = []
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
from teos.tools import can_connect_to_bitcoind, in_correct_network, bitcoin_cli
|
from teos.tools import can_connect_to_bitcoind, in_correct_network, bitcoin_cli
|
||||||
|
|
||||||
from common.tools import check_sha256_hex_format
|
from common.tools import check_sha256_hex_format
|
||||||
|
from test.teos.unit.conftest import bitcoind_connect_params
|
||||||
|
|
||||||
|
|
||||||
def test_in_correct_network(run_bitcoind):
|
def test_in_correct_network(run_bitcoind):
|
||||||
# The simulator runs as if it was regtest, so every other network should fail
|
# The simulator runs as if it was regtest, so every other network should fail
|
||||||
assert in_correct_network("mainnet") is False
|
assert in_correct_network(bitcoind_connect_params, "mainnet") is False
|
||||||
assert in_correct_network("testnet") is False
|
assert in_correct_network(bitcoind_connect_params, "testnet") is False
|
||||||
assert in_correct_network("regtest") is True
|
assert in_correct_network(bitcoind_connect_params, "regtest") is True
|
||||||
|
|
||||||
|
|
||||||
def test_can_connect_to_bitcoind():
|
def test_can_connect_to_bitcoind():
|
||||||
assert can_connect_to_bitcoind() is True
|
assert can_connect_to_bitcoind(bitcoind_connect_params) is True
|
||||||
|
|
||||||
|
|
||||||
# def test_can_connect_to_bitcoind_bitcoin_not_running():
|
# def test_can_connect_to_bitcoind_bitcoin_not_running():
|
||||||
@@ -22,7 +22,7 @@ def test_can_connect_to_bitcoind():
|
|||||||
|
|
||||||
def test_bitcoin_cli():
|
def test_bitcoin_cli():
|
||||||
try:
|
try:
|
||||||
bitcoin_cli().help()
|
bitcoin_cli(bitcoind_connect_params).help()
|
||||||
assert True
|
assert True
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|||||||
@@ -4,11 +4,19 @@ from shutil import rmtree
|
|||||||
from threading import Thread
|
from threading import Thread
|
||||||
from coincurve import PrivateKey
|
from coincurve import PrivateKey
|
||||||
|
|
||||||
|
from teos import LOG_PREFIX
|
||||||
|
from teos.carrier import Carrier
|
||||||
from teos.watcher import Watcher
|
from teos.watcher import Watcher
|
||||||
from teos.responder import Responder
|
|
||||||
from teos.tools import bitcoin_cli
|
from teos.tools import bitcoin_cli
|
||||||
from teos.chain_monitor import ChainMonitor
|
from teos.responder import Responder
|
||||||
from teos.db_manager import DBManager
|
from teos.db_manager import DBManager
|
||||||
|
from teos.chain_monitor import ChainMonitor
|
||||||
|
from teos.block_processor import BlockProcessor
|
||||||
|
|
||||||
|
import common.cryptographer
|
||||||
|
from common.logger import Logger
|
||||||
|
from common.tools import compute_locator
|
||||||
|
from common.cryptographer import Cryptographer
|
||||||
|
|
||||||
from test.teos.unit.conftest import (
|
from test.teos.unit.conftest import (
|
||||||
generate_blocks,
|
generate_blocks,
|
||||||
@@ -16,14 +24,9 @@ from test.teos.unit.conftest import (
|
|||||||
get_random_value_hex,
|
get_random_value_hex,
|
||||||
generate_keypair,
|
generate_keypair,
|
||||||
get_config,
|
get_config,
|
||||||
|
bitcoind_feed_params,
|
||||||
|
bitcoind_connect_params,
|
||||||
)
|
)
|
||||||
from teos.conf import EXPIRY_DELTA, MAX_APPOINTMENTS
|
|
||||||
|
|
||||||
import common.cryptographer
|
|
||||||
from teos import LOG_PREFIX
|
|
||||||
from common.logger import Logger
|
|
||||||
from common.tools import compute_locator
|
|
||||||
from common.cryptographer import Cryptographer
|
|
||||||
|
|
||||||
common.cryptographer.logger = Logger(actor="Cryptographer", log_name_prefix=LOG_PREFIX)
|
common.cryptographer.logger = Logger(actor="Cryptographer", log_name_prefix=LOG_PREFIX)
|
||||||
|
|
||||||
@@ -33,6 +36,7 @@ START_TIME_OFFSET = 1
|
|||||||
END_TIME_OFFSET = 1
|
END_TIME_OFFSET = 1
|
||||||
TEST_SET_SIZE = 200
|
TEST_SET_SIZE = 200
|
||||||
|
|
||||||
|
config = get_config()
|
||||||
|
|
||||||
signing_key, public_key = generate_keypair()
|
signing_key, public_key = generate_keypair()
|
||||||
|
|
||||||
@@ -50,8 +54,22 @@ def temp_db_manager():
|
|||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def watcher(db_manager):
|
def watcher(db_manager):
|
||||||
watcher = Watcher(db_manager, Responder(db_manager), signing_key.to_der(), get_config())
|
block_processor = BlockProcessor(bitcoind_connect_params)
|
||||||
chain_monitor = ChainMonitor(watcher.block_queue, watcher.responder.block_queue)
|
carrier = Carrier(bitcoind_connect_params)
|
||||||
|
|
||||||
|
responder = Responder(db_manager, carrier, block_processor)
|
||||||
|
watcher = Watcher(
|
||||||
|
db_manager,
|
||||||
|
block_processor,
|
||||||
|
responder,
|
||||||
|
signing_key.to_der(),
|
||||||
|
config.get("MAX_APPOINTMENTS"),
|
||||||
|
config.get("EXPIRY_DELTA"),
|
||||||
|
)
|
||||||
|
|
||||||
|
chain_monitor = ChainMonitor(
|
||||||
|
watcher.block_queue, watcher.responder.block_queue, block_processor, bitcoind_feed_params
|
||||||
|
)
|
||||||
chain_monitor.monitor_chain()
|
chain_monitor.monitor_chain()
|
||||||
|
|
||||||
return watcher
|
return watcher
|
||||||
@@ -89,9 +107,11 @@ def test_init(run_bitcoind, watcher):
|
|||||||
assert isinstance(watcher.appointments, dict) and len(watcher.appointments) == 0
|
assert isinstance(watcher.appointments, dict) and len(watcher.appointments) == 0
|
||||||
assert isinstance(watcher.locator_uuid_map, dict) and len(watcher.locator_uuid_map) == 0
|
assert isinstance(watcher.locator_uuid_map, dict) and len(watcher.locator_uuid_map) == 0
|
||||||
assert watcher.block_queue.empty()
|
assert watcher.block_queue.empty()
|
||||||
assert isinstance(watcher.config, dict)
|
assert isinstance(watcher.block_processor, BlockProcessor)
|
||||||
assert isinstance(watcher.signing_key, PrivateKey)
|
|
||||||
assert isinstance(watcher.responder, Responder)
|
assert isinstance(watcher.responder, Responder)
|
||||||
|
assert isinstance(watcher.max_appointments, int)
|
||||||
|
assert isinstance(watcher.expiry_delta, int)
|
||||||
|
assert isinstance(watcher.signing_key, PrivateKey)
|
||||||
|
|
||||||
|
|
||||||
def test_add_appointment(watcher):
|
def test_add_appointment(watcher):
|
||||||
@@ -120,7 +140,7 @@ def test_add_too_many_appointments(watcher):
|
|||||||
# Any appointment on top of those should fail
|
# Any appointment on top of those should fail
|
||||||
watcher.appointments = dict()
|
watcher.appointments = dict()
|
||||||
|
|
||||||
for _ in range(MAX_APPOINTMENTS):
|
for _ in range(config.get("MAX_APPOINTMENTS")):
|
||||||
appointment, dispute_tx = generate_dummy_appointment(
|
appointment, dispute_tx = generate_dummy_appointment(
|
||||||
start_time_offset=START_TIME_OFFSET, end_time_offset=END_TIME_OFFSET
|
start_time_offset=START_TIME_OFFSET, end_time_offset=END_TIME_OFFSET
|
||||||
)
|
)
|
||||||
@@ -160,7 +180,7 @@ def test_do_watch(watcher, temp_db_manager):
|
|||||||
|
|
||||||
# Broadcast the first two
|
# Broadcast the first two
|
||||||
for dispute_tx in dispute_txs[:2]:
|
for dispute_tx in dispute_txs[:2]:
|
||||||
bitcoin_cli().sendrawtransaction(dispute_tx)
|
bitcoin_cli(bitcoind_connect_params).sendrawtransaction(dispute_tx)
|
||||||
|
|
||||||
# After generating enough blocks, the number of appointments should have reduced by two
|
# After generating enough blocks, the number of appointments should have reduced by two
|
||||||
generate_blocks(START_TIME_OFFSET + END_TIME_OFFSET)
|
generate_blocks(START_TIME_OFFSET + END_TIME_OFFSET)
|
||||||
@@ -169,7 +189,7 @@ def test_do_watch(watcher, temp_db_manager):
|
|||||||
|
|
||||||
# The rest of appointments will timeout after the end (2) + EXPIRY_DELTA
|
# The rest of appointments will timeout after the end (2) + EXPIRY_DELTA
|
||||||
# Wait for an additional block to be safe
|
# Wait for an additional block to be safe
|
||||||
generate_blocks(EXPIRY_DELTA + START_TIME_OFFSET + END_TIME_OFFSET)
|
generate_blocks(config.get("EXPIRY_DELTA") + START_TIME_OFFSET + END_TIME_OFFSET)
|
||||||
|
|
||||||
assert len(watcher.appointments) == 0
|
assert len(watcher.appointments) == 0
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user