def dontUseServer(blockstackd_server): """ Return false if server fails any tests """ from registrar.config import CONSENSUS_SERVERS from basicrpc import Proxy servers_to_check = CONSENSUS_SERVERS servers_to_check.append(blockstackd_server) consensus_hashes = [] # initialize to a very large number last_block_everyone = 2000000000 for server in servers_to_check: bs_client = Proxy(server, BLOCKSTACKD_PORT) last_block_seen = bs_client.getinfo()[0]['bitcoind_blocks'] try: last_block_processed = bs_client.getinfo()[0]['last_block'] except: last_block_processed = bs_client.getinfo()[0]['blocks'] if (last_block_seen - last_block_processed) > 10: log.debug("Server %s, seems to be lagging: (%s, %s)" % (server, last_block_seen, last_block_processed)) return True if last_block_processed < last_block_everyone: last_block_everyone = last_block_processed for server in servers_to_check: bs_client = Proxy(server, BLOCKSTACKD_PORT) consensus_hash = bs_client.get_consensus_at(last_block_everyone)[0] print consensus_hash consensus_hashes.append(consensus_hash) check_hash = consensus_hashes[0] for stored_hash in consensus_hashes: if check_hash != stored_hash: log.debug('Mismatch in consensus hashes from %s' % servers_to_check) return True # can use server, if all tests pass return False
def test_getinfo(self): """ Check getinfo """ resp = client.getinfo() if 'blocks' not in resp: raise ValueError('blocks not in response') self.assertIsInstance(resp, dict, msg="Not json")
def get_name_blockchain_history(fqu): try: info = bs_client.getinfo() height = int(info["last_block_processed"]) start_block = 0 end_block = height blockchain_history = bs_client.get_name_blockchain_history( fqu, start_block, end_block) if blockchain_history == {}: return jsonify({'error': 'Not found'}), 404, { 'Cache-Control': 'public, max-age=300' } else: return jsonify(blockchain_history), 200, { 'Cache-Control': 'public, max-age=300' } except Exception as e: return jsonify(str(e)), 500
def get_nameops_at(blocknum): try: nameops = {} info = bs_client.getinfo() height = int(info["last_block_processed"]) # block has yet to be processed by blockstack core if height < int(blocknum): return jsonify([]), 404, {'Cache-Control': 'public, max-age=10'} nameops["nameops"] = bs_client.get_nameops_at(int(blocknum)) # get_nameops_at is very expensive for blocks with many ops # and results never change (blockchains! yay!) so cache for 1 year return jsonify(nameops), 200, { 'Cache-Control': 'public, max-age=31536000' } except Exception as e: return jsonify(str(e)), 500
def ping(): try: result = bs_client.getinfo() return jsonify(result), 200, {'Cache-Control': 'public, max-age=60'} except Exception as e: return jsonify(str(e)), 500
def run_cli(): """ run cli """ conf = config.get_config() if conf is None: log.error("Failed to load config") sys.exit(1) advanced_mode = conf['advanced_mode'] parser = argparse.ArgumentParser( description='Blockstack cli version {}'.format(config.VERSION)) parser.register('action', 'parsers', AliasedSubParsersAction) subparsers = parser.add_subparsers(dest='action') add_subparsers(subparsers) if advanced_mode == "on": add_advanced_subparsers(subparsers) # Print default help message, if no argument is given if len(sys.argv) == 1: parser.print_help() sys.exit(1) args, unknown_args = parser.parse_known_args() result = {} conf = config.get_config() blockstack_server = conf['server'] blockstack_port = conf['port'] proxy = client.session(conf=conf, server_host=blockstack_server, server_port=blockstack_port, set_global=True) # start the two background processes (rpc daemon and monitor queue) start_background_daemons() if args.action == 'balance': if not os.path.exists(WALLET_PATH): initialize_wallet() total_balance, addresses = get_total_balance() result['total_balance'] = total_balance if args.details: result['addresses'] = addresses elif args.action == 'price': fqu = str(args.name) check_valid_name(fqu) try: resp = client.get_name_cost(fqu) except socket_error: exit_with_error("Error connecting to server") if 'error' in resp: exit_with_error(resp['error']) data = get_total_fees(resp) result = data elif args.action == 'config': data = {} settings_updated = False data["message"] = "Updated settings for" if args.host is not None: config.update_config('blockstack-client', 'server', args.host) data["message"] += " host" settings_updated = True if args.port is not None: config.update_config('blockstack-client', 'port', args.port) data["message"] += " port" settings_updated = True if args.advanced is not None: if args.advanced != "on" and args.advanced != "off": exit_with_error("Use --advanced=on or --advanced=off") else: config.update_config('blockstack-client', 'advanced_mode', args.advanced) data["message"] += " advanced" settings_updated = True # reload conf conf = config.get_config() if settings_updated: result['message'] = data['message'] else: result['message'] = "No config settings were updated." elif args.action == 'deposit': if not os.path.exists(WALLET_PATH): initialize_wallet() result['message'] = 'Send bitcoins to the address specified.' result['address'], owner_address = get_addresses_from_file() elif args.action == 'import': if not os.path.exists(WALLET_PATH): initialize_wallet() result['message'] = 'Send the name you want to receive to the' result['message'] += ' address specified.' payment_address, result['address'] = get_addresses_from_file() elif args.action == 'names': if not os.path.exists(WALLET_PATH): initialize_wallet() result['names_owned'] = get_all_names_owned() if args.details: result['addresses'] = get_owner_addresses() elif args.action in ('info', 'status', 'ping', 'details'): resp = client.getinfo() result = {} result['server_host'] = conf['server'] result['server_port'] = str(conf['port']) result['cli_version'] = config.VERSION result['advanced_mode'] = conf['advanced_mode'] if 'error' in resp: result['server_alive'] = False result['server_error'] = resp['error'] else: result['server_alive'] = True result['server_version'] = resp['blockstore_version'] try: result['last_block_processed'] = resp['last_block'] except: result['last_block_processed'] = resp['blocks'] result['last_block_seen'] = resp['bitcoind_blocks'] result['consensus_hash'] = resp['consensus'] if advanced_mode == 'on': result['testset'] = resp['testset'] proxy = get_local_proxy() if proxy is not False: current_state = json.loads(proxy.state()) queue = {} pending_queue = [] preorder_queue = [] register_queue = [] update_queue = [] transfer_queue = [] def format_new_entry(entry): new_entry = {} new_entry['name'] = entry['fqu'] confirmations = get_tx_confirmations(entry['tx_hash']) if confirmations is None: confirmations = 0 new_entry['confirmations'] = confirmations return new_entry def format_queue_display(preorder_queue, register_queue): for entry in register_queue: name = entry['name'] for check_entry in preorder_queue: if check_entry['name'] == name: preorder_queue.remove(check_entry) for entry in current_state: if 'type' in entry: if entry['type'] == 'preorder': preorder_queue.append(format_new_entry(entry)) elif entry['type'] == 'register': register_queue.append(format_new_entry(entry)) elif entry['type'] == 'update': update_queue.append(format_new_entry(entry)) elif entry['type'] == 'transfer': transfer_queue.append(format_new_entry(entry)) format_queue_display(preorder_queue, register_queue) if len(preorder_queue) != 0: queue['preorder'] = preorder_queue if len(register_queue) != 0: queue['register'] = register_queue if len(update_queue) != 0: queue['update'] = update_queue if len(transfer_queue) != 0: queue['transfer'] = transfer_queue if queue != {}: result['queue'] = queue elif args.action == 'lookup': data = {} blockchain_record = None fqu = str(args.name) check_valid_name(fqu) try: blockchain_record = client.get_name_blockchain_record(fqu) except socket_error: exit_with_error("Error connecting to server.") if 'value_hash' not in blockchain_record: exit_with_error("%s is not registered" % fqu) data_id = blockchain_record['value_hash'] owner_address = blockchain_record['address'] profile = client.get_immutable(str(args.name), data_id)['data'] zone_file = profile profile = resolve_zone_file_to_profile(profile, owner_address) if not is_profile_in_legacy_format(profile): data['data_record'] = profile data['zone_file'] = zone_file else: data['data_record'] = json.loads(profile) #except Exception as e: # print e # data['data_record'] = None result = data elif args.action == 'whois': data = {} record = None fqu = str(args.name) check_valid_name(fqu) try: record = client.get_name_blockchain_record(fqu) except socket_error: exit_with_error("Error connecting to server.") if 'value_hash' not in record: result['registered'] = False else: result['registered'] = True result['block_preordered_at'] = record['preorder_block_number'] result['block_renewed_at'] = record['last_renewed'] result['owner_address'] = record['address'] result['owner_public_key'] = record['sender_pubkey'] result['owner_script'] = record['sender'] result['preorder_transaction_id'] = record['txid'] elif args.action == 'register': if not os.path.exists(WALLET_PATH): initialize_wallet() result = {} fqu = str(args.name) check_valid_name(fqu) cost = client.get_name_cost(fqu) if 'error' in cost: exit_with_error(cost['error']) if nameRegistered(fqu): exit_with_error("%s is already registered." % fqu) if not walletUnlocked(): unlock_wallet() fees = get_total_fees(cost) try: cost = fees['total_estimated_cost'] input_prompt = "Registering %s will cost %s BTC." % (fqu, cost) input_prompt += " Continue? (y/n): " user_input = raw_input(input_prompt) user_input = user_input.lower() if user_input != 'y': print "Not registering." exit(0) except KeyboardInterrupt: print "\nExiting." exit(0) payment_address, owner_address = get_addresses_from_file() if not hasEnoughBalance(payment_address, fees['total_estimated_cost']): msg = "Address %s doesn't have enough balance." % payment_address exit_with_error(msg) if recipientNotReady(owner_address): msg = "Address %s owns too many names already." % owner_address exit_with_error(msg) if dontuseAddress(payment_address): msg = "Address %s has pending transactions." % payment_address msg += " Wait and try later." exit_with_error(msg) proxy = get_local_proxy() try: resp = proxy.preorder(fqu) except: exit_with_error("Error talking to server, try again.") if 'success' in resp and resp['success']: result = resp else: if 'error' in resp: exit_with_error(resp['error']) if 'message' in resp: exit_with_error(resp['message']) elif args.action == 'update': if not os.path.exists(WALLET_PATH): initialize_wallet() fqu = str(args.name) check_valid_name(fqu) user_data = str(args.data) try: user_data = json.loads(user_data) except: exit_with_error("Data is not in JSON format.") tests_for_update_and_transfer(fqu) if profileonBlockchain(fqu, user_data): msg = "Data is same as current data record, update not needed." exit_with_error(msg) if not walletUnlocked(): unlock_wallet() proxy = get_local_proxy() try: resp = proxy.update(fqu, user_data) except: exit_with_error("Error talking to server, try again.") if 'success' in resp and resp['success']: result = resp else: if 'error' in resp: exit_with_error(resp['error']) if 'message' in resp: exit_with_error(resp['message']) elif args.action == 'transfer': if not os.path.exists(WALLET_PATH): initialize_wallet() fqu = str(args.name) check_valid_name(fqu) transfer_address = str(args.address) tests_for_update_and_transfer(fqu, transfer_address=transfer_address) if not walletUnlocked(): unlock_wallet() proxy = get_local_proxy() try: resp = proxy.transfer(fqu, transfer_address) except: exit_with_error("Error talking to server, try again.") if 'success' in resp and resp['success']: result = resp else: if 'error' in resp: exit_with_error(resp['error']) if 'message' in resp: exit_with_error(resp['message']) # ---------------------- Advanced options --------------------------------- elif args.action == 'wallet': if not os.path.exists(WALLET_PATH): result = initialize_wallet() else: unlock_wallet(display_enabled=True) elif args.action == 'consensus': if args.block_height is None: # by default get last indexed block resp = client.getinfo() if 'error' in resp: exit_with_error("Error connecting to server.") elif 'last_block' in resp or 'blocks' in resp: if 'last_block' in resp: args.block_height = client.getinfo()['last_block'] elif 'blocks' in resp: args.block_height = client.getinfo()['blocks'] else: result['error'] = "Server is indexing. Try again" exit(0) resp = client.get_consensus_at(int(args.block_height)) data = {} data['consensus'] = resp data['block_height'] = args.block_height result = data elif args.action == 'register_tx': result = client.register(str(args.name), str(args.privatekey), str(args.addr), tx_only=True) elif args.action == 'register_subsidized': result = client.register_subsidized(str(args.name), str(args.privatekey), str(args.addr), str(args.subsidy_key)) elif args.action == 'update_tx': txid = None if args.txid is not None: txid = str(args.txid) result = client.update(str(args.name), str(args.record_json), str(args.privatekey), txid=txid, tx_only=True) elif args.action == 'update_subsidized': txid = None if args.txid is not None: txid = str(args.txid) result = client.update_subsidized(str(args.name), str(args.record_json), str(args.public_key), str(args.subsidy_key), txid=txid) elif args.action == 'transfer_tx': keepdata = False if args.keepdata.lower() not in ["on", "false"]: print >> sys.stderr, "Pass 'true' or 'false' for keepdata" sys.exit(1) if args.keepdata.lower() == "on": keepdata = True result = client.transfer(str(args.name), str(args.address), keepdata, str(args.privatekey), tx_only=True) elif args.action == 'preorder': register_addr = None if args.address is not None: register_addr = str(args.address) result = client.preorder(str(args.name), str(args.privatekey), register_addr=register_addr) elif args.action == 'preorder_tx': register_addr = None if args.address is not None: register_addr = str(args.address) result = client.preorder(str(args.name), str(args.privatekey), register_addr=register_addr, tx_only=True) elif args.action == 'preorder_subsidized': result = client.preorder_subsidized(str(args.name), str(args.public_key), str(args.address), str(args.subsidy_key)) elif args.action == 'transfer_subsidized': keepdata = False if args.keepdata.lower() not in ["on", "false"]: print >> sys.stderr, "Pass 'true' or 'false' for keepdata" sys.exit(1) if args.keepdata.lower() == "on": keepdata = True result = client.transfer_subsidized(str(args.name), str(args.address), keepdata, str(args.public_key), str(args.subsidy_key)) elif args.action == 'renew': result = client.renew(str(args.name), str(args.privatekey)) elif args.action == 'renew_tx': result = client.renew(str(args.name), str(args.privatekey), tx_only=True) elif args.action == 'renew_subsidized': result = client.renew_subsidized(str(args.name), str(args.public_key), str(args.subsidy_key)) elif args.action == 'revoke': result = client.revoke(str(args.name), str(args.privatekey)) elif args.action == 'revoke_tx': result = client.revoke(str(args.name), str(args.privatekey), tx_only=True) elif args.action == 'revoke_subsidized': result = client.revoke_subsidized(str(args.name), str(args.public_key), str(args.subsidy_key)) elif args.action == 'name_import': result = client.name_import(str(args.name), str(args.address), str(args.hash), str(args.privatekey)) elif args.action == 'namespace_preorder': reveal_addr = None if args.address is not None: reveal_addr = str(args.address) result = client.namespace_preorder(str(args.namespace_id), str(args.privatekey), reveal_addr=reveal_addr) elif args.action == 'namespace_reveal': bucket_exponents = args.bucket_exponents.split(',') if len(bucket_exponents) != 16: raise Exception("bucket_exponents must be a 16-value CSV \ of integers") for i in xrange(0, len(bucket_exponents)): try: bucket_exponents[i] = int(bucket_exponents[i]) except: raise Exception("bucket_exponents must contain integers in \ range [0, 16)") lifetime = int(args.lifetime) if lifetime < 0: lifetime = 0xffffffff # means "infinite" to blockstack-server result = client.namespace_reveal(str(args.namespace_id), str(args.addr), lifetime, int(args.coeff), int(args.base), bucket_exponents, int(args.nonalpha_discount), int(args.no_vowel_discount), str(args.privatekey)) elif args.action == 'namespace_ready': result = client.namespace_ready(str(args.namespace_id), str(args.privatekey)) elif args.action == 'put_mutable': result = client.put_mutable(str(args.name), str(args.data_id), str(args.data), str(args.privatekey)) elif args.action == 'put_immutable': result = client.put_immutable(str(args.name), str(args.data), str(args.privatekey), conf=conf) elif args.action == 'get_mutable': result = client.get_mutable(str(args.name), str(args.data_id), conf=conf) elif args.action == 'get_immutable': result = client.get_immutable(str(args.name), str(args.hash)) elif args.action == 'delete_immutable': result = client.delete_immutable(str(args.name), str(args.hash), str(args.privatekey)) elif args.action == 'delete_mutable': result = client.delete_mutable(str(args.name), str(args.data_id), str(args.privatekey)) elif args.action == 'get_name_blockchain_record': result = client.get_name_blockchain_record(str(args.name)) elif args.action == 'get_namespace_blockchain_record': result = client.get_namespace_blockchain_record(str(args.namespace_id)) elif args.action == 'lookup_snv': result = client.lookup_snv(str(args.name), int(args.block_id), str(args.consensus_hash)) elif args.action == 'get_name_record': result = client.get_name_record(str(args.name)) elif args.action == 'get_names_owned_by_address': result = client.get_names_owned_by_address(str(args.address)) elif args.action == 'get_namespace_cost': result = client.get_namespace_cost(str(args.namespace_id)) elif args.action == 'get_all_names': offset = None count = None if args.offset is not None: offset = int(args.offset) if args.count is not None: count = int(args.count) result = client.get_all_names(offset, count) elif args.action == 'get_names_in_namespace': offset = None count = None if args.offset is not None: offset = int(args.offset) if args.count is not None: count = int(args.count) result = client.get_names_in_namespace(str(args.namespace_id), offset, count) elif args.action == 'get_nameops_at': result = client.get_nameops_at(int(args.block_id)) print_result(result)