Esempio n. 1
0
async def test_peer_pool_answers_connect_commands(event_bus, server,
                                                  receiver_remote):
    # This is the PeerPool which will accept our message and try to connect to {server}
    initiator_peer_pool = ParagonPeerPool(
        privkey=INITIATOR_PRIVKEY,
        context=ParagonContext(),
        event_bus=event_bus,
    )
    async with background_asyncio_service(initiator_peer_pool) as manager:
        await manager.wait_started()
        async with run_peer_pool_event_server(event_bus, initiator_peer_pool):

            assert len(server.peer_pool.connected_nodes) == 0

            await event_bus.wait_until_any_endpoint_subscribed_to(
                ConnectToNodeCommand)
            await event_bus.broadcast(ConnectToNodeCommand(receiver_remote),
                                      TO_NETWORKING_BROADCAST_CONFIG)

            # This test was maybe 30% flaky at 0.1 sleep, so wait in a loop.
            for _ in range(5):
                await asyncio.sleep(0.1)
                if len(server.peer_pool.connected_nodes) == 1:
                    break
            else:
                assert len(server.peer_pool.connected_nodes) == 1
Esempio n. 2
0
async def test_peer_pool_connect(monkeypatch, server, receiver_remote):
    peer_started = asyncio.Event()

    start_peer = server.peer_pool.start_peer

    async def mock_start_peer(peer):
        # Call the original start_peer() so that we create and run Peer/Connection objects,
        # which will ensure everything is cleaned up properly.
        await start_peer(peer)
        peer_started.set()

    monkeypatch.setattr(server.peer_pool, 'start_peer', mock_start_peer)

    initiator_peer_pool = ParagonPeerPool(
        privkey=INITIATOR_PRIVKEY,
        context=ParagonContext(),
    )
    nodes = [receiver_remote]
    async with background_asyncio_service(initiator_peer_pool) as manager:
        await manager.wait_started()
        await initiator_peer_pool.connect_to_nodes(nodes)

        await asyncio.wait_for(peer_started.wait(), timeout=1)

        assert len(initiator_peer_pool.connected_nodes) == 1
Esempio n. 3
0
async def test_remote_dao_fork_validation_skipped_on_eth64(monkeypatch):
    dao_fork_validator_called = False

    async def validate_remote_dao_fork_block():
        nonlocal dao_fork_validator_called
        dao_fork_validator_called = True

    async with LatestETHPeerPairFactory() as (alice, _):
        boot_manager = alice.get_boot_manager()
        monkeypatch.setattr(boot_manager, 'validate_remote_dao_fork_block',
                            validate_remote_dao_fork_block)
        async with background_asyncio_service(boot_manager) as manager:
            await manager.wait_finished()
        assert not dao_fork_validator_called
Esempio n. 4
0
async def test_peer_pool_connect(monkeypatch, server, receiver_remote):
    receiving_peer_pool = server.peer_pool
    peer_started = asyncio.Event()

    add_inbound_peer = receiving_peer_pool.add_inbound_peer

    async def mock_add_inbound_peer(peer):
        # Call the original add_inbound_peer() so that we create and run Peer/Connection objects,
        # which will ensure everything is cleaned up properly.
        await add_inbound_peer(peer)
        peer_started.set()

    monkeypatch.setattr(receiving_peer_pool, 'add_inbound_peer',
                        mock_add_inbound_peer)

    broadcast_msg_buffer = BroadcastMsgCollector()
    receiving_peer_pool.subscribe(broadcast_msg_buffer)

    initiator_peer_pool = ParagonPeerPool(
        privkey=INITIATOR_PRIVKEY,
        context=ParagonContext(),
    )
    nodes = [receiver_remote]
    async with background_asyncio_service(initiator_peer_pool) as manager:
        await manager.wait_started()
        await initiator_peer_pool.connect_to_nodes(nodes)

        await asyncio.wait_for(peer_started.wait(), timeout=2)

        assert len(initiator_peer_pool.connected_nodes) == 1

        peer = list(initiator_peer_pool.connected_nodes.values())[0]

        receiving_peer = list(receiving_peer_pool.connected_nodes.values())[0]
        # Once our peer is running, it will start streaming messages, which will be stored in our
        # msg buffer.
        assert receiving_peer.connection.is_streaming_messages

        peer.connection.get_logic(ParagonAPI.name,
                                  ParagonAPI).send_broadcast_data(b'data')
        msg = await asyncio.wait_for(broadcast_msg_buffer.msg_queue.get(),
                                     timeout=0.5)
        assert msg.command.payload.data == b'data'
Esempio n. 5
0
async def server(event_bus, receiver_remote):
    server = get_server(RECEIVER_PRIVKEY, receiver_remote.address, event_bus)
    async with background_asyncio_service(server):
        yield server
Esempio n. 6
0
async def server(event_bus, receiver_remote):
    server = get_server(RECEIVER_PRIVKEY, receiver_remote.address, event_bus)
    async with background_asyncio_service(server):
        await asyncio.wait_for(server.ready.wait(), timeout=2)
        yield server
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)

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

    async with background_asyncio_service(peer_pool) as manager:
        await manager.wait_started()
        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

        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
Esempio n. 8
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'
            )
Esempio n. 9
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()