Exemple #1
0
async def alice_and_bob(alice_chain, bob_chain):
    pair_factory = ETHPeerPairFactory(
        alice_client_version='alice',
        alice_peer_context=ChainContextFactory(headerdb=AsyncHeaderDB(alice_chain.headerdb.db)),
        bob_client_version='bob',
        bob_peer_context=ChainContextFactory(headerdb=AsyncHeaderDB(bob_chain.headerdb.db)),
    )
    async with pair_factory as (alice, bob):
        yield alice, bob
async def alice_and_bob(common_base_chain, request):
    pair_factory = request.param(
        alice_client_version='alice',
        alice_peer_context=ChainContextFactory(headerdb=AsyncHeaderDB(
            common_base_chain.headerdb.db)),  # noqa: E501
        bob_client_version='bob',
        bob_peer_context=ChainContextFactory(
            headerdb=AsyncHeaderDB(common_base_chain.headerdb.db)),
    )
    async with pair_factory as (alice, bob):
        yield alice, bob
Exemple #3
0
    def make_eth1_request_server(cls,
                                 app_config: Eth1AppConfig,
                                 base_db: BaseAtomicDB,
                                 event_bus: EndpointAPI) -> Service:

        server: Service

        if app_config.database_mode is Eth1DbMode.LIGHT:
            header_db = AsyncHeaderDB(base_db)
            server = LightRequestServer(
                event_bus,
                TO_NETWORKING_BROADCAST_CONFIG,
                header_db
            )
        elif app_config.database_mode is Eth1DbMode.FULL:
            chain_db = AsyncChainDB(base_db)
            server = ETHRequestServer(
                event_bus,
                TO_NETWORKING_BROADCAST_CONFIG,
                chain_db
            )
        else:
            raise Exception(f"Unsupported Database Mode: {app_config.database_mode}")

        return server
Exemple #4
0
async def test_generate_eth_cap_enr_field():
    base_db = AtomicDB()
    ChainDB(base_db).persist_header(ROPSTEN_GENESIS_HEADER)

    enr_field = await generate_eth_cap_enr_field(ROPSTEN_VM_CONFIGURATION, AsyncHeaderDB(base_db))

    enr = ENRFactory(custom_kv_pairs={enr_field[0]: enr_field[1]})
    assert extract_forkid(enr) == ForkID(hash=to_bytes(hexstr='0x30c7ddbc'), next=10)
Exemple #5
0
async def test_handshake_with_incompatible_fork_id(alice_chain, bob_chain):

    alice_chain = build(alice_chain, mine_block())

    pair_factory = ETHPeerPairFactory(alice_peer_context=ChainContextFactory(
        headerdb=AsyncHeaderDB(alice_chain.headerdb.db),
        vm_configuration=((1, PetersburgVM), (2, MuirGlacierVM))), )
    with pytest.raises(WrongForkIDFailure):
        async with pair_factory as (alice, bob):
            pass
Exemple #6
0
    def __init__(self, event_bus: EndpointAPI,
                 trinity_config: TrinityConfig) -> None:
        super().__init__()
        self.trinity_config = trinity_config
        self._base_db = DBClient.connect(trinity_config.database_ipc_path)
        self._headerdb = AsyncHeaderDB(self._base_db)

        self._jsonrpc_ipc_path: Path = trinity_config.jsonrpc_ipc_path
        self._network_id = trinity_config.network_id

        self.event_bus = event_bus
Exemple #7
0
    def __init__(self, event_bus: EndpointAPI,
                 trinity_config: TrinityConfig) -> None:
        self.trinity_config = trinity_config
        self._base_db = DBClient.connect(trinity_config.database_ipc_path)
        self._headerdb = AsyncHeaderDB(self._base_db)

        self._jsonrpc_ipc_path: Path = trinity_config.jsonrpc_ipc_path
        self._network_id = trinity_config.network_id

        self.event_bus = event_bus
        self.master_cancel_token = CancelToken(type(self).__name__)
Exemple #8
0
    async def sync(self, args: Namespace, logger: Logger, chain: AsyncChainAPI,
                   base_db: AtomicDatabaseAPI, peer_pool: BasePeerPool,
                   event_bus: EndpointAPI, cancel_token: CancelToken) -> None:

        syncer = LightChainSyncer(
            chain,
            AsyncHeaderDB(base_db),
            cast(LESPeerPool, peer_pool),
            cancel_token,
        )

        await syncer.run()
