Пример #1
0
async def test_beacon_node_and_validator_client_can_talk(
    autojump_clock,
    node_key,
    eth2_config,
    chain_config,
    database_dir,
    chain_class,
    get_trio_time,
):
    client_id = construct_trinity_client_identifier()
    validator_api_port = 0
    node = BeaconNode(
        node_key,
        eth2_config,
        chain_config,
        database_dir,
        chain_class,
        validator_api_port,
        client_id,
        get_trio_time,
    )

    a_short_timeout = 5
    with trio.move_on_after(a_short_timeout):
        async with trio.open_nursery() as nursery:
            await nursery.start(node.run)
            api_client = BeaconNodeClient(
                chain_config.genesis_time,
                f"http://localhost:{node.validator_api_port}",
                eth2_config.SECONDS_PER_SLOT,
            )
            await api_client.load_client_version()
            assert api_client.client_version == client_id
Пример #2
0
async def test_beacon_node_can_count_slots(
    autojump_clock,
    node_key,
    eth2_config,
    chain_config,
    database_dir,
    chain_class,
    get_trio_time,
):
    validator_api_port = 0
    client_id = construct_trinity_client_identifier()
    node = BeaconNode(
        node_key,
        eth2_config,
        chain_config,
        database_dir,
        chain_class,
        validator_api_port,
        client_id,
        get_trio_time,
    )

    some_slots = 10
    a_future_slot = node.current_tick.slot + some_slots
    seconds = some_slots * eth2_config.SECONDS_PER_SLOT
    with trio.move_on_after(seconds):
        await node.run()
    assert node.current_tick.slot == a_future_slot
Пример #3
0
 def __init__(
     self, chain: BaseBeaconChain, event_bus: EndpointAPI, genesis_time: int
 ):
     self._chain = chain
     self._event_bus = event_bus
     self._genesis_time = genesis_time
     self._client_identifier = construct_trinity_client_identifier()
Пример #4
0
def display_launch_logs(trinity_config: TrinityConfig) -> None:
    logger = logging.getLogger('trinity')
    logger.info(TRINITY_HEADER)
    logger.info("Started main process (pid=%d)", os.getpid())
    logger.info(construct_trinity_client_identifier())
    logger.info("Trinity DEBUG log file is created at %s",
                str(trinity_config.logfile_path))
Пример #5
0
def main_entry_trio(
    app_identifier: str,
    component_types: Tuple[Type[BaseComponentAPI], ...],
    sub_configs: Sequence[Type[BaseAppConfig]],
) -> None:
    boot_info, _ = construct_boot_info(app_identifier, component_types,
                                       sub_configs)
    args = boot_info.args
    trinity_config = boot_info.trinity_config

    # Components can provide a subcommand with a `func` which does then control
    # the entire process from here.
    if hasattr(args, "func"):
        args.func(args, trinity_config)
        return

    _initialize_beacon_filesystem(boot_info)

    logger = logging.getLogger("trinity")
    pid = os.getpid()
    identifier = construct_trinity_client_identifier()
    logger.info("Booted client with identifier: %s and process id %d",
                identifier, pid)

    runtime_component_types = tuple(
        component_cls for component_cls in component_types
        if issubclass(component_cls, TrioComponent))
    trio.run(_run_trio_components_until_interrupt, runtime_component_types,
             boot_info)
    # NOTE: mypy bug that does not type this... it works in `./bootstrap.py`
    if trinity_config.trinity_tmp_root_dir:  # type: ignore
        shutil.rmtree(trinity_config.trinity_root_dir)
Пример #6
0
 def send_handshake(self) -> None:
     # TODO: move import out once this is in the trinity codebase
     from trinity._utils.version import construct_trinity_client_identifier
     data = dict(
         version=self.version,
         client_version_string=construct_trinity_client_identifier(),
         capabilities=self.peer.capabilities,
         listen_port=self.peer.listen_port,
         remote_pubkey=self.peer.privkey.public_key.to_bytes())
     header, body = Hello(self.cmd_id_offset).encode(data)
     self.send(header, body)
