示例#1
0
    def update_users(self, spam_protection=False, reprocess_username=None):
        """
            Process new profile updates from the webapp
        """

        counter = 0
        self.registrar_server.reset_flag()

        for new_user in self.updates.find(no_cursor_timeout=True):

            user = get_db_user_from_id(new_user, self.users)

            if user is None:
                continue

            # for spam protection
            if check_banned_email(user['email']):
                if spam_protection:
                    log.debug("Deleting spam: %s, %s" %
                              (user['email'], user['username']))
                    self.updates.remove({"user_id": new_user['user_id']})
                else:
                    log.debug("Need to delete %s, %s" %
                              (user['email'], user['username']))
                continue

            # mode for reprocessing a single user, ignore others
            if reprocess_username is not None:
                if user['username'] != reprocess_username:
                    #log.debug("Ignoring: %s" % user['username'])
                    continue

            fqu = user['username'] + "." + DEFAULT_NAMESPACE
            btc_address = nmc_to_btc_address(user['namecoin_address'])

            data_value = convert_profile_format(user)

            encrypted_privkey = new_user['encrypted_private_key']
            hex_privkey = bip38_decrypt(str(encrypted_privkey), WALLET_SECRET)

            if nameRegistered(fqu):

                if profilePublished(fqu, data_value):
                    log.debug("Profile match, removing: %s" % fqu)
                    self.updates.remove({"user_id": new_user['user_id']})

                    refresh_resolver(user['username'])
                else:
                    log.debug("Processing: %s, %s" % (fqu, user['email']))
                    try:
                        self.registrar_server.process_subsidized_nameop(
                            fqu,
                            owner_privkey=hex_privkey,
                            profile=data_value,
                            nameop='update')
                    except Exception as e:
                        log.debug(e)
            else:

                log.debug("Not registered: %s" % fqu)
示例#2
0
    def test_username_registered(self):
        """ Check if username is registered on blockchain
        """

        for fqu in test_users:

            resp = nameRegistered(fqu)

            self.assertTrue(resp, msg="Username not registered")
示例#3
0
    def transfer_users(self, spam_protection=False, reprocess_username=None):
        """
            Process new transfer from the webapp
        """

        counter = 0
        self.registrar_server.reset_flag()

        for new_user in self.exports.find(no_cursor_timeout=True):

            user = get_db_user_from_id(new_user, self.users)

            if user is None:
                continue

            # add spam protection here

            # mode for reprocessing a single user, ignore others
            if reprocess_username is not None:
                if user['username'] != reprocess_username:
                    continue

            fqu = user['username'] + "." + DEFAULT_NAMESPACE

            transfer_address = new_user['recipient_address']

            try:
                encrypted_privkey = new_user['encrypted_private_key']
                hex_privkey = bip38_decrypt(str(encrypted_privkey),
                                            WALLET_SECRET)
            except:
                log.debug("no private key")
                #self.exports.remove({"user_id": new_user['user_id']})
            else:
                log.debug("To export: %s to %s" % (fqu, transfer_address))

            if nameRegistered(fqu):

                if ownerName(fqu, transfer_address):
                    log.debug("Name transferred, removing: %s" % fqu)
                    self.exports.remove({"user_id": new_user['user_id']})

                    refresh_resolver(user['username'])
                else:
                    log.debug("Processing: %s, %s" % (fqu, user['email']))
                    #try:
                    self.registrar_server.process_subsidized_nameop(
                        fqu,
                        owner_privkey=hex_privkey,
                        transfer_address=transfer_address,
                        nameop='transfer',
                        profile="")
                    #except Exception as e:
                    #    log.debug(e)
            else:

                log.debug("Not registered: %s" % fqu)
    def test_username_registered(self):
        """ Check if username is registered on blockchain
        """

        for fqu in test_users:

            resp = nameRegistered(fqu)

            self.assertTrue(resp, msg="Username not registered")
    def update_users(self, spam_protection=False, reprocess_username=None):
        """
            Process new profile updates from the webapp
        """

        counter = 0
        self.registrar_server.reset_flag()

        for new_user in self.updates.find(no_cursor_timeout=True):

            user = get_db_user_from_id(new_user, self.users)

            if user is None:
                continue

            # for spam protection
            if check_banned_email(user['email']):
                if spam_protection:
                    log.debug("Deleting spam: %s, %s" % (user['email'], user['username']))
                    self.updates.remove({"user_id": new_user['user_id']})
                else:
                    log.debug("Need to delete %s, %s" % (user['email'], user['username']))
                continue

            # mode for reprocessing a single user, ignore others
            if reprocess_username is not None:
                if user['username'] != reprocess_username:
                    #log.debug("Ignoring: %s" % user['username'])
                    continue

            fqu = user['username'] + "." + DEFAULT_NAMESPACE
            btc_address = nmc_to_btc_address(user['namecoin_address'])

            data_value = convert_profile_format(user)

            encrypted_privkey = new_user['encrypted_private_key']
            hex_privkey = bip38_decrypt(str(encrypted_privkey), WALLET_SECRET)

            if nameRegistered(fqu):

                if profilePublished(fqu, data_value):
                    log.debug("Profile match, removing: %s" % fqu)
                    self.updates.remove({"user_id": new_user['user_id']})

                    refresh_resolver(user['username'])
                else:
                    log.debug("Processing: %s, %s" % (fqu, user['email']))
                    try:
                        self.registrar_server.process_subsidized_nameop(fqu,
                                                                owner_privkey=hex_privkey,
                                                                profile=data_value,
                                                                nameop='update')
                    except Exception as e:
                        log.debug(e)
            else:

                log.debug("Not registered: %s" % fqu)
    def transfer_users(self, spam_protection=False, reprocess_username=None):
        """
            Process new transfer from the webapp
        """

        counter = 0
        self.registrar_server.reset_flag()

        for new_user in self.exports.find(no_cursor_timeout=True):

            user = get_db_user_from_id(new_user, self.users)

            if user is None:
                continue

            # add spam protection here

            # mode for reprocessing a single user, ignore others
            if reprocess_username is not None:
                if user['username'] != reprocess_username:
                    continue

            fqu = user['username'] + "." + DEFAULT_NAMESPACE

            transfer_address = new_user['recipient_address']

            try:
                encrypted_privkey = new_user['encrypted_private_key']
                hex_privkey = bip38_decrypt(str(encrypted_privkey), WALLET_SECRET)
            except:
                log.debug("no private key")
                #self.exports.remove({"user_id": new_user['user_id']})
            else:
                log.debug("To export: %s to %s" % (fqu, transfer_address))

            if nameRegistered(fqu):

                if ownerName(fqu, transfer_address):
                    log.debug("Name transferred, removing: %s" % fqu)
                    self.exports.remove({"user_id": new_user['user_id']})

                    refresh_resolver(user['username'])
                else:
                    log.debug("Processing: %s, %s" % (fqu, user['email']))
                    #try:
                    self.registrar_server.process_subsidized_nameop(fqu,
                                                                owner_privkey=hex_privkey,
                                                                transfer_address=transfer_address,
                                                                nameop='transfer', profile="")
                    #except Exception as e:
                    #    log.debug(e)
            else:

                log.debug("Not registered: %s" % fqu)