Exemple #9
0
    async def sync(self, args: Namespace, logger: logging.Logger,
                   chain: AsyncChainAPI, base_db: AtomicDatabaseAPI,
                   peer_pool: BasePeerPool, event_bus: EndpointAPI) -> None:

        syncer = LightChainSyncer(
            chain,
            AsyncHeaderDB(base_db),
            cast(LESPeerPool, peer_pool),
        )

        async with background_asyncio_service(syncer) as manager:
            await manager.wait_finished()
Exemple #10
0
def get_eth1_chain_with_remote_db(
        boot_info: BootInfo, event_bus: EndpointAPI) -> Iterator[ChainAPI]:
    app_config = boot_info.trinity_config.get_app_config(Eth1AppConfig)
    chain_config = app_config.get_chain_config()

    chain: ChainAPI
    base_db = DBClient.connect(boot_info.trinity_config.database_ipc_path)
    with base_db:
        if boot_info.args.sync_mode == SYNC_LIGHT:
            header_db = AsyncHeaderDB(base_db)
            chain = chain_config.light_chain_class(
                header_db, peer_chain=EventBusLightPeerChain(event_bus))
        else:
            chain = chain_config.full_chain_class(base_db)

        yield chain
Exemple #11
0
def get_server(privkey, address, event_bus):
    base_db = AtomicDB()
    headerdb = AsyncHeaderDB(base_db)
    chaindb = ChainDB(base_db)
    chaindb.persist_header(ROPSTEN_GENESIS_HEADER)
    chain = RopstenChain(base_db)
    server = ParagonServer(
        privkey=privkey,
        port=address.tcp_port,
        chain=chain,
        chaindb=chaindb,
        headerdb=headerdb,
        base_db=base_db,
        network_id=NETWORK_ID,
        event_bus=event_bus,
    )
    return server
Exemple #12
0
    def get_chain(self) -> ChainAPI:
        app_config = self.boot_info.trinity_config.get_app_config(
            Eth1AppConfig)
        chain_config = app_config.get_chain_config()

        chain: ChainAPI
        base_db = DBClient.connect(
            self.boot_info.trinity_config.database_ipc_path)

        if self.boot_info.args.sync_mode == SYNC_LIGHT:
            header_db = AsyncHeaderDB(base_db)
            chain = chain_config.light_chain_class(
                header_db, peer_chain=EventBusLightPeerChain(self.event_bus))
        else:
            chain = chain_config.full_chain_class(base_db)

        return chain
Exemple #13
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()
Exemple #14
0
async def test_sync_integration(request, caplog, geth_ipc_path, enode,
                                geth_process):
    """Test a regular chain sync against a running geth instance.

    In order to run this manually, you can use `tox -e py37-sync_integration` or:

        pytest --integration --capture=no tests/integration/test_sync.py

    The fixture for this test was generated with:

        geth --ropsten --syncmode full

    It only needs the first 11 blocks for this test to succeed.
    """
    if not request.config.getoption("--integration"):
        pytest.skip("Not asked to run integration tests")

    # will almost certainly want verbose logging in a failure
    caplog.set_level(logging.DEBUG)

    # make sure geth has been launched
    wait_for_socket(geth_ipc_path)

    remote = Node.from_uri(enode)
    base_db = AtomicDB()
    chaindb = AsyncChainDB(base_db)
    chaindb.persist_header(ROPSTEN_GENESIS_HEADER)
    headerdb = AsyncHeaderDB(base_db)
    chain_config = Eth1ChainConfig.from_preconfigured_network(
        ROPSTEN_NETWORK_ID)
    chain = chain_config.initialize_chain(base_db)
    context = ChainContext(
        headerdb=headerdb,
        network_id=ROPSTEN_NETWORK_ID,
        vm_configuration=ROPSTEN_VM_CONFIGURATION,
        client_version_string='trinity-test',
        listen_port=30303,
        p2p_version=DEVP2P_V5,
    )
    peer_pool = ETHPeerPool(privkey=ecies.generate_privkey(), context=context)
    syncer = RegularChainSyncer(chain, chaindb, peer_pool)

    async with background_asyncio_service(peer_pool) as manager:
        await manager.wait_started()
        await peer_pool.connect_to_nodes([remote])
        assert len(peer_pool) == 1

        async with background_asyncio_service(syncer) as syncer_manager:
            await syncer_manager.wait_started()

            n = 11

            manager.logger.info(f"Waiting for the chain to sync {n} blocks")

            async def wait_for_header_sync(block_number):
                while chaindb.get_canonical_head().block_number < block_number:
                    await asyncio.sleep(0.1)

            await asyncio.wait_for(wait_for_header_sync(n), 5)

            # https://ropsten.etherscan.io/block/11
            header = chaindb.get_canonical_block_header_by_number(n)
            transactions = chaindb.get_block_transactions(
                header, BaseTransactionFields)
            assert len(transactions) == 15

            receipts = chaindb.get_receipts(header, Receipt)
            assert len(receipts) == 15
            assert encode_hex(keccak(rlp.encode(receipts[0]))) == (
                '0xf709ed2c57efc18a1675e8c740f3294c9e2cb36ba7bb3b89d3ab4c8fef9d8860'
            )