Пример #7
0
 def _make_peer_pool(self) -> BCCPeerPool:
     context = BeaconContext(
         chain_db=cast(BaseAsyncBeaconChainDB, self.chaindb),
         network_id=self.network_id,
         client_version_string=construct_trinity_client_identifier(),
         listen_port=self.port,
     )
     return BCCPeerPool(privkey=self.privkey,
                        max_peers=self.max_peers,
                        context=context,
                        token=self.cancel_token,
                        event_bus=self.event_bus)
Пример #8
0
 def get_node_info(self) -> EthstatsData:
     """Getter for data that should be sent once, on start-up."""
     return {
         'name': self.node_id,
         'contact': self.node_contact,
         'node': construct_trinity_client_identifier(),
         'net': self.boot_info.trinity_config.network_id,
         'port': self.boot_info.trinity_config.port,
         'os': platform.system(),
         'os_v': platform.release(),
         'client': __version__,
         'canUpdateHistory': False,
     }
Пример #9
0
 def _make_peer_pool(self) -> LESPeerPool:
     context = ChainContext(
         headerdb=self.headerdb,
         network_id=self.network_id,
         vm_configuration=self.chain.vm_configuration,
         client_version_string=construct_trinity_client_identifier(),
         listen_port=self.port,
     )
     return LESPeerPool(privkey=self.privkey,
                        max_peers=self.max_peers,
                        context=context,
                        token=self.cancel_token,
                        event_bus=self.event_bus)
Пример #10
0
 def __init__(
         self,
         config: TrinityConfig,
         p2p_maddr: Multiaddr,
         orchestration_profile: str,
         bootstrap_nodes: Tuple[Multiaddr, ...] = (),
         preferred_nodes: Tuple[Multiaddr, ...] = (),
 ) -> None:
     super().__init__(config)
     self.p2p_maddr = p2p_maddr
     self.bootstrap_nodes = config.bootstrap_nodes
     self.preferred_nodes = config.preferred_nodes
     self.client_identifier = construct_trinity_client_identifier()
     self.orchestration_profile = orchestration_profile
Пример #11
0
 async def nodeInfo(self) -> RpcNodeInfoResponse:
     response = await self.event_bus.request(
         GetProtocolCapabilitiesRequest(), TO_NETWORKING_BROADCAST_CONFIG)
     return {
         'enode': format_enode(self.trinity_config),
         # TODO: get the external ip from the upnp service
         'ip': "::",
         'listenAddr': f"[::]:{self.trinity_config.port}",
         'name': construct_trinity_client_identifier(),
         'ports': {
             'discovery': self.trinity_config.port,
             'listener': self.trinity_config.port
         },
         'protocols': await
         self._generate_protocol_info(response.capabilities)
     }
Пример #12
0
    def __init__(
        self,
        privkey: datatypes.PrivateKey,
        port: int,
        chain: AsyncChainAPI,
        chaindb: BaseAsyncChainDB,
        headerdb: BaseAsyncHeaderDB,
        base_db: AtomicDatabaseAPI,
        network_id: int,
        max_peers: int = DEFAULT_MAX_PEERS,
        bootstrap_nodes: Sequence[NodeAPI] = None,
        preferred_nodes: Sequence[NodeAPI] = None,
        event_bus: EndpointAPI = None,
        token: CancelToken = None,
    ) -> None:
        super().__init__(token)
        # cross process event bus
        self.event_bus = event_bus

        # setup parameters for the base devp2p handshake.
        self.p2p_handshake_params = DevP2PHandshakeParams(
            client_version_string=construct_trinity_client_identifier(),
            listen_port=port,
            version=DEVP2P_V5,
        )

        # chain information
        self.chain = chain
        self.chaindb = chaindb
        self.headerdb = headerdb
        self.base_db = base_db

        # node information
        self.privkey = privkey
        self.port = port
        self.network_id = network_id
        self.max_peers = max_peers
        self.bootstrap_nodes = bootstrap_nodes
        self.preferred_nodes = preferred_nodes
        if self.preferred_nodes is None and network_id in DEFAULT_PREFERRED_NODES:
            self.preferred_nodes = DEFAULT_PREFERRED_NODES[self.network_id]

        # child services
        self.peer_pool = self._make_peer_pool()

        if not bootstrap_nodes:
            self.logger.warning("Running with no bootstrap nodes")
