示例#1
0
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")
示例#2
0
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.")
示例#3
0
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)
示例#4
0
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)
示例#5
0
def test_validate_contract_existence_successfully(
        internal_home_bridge_contract):
    validate_contract_existence(internal_home_bridge_contract)
示例#6
0
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()