async def test_lightchain_integration(request, event_loop, caplog,
                                      geth_ipc_path, enode, geth_process):
    """Test LightChainSyncer/LightPeerChain against a running geth instance.

    In order to run this manually, you can use `tox -e py36-lightchain_integration` or:

        pytest --integration --capture=no tests/integration/test_lightchain_integration.py

    The fixture for this test was generated with:

        geth --testnet --syncmode full

    It only needs the first 11 blocks for this test to succeed.
    """
    if not request.config.getoption("--integration"):
        pytest.skip("Not asked to run integration tests")

    # will almost certainly want verbose logging in a failure
    caplog.set_level(logging.DEBUG)

    # make sure geth has been launched
    wait_for_socket(geth_ipc_path)

    remote = Node.from_uri(enode)
    base_db = AtomicDB()
    chaindb = AsyncChainDB(base_db)
    chaindb.persist_header(ROPSTEN_GENESIS_HEADER)
    headerdb = AsyncHeaderDB(base_db)
    context = ChainContext(
        headerdb=headerdb,
        network_id=ROPSTEN_NETWORK_ID,
        vm_configuration=ROPSTEN_VM_CONFIGURATION,
        client_version_string='trinity-test',
        listen_port=30303,
        p2p_version=DEVP2P_V5,
    )
    peer_pool = LESPeerPool(
        privkey=ecies.generate_privkey(),
        context=context,
    )
    chain = AsyncRopstenChain(base_db)
    syncer = LightChainSyncer(chain, chaindb, peer_pool)
    syncer.min_peers_to_sync = 1
    peer_chain = LightPeerChain(headerdb, peer_pool)

    asyncio.ensure_future(peer_pool.run())
    asyncio.ensure_future(connect_to_peers_loop(peer_pool, tuple([remote])))
    asyncio.ensure_future(peer_chain.run())
    asyncio.ensure_future(syncer.run())
    await asyncio.sleep(
        0)  # Yield control to give the LightChainSyncer a chance to start

    def finalizer():
        event_loop.run_until_complete(peer_pool.cancel())
        event_loop.run_until_complete(peer_chain.cancel())
        event_loop.run_until_complete(syncer.cancel())

    request.addfinalizer(finalizer)

    n = 11

    # Wait for the chain to sync a few headers.
    async def wait_for_header_sync(block_number):
        while headerdb.get_canonical_head().block_number < block_number:
            await asyncio.sleep(0.1)

    await asyncio.wait_for(wait_for_header_sync(n), 5)

    # https://ropsten.etherscan.io/block/11
    header = headerdb.get_canonical_block_header_by_number(n)
    body = await peer_chain.coro_get_block_body_by_hash(header.hash)
    assert len(body['transactions']) == 15

    receipts = await peer_chain.coro_get_receipts(header.hash)
    assert len(receipts) == 15
    assert encode_hex(keccak(rlp.encode(receipts[0]))) == (
        '0xf709ed2c57efc18a1675e8c740f3294c9e2cb36ba7bb3b89d3ab4c8fef9d8860')

    assert len(peer_pool) == 1
    peer = peer_pool.highest_td_peer
    head = await peer_chain.coro_get_block_header_by_hash(
        peer.head_info.head_hash)

    # In order to answer queries for contract code, geth needs the state trie entry for the block
    # we specify in the query, but because of fast sync we can only assume it has that for recent
    # blocks, so we use the current head to lookup the code for the contract below.
    # https://ropsten.etherscan.io/address/0x95a48dca999c89e4e284930d9b9af973a7481287
    contract_addr = decode_hex('0x8B09D9ac6A4F7778fCb22852e879C7F3B2bEeF81')
    contract_code = await peer_chain.coro_get_contract_code(
        head.hash, contract_addr)
    assert encode_hex(contract_code) == '0x600060006000600060006000356000f1'

    account = await peer_chain.coro_get_account(head.hash, contract_addr)
    assert account.code_hash == keccak(contract_code)
    assert account.balance == 0
Exemple #16
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()
Exemple #17
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()