Пример #13
0
 def __init__(
     self,
     config: TrinityConfig,
     network_name: str,
     network_config: Eth2Config,
     p2p_maddr: Multiaddr,
     validator_api_port: int,
     bootstrap_nodes: Tuple[Multiaddr, ...] = (),
     preferred_nodes: Tuple[Multiaddr, ...] = (),
     genesis_state_ssz: Optional[Path] = None,
 ) -> None:
     super().__init__(config)
     self.p2p_maddr = p2p_maddr
     self.network_name = network_name
     self.network_config = network_config
     self.validator_api_port = validator_api_port
     self.bootstrap_nodes = bootstrap_nodes
     self.preferred_nodes = preferred_nodes
     self.client_identifier = construct_trinity_client_identifier()
     self.genesis_state_ssz = genesis_state_ssz
Пример #14
0
    def __init__(
        self,
        privkey: datatypes.PrivateKey,
        port: int,
        chain: AsyncChainAPI,
        chaindb: BaseAsyncChainDB,
        headerdb: BaseAsyncHeaderDB,
        base_db: AtomicDatabaseAPI,
        network_id: int,
        max_peers: int = DEFAULT_MAX_PEERS,
        event_bus: EndpointAPI = None,
        metrics_registry: MetricsRegistry = None,
    ) -> None:
        self.logger = get_logger(self.__module__ + '.' +
                                 self.__class__.__name__)
        # cross process event bus
        self.event_bus = event_bus
        self.metrics_registry = metrics_registry

        # setup parameters for the base devp2p handshake.
        self.p2p_handshake_params = DevP2PHandshakeParams(
            client_version_string=construct_trinity_client_identifier(),
            listen_port=port,
            version=DEVP2P_V5,
        )

        # chain information
        self.chain = chain
        self.chaindb = chaindb
        self.headerdb = headerdb
        self.base_db = base_db

        # node information
        self.privkey = privkey
        self.port = port
        self.network_id = network_id
        self.max_peers = max_peers

        # child services
        self.peer_pool = self._make_peer_pool()
Пример #15
0
def _main() -> None:
    logging.basicConfig(level=DEBUG2_LEVEL_NUM, format='%(asctime)s %(levelname)s: %(message)s')

    parser = argparse.ArgumentParser()
    parser.add_argument('-enode', type=str, help="The enode we should connect to", required=True)
    parser.add_argument('-mainnet', action='store_true')
    parser.add_argument('-light', action='store_true', help="Connect as a light node")
    args = parser.parse_args()

    peer_class: Union[Type[ETHPeer], Type[LESPeer]]
    pool_class: Union[Type[ETHPeerPool], Type[LESPeerPool]]

    if args.light:
        peer_class = LESPeer
        pool_class = LESPeerPool
    else:
        peer_class = ETHPeer
        pool_class = ETHPeerPool

    if args.mainnet:
        chain_id = MainnetChain.chain_id
        vm_config = MAINNET_VM_CONFIGURATION
        genesis = MAINNET_GENESIS_HEADER
    else:
        chain_id = RopstenChain.chain_id
        vm_config = ROPSTEN_VM_CONFIGURATION
        genesis = ROPSTEN_GENESIS_HEADER

    headerdb = AsyncHeaderDB(AtomicDB(MemoryDB()))
    headerdb.persist_header(genesis)
    loop = asyncio.get_event_loop()
    nodes = [Node.from_uri(args.enode)]

    context = ChainContext(
        headerdb=headerdb,
        network_id=chain_id,
        vm_configuration=vm_config,
        client_version_string=construct_trinity_client_identifier(),
        listen_port=30309,
        p2p_version=DEVP2P_V5,
    )
    peer_pool = pool_class(
        privkey=ecies.generate_privkey(),
        context=context,
    )

    asyncio.ensure_future(peer_pool.run())
    peer_pool.run_task(connect_to_peers_loop(peer_pool, nodes))

    async def request_stuff() -> None:
        # Request some stuff from ropsten's block 2440319
        # (https://ropsten.etherscan.io/block/2440319), just as a basic test.
        nonlocal peer_pool
        while not peer_pool.connected_nodes:
            peer_pool.logger.info("Waiting for peer connection...")
            await asyncio.sleep(0.2)
        peer = peer_pool.highest_td_peer
        headers = await cast(ETHPeer, peer).eth_api.get_block_headers(
            BlockNumber(2440319),
            max_headers=100
        )
        hashes = tuple(header.hash for header in headers)
        if peer_class == ETHPeer:
            peer = cast(ETHPeer, peer)
            peer.eth_api.send_get_block_bodies(hashes)
            peer.eth_api.send_get_receipts(hashes)
        else:
            peer = cast(LESPeer, peer)
            peer.les_api.send_get_block_bodies(list(hashes))
            peer.les_api.send_get_receipts(hashes[0])

    sigint_received = asyncio.Event()
    for sig in [signal.SIGINT, signal.SIGTERM]:
        loop.add_signal_handler(sig, sigint_received.set)

    async def exit_on_sigint() -> None:
        await sigint_received.wait()
        await peer_pool.cancel()
        loop.stop()

    asyncio.ensure_future(exit_on_sigint())
    asyncio.ensure_future(request_stuff())
    loop.set_debug(True)
    loop.run_forever()
    loop.close()