示例#7
0
    def display_current_states(self):
        """
            Display current states of all pending registrations
        """

        counter_register = 0
        counter_update = 0
        counter_dht = 0
        counter_transfer = 0

        for new_user in self.registrations.find(no_cursor_timeout=True):

            user = get_db_user_from_id(new_user, self.users)

            if not self.validUser(user, new_user):
                continue

            fqu = user['username'] + "." + DEFAULT_NAMESPACE
            transfer_address = nmc_to_btc_address(user['namecoin_address'])
            profile = user['profile']

            if not nameRegistered(fqu):
                counter_register += 1

            elif not profileonBlockchain(fqu, profile):
                counter_update += 1

            elif not profileonDHT(fqu, profile):
                counter_dht += 1

            elif not ownerName(fqu, transfer_address):
                counter_transfer += 1

        log.debug("Pending registrations: %s" % counter_register)
        log.debug("Pending updates: %s" % counter_update)
        log.debug("Pending DHT writes: %s" % counter_dht)
        log.debug("Pending transfers: %s" % counter_transfer)
示例#8
0
    def display_current_states(self):
        """
            Display current states of all pending registrations
        """

        counter_register = 0
        counter_update = 0
        counter_dht = 0
        counter_transfer = 0

        for new_user in self.registrations.find(no_cursor_timeout=True):

            user = get_db_user_from_id(new_user, self.users)

            if not self.validUser(user, new_user):
                continue

            fqu = user['username'] + "." + DEFAULT_NAMESPACE
            transfer_address = nmc_to_btc_address(user['namecoin_address'])
            profile = user['profile']

            if not nameRegistered(fqu):
                counter_register += 1

            elif not profileonBlockchain(fqu, profile):
                counter_update += 1

            elif not profileonDHT(fqu, profile):
                counter_dht += 1

            elif not ownerName(fqu, transfer_address):
                counter_transfer += 1

        log.debug("Pending registrations: %s" % counter_register)
        log.debug("Pending updates: %s" % counter_update)
        log.debug("Pending DHT writes: %s" % counter_dht)
        log.debug("Pending transfers: %s" % counter_transfer)
示例#9
0
def tests_for_update_and_transfer(fqu, transfer_address=None):
    """ Any update or transfer operation
        should pass these tests
    """

    if not nameRegistered(fqu):
        exit_with_error("%s is not registered yet." % fqu)

    payment_address, owner_address = get_addresses_from_file()

    if not ownerName(fqu, owner_address):
        exit_with_error("%s is not in your possession." % fqu)

    tx_fee_satoshi = approx_tx_fees(num_tx=1)
    tx_fee = satoshis_to_btc(tx_fee_satoshi)

    if not hasEnoughBalance(payment_address, tx_fee):
        msg = "Address %s doesn't have enough balance." % payment_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)

    if transfer_address is not None:

        try:
            resp = is_b58check_address(str(transfer_address))
        except:
            msg = "Address %s is not a valid Bitcoin address." % transfer_address
            exit_with_error(msg)

        if recipientNotReady(transfer_address):
            msg = "Address %s owns too many names already." % transfer_address
            exit_with_error(msg)
示例#10
0
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)