def test_work_local_single(local_work_plugin_factory, work_unit_factory): # Enqueue an easy PoW and make sure it is completed work_plugin = local_work_plugin_factory() work_plugin.add_work_units_to_solve( [work_unit_factory(account_id=ACCOUNT_ID)], network_difficulty=to_hex(10000, 16)) work_units = work_plugin.work_units wait_for(lambda: count_solved_units(work_units) == 1, timeout=1) assert count_pending_units(work_units) == 0 # Worker thread should stop soon after the work is finished wait_for(lambda: len([ thread.name for thread in threading.enumerate() if thread.name.startswith("work_local_worker") ]) == 0, timeout=1) # Get the completed work completed_work_unit = next(work_unit for work_unit in work_units.values() if work_unit.solved) assert completed_work_unit.account_id == ACCOUNT_ID assert completed_work_unit.difficulty == to_hex(10000, 16) assert get_work_value(block_hash=completed_work_unit.work_block_hash, work=completed_work_unit.work) > 10000
def test_wallet_update_solved_blocks_precomputed_work( self, wallet, pocketable_block_factory): # Empty accounts won't get precomputed work assert len(wallet.get_work_units_to_solve(TEST_DIFFICULTY)) == 0 account = wallet.accounts[0] account.receive_block( pocketable_block_factory(account_id=account.account_id, amount=10000)) assert len(wallet.get_work_units_to_solve(TEST_DIFFICULTY)) == 2 assert len( wallet.get_work_units_to_solve(TEST_DIFFICULTY, precompute_work=False)) == 1 work_units = wallet.get_work_units_to_solve(TEST_DIFFICULTY) for work_unit in work_units: work_unit.difficulty = to_hex(10000, 16) work_unit.solve_work() wallet.update_solved_blocks(work_units) # Precomputed work should now exist assert account.precomputed_work work = account.precomputed_work.work # Precomputed work will be used when adding a new block account.receive_block( pocketable_block_factory(account_id=account.account_id, amount=20000)) assert account.blocks[-1].work == work assert not account.precomputed_work
def test_work_local_impossible(local_work_plugin_factory, work_unit_factory): # Enqueue an impossible PoW and shutdown the work server while it is # running work_plugin = local_work_plugin_factory(threads=2) work_plugin.add_work_units_to_solve([work_unit_factory()], network_difficulty=to_hex((2**64) - 1, 16)) work_units = work_plugin.work_units with pytest.raises(TimeoutError): wait_for(lambda: count_solved_units(work_units) == 1, timeout=1) # Ensure that there are two active worker threads assert len([ thread.name for thread in threading.enumerate() if thread.name.startswith("work_local_worker") ]) == 2 assert count_solved_units(work_units) == 0 # Shutdown the work server work_plugin.stop() # No threads should be left alive after stopping the work server assert len([ thread.name for thread in threading.enumerate() if thread.name.startswith("work_local_worker") ]) == 0
def test_work_local_multiple(local_work_plugin_factory, work_unit_factory): # Enqueue multiple PoW jobs and ensure they're all completed account_ids = [ get_account_id(private_key=generate_seed()) for _ in range(0, 100) ] work_plugin = local_work_plugin_factory(threads=8) work_plugin.add_work_units_to_solve([ work_unit_factory(account_id=account_id) for account_id in account_ids ], network_difficulty=to_hex(10000, 16)) work_units = work_plugin.work_units # The underlying queue is a set, so the exact amount of results # should be 100 even if more valid PoWs were found wait_for(lambda: count_solved_units(work_units) == 100, timeout=5) for work_unit in work_units.values(): account_ids.remove(work_unit.account_id)
def create_work_unit(account_id=None, difficulty=None): if not difficulty: difficulty = to_hex(10000, 16) block = RawBlock( block_type="state", account=(account_id or get_account_id(public_key=generate_seed())), previous=None, representative=get_account_id(public_key="0" * 64), balance=0, link=generate_seed(), difficulty=difficulty, verify=False) work_unit = WorkUnit(account_id=block.account, block_hash=block.block_hash, work_block_hash=block.work_block_hash, difficulty=block.difficulty) return work_unit
import json import random import time import pytest from nanolib import Block as RawBlock from nanolib import generate_seed, get_account_id, get_account_public_key from siliqua.wallet import (Account, AccountSource, Block, LinkBlock, Timestamp, TimestampSource, Wallet, WalletProperties, WalletSeedAlgorithm, logger) from siliqua.wallet.secret import calculate_key_iteration_count from tests.util import to_hex TEST_DIFFICULTY = to_hex(9459044173002835106, 16) @pytest.fixture(scope="function") def is_encrypted_test(): """ Returns a boolean depending on whether the test case involves an encrypted wallet. The value of this fixture can be changed by adding a @pytest.mark.with_encrypted_scenario marker, which will generate an alternate test scenario using an encrypted wallet. """ return False @pytest.fixture(scope="function") def private_account_factory():