def main(): parser = argparse.ArgumentParser(description="Watch Bitcoin network for new blocks.") parser.add_argument('-s', "--state-dir", help='The directory where state files are stored.') parser.add_argument( '-f', "--fast-forward", type=int, help="block index to fast-forward to (ie. don't download full blocks prior to this one)", default=0 ) parser.add_argument( '-d', "--depth", type=int, help="Minimum depth blocks must be buried before being dropped in blockdir", default=0 ) parser.add_argument('-l', "--log-file", help="Path to log file", default=None) parser.add_argument("blockdir", help='The directory where new blocks are dropped.') args = parser.parse_args() asyncio.tasks._DEBUG = True logging.basicConfig(level=logging.DEBUG, format=LOG_FORMAT) logging.getLogger("asyncio").setLevel(logging.INFO) if args.log_file: log_file(args.log_file) state_dir = args.state_dir block_chain_store = BlockChainStore(state_dir) network = MAINNET if 1: host_port_q = dns_bootstrap_host_port_q(network) else: host_port_q = asyncio.Queue() host_port_q.put_nowait(("127.0.0.1", 8333)) def should_download_block_f(block_hash, block_index): return block_index >= args.fast_forward last_processed_block = max(get_last_processed_block(state_dir), args.fast_forward) update_last_processed_block(state_dir, last_processed_block) change_q = asyncio.Queue() from pycoin.blockchain.BlockChain import _update_q def do_update(blockchain, ops): _update_q(change_q, [list(o) for o in ops]) # block_chain.add_change_callback(do_update) # block_chain.add_nodes(block_chain_store.block_tuple_iterator()) client = Client( network, host_port_q, should_download_block_f, block_chain_store, do_update) blockfetcher = client.blockfetcher # we need to keep block_processor_task referenced in this stack context # or the task will be garbage collected block_processor_task = asyncio.Task( block_processor( change_q, blockfetcher, state_dir, args.blockdir, args.depth)) asyncio.get_event_loop().run_forever()
def main(): parser = argparse.ArgumentParser(description="Watch Bitcoin network for new blocks.") parser.add_argument('-s', "--state-dir", help='The directory where state files are stored.') parser.add_argument( '-f', "--fast-forward", type=int, help="block index to fast-forward to (ie. don't download full blocks prior to this one)", default=0 ) parser.add_argument( '-d', "--depth", type=int, help="Minimum depth blocks must be buried before being dropped in blockdir", default=1 ) parser.add_argument('-l', "--log-file", help="Path to log file", default=None) parser.add_argument("blockdir", help='The directory where new blocks are dropped.') args = parser.parse_args() asyncio.tasks._DEBUG = True logging.basicConfig(level=logging.DEBUG, format=LOG_FORMAT) logging.getLogger("asyncio").setLevel(logging.INFO) if args.log_file: log_file(args.log_file) state_dir = args.state_dir block_chain_store = BlockChainStore(state_dir) network = MAINNET if 1: host_port_q = dns_bootstrap_host_port_q(network) else: host_port_q = asyncio.Queue() host_port_q.put_nowait(("127.0.0.1", 8333)) should_download_block_f = lambda block_hash, block_index: block_index >= args.fast_forward last_processed_block = max(get_last_processed_block(state_dir), args.fast_forward) update_last_processed_block(state_dir, last_processed_block) change_q = asyncio.Queue() from pycoin.blockchain.BlockChain import _update_q def do_update(blockchain, ops): _update_q(change_q, [list(o) for o in ops]) client = Client( network, host_port_q, should_download_block_f, block_chain_store, do_update) blockfetcher = client.blockfetcher block_processor_task = asyncio.Task( block_processor( change_q, blockfetcher, state_dir, args.blockdir, args.depth)) asyncio.get_event_loop().run_forever()
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 main(): parser = argparse.ArgumentParser(description="Watch Bitcoin network for new blocks.") parser.add_argument('-c', "--config-dir", help='The directory where config files are stored.') parser.add_argument( '-f', "--fast-forward", type=int, help="block index to fast-forward to (ie. don't download full blocks prior to this one)", default=0 ) parser.add_argument( '-d', "--depth", type=int, help="Minimum depth blocks must be buried before being dropped in blockdir", default=2 ) parser.add_argument( '-l', "--log-file", help="Path to log file", default=None) parser.add_argument("blockdir", help='The directory where new blocks are dropped.') asyncio.tasks._DEBUG = True logging.basicConfig(level=logging.DEBUG, format=LOG_FORMAT) logging.getLogger("asyncio").setLevel(logging.INFO) if 1: host_port_q = dns_bootstrap_host_port_q(MAINNET) else: host_port_q = asyncio.Queue() host_port_q.put_nowait(("127.0.0.1", 8333)) args = parser.parse_args() if args.log_file: log_file(args.log_file) block_chain_store = BlockChainStore(args.config_dir) block_chain = BlockChain(did_lock_to_index_f=block_chain_store.did_lock_to_index) locker_task = block_chain_locker(block_chain) block_chain.add_nodes(block_chain_store.block_tuple_iterator()) blockfetcher = Blockfetcher() inv_collector = InvCollector() block_store = TwoLevelDict() @asyncio.coroutine def _rotate(block_store): while True: block_store.rotate() yield from asyncio.sleep(1800) rotate_task = asyncio.Task(_rotate(block_store)) blockhandler = BlockHandler(inv_collector, block_chain, block_store, should_download_f=lambda block_hash, block_index: block_index >= args.fast_forward) last_processed_block = max(get_last_processed_block(config_dir), args.fast_forward) update_last_processed_block(config_dir, last_processed_block) change_q = asyncio.Queue() from pycoinnet.util.BlockChain import _update_q block_chain.add_change_callback(lambda blockchain, ops: _update_q(change_q, ops)) block_processor_task = asyncio.Task( block_processor( change_q, blockfetcher, args.config_dir, args.blockdir, args.depth))) fast_forward_add_peer = fast_forwarder_add_peer_f(block_chain) fetcher_task = asyncio.Task(new_block_fetcher(inv_collector, block_chain)) def create_protocol_callback(): peer = BitcoinPeerProtocol(MAINNET["MAGIC_HEADER"]) install_pingpong_manager(peer) fetcher = Fetcher(peer) peer.add_task(run_peer( peer, fetcher, fast_forward_add_peer, blockfetcher, inv_collector, blockhandler)) return peer connection_info_q = manage_connection_count(host_port_q, create_protocol_callback, 8) show_task = asyncio.Task(show_connection_info(connection_info_q)) asyncio.get_event_loop().run_forever()
def __init__(self, network, initial_blockchain_view, bloom_filter, block_index_queue=None, filter_f=lambda idx, h: True, host_port_q=None): """ network: a value from pycoinnet.helpers.networks initial_blockchain_view: BlockChainView instance which is update automatically bloom_filter: the filter sent to remotes block_index_queue: a Queue which is fed with (block, index) items which need to be processed host_port_q: a Queue that is being fed potential places to connect """ if host_port_q is None: host_port_q = dns_bootstrap_host_port_q(network) self.network = network self.blockchain_view = initial_blockchain_view self.bloom_filter = bloom_filter self.block_futures = asyncio.Queue(maxsize=2000) if block_index_queue is None: block_index_queue = asyncio.Queue() self._block_index_queue = block_index_queue self.feed_task = asyncio.Task(self.feed_blocks()) self.blockfetcher = Blockfetcher() self.inv_collector = InvCollector() if bloom_filter: self.get_future = self.blockfetcher.get_merkle_block_future else: self.get_future = self.blockfetcher.get_block_future self.filter_f = filter_f self.getheaders_add_peer = getheaders_add_peer_f(self.blockchain_view, self.handle_reorg) self.nonce = int.from_bytes(os.urandom(8), byteorder="big") self.subversion = "/Notoshi/".encode("utf8") @asyncio.coroutine def run_peer(peer, fetcher, getheaders_add_peer, blockfetcher, inv_collector): yield from asyncio.wait_for(peer.connection_made_future, timeout=None) last_block_index = max(0, self.blockchain_view.last_block_index()) version_parameters = version_data_for_peer( peer, local_port=0, last_block_index=last_block_index, nonce=self.nonce, subversion=self.subversion) version_data = yield from initial_handshake(peer, version_parameters) if self.bloom_filter: filter_bytes, hash_function_count, tweak = self.bloom_filter.filter_load_params() # TODO: figure out flags flags = 0 peer.send_msg( "filterload", filter=filter_bytes, hash_function_count=hash_function_count, tweak=tweak, flags=flags) last_block_index = version_data["last_block_index"] getheaders_add_peer(peer, last_block_index) blockfetcher.add_peer(peer, fetcher, last_block_index) inv_collector.add_peer(peer) def create_protocol_callback(): peer = BitcoinPeerProtocol(network["MAGIC_HEADER"]) install_pingpong_manager(peer) fetcher = Fetcher(peer) peer.add_task(run_peer( peer, fetcher, self.getheaders_add_peer, self.blockfetcher, self.inv_collector)) return peer self.connection_info_q = manage_connection_count(host_port_q, create_protocol_callback, 8) self.show_task = asyncio.Task(show_connection_info(self.connection_info_q))
def __init__(self, network, initial_blockchain_view, bloom_filter, block_index_queue=None, filter_f=lambda idx, h: True, host_port_q=None): """ network: a value from pycoinnet.helpers.networks initial_blockchain_view: BlockChainView instance which is update automatically bloom_filter: the filter sent to remotes block_index_queue: a Queue which is fed with (block, index) items which need to be processed host_port_q: a Queue that is being fed potential places to connect """ if host_port_q is None: host_port_q = dns_bootstrap_host_port_q(network) self.network = network self.blockchain_view = initial_blockchain_view self.bloom_filter = bloom_filter self.block_futures = asyncio.Queue(maxsize=2000) if block_index_queue is None: block_index_queue = asyncio.Queue() self._block_index_queue = block_index_queue self.feed_task = asyncio.Task(self.feed_blocks()) self.blockfetcher = Blockfetcher() self.inv_collector = InvCollector() if bloom_filter: self.get_future = self.blockfetcher.get_merkle_block_future else: self.get_future = self.blockfetcher.get_block_future self.filter_f = filter_f self.getheaders_add_peer = getheaders_add_peer_f( self.blockchain_view, self.handle_reorg) self.nonce = int.from_bytes(os.urandom(8), byteorder="big") self.subversion = "/Notoshi/".encode("utf8") @asyncio.coroutine def run_peer(peer, fetcher, getheaders_add_peer, blockfetcher, inv_collector): yield from asyncio.wait_for(peer.connection_made_future, timeout=None) last_block_index = max(0, self.blockchain_view.last_block_index()) version_parameters = version_data_for_peer( peer, local_port=0, last_block_index=last_block_index, nonce=self.nonce, subversion=self.subversion) version_data = yield from initial_handshake( peer, version_parameters) if self.bloom_filter: filter_bytes, hash_function_count, tweak = self.bloom_filter.filter_load_params( ) # TODO: figure out flags flags = 0 peer.send_msg("filterload", filter=filter_bytes, hash_function_count=hash_function_count, tweak=tweak, flags=flags) last_block_index = version_data["last_block_index"] getheaders_add_peer(peer, last_block_index) blockfetcher.add_peer(peer, fetcher, last_block_index) inv_collector.add_peer(peer) def create_protocol_callback(): peer = BitcoinPeerProtocol(network["MAGIC_HEADER"]) install_pingpong_manager(peer) fetcher = Fetcher(peer) peer.add_task( run_peer(peer, fetcher, self.getheaders_add_peer, self.blockfetcher, self.inv_collector)) return peer self.connection_info_q = manage_connection_count( host_port_q, create_protocol_callback, 8) self.show_task = asyncio.Task( show_connection_info(self.connection_info_q))