def wait_until_foreign_node_is_ready(config): wait_for_node_fully_synced(config, ChainRole.foreign) w3_foreign = make_w3_foreign(config) token_contract = w3_foreign.eth.contract( address=config["foreign_chain"]["token_contract_address"], abi=MINIMAL_ERC20_TOKEN_ABI, ) validate_contract_existence(token_contract) logger.info("foreign node has passed the sanity checks")
def sanity_check_home_bridge_contracts(home_bridge_contract): 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 SetupError( "Serious bridge setup error. The validator proxy contract at the address the home " "bridge property points to does not exist or is not intact!" ) from error balance = home_bridge_contract.web3.eth.getBalance(home_bridge_contract.address) if balance == 0: raise SetupError("Serious bridge setup error. The bridge has no funds.")
def test_validate_contract_existence_not_matching_abi( internal_home_bridge_contract): internal_home_bridge_contract.abi = FAKE_ERC20_TOKEN_ABI with pytest.raises(ValueError): validate_contract_existence(internal_home_bridge_contract)
def test_validate_contract_existence_undeployed_address( internal_home_bridge_contract): internal_home_bridge_contract.address = "0x0000000000000000000000000000000000000000" with pytest.raises(ValueError): validate_contract_existence(internal_home_bridge_contract)
def test_validate_contract_existence_successfully( internal_home_bridge_contract): validate_contract_existence(internal_home_bridge_contract)
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()