def __init__(self, config): super(CounterpartydAPI, self).__init__() clientapi.initialize( testnet=config.TESTNET, testcoin=False, counterparty_rpc_connect=config.COUNTERPARTY_RPC_CONNECT, counterparty_rpc_port=config.COUNTERPARTY_RPC_PORT, counterparty_rpc_user=config.COUNTERPARTY_RPC_USER, counterparty_rpc_password=config.COUNTERPARTY_RPC_PASSWORD, counterparty_rpc_ssl=config.COUNTERPARTY_RPC_SSL, counterparty_rpc_ssl_verify=config.COUNTERPARTY_RPC_SSL_VERIFY, wallet_name=config.WALLET_NAME, wallet_connect=config.WALLET_CONNECT, wallet_port=config.WALLET_PORT, wallet_user=config.WALLET_USER, wallet_password=config.WALLET_PASSWORD, wallet_ssl=config.WALLET_SSL, wallet_ssl_verify=config.WALLET_SSL_VERIFY, requests_timeout=config.REQUESTS_TIMEOUT) log.set_up(logger, verbose=config.VERBOSE, logfile=config.LOG_FILE)
def initialise_config( database_file=None, log_file=None, api_log_file=None, testnet=False, testcoin=False, backend_name=None, backend_connect=None, backend_port=None, backend_user=None, backend_password=None, backend_ssl=False, backend_ssl_no_verify=False, backend_poll_interval=None, rpc_host=None, rpc_port=None, rpc_user=None, rpc_password=None, rpc_no_allow_cors=False, force=False, verbose=False, console_logfilter=None, requests_timeout=config.DEFAULT_REQUESTS_TIMEOUT, rpc_batch_size=config.DEFAULT_RPC_BATCH_SIZE, check_asset_conservation=config.DEFAULT_CHECK_ASSET_CONSERVATION, backend_ssl_verify=None, rpc_allow_cors=None, p2sh_dust_return_pubkey=None, utxo_locks_max_addresses=config.DEFAULT_UTXO_LOCKS_MAX_ADDRESSES, utxo_locks_max_age=config.DEFAULT_UTXO_LOCKS_MAX_AGE, estimate_fee_per_kb=None): # Data directory data_dir = appdirs.user_data_dir(appauthor=config.XCP_NAME, appname=config.APP_NAME, roaming=True) if not os.path.isdir(data_dir): os.makedirs(data_dir, mode=0o755) # testnet if testnet: config.TESTNET = testnet else: config.TESTNET = False # testcoin if testcoin: config.TESTCOIN = testcoin else: config.TESTCOIN = False network = '' if config.TESTNET: network += '.testnet' if config.TESTCOIN: network += '.testcoin' # Database if database_file: config.DATABASE = database_file else: filename = '{}{}.db'.format(config.APP_NAME, network) config.DATABASE = os.path.join(data_dir, filename) # Log directory log_dir = appdirs.user_log_dir(appauthor=config.XCP_NAME, appname=config.APP_NAME) if not os.path.isdir(log_dir): os.makedirs(log_dir, mode=0o755) # Log if log_file is False: # no file logging config.LOG = None elif not log_file: # default location filename = 'server{}.log'.format(network) config.LOG = os.path.join(log_dir, filename) else: # user-specified location config.LOG = log_file # Set up logging. log.set_up(log.ROOT_LOGGER, verbose=verbose, logfile=config.LOG, console_logfilter=console_logfilter) if config.LOG: logger.debug('Writing server log to file: `{}`'.format(config.LOG)) if api_log_file is False: # no file logging config.API_LOG = None elif not api_log_file: # default location filename = 'server{}.access.log'.format(network) config.API_LOG = os.path.join(log_dir, filename) else: # user-specified location config.API_LOG = api_log_file if config.API_LOG: logger.debug('Writing API accesses log to file: `{}`'.format( config.API_LOG)) # Log unhandled errors. def handle_exception(exc_type, exc_value, exc_traceback): logger.error("Unhandled Exception", exc_info=(exc_type, exc_value, exc_traceback)) sys.excepthook = handle_exception ############## # THINGS WE CONNECT TO # Backend name if backend_name: config.BACKEND_NAME = backend_name else: config.BACKEND_NAME = 'addrindex' if config.BACKEND_NAME == 'jmcorgan': config.BACKEND_NAME = 'addrindex' # Backend RPC host (Bitcoin Core) if backend_connect: config.BACKEND_CONNECT = backend_connect else: config.BACKEND_CONNECT = 'localhost' # Backend Core RPC port (Bitcoin Core) if backend_port: config.BACKEND_PORT = backend_port else: if config.TESTNET: if config.BACKEND_NAME == 'btcd': config.BACKEND_PORT = config.DEFAULT_BACKEND_PORT_TESTNET_BTCD else: config.BACKEND_PORT = config.DEFAULT_BACKEND_PORT_TESTNET else: if config.BACKEND_NAME == 'btcd': config.BACKEND_PORT = config.DEFAULT_BACKEND_PORT_BTCD else: config.BACKEND_PORT = config.DEFAULT_BACKEND_PORT try: config.BACKEND_PORT = int(config.BACKEND_PORT) if not (int(config.BACKEND_PORT) > 1 and int(config.BACKEND_PORT) < 65535): raise ConfigurationError('invalid backend API port number') except: raise ConfigurationError( "Please specific a valid port number backend-port configuration parameter" ) # Backend Core RPC user (Bitcoin Core) if backend_user: config.BACKEND_USER = backend_user else: config.BACKEND_USER = '******' # Backend Core RPC password (Bitcoin Core) if backend_password: config.BACKEND_PASSWORD = backend_password else: raise ConfigurationError( 'backend RPC password not set. (Use configuration file or --backend-password=PASSWORD)' ) # Backend Core RPC SSL if backend_ssl: config.BACKEND_SSL = backend_ssl else: config.BACKEND_SSL = False # Default to off. # Backend Core RPC SSL Verify if backend_ssl_verify is not None: logger.warning( 'The server parameter `backend_ssl_verify` is deprecated. Use `backend_ssl_no_verify` instead.' ) config.BACKEND_SSL_NO_VERIFY = not backend_ssl_verify else: if backend_ssl_no_verify: config.BACKEND_SSL_NO_VERIFY = backend_ssl_no_verify else: config.BACKEND_SSL_NO_VERIFY = False # Default to on (don't support self‐signed certificates) # Backend Poll Interval if backend_poll_interval: config.BACKEND_POLL_INTERVAL = backend_poll_interval else: config.BACKEND_POLL_INTERVAL = 0.5 # Construct backend URL. config.BACKEND_URL = config.BACKEND_USER + ':' + config.BACKEND_PASSWORD + '@' + config.BACKEND_CONNECT + ':' + str( config.BACKEND_PORT) if config.BACKEND_SSL: config.BACKEND_URL = 'https://' + config.BACKEND_URL else: config.BACKEND_URL = 'http://' + config.BACKEND_URL ############## # THINGS WE SERVE # Server API RPC host if rpc_host: config.RPC_HOST = rpc_host else: config.RPC_HOST = 'localhost' # The web root directory for API calls, eg. localhost:14000/rpc/ config.RPC_WEBROOT = '/rpc/' # Server API RPC port if rpc_port: config.RPC_PORT = rpc_port else: if config.TESTNET: if config.TESTCOIN: config.RPC_PORT = config.DEFAULT_RPC_PORT_TESTNET + 1 else: config.RPC_PORT = config.DEFAULT_RPC_PORT_TESTNET else: if config.TESTCOIN: config.RPC_PORT = config.DEFAULT_RPC_PORT + 1 else: config.RPC_PORT = config.DEFAULT_RPC_PORT try: config.RPC_PORT = int(config.RPC_PORT) if not (int(config.RPC_PORT) > 1 and int(config.RPC_PORT) < 65535): raise ConfigurationError('invalid server API port number') except: raise ConfigurationError( "Please specific a valid port number rpc-port configuration parameter" ) # Server API RPC user if rpc_user: config.RPC_USER = rpc_user else: config.RPC_USER = '******' # Server API RPC password if rpc_password: config.RPC_PASSWORD = rpc_password config.RPC = 'http://' + urlencode(config.RPC_USER) + ':' + urlencode( config.RPC_PASSWORD) + '@' + config.RPC_HOST + ':' + str( config.RPC_PORT) + config.RPC_WEBROOT else: config.RPC = 'http://' + config.RPC_HOST + ':' + str( config.RPC_PORT) + config.RPC_WEBROOT # RPC CORS if rpc_allow_cors is not None: logger.warning( 'The server parameter `rpc_allow_cors` is deprecated. Use `rpc_no_allow_cors` instead.' ) config.RPC_NO_ALLOW_CORS = not rpc_allow_cors else: if rpc_no_allow_cors: config.RPC_NO_ALLOW_CORS = rpc_no_allow_cors else: config.RPC_NO_ALLOW_CORS = False config.RPC_BATCH_SIZE = rpc_batch_size ############## # OTHER SETTINGS # skip checks if force: config.FORCE = force else: config.FORCE = False # Encoding if config.TESTCOIN: config.PREFIX = b'XX' # 2 bytes (possibly accidentally created) else: config.PREFIX = b'CNTRPRTY' # 8 bytes # (more) Testnet if config.TESTNET: config.MAGIC_BYTES = config.MAGIC_BYTES_TESTNET if config.TESTCOIN: config.ADDRESSVERSION = config.ADDRESSVERSION_TESTNET config.P2SH_ADDRESSVERSION = config.P2SH_ADDRESSVERSION_TESTNET config.BLOCK_FIRST = config.BLOCK_FIRST_TESTNET_TESTCOIN config.BURN_START = config.BURN_START_TESTNET_TESTCOIN config.BURN_END = config.BURN_END_TESTNET_TESTCOIN config.UNSPENDABLE = config.UNSPENDABLE_TESTNET config.P2SH_DUST_RETURN_PUBKEY = p2sh_dust_return_pubkey else: config.ADDRESSVERSION = config.ADDRESSVERSION_TESTNET config.P2SH_ADDRESSVERSION = config.P2SH_ADDRESSVERSION_TESTNET config.BLOCK_FIRST = config.BLOCK_FIRST_TESTNET config.BURN_START = config.BURN_START_TESTNET config.BURN_END = config.BURN_END_TESTNET config.UNSPENDABLE = config.UNSPENDABLE_TESTNET config.P2SH_DUST_RETURN_PUBKEY = p2sh_dust_return_pubkey else: config.MAGIC_BYTES = config.MAGIC_BYTES_MAINNET if config.TESTCOIN: config.ADDRESSVERSION = config.ADDRESSVERSION_MAINNET config.P2SH_ADDRESSVERSION = config.P2SH_ADDRESSVERSION_MAINNET config.BLOCK_FIRST = config.BLOCK_FIRST_MAINNET_TESTCOIN config.BURN_START = config.BURN_START_MAINNET_TESTCOIN config.BURN_END = config.BURN_END_MAINNET_TESTCOIN config.UNSPENDABLE = config.UNSPENDABLE_MAINNET config.P2SH_DUST_RETURN_PUBKEY = p2sh_dust_return_pubkey else: config.ADDRESSVERSION = config.ADDRESSVERSION_MAINNET config.P2SH_ADDRESSVERSION = config.P2SH_ADDRESSVERSION_MAINNET config.BLOCK_FIRST = config.BLOCK_FIRST_MAINNET config.BURN_START = config.BURN_START_MAINNET config.BURN_END = config.BURN_END_MAINNET config.UNSPENDABLE = config.UNSPENDABLE_MAINNET config.P2SH_DUST_RETURN_PUBKEY = p2sh_dust_return_pubkey # Misc config.REQUESTS_TIMEOUT = requests_timeout config.CHECK_ASSET_CONSERVATION = check_asset_conservation config.UTXO_LOCKS_MAX_ADDRESSES = utxo_locks_max_addresses config.UTXO_LOCKS_MAX_AGE = utxo_locks_max_age transaction.UTXO_LOCKS = None # reset the UTXO_LOCKS (for tests really) if estimate_fee_per_kb is not None: config.ESTIMATE_FEE_PER_KB = estimate_fee_per_kb logger.info('Running v{} of counterparty-lib.'.format( config.VERSION_STRING))
def main(): if os.name == 'nt': from counterpartylib.lib import util_windows #patch up cmd.exe's "challenged" (i.e. broken/non-existent) UTF-8 logging util_windows.fix_win32_unicode() # Post installation tasks generate_config_files() # Parse command-line arguments. parser = argparse.ArgumentParser( prog=APP_NAME, description='Counterparty CLI for counterparty-server', add_help=False) parser.add_argument('-h', '--help', dest='help', action='store_true', help='show this help message and exit') parser.add_argument('-V', '--version', action='version', version="{} v{}; {} v{}".format( APP_NAME, APP_VERSION, 'counterparty-lib', config.VERSION_STRING)) parser.add_argument('--config-file', help='the location of the configuration file') parser = add_config_arguments(parser, CONFIG_ARGS, 'client.conf') subparsers = parser.add_subparsers(dest='action', help='the action to be taken') parser_send = subparsers.add_parser( 'send', help='create and broadcast a *send* message') parser_send.add_argument('--source', required=True, help='the source address') parser_send.add_argument('--destination', required=True, help='the destination address') parser_send.add_argument('--quantity', required=True, help='the quantity of ASSET to send') parser_send.add_argument( '--asset', required=True, help='the ASSET of which you would like to send QUANTITY') parser_send.add_argument( '--fee', help='the exact {} fee to be paid to miners'.format(config.BTC)) parser_order = subparsers.add_parser( 'order', help='create and broadcast an *order* message') parser_order.add_argument('--source', required=True, help='the source address') parser_order.add_argument( '--get-quantity', required=True, help='the quantity of GET_ASSET that you would like to receive') parser_order.add_argument('--get-asset', required=True, help='the asset that you would like to buy') parser_order.add_argument( '--give-quantity', required=True, help='the quantity of GIVE_ASSET that you are willing to give') parser_order.add_argument('--give-asset', required=True, help='the asset that you would like to sell') parser_order.add_argument( '--expiration', type=int, required=True, help='the number of blocks for which the order should be valid') parser_order.add_argument( '--fee-fraction-required', default=config.DEFAULT_FEE_FRACTION_REQUIRED, help= 'the miners’ fee required for an order to match this one, as a fraction of the {} to be bought' .format(config.BTC)) parser_order_fees = parser_order.add_mutually_exclusive_group() parser_order_fees.add_argument( '--fee-fraction-provided', default=config.DEFAULT_FEE_FRACTION_PROVIDED, help='the miners’ fee provided, as a fraction of the {} to be sold'. format(config.BTC)) parser_order_fees.add_argument( '--fee', help='the exact {} fee to be paid to miners'.format(config.BTC)) parser_btcpay = subparsers.add_parser( '{}pay'.format(config.BTC).lower(), help= 'create and broadcast a *{}pay* message, to settle an Order Match for which you owe {}' .format(config.BTC, config.BTC)) parser_btcpay.add_argument('--source', required=True, help='the source address') parser_btcpay.add_argument( '--order-match-id', required=True, help= 'the concatenation of the hashes of the two transactions which compose the order match' ) parser_btcpay.add_argument( '--fee', help='the exact {} fee to be paid to miners'.format(config.BTC)) parser_issuance = subparsers.add_parser( 'issuance', help= 'issue a new asset, issue more of an existing asset or transfer the ownership of an asset' ) parser_issuance.add_argument('--source', required=True, help='the source address') parser_issuance.add_argument( '--transfer-destination', help='for transfer of ownership of asset issuance rights') parser_issuance.add_argument('--quantity', default=0, help='the quantity of ASSET to be issued') parser_issuance.add_argument( '--asset', required=True, help='the name of the asset to be issued (if it’s available)') parser_issuance.add_argument( '--divisible', action='store_true', help= 'whether or not the asset is divisible (must agree with previous issuances)' ) parser_issuance.add_argument( '--description', type=str, required=True, help= 'a description of the asset (set to ‘LOCK’ to lock against further issuances with non‐zero quantitys)' ) parser_issuance.add_argument( '--fee', help='the exact {} fee to be paid to miners'.format(config.BTC)) parser_broadcast = subparsers.add_parser( 'broadcast', help='broadcast textual and numerical information to the network') parser_broadcast.add_argument('--source', required=True, help='the source address') parser_broadcast.add_argument( '--text', type=str, required=True, help='the textual part of the broadcast (set to ‘LOCK’ to lock feed)') parser_broadcast.add_argument('--value', type=float, default=-1, help='numerical value of the broadcast') parser_broadcast.add_argument( '--fee-fraction', default=0, help='the fraction of bets on this feed that go to its operator') parser_broadcast.add_argument( '--fee', help='the exact {} fee to be paid to miners'.format(config.BTC)) parser_bet = subparsers.add_parser( 'bet', help='offer to make a bet on the value of a feed') parser_bet.add_argument('--source', required=True, help='the source address') parser_bet.add_argument( '--feed-address', required=True, help='the address which publishes the feed to bet on') parser_bet.add_argument('--bet-type', choices=list(BET_TYPE_NAME.values()), required=True, help='choices: {}'.format( list(BET_TYPE_NAME.values()))) parser_bet.add_argument( '--deadline', required=True, help='the date and time at which the bet should be decided/settled') parser_bet.add_argument('--wager', required=True, help='the quantity of XCP to wager') parser_bet.add_argument( '--counterwager', required=True, help= 'the minimum quantity of XCP to be wagered by the user to bet against you, if he were to accept the whole thing' ) parser_bet.add_argument('--target-value', default=0.0, help='target value for Equal/NotEqual bet') parser_bet.add_argument('--leverage', type=int, default=5040, help='leverage, as a fraction of 5040') parser_bet.add_argument( '--expiration', type=int, required=True, help='the number of blocks for which the bet should be valid') parser_bet.add_argument( '--fee', help='the exact {} fee to be paid to miners'.format(config.BTC)) parser_dividend = subparsers.add_parser( 'dividend', help= 'pay dividends to the holders of an asset (in proportion to their stake in it)' ) parser_dividend.add_argument('--source', required=True, help='the source address') parser_dividend.add_argument( '--quantity-per-unit', required=True, help='the quantity of XCP to be paid per whole unit held of ASSET') parser_dividend.add_argument('--asset', required=True, help='the asset to which pay dividends') parser_dividend.add_argument('--dividend-asset', required=True, help='asset in which to pay the dividends') parser_dividend.add_argument( '--fee', help='the exact {} fee to be paid to miners'.format(config.BTC)) parser_burn = subparsers.add_parser( 'burn', help='destroy {} to earn XCP, during an initial period of time') parser_burn.add_argument('--source', required=True, help='the source address') parser_burn.add_argument('--quantity', required=True, help='quantity of {} to be burned'.format( config.BTC)) parser_burn.add_argument( '--fee', help='the exact {} fee to be paid to miners'.format(config.BTC)) parser_cancel = subparsers.add_parser( 'cancel', help='cancel an open order or bet you created') parser_cancel.add_argument('--source', required=True, help='the source address') parser_cancel.add_argument('--offer-hash', required=True, help='the transaction hash of the order or bet') parser_cancel.add_argument( '--fee', help='the exact {} fee to be paid to miners'.format(config.BTC)) parser_rps = subparsers.add_parser( 'rps', help='open a rock-paper-scissors like game') parser_rps.add_argument('--source', required=True, help='the source address') parser_rps.add_argument('--wager', required=True, help='the quantity of XCP to wager') parser_rps.add_argument('--move', type=int, required=True, help='the selected move') parser_rps.add_argument( '--possible-moves', type=int, required=True, help='the number of possible moves (odd number greater or equal than 3)' ) parser_rps.add_argument( '--expiration', type=int, required=True, help='the number of blocks for which the bet should be valid') parser_rps.add_argument('--fee', help='the exact BTC fee to be paid to miners') parser_rpsresolve = subparsers.add_parser( 'rpsresolve', help='resolve a rock-paper-scissors like game') parser_rpsresolve.add_argument('--source', required=True, help='the source address') parser_rpsresolve.add_argument( '--random', type=str, required=True, help='the random number used in the corresponding rps transaction') parser_rpsresolve.add_argument( '--move', type=int, required=True, help='the selected move in the corresponding rps transaction') parser_rpsresolve.add_argument( '--rps-match-id', required=True, help= 'the concatenation of the hashes of the two transactions which compose the rps match' ) parser_rpsresolve.add_argument( '--fee', help='the exact BTC fee to be paid to miners') parser_publish = subparsers.add_parser( 'publish', help='publish contract code in the blockchain') parser_publish.add_argument('--source', required=True, help='the source address') parser_publish.add_argument('--gasprice', required=True, type=int, help='the price of gas') parser_publish.add_argument( '--startgas', required=True, type=int, help= 'the maximum quantity of {} to be used to pay for the execution (satoshis)' .format(config.XCP)) parser_publish.add_argument( '--endowment', required=True, type=int, help='quantity of {} to be transfered to the contract (satoshis)'. format(config.XCP)) parser_publish.add_argument( '--code-hex', required=True, type=str, help='the hex‐encoded contract (returned by `serpent compile`)') parser_publish.add_argument( '--fee', help='the exact {} fee to be paid to miners'.format(config.BTC)) parser_execute = subparsers.add_parser( 'execute', help='execute contract code in the blockchain') parser_execute.add_argument('--source', required=True, help='the source address') parser_execute.add_argument( '--contract-id', required=True, help='the contract ID of the contract to be executed') parser_execute.add_argument('--gasprice', required=True, type=int, help='the price of gas') parser_execute.add_argument( '--startgas', required=True, type=int, help= 'the maximum quantity of {} to be used to pay for the execution (satoshis)' .format(config.XCP)) parser_execute.add_argument( '--value', required=True, type=int, help='quantity of {} to be transfered to the contract (satoshis)'. format(config.XCP)) parser_execute.add_argument( '--payload-hex', required=True, type=str, help= 'data to be provided to the contract (returned by `serpent encode_datalist`)' ) parser_execute.add_argument( '--fee', help='the exact {} fee to be paid to miners'.format(config.BTC)) parser_destroy = subparsers.add_parser( 'destroy', help='destroy a quantity of a Counterparty asset') parser_destroy.add_argument('--source', required=True, help='the source address') parser_destroy.add_argument( '--asset', required=True, help='the ASSET of which you would like to destroy QUANTITY') parser_destroy.add_argument('--quantity', required=True, help='the quantity of ASSET to destroy') parser_destroy.add_argument('--tag', default='', help='tag') parser_destroy.add_argument( '--fee', help='the exact {} fee to be paid to miners'.format(config.BTC)) parser_address = subparsers.add_parser( 'balances', help='display the balances of a {} address'.format(config.XCP_NAME)) parser_address.add_argument('address', help='the address you are interested in') parser_asset = subparsers.add_parser( 'asset', help='display the basic properties of a {} asset'.format( config.XCP_NAME)) parser_asset.add_argument('asset', help='the asset you are interested in') parser_wallet = subparsers.add_parser( 'wallet', help= 'list the addresses in your backend wallet along with their balances in all {} assets' .format(config.XCP_NAME)) parser_pending = subparsers.add_parser( 'pending', help='list pending order matches awaiting {}payment from you'.format( config.BTC)) parser_getrows = subparsers.add_parser( 'getrows', help='get rows from a Counterparty table') parser_getrows.add_argument('--table', required=True, help='table name') parser_getrows.add_argument('--filter', nargs=3, action='append', help='filters to get specific rows') parser_getrows.add_argument('--filter-op', choices=['AND', 'OR'], help='operator uses to combine filters', default='AND') parser_getrows.add_argument('--order-by', help='field used to order results') parser_getrows.add_argument('--order-dir', choices=['ASC', 'DESC'], help='direction used to order results') parser_getrows.add_argument( '--start-block', help='return only rows with block_index greater than start-block') parser_getrows.add_argument( '--end-block', help='return only rows with block_index lower than end-block') parser_getrows.add_argument( '--status', help='return only rows with the specified status') parser_getrows.add_argument('--limit', help='number of rows to return', default=100) parser_getrows.add_argument('--offset', help='number of rows to skip', default=0) parser_getrunninginfo = subparsers.add_parser( 'getinfo', help='get the current state of the server') args = parser.parse_args() # Logging log.set_up(logger, verbose=args.verbose) logger.propagate = False logger.info('Running v{} of {}.'.format(APP_VERSION, APP_NAME)) # Help message if args.help: parser.print_help() sys.exit() # Configuration clientapi.initialize( testnet=args.testnet, testcoin=args.testcoin, counterparty_rpc_connect=args.counterparty_rpc_connect, counterparty_rpc_port=args.counterparty_rpc_port, counterparty_rpc_user=args.counterparty_rpc_user, counterparty_rpc_password=args.counterparty_rpc_password, counterparty_rpc_ssl=args.counterparty_rpc_ssl, counterparty_rpc_ssl_verify=args.counterparty_rpc_ssl_verify, wallet_name=args.wallet_name, wallet_connect=args.wallet_connect, wallet_port=args.wallet_port, wallet_user=args.wallet_user, wallet_password=args.wallet_password, wallet_ssl=args.wallet_ssl, wallet_ssl_verify=args.wallet_ssl_verify, requests_timeout=args.requests_timeout) # MESSAGE CREATION if args.action in list(messages.MESSAGE_PARAMS.keys()): unsigned_hex = messages.compose(args.action, args) logger.info('Transaction (unsigned): {}'.format(unsigned_hex)) if not args.unsigned: if script.is_multisig(args.source): logger.info( 'Multi‐signature transactions are signed and broadcasted manually.' ) elif input('Sign and broadcast? (y/N) ') == 'y': if wallet.is_mine(args.source): if wallet.is_locked(): passphrase = getpass.getpass( 'Enter your wallet passhrase: ') logger.info('Unlocking wallet for 60 (more) seconds.') wallet.unlock(passphrase) signed_tx_hex = wallet.sign_raw_transaction(unsigned_hex) else: private_key_wif = input( 'Source address not in wallet. Please enter the private key in WIF format for {}:' .format(args.source)) if not private_key_wif: raise TransactionError('invalid private key') signed_tx_hex = wallet.sign_raw_transaction( unsigned_hex, private_key_wif=private_key_wif) logger.info('Transaction (signed): {}'.format(signed_tx_hex)) tx_hash = wallet.send_raw_transaction(signed_tx_hex) logger.info( 'Hash of transaction (broadcasted): {}'.format(tx_hash)) # VIEWING elif args.action in [ 'balances', 'asset', 'wallet', 'pending', 'getinfo', 'getrows' ]: view = console.get_view(args.action, args) print_method = getattr(console, 'print_{}'.format(args.action), None) if args.json_output or print_method is None: util.json_print(view) else: print_method(view) else: parser.print_help()
def main(): if os.name == 'nt': from counterpartylib.lib import util_windows #patch up cmd.exe's "challenged" (i.e. broken/non-existent) UTF-8 logging util_windows.fix_win32_unicode() # Post installation tasks generate_config_files() # Parse command-line arguments. parser = argparse.ArgumentParser(prog=APP_NAME, description='Server for the {} protocol'.format(config.XCP_NAME), add_help=False) parser.add_argument('-h', '--help', dest='help', action='store_true', help='show this help message and exit') parser.add_argument('-V', '--version', action='version', version="{} v{}; {} v{}".format(APP_NAME, APP_VERSION, 'counterparty-lib', config.VERSION_STRING)) parser.add_argument('--config-file', help='the path to the configuration file') parser = add_config_arguments(parser, CONFIG_ARGS, 'server.conf') subparsers = parser.add_subparsers(dest='action', help='the action to be taken') parser_server = subparsers.add_parser('start', help='run the server') parser_reparse = subparsers.add_parser('reparse', help='reparse all transactions in the database') parser_rollback = subparsers.add_parser('rollback', help='rollback database') parser_rollback.add_argument('block_index', type=int, help='the index of the last known good block') parser_kickstart = subparsers.add_parser('kickstart', help='rapidly build database by reading from Bitcoin Core blockchain') parser_kickstart.add_argument('--bitcoind-dir', help='Bitcoin Core data directory') parser_bootstrap = subparsers.add_parser('bootstrap', help='bootstrap database with hosted snapshot') args = parser.parse_args() log.set_up(logger, verbose=args.verbose) logger.info('Running v{} of {}.'.format(APP_VERSION, APP_NAME)) # Help message if args.help: parser.print_help() sys.exit() # Bootstrapping if args.action == 'bootstrap': bootstrap(testnet=args.testnet) sys.exit() # Configuration if args.action in ['reparse', 'rollback', 'kickstart', 'start']: try: db = server.initialise(database_file=args.database_file, log_file=args.log_file, api_log_file=args.api_log_file, testnet=args.testnet, testcoin=args.testcoin, backend_name=args.backend_name, backend_connect=args.backend_connect, backend_port=args.backend_port, backend_user=args.backend_user, backend_password=args.backend_password, backend_ssl=args.backend_ssl, backend_ssl_no_verify=args.backend_ssl_no_verify, backend_poll_interval=args.backend_poll_interval, rpc_host=args.rpc_host, rpc_port=args.rpc_port, rpc_user=args.rpc_user, rpc_password=args.rpc_password, rpc_no_allow_cors=args.rpc_no_allow_cors, requests_timeout=args.requests_timeout, rpc_batch_size=args.rpc_batch_size, check_asset_conservation=not args.no_check_asset_conservation, force=args.force, verbose=args.verbose) #,broadcast_tx_mainnet=args.broadcast_tx_mainnet) except TypeError as e: if 'unexpected keyword argument' in str(e): raise VersionError('Unsupported Server Parameter. CLI/Library Version Incompatibility.') else: raise e # PARSING if args.action == 'reparse': server.reparse(db) elif args.action == 'rollback': server.reparse(db, block_index=args.block_index) elif args.action == 'kickstart': server.kickstart(db, bitcoind_dir=args.bitcoind_dir) elif args.action == 'start': server.start_all(db) else: parser.print_help()
def main(): if os.name == 'nt': from counterpartylib.lib import util_windows #patch up cmd.exe's "challenged" (i.e. broken/non-existent) UTF-8 logging util_windows.fix_win32_unicode() # Post installation tasks generate_config_files() # Parse command-line arguments. parser = argparse.ArgumentParser(prog=APP_NAME, description='Counterparty CLI for counterparty-server', add_help=False) parser.add_argument('-h', '--help', dest='help', action='store_true', help='show this help message and exit') parser.add_argument('-V', '--version', action='version', version="{} v{}; {} v{}".format(APP_NAME, APP_VERSION, 'counterparty-lib', config.VERSION_STRING)) parser.add_argument('--config-file', help='the location of the configuration file') parser = add_config_arguments(parser, CONFIG_ARGS, 'client.conf') subparsers = parser.add_subparsers(dest='action', help='the action to be taken') parser_send = subparsers.add_parser('send', help='create and broadcast a *send* message') parser_send.add_argument('--source', required=True, help='the source address') parser_send.add_argument('--destination', required=True, help='the destination address') parser_send.add_argument('--quantity', required=True, help='the quantity of ASSET to send') parser_send.add_argument('--asset', required=True, help='the ASSET of which you would like to send QUANTITY') parser_send.add_argument('--fee', help='the exact {} fee to be paid to miners'.format(config.BTC)) parser_order = subparsers.add_parser('order', help='create and broadcast an *order* message') parser_order.add_argument('--source', required=True, help='the source address') parser_order.add_argument('--get-quantity', required=True, help='the quantity of GET_ASSET that you would like to receive') parser_order.add_argument('--get-asset', required=True, help='the asset that you would like to buy') parser_order.add_argument('--give-quantity', required=True, help='the quantity of GIVE_ASSET that you are willing to give') parser_order.add_argument('--give-asset', required=True, help='the asset that you would like to sell') parser_order.add_argument('--expiration', type=int, required=True, help='the number of blocks for which the order should be valid') parser_order.add_argument('--fee-fraction-required', default=config.DEFAULT_FEE_FRACTION_REQUIRED, help='the miners’ fee required for an order to match this one, as a fraction of the {} to be bought'.format(config.BTC)) parser_order_fees = parser_order.add_mutually_exclusive_group() parser_order_fees.add_argument('--fee-fraction-provided', default=config.DEFAULT_FEE_FRACTION_PROVIDED, help='the miners’ fee provided, as a fraction of the {} to be sold'.format(config.BTC)) parser_order_fees.add_argument('--fee', help='the exact {} fee to be paid to miners'.format(config.BTC)) parser_btcpay = subparsers.add_parser('{}pay'.format(config.BTC).lower(), help='create and broadcast a *{}pay* message, to settle an Order Match for which you owe {}'.format(config.BTC, config.BTC)) parser_btcpay.add_argument('--source', required=True, help='the source address') parser_btcpay.add_argument('--order-match-id', required=True, help='the concatenation of the hashes of the two transactions which compose the order match') parser_btcpay.add_argument('--fee', help='the exact {} fee to be paid to miners'.format(config.BTC)) parser_issuance = subparsers.add_parser('issuance', help='issue a new asset, issue more of an existing asset or transfer the ownership of an asset') parser_issuance.add_argument('--source', required=True, help='the source address') parser_issuance.add_argument('--transfer-destination', help='for transfer of ownership of asset issuance rights') parser_issuance.add_argument('--quantity', default=0, help='the quantity of ASSET to be issued') parser_issuance.add_argument('--asset', required=True, help='the name of the asset to be issued (if it’s available)') parser_issuance.add_argument('--divisible', action='store_true', help='whether or not the asset is divisible (must agree with previous issuances)') parser_issuance.add_argument('--description', type=str, required=True, help='a description of the asset (set to ‘LOCK’ to lock against further issuances with non‐zero quantitys)') parser_issuance.add_argument('--fee', help='the exact {} fee to be paid to miners'.format(config.BTC)) parser_broadcast = subparsers.add_parser('broadcast', help='broadcast textual and numerical information to the network') parser_broadcast.add_argument('--source', required=True, help='the source address') parser_broadcast.add_argument('--text', type=str, required=True, help='the textual part of the broadcast (set to ‘LOCK’ to lock feed)') parser_broadcast.add_argument('--value', type=float, default=-1, help='numerical value of the broadcast') parser_broadcast.add_argument('--fee-fraction', default=0, help='the fraction of bets on this feed that go to its operator') parser_broadcast.add_argument('--fee', help='the exact {} fee to be paid to miners'.format(config.BTC)) parser_bet = subparsers.add_parser('bet', help='offer to make a bet on the value of a feed') parser_bet.add_argument('--source', required=True, help='the source address') parser_bet.add_argument('--feed-address', required=True, help='the address which publishes the feed to bet on') parser_bet.add_argument('--bet-type', choices=list(BET_TYPE_NAME.values()), required=True, help='choices: {}'.format(list(BET_TYPE_NAME.values()))) parser_bet.add_argument('--deadline', required=True, help='the date and time at which the bet should be decided/settled') parser_bet.add_argument('--wager', required=True, help='the quantity of XCP to wager') parser_bet.add_argument('--counterwager', required=True, help='the minimum quantity of XCP to be wagered by the user to bet against you, if he were to accept the whole thing') parser_bet.add_argument('--target-value', default=0.0, help='target value for Equal/NotEqual bet') parser_bet.add_argument('--leverage', type=int, default=5040, help='leverage, as a fraction of 5040') parser_bet.add_argument('--expiration', type=int, required=True, help='the number of blocks for which the bet should be valid') parser_bet.add_argument('--fee', help='the exact {} fee to be paid to miners'.format(config.BTC)) parser_dividend = subparsers.add_parser('dividend', help='pay dividends to the holders of an asset (in proportion to their stake in it)') parser_dividend.add_argument('--source', required=True, help='the source address') parser_dividend.add_argument('--quantity-per-unit', required=True, help='the quantity of XCP to be paid per whole unit held of ASSET') parser_dividend.add_argument('--asset', required=True, help='the asset to which pay dividends') parser_dividend.add_argument('--dividend-asset', required=True, help='asset in which to pay the dividends') parser_dividend.add_argument('--fee', help='the exact {} fee to be paid to miners'.format(config.BTC)) parser_burn = subparsers.add_parser('burn', help='destroy {} to earn XCP, during an initial period of time') parser_burn.add_argument('--source', required=True, help='the source address') parser_burn.add_argument('--quantity', required=True, help='quantity of {} to be burned'.format(config.BTC)) parser_burn.add_argument('--fee', help='the exact {} fee to be paid to miners'.format(config.BTC)) parser_cancel = subparsers.add_parser('cancel', help='cancel an open order or bet you created') parser_cancel.add_argument('--source', required=True, help='the source address') parser_cancel.add_argument('--offer-hash', required=True, help='the transaction hash of the order or bet') parser_cancel.add_argument('--fee', help='the exact {} fee to be paid to miners'.format(config.BTC)) parser_rps = subparsers.add_parser('rps', help='open a rock-paper-scissors like game') parser_rps.add_argument('--source', required=True, help='the source address') parser_rps.add_argument('--wager', required=True, help='the quantity of XCP to wager') parser_rps.add_argument('--move', type=int, required=True, help='the selected move') parser_rps.add_argument('--possible-moves', type=int, required=True, help='the number of possible moves (odd number greater or equal than 3)') parser_rps.add_argument('--expiration', type=int, required=True, help='the number of blocks for which the bet should be valid') parser_rps.add_argument('--fee', help='the exact BTC fee to be paid to miners') parser_rpsresolve = subparsers.add_parser('rpsresolve', help='resolve a rock-paper-scissors like game') parser_rpsresolve.add_argument('--source', required=True, help='the source address') parser_rpsresolve.add_argument('--random', type=str, required=True, help='the random number used in the corresponding rps transaction') parser_rpsresolve.add_argument('--move', type=int, required=True, help='the selected move in the corresponding rps transaction') parser_rpsresolve.add_argument('--rps-match-id', required=True, help='the concatenation of the hashes of the two transactions which compose the rps match') parser_rpsresolve.add_argument('--fee', help='the exact BTC fee to be paid to miners') parser_publish = subparsers.add_parser('publish', help='publish contract code in the blockchain') parser_publish.add_argument('--source', required=True, help='the source address') parser_publish.add_argument('--gasprice', required=True, type=int, help='the price of gas') parser_publish.add_argument('--startgas', required=True, type=int, help='the maximum quantity of {} to be used to pay for the execution (satoshis)'.format(config.XCP)) parser_publish.add_argument('--endowment', required=True, type=int, help='quantity of {} to be transfered to the contract (satoshis)'.format(config.XCP)) parser_publish.add_argument('--code-hex', required=True, type=str, help='the hex‐encoded contract (returned by `serpent compile`)') parser_publish.add_argument('--fee', help='the exact {} fee to be paid to miners'.format(config.BTC)) parser_execute = subparsers.add_parser('execute', help='execute contract code in the blockchain') parser_execute.add_argument('--source', required=True, help='the source address') parser_execute.add_argument('--contract-id', required=True, help='the contract ID of the contract to be executed') parser_execute.add_argument('--gasprice', required=True, type=int, help='the price of gas') parser_execute.add_argument('--startgas', required=True, type=int, help='the maximum quantity of {} to be used to pay for the execution (satoshis)'.format(config.XCP)) parser_execute.add_argument('--value', required=True, type=int, help='quantity of {} to be transfered to the contract (satoshis)'.format(config.XCP)) parser_execute.add_argument('--payload-hex', required=True, type=str, help='data to be provided to the contract (returned by `serpent encode_datalist`)') parser_execute.add_argument('--fee', help='the exact {} fee to be paid to miners'.format(config.BTC)) parser_destroy = subparsers.add_parser('destroy', help='destroy a quantity of a Counterparty asset') parser_destroy.add_argument('--source', required=True, help='the source address') parser_destroy.add_argument('--asset', required=True, help='the ASSET of which you would like to destroy QUANTITY') parser_destroy.add_argument('--quantity', required=True, help='the quantity of ASSET to destroy') parser_destroy.add_argument('--tag', default='', help='tag') parser_destroy.add_argument('--fee', help='the exact {} fee to be paid to miners'.format(config.BTC)) parser_address = subparsers.add_parser('balances', help='display the balances of a {} address'.format(config.XCP_NAME)) parser_address.add_argument('address', help='the address you are interested in') parser_asset = subparsers.add_parser('asset', help='display the basic properties of a {} asset'.format(config.XCP_NAME)) parser_asset.add_argument('asset', help='the asset you are interested in') parser_wallet = subparsers.add_parser('wallet', help='list the addresses in your backend wallet along with their balances in all {} assets'.format(config.XCP_NAME)) parser_pending = subparsers.add_parser('pending', help='list pending order matches awaiting {}payment from you'.format(config.BTC)) parser_getrows = subparsers.add_parser('getrows', help='get rows from a Counterparty table') parser_getrows.add_argument('--table', required=True, help='table name') parser_getrows.add_argument('--filter', nargs=3, action='append', help='filters to get specific rows') parser_getrows.add_argument('--filter-op', choices=['AND', 'OR'], help='operator uses to combine filters', default='AND') parser_getrows.add_argument('--order-by', help='field used to order results') parser_getrows.add_argument('--order-dir', choices=['ASC', 'DESC'], help='direction used to order results') parser_getrows.add_argument('--start-block', help='return only rows with block_index greater than start-block') parser_getrows.add_argument('--end-block', help='return only rows with block_index lower than end-block') parser_getrows.add_argument('--status', help='return only rows with the specified status') parser_getrows.add_argument('--limit', help='number of rows to return', default=100) parser_getrows.add_argument('--offset', help='number of rows to skip', default=0) parser_getrunninginfo = subparsers.add_parser('getinfo', help='get the current state of the server') args = parser.parse_args() # Logging log.set_up(logger, verbose=args.verbose) logger.propagate = False logger.info('Running v{} of {}.'.format(APP_VERSION, APP_NAME)) # Help message if args.help: parser.print_help() sys.exit() # Configuration clientapi.initialize(testnet=args.testnet, testcoin=args.testcoin, counterparty_rpc_connect=args.counterparty_rpc_connect, counterparty_rpc_port=args.counterparty_rpc_port, counterparty_rpc_user=args.counterparty_rpc_user, counterparty_rpc_password=args.counterparty_rpc_password, counterparty_rpc_ssl=args.counterparty_rpc_ssl, counterparty_rpc_ssl_verify=args.counterparty_rpc_ssl_verify, wallet_name=args.wallet_name, wallet_connect=args.wallet_connect, wallet_port=args.wallet_port, wallet_user=args.wallet_user, wallet_password=args.wallet_password, wallet_ssl=args.wallet_ssl, wallet_ssl_verify=args.wallet_ssl_verify, requests_timeout=args.requests_timeout) # MESSAGE CREATION if args.action in list(messages.MESSAGE_PARAMS.keys()): unsigned_hex = messages.compose(args.action, args) logger.info('Transaction (unsigned): {}'.format(unsigned_hex)) if not args.unsigned: if script.is_multisig(args.source): logger.info('Multi‐signature transactions are signed and broadcasted manually.') elif input('Sign and broadcast? (y/N) ') == 'y': if wallet.is_mine(args.source): if wallet.is_locked(): passphrase = getpass.getpass('Enter your wallet passhrase: ') logger.info('Unlocking wallet for 60 (more) seconds.') wallet.unlock(passphrase) signed_tx_hex = wallet.sign_raw_transaction(unsigned_hex) else: private_key_wif = input('Source address not in wallet. Please enter the private key in WIF format for {}:'.format(args.source)) if not private_key_wif: raise TransactionError('invalid private key') signed_tx_hex = wallet.sign_raw_transaction(unsigned_hex, private_key_wif=private_key_wif) logger.info('Transaction (signed): {}'.format(signed_tx_hex)) tx_hash = wallet.send_raw_transaction(signed_tx_hex) logger.info('Hash of transaction (broadcasted): {}'.format(tx_hash)) # VIEWING elif args.action in ['balances', 'asset', 'wallet', 'pending', 'getinfo', 'getrows']: view = console.get_view(args.action, args) print_method = getattr(console, 'print_{}'.format(args.action), None) if args.json_output or print_method is None: util.json_print(view) else: print_method(view) else: parser.print_help()
def setup_logging(): print( "") # for --verbose output this makes sure the logs start on a newline log.set_up(log.ROOT_LOGGER, verbose=True, console_logfilter=os.environ.get('COUNTERPARTY_LOGGING', None))
def main(): if os.name == 'nt': from counterpartylib.lib import util_windows #patch up cmd.exe's "challenged" (i.e. broken/non-existent) UTF-8 logging util_windows.fix_win32_unicode() # Post installation tasks generate_config_files() # Parse command-line arguments. parser = argparse.ArgumentParser( prog=APP_NAME, description='Server for the {} protocol'.format(config.XCP_NAME), add_help=False) parser.add_argument('-h', '--help', dest='help', action='store_true', help='show this help message and exit') parser.add_argument('-V', '--version', action='version', version="{} v{}; {} v{}".format( APP_NAME, APP_VERSION, 'counterparty-lib', config.VERSION_STRING)) parser.add_argument('--config-file', help='the path to the configuration file') add_config_arguments(parser, CONFIG_ARGS, 'server.conf') subparsers = parser.add_subparsers(dest='action', help='the action to be taken') parser_server = subparsers.add_parser('start', help='run the server') parser_reparse = subparsers.add_parser( 'reparse', help='reparse all transactions in the database') parser_rollback = subparsers.add_parser('rollback', help='rollback database') parser_rollback.add_argument('block_index', type=int, help='the index of the last known good block') parser_kickstart = subparsers.add_parser( 'kickstart', help='rapidly build database by reading from Bitcoin Core blockchain') parser_kickstart.add_argument('--bitcoind-dir', help='Bitcoin Core data directory') parser_bootstrap = subparsers.add_parser( 'bootstrap', help='bootstrap database with hosted snapshot') parser_bootstrap.add_argument('-q', '--quiet', dest='quiet', action='store_true', help='suppress progress bar') args = parser.parse_args() log.set_up(log.ROOT_LOGGER, verbose=args.verbose, console_logfilter=os.environ.get('COUNTERPARTY_LOGGING', None)) logger.info('Running v{} of {}.'.format(APP_VERSION, APP_NAME)) # Help message if args.help: parser.print_help() sys.exit() # Bootstrapping if args.action == 'bootstrap': bootstrap(testnet=args.testnet, quiet=args.quiet) sys.exit() def init_with_catch(fn, init_args): try: return fn(**init_args) except TypeError as e: if 'unexpected keyword argument' in str(e): raise VersionError( 'Unsupported Server Parameter. CLI/Library Version Incompatibility.' ) else: raise e # Configuration COMMANDS_WITH_DB = ['reparse', 'rollback', 'kickstart', 'start'] COMMANDS_WITH_CONFIG = ['debug_config'] if args.action in COMMANDS_WITH_DB or args.action in COMMANDS_WITH_CONFIG: init_args = dict( database_file=args.database_file, log_file=args.log_file, api_log_file=args.api_log_file, testnet=args.testnet, testcoin=args.testcoin, backend_name=args.backend_name, backend_connect=args.backend_connect, backend_port=args.backend_port, backend_user=args.backend_user, backend_password=args.backend_password, backend_ssl=args.backend_ssl, backend_ssl_no_verify=args.backend_ssl_no_verify, backend_poll_interval=args.backend_poll_interval, rpc_host=args.rpc_host, rpc_port=args.rpc_port, rpc_user=args.rpc_user, rpc_password=args.rpc_password, rpc_no_allow_cors=args.rpc_no_allow_cors, requests_timeout=args.requests_timeout, rpc_batch_size=args.rpc_batch_size, check_asset_conservation=not args.no_check_asset_conservation, force=args.force, verbose=args.verbose, console_logfilter=os.environ.get('COUNTERPARTY_LOGGING', None), p2sh_dust_return_pubkey=args.p2sh_dust_return_pubkey, utxo_locks_max_addresses=args.utxo_locks_max_addresses, utxo_locks_max_age=args.utxo_locks_max_age) #,broadcast_tx_mainnet=args.broadcast_tx_mainnet) if args.action in COMMANDS_WITH_DB: db = init_with_catch(server.initialise, init_args) elif args.action in COMMANDS_WITH_CONFIG: init_with_catch(server.initialise_config, init_args) # PARSING if args.action == 'reparse': server.reparse(db) elif args.action == 'rollback': server.reparse(db, block_index=args.block_index) elif args.action == 'kickstart': server.kickstart(db, bitcoind_dir=args.bitcoind_dir) elif args.action == 'start': server.start_all(db) elif args.action == 'debug_config': server.debug_config() else: parser.print_help()
def initialize(self, openDialog=False): configdir = appdirs.user_config_dir(appauthor=config.XCP_NAME, appname=config.APP_NAME, roaming=True) configfile = os.path.join(configdir, 'client.conf') config_exists = os.path.exists(configfile) if not config_exists: generate_config_file(configfile, client.CONFIG_ARGS) # Parse command-line arguments. parser = argparse.ArgumentParser( prog=APP_NAME, description=tr('Counterparty CLI for counterparty-server'), add_help=False, conflict_handler='resolve') parser.add_argument('-h', '--help', dest='help', action='store_true', help=tr('show this help message and exit')) parser.add_argument('-V', '--version', action='version', version="{} v{}".format(APP_NAME, APP_VERSION)) parser.add_argument( '--config-file', help=tr( 'the location of the counterparty-client configuration file')) self.args = parser.parse_known_args()[0] if not config_exists or openDialog: is_splash_visible = False if self.splash: is_splash_visible = self.splash.isVisible() if is_splash_visible: self.splash.hide() configfile = getattr(self.args, 'config_file', None) or configfile configUI = ConfigDialog(configfile, newconfig=not config_exists) result = configUI.exec() if is_splash_visible: self.splash.show() if openDialog and result == 0: return False parser = add_config_arguments(parser, CONFIG_ARGS, 'client.conf', config_file_arg_name='config_file') self.args = parser.parse_args() dargs = vars(self.args) for argName in dargs: print('{}: {}'.format(argName.upper(), dargs[argName])) setattr(self, argName.upper(), dargs[argName]) # Help message if self.args.help: parser.print_help() sys.exit() # Logging logdir = appdirs.user_log_dir(appauthor=config.XCP_NAME, appname=config.APP_NAME) if not os.path.exists(logdir): os.makedirs(logdir, mode=0o755) self.LOG_FILE = os.path.join(logdir, 'counterpartygui.log') log.set_up(logger, verbose=self.args.verbose, logfile=self.LOG_FILE) return True
def initialise_config(database_file=None, log_file=None, api_log_file=None, testnet=False, testcoin=False, backend_name=None, backend_connect=None, backend_port=None, backend_user=None, backend_password=None, backend_ssl=False, backend_ssl_no_verify=False, backend_poll_interval=None, rpc_host=None, rpc_port=None, rpc_user=None, rpc_password=None, rpc_no_allow_cors=False, force=False, verbose=False, console_logfilter=None, requests_timeout=config.DEFAULT_REQUESTS_TIMEOUT, rpc_batch_size=config.DEFAULT_RPC_BATCH_SIZE, check_asset_conservation=config.DEFAULT_CHECK_ASSET_CONSERVATION, backend_ssl_verify=None, rpc_allow_cors=None, p2sh_dust_return_pubkey=None, utxo_locks_max_addresses=config.DEFAULT_UTXO_LOCKS_MAX_ADDRESSES, utxo_locks_max_age=config.DEFAULT_UTXO_LOCKS_MAX_AGE, estimate_fee_per_kb=None): # Data directory data_dir = appdirs.user_data_dir(appauthor=config.XCP_NAME, appname=config.APP_NAME, roaming=True) if not os.path.isdir(data_dir): os.makedirs(data_dir, mode=0o755) # testnet if testnet: config.TESTNET = testnet else: config.TESTNET = False # testcoin if testcoin: config.TESTCOIN = testcoin else: config.TESTCOIN = False network = '' if config.TESTNET: network += '.testnet' if config.TESTCOIN: network += '.testcoin' # Database if database_file: config.DATABASE = database_file else: filename = '{}{}.db'.format(config.APP_NAME, network) config.DATABASE = os.path.join(data_dir, filename) # Log directory log_dir = appdirs.user_log_dir(appauthor=config.XCP_NAME, appname=config.APP_NAME) if not os.path.isdir(log_dir): os.makedirs(log_dir, mode=0o755) # Log if log_file is False: # no file logging config.LOG = None elif not log_file: # default location filename = 'server{}.log'.format(network) config.LOG = os.path.join(log_dir, filename) else: # user-specified location config.LOG = log_file # Set up logging. log.set_up(log.ROOT_LOGGER, verbose=verbose, logfile=config.LOG, console_logfilter=console_logfilter) if config.LOG: logger.debug('Writing server log to file: `{}`'.format(config.LOG)) if api_log_file is False: # no file logging config.API_LOG = None elif not api_log_file: # default location filename = 'server{}.access.log'.format(network) config.API_LOG = os.path.join(log_dir, filename) else: # user-specified location config.API_LOG = api_log_file if config.API_LOG: logger.debug('Writing API accesses log to file: `{}`'.format(config.API_LOG)) # Log unhandled errors. def handle_exception(exc_type, exc_value, exc_traceback): logger.error("Unhandled Exception", exc_info=(exc_type, exc_value, exc_traceback)) sys.excepthook = handle_exception ############## # THINGS WE CONNECT TO # Backend name if backend_name: config.BACKEND_NAME = backend_name else: config.BACKEND_NAME = 'addrindex' if config.BACKEND_NAME == 'jmcorgan': config.BACKEND_NAME = 'addrindex' # Backend RPC host (Bitcoin Core) if backend_connect: config.BACKEND_CONNECT = backend_connect else: config.BACKEND_CONNECT = 'localhost' # Backend Core RPC port (Bitcoin Core) if backend_port: config.BACKEND_PORT = backend_port else: if config.TESTNET: if config.BACKEND_NAME == 'btcd': config.BACKEND_PORT = config.DEFAULT_BACKEND_PORT_TESTNET_BTCD else: config.BACKEND_PORT = config.DEFAULT_BACKEND_PORT_TESTNET else: if config.BACKEND_NAME == 'btcd': config.BACKEND_PORT = config.DEFAULT_BACKEND_PORT_BTCD else: config.BACKEND_PORT = config.DEFAULT_BACKEND_PORT try: config.BACKEND_PORT = int(config.BACKEND_PORT) if not (int(config.BACKEND_PORT) > 1 and int(config.BACKEND_PORT) < 65535): raise ConfigurationError('invalid backend API port number') except: raise ConfigurationError("Please specific a valid port number backend-port configuration parameter") # Backend Core RPC user (Bitcoin Core) if backend_user: config.BACKEND_USER = backend_user else: config.BACKEND_USER = '******' # Backend Core RPC password (Bitcoin Core) if backend_password: config.BACKEND_PASSWORD = backend_password else: raise ConfigurationError('backend RPC password not set. (Use configuration file or --backend-password=PASSWORD)') # Backend Core RPC SSL if backend_ssl: config.BACKEND_SSL = backend_ssl else: config.BACKEND_SSL = False # Default to off. # Backend Core RPC SSL Verify if backend_ssl_verify is not None: logger.warning('The server parameter `backend_ssl_verify` is deprecated. Use `backend_ssl_no_verify` instead.') config.BACKEND_SSL_NO_VERIFY = not backend_ssl_verify else: if backend_ssl_no_verify: config.BACKEND_SSL_NO_VERIFY = backend_ssl_no_verify else: config.BACKEND_SSL_NO_VERIFY = False # Default to on (don't support self‐signed certificates) # Backend Poll Interval if backend_poll_interval: config.BACKEND_POLL_INTERVAL = backend_poll_interval else: config.BACKEND_POLL_INTERVAL = 0.5 # Construct backend URL. config.BACKEND_URL = config.BACKEND_USER + ':' + config.BACKEND_PASSWORD + '@' + config.BACKEND_CONNECT + ':' + str(config.BACKEND_PORT) if config.BACKEND_SSL: config.BACKEND_URL = 'https://' + config.BACKEND_URL else: config.BACKEND_URL = 'http://' + config.BACKEND_URL ############## # THINGS WE SERVE # Server API RPC host if rpc_host: config.RPC_HOST = rpc_host else: config.RPC_HOST = 'localhost' # The web root directory for API calls, eg. localhost:14000/rpc/ config.RPC_WEBROOT = '/rpc/' # Server API RPC port if rpc_port: config.RPC_PORT = rpc_port else: if config.TESTNET: if config.TESTCOIN: config.RPC_PORT = config.DEFAULT_RPC_PORT_TESTNET + 1 else: config.RPC_PORT = config.DEFAULT_RPC_PORT_TESTNET else: if config.TESTCOIN: config.RPC_PORT = config.DEFAULT_RPC_PORT + 1 else: config.RPC_PORT = config.DEFAULT_RPC_PORT try: config.RPC_PORT = int(config.RPC_PORT) if not (int(config.RPC_PORT) > 1 and int(config.RPC_PORT) < 65535): raise ConfigurationError('invalid server API port number') except: raise ConfigurationError("Please specific a valid port number rpc-port configuration parameter") # Server API RPC user if rpc_user: config.RPC_USER = rpc_user else: config.RPC_USER = '******' # Server API RPC password if rpc_password: config.RPC_PASSWORD = rpc_password config.RPC = 'http://' + urlencode(config.RPC_USER) + ':' + urlencode(config.RPC_PASSWORD) + '@' + config.RPC_HOST + ':' + str(config.RPC_PORT) + config.RPC_WEBROOT else: config.RPC = 'http://' + config.RPC_HOST + ':' + str(config.RPC_PORT) + config.RPC_WEBROOT # RPC CORS if rpc_allow_cors is not None: logger.warning('The server parameter `rpc_allow_cors` is deprecated. Use `rpc_no_allow_cors` instead.') config.RPC_NO_ALLOW_CORS = not rpc_allow_cors else: if rpc_no_allow_cors: config.RPC_NO_ALLOW_CORS = rpc_no_allow_cors else: config.RPC_NO_ALLOW_CORS = False config.RPC_BATCH_SIZE = rpc_batch_size ############## # OTHER SETTINGS # skip checks if force: config.FORCE = force else: config.FORCE = False # Encoding if config.TESTCOIN: config.PREFIX = b'XX' # 2 bytes (possibly accidentally created) else: config.PREFIX = b'CNTRPRTY' # 8 bytes # (more) Testnet if config.TESTNET: config.MAGIC_BYTES = config.MAGIC_BYTES_TESTNET if config.TESTCOIN: config.ADDRESSVERSION = config.ADDRESSVERSION_TESTNET config.P2SH_ADDRESSVERSION = config.P2SH_ADDRESSVERSION_TESTNET config.BLOCK_FIRST = config.BLOCK_FIRST_TESTNET_TESTCOIN config.BURN_START = config.BURN_START_TESTNET_TESTCOIN config.BURN_END = config.BURN_END_TESTNET_TESTCOIN config.UNSPENDABLE = config.UNSPENDABLE_TESTNET config.P2SH_DUST_RETURN_PUBKEY = p2sh_dust_return_pubkey else: config.ADDRESSVERSION = config.ADDRESSVERSION_TESTNET config.P2SH_ADDRESSVERSION = config.P2SH_ADDRESSVERSION_TESTNET config.BLOCK_FIRST = config.BLOCK_FIRST_TESTNET config.BURN_START = config.BURN_START_TESTNET config.BURN_END = config.BURN_END_TESTNET config.UNSPENDABLE = config.UNSPENDABLE_TESTNET config.P2SH_DUST_RETURN_PUBKEY = p2sh_dust_return_pubkey else: config.MAGIC_BYTES = config.MAGIC_BYTES_MAINNET if config.TESTCOIN: config.ADDRESSVERSION = config.ADDRESSVERSION_MAINNET config.P2SH_ADDRESSVERSION = config.P2SH_ADDRESSVERSION_MAINNET config.BLOCK_FIRST = config.BLOCK_FIRST_MAINNET_TESTCOIN config.BURN_START = config.BURN_START_MAINNET_TESTCOIN config.BURN_END = config.BURN_END_MAINNET_TESTCOIN config.UNSPENDABLE = config.UNSPENDABLE_MAINNET config.P2SH_DUST_RETURN_PUBKEY = p2sh_dust_return_pubkey else: config.ADDRESSVERSION = config.ADDRESSVERSION_MAINNET config.P2SH_ADDRESSVERSION = config.P2SH_ADDRESSVERSION_MAINNET config.BLOCK_FIRST = config.BLOCK_FIRST_MAINNET config.BURN_START = config.BURN_START_MAINNET config.BURN_END = config.BURN_END_MAINNET config.UNSPENDABLE = config.UNSPENDABLE_MAINNET config.P2SH_DUST_RETURN_PUBKEY = p2sh_dust_return_pubkey # Misc config.REQUESTS_TIMEOUT = requests_timeout config.CHECK_ASSET_CONSERVATION = check_asset_conservation config.UTXO_LOCKS_MAX_ADDRESSES = utxo_locks_max_addresses config.UTXO_LOCKS_MAX_AGE = utxo_locks_max_age transaction.UTXO_LOCKS = None # reset the UTXO_LOCKS (for tests really) if estimate_fee_per_kb is not None: config.ESTIMATE_FEE_PER_KB = estimate_fee_per_kb logger.info('Running v{} of counterparty-lib.'.format(config.VERSION_STRING))
def main(): if os.name == 'nt': from counterpartylib.lib import util_windows #patch up cmd.exe's "challenged" (i.e. broken/non-existent) UTF-8 logging util_windows.fix_win32_unicode() # Post installation tasks generate_config_files() # Parse command-line arguments. parser = argparse.ArgumentParser( prog=APP_NAME, description='Server for the {} protocol'.format(config.XCP_NAME), add_help=False) parser.add_argument('-h', '--help', dest='help', action='store_true', help='show this help message and exit') parser.add_argument('-V', '--version', action='version', version="{} v{}; {} v{}".format( APP_NAME, APP_VERSION, 'counterparty-lib', config.VERSION_STRING)) parser.add_argument('--config-file', help='the path to the configuration file') parser = add_config_arguments(parser, CONFIG_ARGS, 'server.conf') subparsers = parser.add_subparsers(dest='action', help='the action to be taken') parser_server = subparsers.add_parser('start', help='run the server') parser_reparse = subparsers.add_parser( 'reparse', help='reparse all transactions in the database') parser_rollback = subparsers.add_parser('rollback', help='rollback database') parser_rollback.add_argument('block_index', type=int, help='the index of the last known good block') parser_kickstart = subparsers.add_parser( 'kickstart', help='rapidly build database by reading from Bitcoin Core blockchain') parser_kickstart.add_argument('--bitcoind-dir', help='Bitcoin Core data directory') parser_bootstrap = subparsers.add_parser( 'bootstrap', help='bootstrap database with hosted snapshot') args = parser.parse_args() log.set_up(logger, verbose=args.verbose) logger.info('Running v{} of {}.'.format(APP_VERSION, APP_NAME)) # Help message if args.help: parser.print_help() sys.exit() # Bootstrapping if args.action == 'bootstrap': bootstrap(testnet=args.testnet) sys.exit() # Configuration if args.action in ['reparse', 'rollback', 'kickstart', 'start']: try: db = server.initialise( database_file=args.database_file, log_file=args.log_file, api_log_file=args.api_log_file, testnet=args.testnet, testcoin=args.testcoin, backend_name=args.backend_name, backend_connect=args.backend_connect, backend_port=args.backend_port, backend_user=args.backend_user, backend_password=args.backend_password, backend_ssl=args.backend_ssl, backend_ssl_no_verify=args.backend_ssl_no_verify, backend_poll_interval=args.backend_poll_interval, rpc_host=args.rpc_host, rpc_port=args.rpc_port, rpc_user=args.rpc_user, rpc_password=args.rpc_password, rpc_no_allow_cors=args.rpc_no_allow_cors, force=args.force, verbose=args.verbose) #,broadcast_tx_mainnet=args.broadcast_tx_mainnet) except TypeError as e: if 'unexpected keyword argument' in str(e): raise VersionError( 'Unsupported Server Parameter. CLI/Library Version Incompatibility.' ) else: raise e # PARSING if args.action == 'reparse': server.reparse(db) elif args.action == 'rollback': server.reparse(db, block_index=args.block_index) elif args.action == 'kickstart': server.kickstart(db, bitcoind_dir=args.bitcoind_dir) elif args.action == 'start': server.start_all(db) else: parser.print_help()
def initialise( database_file=None, log_file=None, api_log_file=None, testnet=False, testcoin=False, backend_name=None, backend_connect=None, backend_port=None, backend_user=None, backend_password=None, backend_ssl=False, backend_ssl_no_verify=False, backend_poll_interval=None, rpc_host=None, rpc_port=None, rpc_user=None, rpc_password=None, rpc_no_allow_cors=False, force=False, verbose=False, requests_timeout=config.DEFAULT_REQUESTS_TIMEOUT, rpc_batch_size=config.DEFAULT_RPC_BATCH_SIZE, check_asset_conservation=config.DEFAULT_CHECK_ASSET_CONSERVATION, backend_ssl_verify=None, rpc_allow_cors=None, ): # Data directory data_dir = appdirs.user_data_dir(appauthor=config.XCP_NAME, appname=config.APP_NAME, roaming=True) if not os.path.isdir(data_dir): os.makedirs(data_dir, mode=0o755) # testnet if testnet: config.TESTNET = testnet else: config.TESTNET = False # testcoin if testcoin: config.TESTCOIN = testcoin else: config.TESTCOIN = False network = "" if config.TESTNET: network += ".testnet" if config.TESTCOIN: network += ".testcoin" # Database if database_file: config.DATABASE = database_file else: filename = "{}{}.db".format(config.APP_NAME, network) config.DATABASE = os.path.join(data_dir, filename) # Log directory log_dir = appdirs.user_log_dir(appauthor=config.XCP_NAME, appname=config.APP_NAME) if not os.path.isdir(log_dir): os.makedirs(log_dir, mode=0o755) # Log if log_file: config.LOG = log_file else: filename = "server{}.log".format(network) config.LOG = os.path.join(log_dir, filename) logger.debug("Writing server log to file: `{}`".format(config.LOG)) if api_log_file: config.API_LOG = api_log_file else: filename = "server{}.access.log".format(network) config.API_LOG = os.path.join(log_dir, filename) logger.debug("Writing API accesses log to file: `{}`".format(config.API_LOG)) # Set up logging. root_logger = logging.getLogger() # Get root logger. log.set_up(root_logger, verbose=verbose, logfile=config.LOG) # Log unhandled errors. def handle_exception(exc_type, exc_value, exc_traceback): logger.error("Unhandled Exception", exc_info=(exc_type, exc_value, exc_traceback)) sys.excepthook = handle_exception ############## # THINGS WE CONNECT TO # Backend name if backend_name: config.BACKEND_NAME = backend_name else: config.BACKEND_NAME = "addrindex" if config.BACKEND_NAME == "jmcorgan": config.BACKEND_NAME = "addrindex" # Backend RPC host (Bitcoin Core) if backend_connect: config.BACKEND_CONNECT = backend_connect else: config.BACKEND_CONNECT = "localhost" # Backend Core RPC port (Bitcoin Core) if backend_port: config.BACKEND_PORT = backend_port else: if config.TESTNET: if config.BACKEND_NAME == "btcd": config.BACKEND_PORT = config.DEFAULT_BACKEND_PORT_TESTNET_BTCD else: config.BACKEND_PORT = config.DEFAULT_BACKEND_PORT_TESTNET else: if config.BACKEND_NAME == "btcd": config.BACKEND_PORT = config.DEFAULT_BACKEND_PORT_BTCD else: config.BACKEND_PORT = config.DEFAULT_BACKEND_PORT try: config.BACKEND_PORT = int(config.BACKEND_PORT) if not (int(config.BACKEND_PORT) > 1 and int(config.BACKEND_PORT) < 65535): raise ConfigurationError("invalid backend API port number") except: raise ConfigurationError("Please specific a valid port number backend-port configuration parameter") # Backend Core RPC user (Bitcoin Core) if backend_user: config.BACKEND_USER = backend_user else: config.BACKEND_USER = "******" # Backend Core RPC password (Bitcoin Core) if backend_password: config.BACKEND_PASSWORD = backend_password else: raise ConfigurationError( "backend RPC password not set. (Use configuration file or --backend-password=PASSWORD)" ) # Backend Core RPC SSL if backend_ssl: config.BACKEND_SSL = backend_ssl else: config.BACKEND_SSL = False # Default to off. # Backend Core RPC SSL Verify if backend_ssl_verify is not None: logger.warning("The server parameter `backend_ssl_verify` is deprecated. Use `backend_ssl_no_verify` instead.") config.BACKEND_SSL_NO_VERIFY = not backend_ssl_verify else: if backend_ssl_no_verify: config.BACKEND_SSL_NO_VERIFY = backend_ssl_no_verify else: config.BACKEND_SSL_NO_VERIFY = False # Default to on (don't support self‐signed certificates) # Backend Poll Interval if backend_poll_interval: config.BACKEND_POLL_INTERVAL = backend_poll_interval else: config.BACKEND_POLL_INTERVAL = 0.5 # Construct backend URL. config.BACKEND_URL = ( config.BACKEND_USER + ":" + config.BACKEND_PASSWORD + "@" + config.BACKEND_CONNECT + ":" + str(config.BACKEND_PORT) ) if config.BACKEND_SSL: config.BACKEND_URL = "https://" + config.BACKEND_URL else: config.BACKEND_URL = "http://" + config.BACKEND_URL ############## # THINGS WE SERVE # Server API RPC host if rpc_host: config.RPC_HOST = rpc_host else: config.RPC_HOST = "localhost" # The web root directory for API calls, eg. localhost:14000/rpc/ config.RPC_WEBROOT = "/rpc/" # Server API RPC port if rpc_port: config.RPC_PORT = rpc_port else: if config.TESTNET: if config.TESTCOIN: config.RPC_PORT = config.DEFAULT_RPC_PORT_TESTNET + 1 else: config.RPC_PORT = config.DEFAULT_RPC_PORT_TESTNET else: if config.TESTCOIN: config.RPC_PORT = config.DEFAULT_RPC_PORT + 1 else: config.RPC_PORT = config.DEFAULT_RPC_PORT try: config.RPC_PORT = int(config.RPC_PORT) if not (int(config.RPC_PORT) > 1 and int(config.RPC_PORT) < 65535): raise ConfigurationError("invalid server API port number") except: raise ConfigurationError("Please specific a valid port number rpc-port configuration parameter") # Server API RPC user if rpc_user: config.RPC_USER = rpc_user else: config.RPC_USER = "******" # Server API RPC password if rpc_password: config.RPC_PASSWORD = rpc_password config.RPC = ( "http://" + urlencode(config.RPC_USER) + ":" + urlencode(config.RPC_PASSWORD) + "@" + config.RPC_HOST + ":" + str(config.RPC_PORT) + config.RPC_WEBROOT ) else: config.RPC = "http://" + config.RPC_HOST + ":" + str(config.RPC_PORT) + config.RPC_WEBROOT # RPC CORS if rpc_allow_cors is not None: logger.warning("The server parameter `rpc_allow_cors` is deprecated. Use `rpc_no_allow_cors` instead.") config.RPC_NO_ALLOW_CORS = not rpc_allow_cors else: if rpc_no_allow_cors: config.RPC_NO_ALLOW_CORS = rpc_no_allow_cors else: config.RPC_NO_ALLOW_CORS = False config.REQUESTS_TIMEOUT = requests_timeout config.RPC_BATCH_SIZE = rpc_batch_size config.CHECK_ASSET_CONSERVATION = check_asset_conservation ############## # OTHER SETTINGS # skip checks if force: config.FORCE = force else: config.FORCE = False # Encoding if config.TESTCOIN: config.PREFIX = b"XX" # 2 bytes (possibly accidentally created) else: config.PREFIX = b"CNTRPRTY" # 8 bytes # (more) Testnet if config.TESTNET: config.MAGIC_BYTES = config.MAGIC_BYTES_TESTNET if config.TESTCOIN: config.ADDRESSVERSION = config.ADDRESSVERSION_TESTNET config.BLOCK_FIRST = config.BLOCK_FIRST_TESTNET_TESTCOIN config.BURN_START = config.BURN_START_TESTNET_TESTCOIN config.BURN_END = config.BURN_END_TESTNET_TESTCOIN config.UNSPENDABLE = config.UNSPENDABLE_TESTNET else: config.ADDRESSVERSION = config.ADDRESSVERSION_TESTNET config.BLOCK_FIRST = config.BLOCK_FIRST_TESTNET config.BURN_START = config.BURN_START_TESTNET config.BURN_END = config.BURN_END_TESTNET config.UNSPENDABLE = config.UNSPENDABLE_TESTNET else: config.MAGIC_BYTES = config.MAGIC_BYTES_MAINNET if config.TESTCOIN: config.ADDRESSVERSION = config.ADDRESSVERSION_MAINNET config.BLOCK_FIRST = config.BLOCK_FIRST_MAINNET_TESTCOIN config.BURN_START = config.BURN_START_MAINNET_TESTCOIN config.BURN_END = config.BURN_END_MAINNET_TESTCOIN config.UNSPENDABLE = config.UNSPENDABLE_MAINNET else: config.ADDRESSVERSION = config.ADDRESSVERSION_MAINNET config.BLOCK_FIRST = config.BLOCK_FIRST_MAINNET config.BURN_START = config.BURN_START_MAINNET config.BURN_END = config.BURN_END_MAINNET config.UNSPENDABLE = config.UNSPENDABLE_MAINNET logger.info("Running v{} of counterparty-lib.".format(config.VERSION_STRING)) if config.FORCE: logger.warning("THE OPTION `--force` IS NOT FOR USE ON PRODUCTION SYSTEMS.") # Lock if not config.FORCE: get_lock() # Database logger.info("Connecting to database.") db = database.get_connection(read_only=False) util.CURRENT_BLOCK_INDEX = blocks.last_db_index(db) return db
def initialise(database_file=None, log_file=None, api_log_file=None, testnet=False, testcoin=False, backend_name=None, backend_connect=None, backend_port=None, backend_user=None, backend_password=None, backend_ssl=False, backend_ssl_verify=True, backend_poll_interval=None, rpc_host=None, rpc_port=None, rpc_user=None, rpc_password=None, rpc_allow_cors=None, force=False, verbose=False): # Data directory data_dir = appdirs.user_data_dir(appauthor=config.XCP_NAME, appname=config.APP_NAME, roaming=True) if not os.path.isdir(data_dir): os.makedirs(data_dir, mode=0o755) # testnet if testnet: config.TESTNET = testnet else: config.TESTNET = False # testcoin if testcoin: config.TESTCOIN = testcoin else: config.TESTCOIN = False network = '' if config.TESTNET: network += '.testnet' if config.TESTCOIN: network += '.testcoin' # Database if database_file: config.DATABASE = database_file else: filename = '{}{}.db'.format(config.APP_NAME, network) config.DATABASE = os.path.join(data_dir, filename) # Log directory log_dir = appdirs.user_log_dir(appauthor=config.XCP_NAME, appname=config.APP_NAME) if not os.path.isdir(log_dir): os.makedirs(log_dir, mode=0o755) # Log if log_file: config.LOG = log_file else: filename = 'server{}.log'.format(network) config.LOG = os.path.join(log_dir, filename) logger.debug('Writing server log to file: `{}`'.format(config.LOG)) if api_log_file: config.API_LOG = api_log_file else: filename = 'server{}.api.log'.format(network) config.API_LOG = os.path.join(log_dir, filename) logger.debug('Writing API log to file: `{}`'.format(config.API_LOG)) ############## # THINGS WE CONNECT TO # Backend name if backend_name: config.BACKEND_NAME = backend_name else: config.BACKEND_NAME = 'addrindex' if config.BACKEND_NAME == 'jmcorgan': config.BACKEND_NAME = 'addrindex' # Backend RPC host (Bitcoin Core) if backend_connect: config.BACKEND_CONNECT = backend_connect else: config.BACKEND_CONNECT = 'localhost' # Backend Core RPC port (Bitcoin Core) if backend_port: config.BACKEND_PORT = backend_port else: if config.TESTNET: config.BACKEND_PORT = config.DEFAULT_BACKEND_PORT_TESTNET else: config.BACKEND_PORT = config.DEFAULT_BACKEND_PORT try: config.BACKEND_PORT = int(config.BACKEND_PORT) if not (int(config.BACKEND_PORT) > 1 and int(config.BACKEND_PORT) < 65535): raise ConfigurationError('invalid backend API port number') except: raise ConfigurationError( "Please specific a valid port number backend-port configuration parameter" ) # Backend Core RPC user (Bitcoin Core) if backend_user: config.BACKEND_USER = backend_user else: config.BACKEND_USER = '******' # Backend Core RPC password (Bitcoin Core) if backend_password: config.BACKEND_PASSWORD = backend_password else: raise ConfigurationError( 'backend RPC password not set. (Use configuration file or --backend-password=PASSWORD)' ) # Backend Core RPC SSL if backend_ssl: config.BACKEND_SSL = backend_ssl else: config.BACKEND_SSL = False # Default to off. # Backend Core RPC SSL Verify if backend_ssl_verify is not None: config.BACKEND_SSL_VERIFY = backend_ssl_verify else: config.BACKEND_SSL_VERIFY = True # Default to on (don't support self‐signed certificates) # Backend Poll Interval if backend_poll_interval: config.BACKEND_POLL_INTERVAL = backend_poll_interval else: config.BACKEND_POLL_INTERVAL = 2.0 # Construct backend URL. config.BACKEND_URL = config.BACKEND_USER + ':' + config.BACKEND_PASSWORD + '@' + config.BACKEND_CONNECT + ':' + str( config.BACKEND_PORT) if config.BACKEND_SSL: config.BACKEND_URL = 'https://' + config.BACKEND_URL else: config.BACKEND_URL = 'http://' + config.BACKEND_URL ############## # THINGS WE SERVE # counterpartyd API RPC host if rpc_host: config.RPC_HOST = rpc_host else: config.RPC_HOST = 'localhost' # counterpartyd API RPC port if rpc_port: config.RPC_PORT = rpc_port else: if config.TESTNET: if config.TESTCOIN: config.RPC_PORT = config.DEFAULT_RPC_PORT_TESTNET + 1 else: config.RPC_PORT = config.DEFAULT_RPC_PORT_TESTNET else: if config.TESTCOIN: config.RPC_PORT = config.DEFAULT_RPC_PORT + 1 else: config.RPC_PORT = config.DEFAULT_RPC_PORT try: config.RPC_PORT = int(config.RPC_PORT) if not (int(config.RPC_PORT) > 1 and int(config.RPC_PORT) < 65535): raise ConfigurationError('invalid counterpartyd API port number') except: raise ConfigurationError( "Please specific a valid port number rpc-port configuration parameter" ) # counterpartyd API RPC user if rpc_user: config.RPC_USER = rpc_user else: config.RPC_USER = '******' # counterpartyd API RPC password if rpc_password: config.RPC_PASSWORD = rpc_password else: raise ConfigurationError( 'RPC password not set. (Use configuration file or --rpc-password=PASSWORD)' ) config.RPC = 'http://' + urlencode(config.RPC_USER) + ':' + urlencode( config.RPC_PASSWORD) + '@' + config.RPC_HOST + ':' + str( config.RPC_PORT) # RPC CORS if rpc_allow_cors is not None: config.RPC_ALLOW_CORS = rpc_allow_cors else: config.RPC_ALLOW_CORS = True ############## # OTHER SETTINGS # skip checks if force: config.FORCE = force else: config.FORCE = False # Encoding if config.TESTCOIN: config.PREFIX = b'XX' # 2 bytes (possibly accidentally created) else: config.PREFIX = b'CNTRPRTY' # 8 bytes # (more) Testnet if config.TESTNET: config.MAGIC_BYTES = config.MAGIC_BYTES_TESTNET if config.TESTCOIN: config.ADDRESSVERSION = config.ADDRESSVERSION_TESTNET config.BLOCK_FIRST = config.BLOCK_FIRST_TESTNET_TESTCOIN config.BURN_START = config.BURN_START_TESTNET_TESTCOIN config.BURN_END = config.BURN_END_TESTNET_TESTCOIN config.UNSPENDABLE = config.UNSPENDABLE_TESTNET else: config.ADDRESSVERSION = config.ADDRESSVERSION_TESTNET config.BLOCK_FIRST = config.BLOCK_FIRST_TESTNET config.BURN_START = config.BURN_START_TESTNET config.BURN_END = config.BURN_END_TESTNET config.UNSPENDABLE = config.UNSPENDABLE_TESTNET else: config.MAGIC_BYTES = config.MAGIC_BYTES_MAINNET if config.TESTCOIN: config.ADDRESSVERSION = config.ADDRESSVERSION_MAINNET config.BLOCK_FIRST = config.BLOCK_FIRST_MAINNET_TESTCOIN config.BURN_START = config.BURN_START_MAINNET_TESTCOIN config.BURN_END = config.BURN_END_MAINNET_TESTCOIN config.UNSPENDABLE = config.UNSPENDABLE_MAINNET else: config.ADDRESSVERSION = config.ADDRESSVERSION_MAINNET config.BLOCK_FIRST = config.BLOCK_FIRST_MAINNET config.BURN_START = config.BURN_START_MAINNET config.BURN_END = config.BURN_END_MAINNET config.UNSPENDABLE = config.UNSPENDABLE_MAINNET # Set up logging. root_logger = logging.getLogger() # Get root logger. log.set_up(root_logger, verbose=verbose, logfile=config.LOG) # Log unhandled errors. def handle_exception(exc_type, exc_value, exc_traceback): logger.error("Unhandled Exception", exc_info=(exc_type, exc_value, exc_traceback)) sys.excepthook = handle_exception logger.info('Running v{} of counterparty-lib.'.format( config.VERSION_STRING)) if config.FORCE: logger.warning( 'THE OPTION `--force` IS NOT FOR USE ON PRODUCTION SYSTEMS.') # Lock if not config.FORCE: get_lock() # Database logger.info('Connecting to database.') db = database.get_connection(read_only=False) util.CURRENT_BLOCK_INDEX = blocks.last_db_index(db) return db
def setup_logging(): print("") # for --verbose output this makes sure the logs start on a newline log.set_up(log.ROOT_LOGGER, verbose=True, console_logfilter=os.environ.get('COUNTERPARTY_LOGGING', None))
import collections import logging import binascii from datetime import datetime from dateutil.tz import tzlocal import argparse import configparser import appdirs import tarfile import urllib.request import shutil import codecs from counterpartylib.lib import log logger = logging.getLogger(__name__) log.set_up(logger) D = decimal.Decimal from counterpartylib import server from counterpartylib.lib import config from counterpartylib.lib.util import value_input, value_output rpc_sessions = {} json_print = lambda x: print(json.dumps(x, sort_keys=True, indent=4)) class RPCError(Exception): pass def rpc(url, method, params=None, ssl_verify=False):