def main(): if os.name == 'nt': from shellpartylib.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.SHP_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, 'shellparty-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 Shellcoin Core blockchain') parser_kickstart.add_argument('--SatoshiChaind-dir', help='Shellcoin 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, SatoshiChaind_dir=args.SatoshiChaind_dir) elif args.action == 'start': server.start_all(db) else: parser.print_help()
def main(): if os.name == 'nt': from shellpartylib.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='Shellparty CLI for shellparty-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, 'shellparty-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.SCH)) 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.SCH)) 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.SCH)) parser_order_fees.add_argument('--fee', help='the exact {} fee to be paid to miners'.format(config.SCH)) parser_shellpay = subparsers.add_parser('{}pay'.format(config.SCH).lower(), help='create and broadcast a *{}pay* message, to settle an Order Match for which you owe {}'.format(config.SCH, config.SCH)) parser_shellpay.add_argument('--source', required=True, help='the source address') parser_shellpay.add_argument('--order-match-id', required=True, help='the concatenation of the hashes of the two transactions which compose the order match') parser_shellpay.add_argument('--fee', help='the exact {} fee to be paid to miners'.format(config.SCH)) 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.SCH)) 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.SCH)) 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 SHP to wager') parser_bet.add_argument('--counterwager', required=True, help='the minimum quantity of SHP 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.SCH)) 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 SHP 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.SCH)) parser_burn = subparsers.add_parser('burn', help='destroy {} to earn SHP, 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.SCH)) parser_burn.add_argument('--fee', help='the exact {} fee to be paid to miners'.format(config.SCH)) 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.SCH)) 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 SHP 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 SCH 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 SCH 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.SHP)) parser_publish.add_argument('--endowment', required=True, type=int, help='quantity of {} to be transfered to the contract (satoshis)'.format(config.SHP)) 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.SCH)) 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.SHP)) parser_execute.add_argument('--value', required=True, type=int, help='quantity of {} to be transfered to the contract (satoshis)'.format(config.SHP)) 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.SCH)) parser_destroy = subparsers.add_parser('destroy', help='destroy a quantity of a Shellparty 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.SCH)) parser_address = subparsers.add_parser('balances', help='display the balances of a {} address'.format(config.SHP_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.SHP_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.SHP_NAME)) parser_pending = subparsers.add_parser('pending', help='list pending order matches awaiting {}payment from you'.format(config.SCH)) parser_getrows = subparsers.add_parser('getrows', help='get rows from a Shellparty 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, shellparty_rpc_connect=args.shellparty_rpc_connect, shellparty_rpc_port=args.shellparty_rpc_port, shellparty_rpc_user=args.shellparty_rpc_user, shellparty_rpc_password=args.shellparty_rpc_password, shellparty_rpc_ssl=args.shellparty_rpc_ssl, shellparty_rpc_ssl_verify=args.shellparty_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 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.SHP_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.SHP_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 (Shellcoin Core) if backend_connect: config.BACKEND_CONNECT = backend_connect else: config.BACKEND_CONNECT = 'localhost' # Backend Core RPC port (Shellcoin Core) if backend_port: config.BACKEND_PORT = backend_port else: if config.TESTNET: if config.BACKEND_NAME == 'shelld': config.BACKEND_PORT = config.DEFAULT_BACKEND_PORT_TESTNET_SCHD else: config.BACKEND_PORT = config.DEFAULT_BACKEND_PORT_TESTNET else: if config.BACKEND_NAME == 'shelld': config.BACKEND_PORT = config.DEFAULT_BACKEND_PORT_SCHD 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 (Shellcoin Core) if backend_user: config.BACKEND_USER = backend_user else: config.BACKEND_USER = '******' # Backend Core RPC password (Shellcoin 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 = 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 # 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 shellparty-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