def sync_blockchain(bc_config, last_block=None, expected_snapshots={}, **virtualchain_args): """ synchronize state with the blockchain. Return True on success Return False if we're supposed to stop indexing Abort on error """ impl = sys.modules[__name__] if virtualchain.get_implementation() is not None: impl = None db_filename = virtualchain.get_db_filename(impl=impl) new_db = TalosPolicyDB(db_filename, expected_snapshots=expected_snapshots, read_only=False) try: if last_block is None: last_block = _get_newest_block(bc_config) rc = virtualchain.sync_virtualchain( bc_config, last_block, new_db, expected_snapshots=expected_snapshots) finally: new_db.close() return rc
def sync_blockchain(bt_opts, last_block, expected_snapshots={}, **virtualchain_args): """ synchronize state with the blockchain. Return True on success Return False if we're supposed to stop indexing Abort on error """ # make this usable even if we haven't explicitly configured virtualchain impl = sys.modules[__name__] if virtualchain.get_implementation() is not None: impl = None log.info("Synchronizing database up to block %s" % last_block) db_filename = virtualchain.get_db_filename(impl=impl) # NOTE: this is the only place where a read-write handle should be created, # since this is the only place where the db should be modified. new_db = BlockstackDB.borrow_readwrite_instance( db_filename, last_block, expected_snapshots=expected_snapshots) rc = virtualchain.sync_virtualchain(bt_opts, last_block, new_db, expected_snapshots=expected_snapshots, **virtualchain_args) BlockstackDB.release_readwrite_instance(new_db, last_block) return rc
def get_announce_filename( working_dir=None ): """ Get the path to the file that stores all of the announcements. """ if working_dir is None: working_dir = virtualchain.get_working_dir() announce_filepath = os.path.join( working_dir, virtualchain.get_implementation().get_virtual_chain_name() ) + ".announce" return announce_filepath
def get_testset_filename( working_dir=None ): """ Get the path to the file to determine whether or not we're in testset. """ if working_dir is None: working_dir = virtualchain.get_working_dir() testset_filepath = os.path.join( working_dir, virtualchain.get_implementation().get_virtual_chain_name() ) + ".testset" return testset_filepath
def get_default_virtualchain_impl(): """ Get the set of virtualchain hooks--to serve as the virtualchain's implementation. Uses the one set in the virtualchain runtime config, but falls back to Blockstack's by default (i.e. if blockstack is getting imported as part of a library). """ import nameset.virtualchain_hooks as virtualchain_hooks blockstack_impl = virtualchain.get_implementation() if blockstack_impl is None: blockstack_impl = virtualchain_hooks return blockstack_impl
def get_db_state(): """ Return an opaque 'state' object that will be preserved across calls to the blockchain indexing callbacks. """ impl = virtualchain.get_implementation() if impl is None: impl = sys.modules[__name__] db_filename = virtualchain.get_db_filename(impl=impl) db_inst = TalosPolicyDB(db_filename) return db_inst
def get_db_state(disposition=DISPOSITION_RO): """ (required by virtualchain state engine) Callback to the virtual chain state engine. Get a handle to our state engine implementation (i.e. our name database). Note that in this implementation, the database handle returned will only support read-only operations by default. NO COMMITS WILL BE ALLOWED. """ # make this usable even if we haven't explicitly configured virtualchain impl = virtualchain.get_implementation() if impl is None: impl = sys.modules[__name__] db_filename = virtualchain.get_db_filename(impl=impl) lastblock_filename = virtualchain.get_lastblock_filename(impl=impl) lastblock = None firstcheck = True for path in [db_filename, lastblock_filename]: if os.path.exists(path): # have already created the db firstcheck = False if not firstcheck and not os.path.exists(lastblock_filename): # this can't ever happen log.error("FATAL: no such file or directory: %s" % lastblock_filename) os.abort() # verify that it is well-formed, if it exists elif os.path.exists(lastblock_filename): try: with open(lastblock_filename, "r") as f: lastblock = int(f.read().strip()) except Exception, e: # this can't ever happen log.error("FATAL: failed to parse: %s" % lastblock_filename) log.exception(e) os.abort()
def get_db_state( disposition=DISPOSITION_RO ): """ (required by virtualchain state engine) Callback to the virtual chain state engine. Get a handle to our state engine implementation (i.e. our name database). Note that in this implementation, the database handle returned will only support read-only operations by default. NO COMMITS WILL BE ALLOWED. """ # make this usable even if we haven't explicitly configured virtualchain impl = virtualchain.get_implementation() if impl is None: impl = sys.modules[__name__] db_filename = virtualchain.get_db_filename(impl=impl) lastblock_filename = virtualchain.get_lastblock_filename(impl=impl) lastblock = None firstcheck = True for path in [db_filename, lastblock_filename]: if os.path.exists( path ): # have already created the db firstcheck = False if not firstcheck and not os.path.exists( lastblock_filename ): # this can't ever happen log.error("FATAL: no such file or directory: %s" % lastblock_filename ) os.abort() # verify that it is well-formed, if it exists elif os.path.exists( lastblock_filename ): try: with open(lastblock_filename, "r") as f: lastblock = int( f.read().strip() ) except Exception, e: # this can't ever happen log.error("FATAL: failed to parse: %s" % lastblock_filename) log.exception(e) os.abort()
def get_last_block(): """ Get the last block processed Return the integer on success Return None on error """ # make this usable even if we haven't explicitly configured virtualchain impl = virtualchain.get_implementation() if impl is None: impl = sys.modules[__name__] lastblock_filename = virtualchain.get_lastblock_filename(impl=impl) if os.path.exists(lastblock_filename): try: with open(lastblock_filename, "r") as f: lastblock = int(f.read().strip()) return lastblock except Exception, e: # this can't ever happen log.exception(e) return None
def get_snapshots(): """ Read the virtualchain snapshots Returns the dict of {snapshots: {$block_height: $consensus_hash}} on success Returns None on error """ # make this usable even if we haven't explicitly configured virtualchain impl = virtualchain.get_implementation() if impl is None: impl = sys.modules[__name__] snapshots_filename = virtualchain.get_snapshots_filename(impl=impl) if os.path.exists(snapshots_filename): try: with open(snapshots_filename, 'r') as f: snapshots_bin = f.read() snapshots = json.loads(snapshots_bin) return snapshots except Exception as e: log.exception(e) return None return None
def sync_blockchain( bt_opts, last_block, expected_snapshots={}, **virtualchain_args ): """ synchronize state with the blockchain. Return True on success Return False if we're supposed to stop indexing Abort on error """ # make this usable even if we haven't explicitly configured virtualchain impl = sys.modules[__name__] if virtualchain.get_implementation() is not None: impl = None log.info("Synchronizing database up to block %s" % last_block) db_filename = virtualchain.get_db_filename(impl=impl) # NOTE: this is the only place where a read-write handle should be created, # since this is the only place where the db should be modified. new_db = BlockstackDB.borrow_readwrite_instance( db_filename, last_block, expected_snapshots=expected_snapshots ) rc = virtualchain.sync_virtualchain( bt_opts, last_block, new_db, expected_snapshots=expected_snapshots, **virtualchain_args ) BlockstackDB.release_readwrite_instance( new_db, last_block ) return rc
def check(state_engine): expected_hash = "13a76219ed16c5e53e2c08dde8660609bb8f63da" # not revealed, but ready ns = state_engine.get_namespace_reveal("id") if ns is not None: return False ns = state_engine.get_namespace("id") if ns is None: return False if ns['namespace_id'] != 'id': return False # not preordered preorder = state_engine.get_name_preorder( "judecn.id", pybitcoin.make_pay_to_address_script(wallets[2].addr), wallets[3].addr) if preorder is not None: return False # registered name_rec = state_engine.get_name("judecn.id") if name_rec is None: return False # owned by if name_rec['address'] != wallets[3].addr or name_rec[ 'sender'] != pybitcoin.make_pay_to_address_script(wallets[3].addr): return False # announcements exist... if not os.path.exists(working_dir): print >> sys.stderr, "No such directory %s" % working_dir return False # "hello world!" exists... announce_path = os.path.join(working_dir, "announcements", expected_hash + ".txt") hashes_path = os.path.join( working_dir, virtualchain.get_implementation().get_virtual_chain_name() + ".announce") if not os.path.exists(announce_path): print >> sys.stderr, "No announcement text: %s" % announce_path return False if not os.path.exists(hashes_path): print >> sys.stderr, "No announcement hash text" return False # announcement contains "hello world!" txt = None with open(announce_path, "r") as f: txt = f.read() if txt.strip() != "hello world!": print >> sys.stderr, "Wrong announcement text" return False # announcement list includes the hash announce_hashes = None with open(hashes_path, "r") as f: txt = f.read() txt = txt.strip() if txt != expected_hash: print >> sys.stderr, "Wring announcement hash text" return False return True
def check( state_engine ): # not revealed, but ready ns = state_engine.get_namespace_reveal( "id" ) if ns is not None: return False ns = state_engine.get_namespace( "id" ) if ns is None: return False if ns['namespace_id'] != 'id': return False # not preordered preorder = state_engine.get_name_preorder( "judecn.id", pybitcoin.make_pay_to_address_script(wallets[2].addr), wallets[3].addr ) if preorder is not None: return False # registered name_rec = state_engine.get_name( "judecn.id" ) if name_rec is None: return False # owned by if name_rec['address'] != wallets[3].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script(wallets[3].addr): return False # announcements exist... if not os.path.exists( working_dir ): print >> sys.stderr, "No such directory %s" % working_dir return False # "hello world!" exists... announce_path = os.path.join(working_dir, "announcements", "13a76219ed16c5e53e2c08dde8660609bb8f63da.txt") hashes_path = os.path.join( working_dir, virtualchain.get_implementation().get_virtual_chain_name() + ".announce" ) if not os.path.exists( announce_path ): print >> sys.stderr, "No announcement text" return False if not os.path.exists( hashes_path ): print >> sys.stderr, "No announcement hash text" return False # announcement contains "hello world!" txt = None with open( announce_path, "r" ) as f: txt = f.read() txt = txt.strip() if txt != "hello world!": print >> sys.stderr, "Wrong announcement text" return False # announcement list includes the hash announce_hashes = None with open( hashes_path, "r" ) as f: txt = f.read() txt = txt.strip() if txt != "13a76219ed16c5e53e2c08dde8660609bb8f63da": print >> sys.stderr, "Wring announcement hash text" return False return True