def reload_logging_config(config_path): logger.info(f"Trying to reload the logging configuration from {config_path}") try: config = load_config(config_path) configure_logging(config) logger.info("Logging has been reconfigured") except Exception as err: # this function is being called as signal handler. make sure # we don't die as this would raise the error in the main # greenlet. logger.critical( f"Error while trying to reload the logging configuration from {config_path}: {err}" )
def main(ctx, config_path: str) -> None: """The Trustlines Bridge Validation Server Configuration can be made using a TOML file. See config.py for valid configuration options and defaults. """ try: logger.info(f"Loading configuration file from {config_path}") config = load_config(config_path) except TomlDecodeError as decode_error: raise click.UsageError(f"Invalid config file: {decode_error}") from decode_error except ValidationError as validation_error: raise click.UsageError( f"Invalid config file: {validation_error}" ) from validation_error configure_logging(config) validator_address = make_validator_address(config) logger.info( f"Starting Trustlines Bridge Validation Server for address {to_checksum_address(validator_address)}" ) install_signal_handler( signal.SIGHUP, "reload-logging-config", reload_logging_config, config_path ) for signum in [signal.SIGINT, signal.SIGTERM]: install_signal_handler(signum, "terminator", shutdown_raw, exitcode=0) try: start_services_in_main_pool([Service("start_system", start_system, config)]) except Exception as exception: logger.exception("Application error", exc_info=exception) os._exit(os.EX_SOFTWARE) finally: gevent.hub.get_hub().join()
def main(config_path: str) -> None: """The Trustlines Bridge Validation Server Configuration can be made using a TOML file or via Environment Variables. A dotenv (.env) file will be automatically evaluated. See .env.example and config.py for valid configuration options and defaults. """ try: config = load_config(config_path) except TomlDecodeError as decode_error: raise click.UsageError( f"Invalid config file: {decode_error}") from decode_error except ValueError as value_error: raise click.UsageError( f"Invalid config file: {value_error}") from value_error configure_logging(config) logger.info("Starting Trustlines Bridge Validation Server") w3_foreign = Web3( HTTPProvider( config["foreign_rpc_url"], request_kwargs={"timeout": config["foreign_rpc_timeout"]}, )) w3_home = Web3( HTTPProvider( config["home_rpc_url"], request_kwargs={"timeout": config["home_rpc_timeout"]}, )) home_bridge_contract = w3_home.eth.contract( address=config["home_bridge_contract_address"], abi=HOME_BRIDGE_ABI) validate_contract_existence(home_bridge_contract) validator_proxy_contract = get_validator_proxy_contract( home_bridge_contract) try: validate_contract_existence(validator_proxy_contract) except ValueError as error: raise ValueError( f"Serious bridge setup error. The validator proxy contract at the address the home " f"bridge property points to does not exist or is not intact!" ) from error token_contract = w3_foreign.eth.contract( address=config["foreign_chain_token_contract_address"], abi=MINIMAL_ERC20_TOKEN_ABI, ) validate_contract_existence(token_contract) validator_private_key = config["validator_private_key"] validator_address = PrivateKey( validator_private_key).public_key.to_canonical_address() transfer_event_queue = Queue() home_bridge_event_queue = Queue() confirmation_task_queue = Queue() transfer_event_fetcher = EventFetcher( web3=w3_foreign, contract=token_contract, filter_definition={ TRANSFER_EVENT_NAME: { "to": config["foreign_bridge_contract_address"] } }, event_queue=transfer_event_queue, max_reorg_depth=config["foreign_chain_max_reorg_depth"], start_block_number=config[ "foreign_chain_event_fetch_start_block_number"], ) home_bridge_event_fetcher = EventFetcher( web3=w3_home, contract=home_bridge_contract, filter_definition={ CONFIRMATION_EVENT_NAME: { "validator": validator_address }, COMPLETION_EVENT_NAME: {}, }, event_queue=home_bridge_event_queue, max_reorg_depth=config["home_chain_max_reorg_depth"], start_block_number=config["home_chain_event_fetch_start_block_number"], ) confirmation_task_planner = ConfirmationTaskPlanner( sync_persistence_time=HOME_CHAIN_STEP_DURATION, transfer_event_queue=transfer_event_queue, home_bridge_event_queue=home_bridge_event_queue, confirmation_task_queue=confirmation_task_queue, ) confirmation_sender = ConfirmationSender( transfer_event_queue=confirmation_task_queue, home_bridge_contract=home_bridge_contract, private_key=config["validator_private_key"], gas_price=config["home_chain_gas_price"], max_reorg_depth=config["home_chain_max_reorg_depth"], ) try: coroutines_and_args = [ ( transfer_event_fetcher.fetch_events, config["foreign_chain_event_poll_interval"], ), ( home_bridge_event_fetcher.fetch_events, config["home_chain_event_poll_interval"], ), (confirmation_task_planner.run, ), (confirmation_sender.run, ), ] greenlets = [ Greenlet.spawn(*coroutine_and_args) for coroutine_and_args in coroutines_and_args ] gevent.joinall(greenlets, raise_error=True) finally: for greenlet in greenlets: greenlet.kill()