Пример #16
0
 async def clientVersion(self) -> str:
     """
     Returns the current client version.
     """
     return construct_trinity_client_identifier()
Пример #17
0
 def __init__(self, config: TrinityConfig) -> None:
     super().__init__(config)
     self.bootstrap_nodes = config.bootstrap_nodes
     self.preferred_nodes = config.preferred_nodes
     self.client_identifier = construct_trinity_client_identifier()
Пример #18
0
 ),
 (
     build_request('eth_mining'),
     {'result': False, 'id': 3, 'jsonrpc': '2.0'},
 ),
 (
     build_request('eth_coinbase'),
     {'result': '0x0000000000000000000000000000000000000000', 'id': 3, 'jsonrpc': '2.0'},
 ),
 (
     build_request('eth_hashrate'),
     {'result': '0x0', 'id': 3, 'jsonrpc': '2.0'},
 ),
 (
     build_request('web3_clientVersion'),
     {'result': construct_trinity_client_identifier(), 'id': 3, 'jsonrpc': '2.0'},
 ),
 (
     build_request('web3_sha3', ['0x89987239849872']),
     {
         'result': '0xb3406131994d9c859de3c4400e12f630638e1e992c6453358c16d0e6ce2b1a70',
         'id': 3,
         'jsonrpc': '2.0',
     },
 ),
 (
     build_request('web3_sha3', ['0x']),
     {
         'result': '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470',
         'id': 3,
         'jsonrpc': '2.0',
Пример #19
0
async def _main() -> None:
    parser = argparse.ArgumentParser()
    parser.add_argument('-enode',
                        type=str,
                        help="The enode we should connect to",
                        required=True)
    parser.add_argument('-mainnet', action='store_true')
    parser.add_argument('-light',
                        action='store_true',
                        help="Connect as a light node")
    parser.add_argument('-debug', action="store_true")
    args = parser.parse_args()

    log_level = logging.INFO
    if args.debug:
        log_level = DEBUG2_LEVEL_NUM
    logging.basicConfig(level=log_level,
                        format='%(asctime)s %(levelname)s: %(message)s',
                        datefmt='%H:%M:%S')

    peer_class: Union[Type[ETHPeer], Type[LESPeer]]
    pool_class: Union[Type[ETHPeerPool], Type[LESPeerPool]]

    if args.light:
        peer_class = LESPeer
        pool_class = LESPeerPool
    else:
        peer_class = ETHPeer
        pool_class = ETHPeerPool

    bootnodes: Tuple[str, ...]
    if args.mainnet:
        bootnodes = MAINNET_BOOTNODES
        chain_id = MainnetChain.chain_id
        vm_config = MAINNET_VM_CONFIGURATION
        genesis = MAINNET_GENESIS_HEADER
    else:
        bootnodes = ROPSTEN_BOOTNODES
        chain_id = RopstenChain.chain_id
        vm_config = ROPSTEN_VM_CONFIGURATION
        genesis = ROPSTEN_GENESIS_HEADER

    headerdb = AsyncHeaderDB(AtomicDB(MemoryDB()))
    headerdb.persist_header(genesis)
    loop = asyncio.get_event_loop()
    if args.enode == "bootnodes":
        nodes = [Node.from_uri(enode) for enode in bootnodes]
    else:
        nodes = [Node.from_uri(args.enode)]

    context = ChainContext(
        headerdb=headerdb,
        network_id=chain_id,
        vm_configuration=vm_config,
        client_version_string=construct_trinity_client_identifier(),
        listen_port=30309,
        p2p_version=DEVP2P_V5,
    )
    peer_pool = pool_class(privkey=ecies.generate_privkey(), context=context)

    async def request_stuff() -> None:
        nonlocal peer_pool
        # Request some stuff from ropsten's block 2440319
        # (https://ropsten.etherscan.io/block/2440319), just as a basic test.
        peer = peer_pool.highest_td_peer
        if peer_class == ETHPeer:
            peer = cast(ETHPeer, peer)
            headers = await peer.eth_api.get_block_headers(
                BlockNumber(2440319), max_headers=100)
            hashes = tuple(header.hash for header in headers)
            peer.eth_api.send_get_block_bodies(hashes)
            peer.eth_api.send_get_receipts(hashes)
        else:
            peer = cast(LESPeer, peer)
            headers = await peer.les_api.get_block_headers(
                BlockNumber(2440319), max_headers=100)
            peer.les_api.send_get_block_bodies(list(hashes))
            peer.les_api.send_get_receipts(hashes[:1])

    async with background_asyncio_service(peer_pool) as manager:
        for sig in [signal.SIGINT, signal.SIGTERM]:
            loop.add_signal_handler(sig, manager.cancel)

        await peer_pool.connect_to_nodes(nodes)
        await asyncio.sleep(1)
        if len(peer_pool) == 0:
            peer_pool.logger.error(f"Unable to connect to any of {nodes}")
            return

        try:
            await asyncio.wait_for(request_stuff(), timeout=2)
        except asyncio.TimeoutError:
            peer_pool.logger.error("Timeout waiting for replies")
        await manager.wait_finished()
Пример #20
0
def client_id():
    return construct_trinity_client_identifier()
Пример #21
0
def test_construct_trinity_client_identifier():
    assert construct_trinity_client_identifier().startswith('Trinity/')
Пример #22
0
async def _main() -> None:
    parser = argparse.ArgumentParser()
    parser.add_argument('-db', type=str, required=True)
    parser.add_argument('-light', action="store_true")
    parser.add_argument('-nodekey', type=str)
    parser.add_argument('-enode',
                        type=str,
                        required=False,
                        help="The enode we should connect to")
    parser.add_argument('-debug', action="store_true")
    args = parser.parse_args()

    logging.basicConfig(level=logging.INFO,
                        format='%(asctime)s %(levelname)s: %(message)s',
                        datefmt='%H:%M:%S')
    log_level = logging.INFO
    if args.debug:
        log_level = logging.DEBUG

    loop = asyncio.get_event_loop()

    base_db = LevelDB(args.db)
    headerdb = AsyncHeaderDB(AtomicDB(base_db))
    chaindb = AsyncChainDB(AtomicDB(base_db))
    try:
        genesis = chaindb.get_canonical_block_header_by_number(BlockNumber(0))
    except HeaderNotFound:
        genesis = ROPSTEN_GENESIS_HEADER
        chaindb.persist_header(genesis)

    peer_pool_class: Type[Union[ETHPeerPool, LESPeerPool]] = ETHPeerPool
    if args.light:
        peer_pool_class = LESPeerPool

    chain_class: Union[Type[AsyncRopstenChain], Type[AsyncMainnetChain]]
    if genesis.hash == ROPSTEN_GENESIS_HEADER.hash:
        chain_id = RopstenChain.chain_id
        vm_config = ROPSTEN_VM_CONFIGURATION
        chain_class = AsyncRopstenChain
    elif genesis.hash == MAINNET_GENESIS_HEADER.hash:
        chain_id = MainnetChain.chain_id
        vm_config = MAINNET_VM_CONFIGURATION  # type: ignore
        chain_class = AsyncMainnetChain
    else:
        raise RuntimeError("Unknown genesis: %s", genesis)

    if args.nodekey:
        privkey = load_nodekey(Path(args.nodekey))
    else:
        privkey = ecies.generate_privkey()

    context = ChainContext(
        headerdb=headerdb,
        network_id=chain_id,
        vm_configuration=vm_config,
        client_version_string=construct_trinity_client_identifier(),
        listen_port=30309,
        p2p_version=DEVP2P_V5,
    )

    peer_pool = peer_pool_class(privkey=privkey, context=context)

    if args.enode:
        nodes = tuple([Node.from_uri(args.enode)])
    else:
        nodes = DEFAULT_PREFERRED_NODES[chain_id]

    async with background_asyncio_service(peer_pool) as manager:
        manager.run_task(connect_to_peers_loop(peer_pool,
                                               nodes))  # type: ignore
        chain = chain_class(base_db)
        syncer: Service = None
        if args.light:
            syncer = LightChainSyncer(chain, headerdb,
                                      cast(LESPeerPool, peer_pool))
        else:
            syncer = RegularChainSyncer(chain, chaindb,
                                        cast(ETHPeerPool, peer_pool))
        logging.getLogger().setLevel(log_level)

        sigint_received = asyncio.Event()
        for sig in [signal.SIGINT, signal.SIGTERM]:
            loop.add_signal_handler(sig, sigint_received.set)

        async def exit_on_sigint() -> None:
            await sigint_received.wait()
            syncer.get_manager().cancel()

        asyncio.ensure_future(exit_on_sigint())

        async with background_asyncio_service(syncer) as syncer_manager:
            await syncer_manager.wait_finished()
Пример #23
0
         'id': 3,
         'jsonrpc': '2.0'
     },
 ),
 (
     build_request('eth_hashrate'),
     {
         'result': '0x0',
         'id': 3,
         'jsonrpc': '2.0'
     },
 ),
 (
     build_request('web3_clientVersion'),
     {
         'result': construct_trinity_client_identifier(),
         'id': 3,
         'jsonrpc': '2.0'
     },
 ),
 (
     build_request('web3_sha3', ['0x89987239849872']),
     {
         'result':
         '0xb3406131994d9c859de3c4400e12f630638e1e992c6453358c16d0e6ce2b1a70',
         'id': 3,
         'jsonrpc': '2.0',
     },
 ),
 (
     build_request('web3_sha3', ['0x']),
Пример #24
0
class Network(enum.IntEnum):
    MAINNET = MAINNET_NETWORK_ID
    GOERLI = GOERLI_NETWORK_ID
    ROPSTEN = ROPSTEN_NETWORK_ID


API_URLS = {
    Network.MAINNET: "https://api.etherscan.io/api",
    Network.GOERLI: "https://api-goerli.etherscan.io/api",
    Network.ROPSTEN: "https://api-ropsten.etherscan.io/api",
}

# The Etherscan API for Goerli and Ropsten rejects any requests without User-Agent

COMMON_REQUEST_HEADERS = {'User-Agent': construct_trinity_client_identifier()}


class Etherscan:
    def __init__(self, api_key: str) -> None:
        if not api_key:
            raise ValueError(
                "Must provide an API key for Etherscan API access")

        self.api_key = api_key

    def get_proxy_api_url(self, network: Network) -> str:
        return f"{API_URLS[network]}?module=proxy&apikey={self.api_key}"

    def post(self, action: str, network: Network) -> Any:
        response = requests.post(