Example #1
0
class BlockchainManager(object):
    """Client to synchronise blockchain headers."""
    def __init__(self):
        """Initialise the blockchain manager."""
        self.bcs = BlockChainStore(data_dir)
        self.client = None

    def _blockchain_change_callback(self, blockchain, ops):
        pass

    def _sync_loop(self, timeout, length_change_callback):
        interval_time = 1
        current_length = 0
        time_elapsed_since_length_change = 0
        while True:
            new_length = self.blockchain().length()
            if current_length == new_length:
                time_elapsed_since_length_change += interval_time
                if time_elapsed_since_length_change > timeout:
                    self.event_loop.stop()
                    break
            else:
                time_elapsed_since_length_change = 0
                current_length = new_length
                if length_change_callback:
                    length_change_callback(current_length)

            time.sleep(interval_time)

    def sync(self, timeout, length_change_callback=None):
        """
        Synchronise the blockchain to the latest headers.

        Args:
            timeout: the timeout to stop after not receiving any new blocks.
            length_change_callback: a function to call with arg (length) when the blockchain length changes.
        """
        self.client = Client(
            network=MAINNET,
            host_port_q=dns_bootstrap_host_port_q(MAINNET),
            should_download_block_f=should_download_block_false,
            block_chain_store=self.bcs,
            blockchain_change_callback=self._blockchain_change_callback,
        )

        self.event_loop = asyncio.get_event_loop()
        t = threading.Thread(target=self._sync_loop,
                             args=(timeout, length_change_callback))
        t.start()
        self.event_loop.run_forever()

    def blockchain(self):
        """Returns the current Blockchain object."""
        if self.client:
            return self.client.blockhandler.block_chain
        else:
            blockchain = BlockChain(
                did_lock_to_index_f=self.bcs.did_lock_to_index)
            blockchain.preload_locked_blocks(self.bcs.headers())
            return blockchain
def test_BlockChainStore():
    with TemporaryDirectory() as the_dir:
        db = BlockChainStore(dir_path=the_dir, parent_to_0=h_f(-1))
        check_prepopulate(db)
        check_postpopulate(db)

        db1 = BlockChainStore(dir_path=the_dir, parent_to_0=h_f(-1))
        check_postpopulate(db1)

        BHOS1 = [FakeHeader(h_f(i), h_f(i-1)) for i in range(10000,10050)]

        db2 = BlockChainStore(dir_path=the_dir, parent_to_0=h_f(-1))
        check_postpopulate(db2)
        db2.did_lock_to_index(BHOS1, len(BHOS))
        assert list(db2.headers()) == BHOS + BHOS1

        db3 = BlockChainStore(dir_path=the_dir, parent_to_0=h_f(-1))
        assert list(db3.headers()) == BHOS + BHOS1