Search in sources :

Example 1 with Message

use of org.hyperledger.besu.ethereum.p2p.rlpx.wire.Message in project besu by hyperledger.

the class EthProtocolManager method processMessage.

@Override
public void processMessage(final Capability cap, final Message message) {
    checkArgument(getSupportedCapabilities().contains(cap), "Unsupported capability passed to processMessage(): " + cap);
    final MessageData messageData = message.getData();
    final int code = messageData.getCode();
    LOG.trace("Process message {}, {}", cap, code);
    final EthPeer ethPeer = ethPeers.peer(message.getConnection());
    if (ethPeer == null) {
        LOG.debug("Ignoring message received from unknown peer connection: {}", message.getConnection());
        return;
    }
    if (messageData.getSize() > 10 * 1_000_000) /*10MB*/
    {
        LOG.debug("Received message over 10MB. Disconnecting from {}", ethPeer);
        ethPeer.disconnect(DisconnectReason.BREACH_OF_PROTOCOL);
        return;
    }
    // Handle STATUS processing
    if (code == EthPV62.STATUS) {
        handleStatusMessage(ethPeer, messageData);
        return;
    } else if (!ethPeer.statusHasBeenReceived()) {
        // Peers are required to send status messages before any other message type
        LOG.debug("{} requires a Status ({}) message to be sent first.  Instead, received message {}.  Disconnecting from {}.", this.getClass().getSimpleName(), EthPV62.STATUS, code, ethPeer);
        ethPeer.disconnect(DisconnectReason.BREACH_OF_PROTOCOL);
        return;
    }
    final EthMessage ethMessage = new EthMessage(ethPeer, messageData);
    if (!ethPeer.validateReceivedMessage(ethMessage, getSupportedProtocol())) {
        LOG.debug("Unsolicited message received from, disconnecting: {}", ethPeer);
        ethPeer.disconnect(DisconnectReason.BREACH_OF_PROTOCOL);
        return;
    }
    if (isFinalized() && (code == EthPV62.NEW_BLOCK || code == EthPV62.NEW_BLOCK_HASHES)) {
        LOG.debug("disconnecting peer for sending new blocks after transition to PoS");
        ethPeer.disconnect(DisconnectReason.SUBPROTOCOL_TRIGGERED);
    }
    // This will handle responses
    ethPeers.dispatchMessage(ethPeer, ethMessage, getSupportedProtocol());
    // This will handle requests
    Optional<MessageData> maybeResponseData = Optional.empty();
    try {
        if (EthProtocol.isEth66Compatible(cap) && EthProtocol.requestIdCompatible(code)) {
            final Map.Entry<BigInteger, MessageData> requestIdAndEthMessage = ethMessage.getData().unwrapMessageData();
            maybeResponseData = ethMessages.dispatch(new EthMessage(ethPeer, requestIdAndEthMessage.getValue())).map(responseData -> responseData.wrapMessageData(requestIdAndEthMessage.getKey()));
        } else {
            maybeResponseData = ethMessages.dispatch(ethMessage);
        }
    } catch (final RLPException e) {
        LOG.debug("Received malformed message {} , disconnecting: {}", messageData.getData(), ethPeer, e);
        ethPeer.disconnect(DisconnectMessage.DisconnectReason.BREACH_OF_PROTOCOL);
    }
    maybeResponseData.ifPresent(responseData -> {
        try {
            ethPeer.send(responseData, getSupportedProtocol());
        } catch (final PeerNotConnected missingPeerException) {
        // Peer disconnected before we could respond - nothing to do
        }
    });
}
Also used : MinedBlockObserver(org.hyperledger.besu.ethereum.chain.MinedBlockObserver) StatusMessage(org.hyperledger.besu.ethereum.eth.messages.StatusMessage) RLPException(org.hyperledger.besu.ethereum.rlp.RLPException) EthPV62(org.hyperledger.besu.ethereum.eth.messages.EthPV62) NewMergeStateCallback(org.hyperledger.besu.consensus.merge.NewMergeStateCallback) LoggerFactory(org.slf4j.LoggerFactory) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Bytes(org.apache.tuweni.bytes.Bytes) EthProtocol(org.hyperledger.besu.ethereum.eth.EthProtocol) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) ImmutableList(com.google.common.collect.ImmutableList) PeerConnection(org.hyperledger.besu.ethereum.p2p.rlpx.connections.PeerConnection) Map(java.util.Map) WorldStateArchive(org.hyperledger.besu.ethereum.worldstate.WorldStateArchive) BigInteger(java.math.BigInteger) Block(org.hyperledger.besu.ethereum.core.Block) NewForkchoiceMessageListener(org.hyperledger.besu.consensus.merge.NewForkchoiceMessageListener) DisconnectReason(org.hyperledger.besu.ethereum.p2p.rlpx.wire.messages.DisconnectMessage.DisconnectReason) ProtocolManager(org.hyperledger.besu.ethereum.p2p.network.ProtocolManager) Difficulty(org.hyperledger.besu.ethereum.core.Difficulty) TransactionPool(org.hyperledger.besu.ethereum.eth.transactions.TransactionPool) Logger(org.slf4j.Logger) PeerValidatorRunner(org.hyperledger.besu.ethereum.eth.peervalidation.PeerValidatorRunner) EthProtocolConfiguration(org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration) Blockchain(org.hyperledger.besu.ethereum.chain.Blockchain) DisconnectMessage(org.hyperledger.besu.ethereum.p2p.rlpx.wire.messages.DisconnectMessage) PeerValidator(org.hyperledger.besu.ethereum.eth.peervalidation.PeerValidator) CountDownLatch(java.util.concurrent.CountDownLatch) AtomicLong(java.util.concurrent.atomic.AtomicLong) List(java.util.List) Message(org.hyperledger.besu.ethereum.p2p.rlpx.wire.Message) MessageData(org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData) PeerNotConnected(org.hyperledger.besu.ethereum.p2p.rlpx.connections.PeerConnection.PeerNotConnected) Optional(java.util.Optional) Capability(org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability) VisibleForTesting(com.google.common.annotations.VisibleForTesting) BlockBroadcaster(org.hyperledger.besu.ethereum.eth.sync.BlockBroadcaster) Collections(java.util.Collections) StampedLock(java.util.concurrent.locks.StampedLock) Hash(org.hyperledger.besu.datatypes.Hash) PeerNotConnected(org.hyperledger.besu.ethereum.p2p.rlpx.connections.PeerConnection.PeerNotConnected) MessageData(org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData) RLPException(org.hyperledger.besu.ethereum.rlp.RLPException) BigInteger(java.math.BigInteger) Map(java.util.Map)

Example 2 with Message

use of org.hyperledger.besu.ethereum.p2p.rlpx.wire.Message in project besu by hyperledger.

the class P2PPlainNetworkTest method p2pOverTlsCanHandleRecordFragmentation.

@Test
public void p2pOverTlsCanHandleRecordFragmentation() throws Exception {
    // Given
    final int tlsRecordSize = 16 * 1024;
    final int threeTlsRecords = 2 * tlsRecordSize + 1;
    final LargeMessageData largeMessageData = new LargeMessageData(Bytes.of(buildPaddedMessage(threeTlsRecords)));
    final NodeKey nodeKey = NodeKeyUtils.generate();
    try (final P2PNetwork listener = builder("partner1client1").nodeKey(nodeKey).build();
        final P2PNetwork connector = builder("partner2client1").build()) {
        final CompletableFuture<DisconnectReason> disconnectReasonFuture = new CompletableFuture<>();
        listener.subscribeDisconnect((peerConnection, reason, initiatedByPeer) -> {
            if (!DisconnectReason.CLIENT_QUITTING.equals(reason)) {
                // client quitting is the valid end state
                disconnectReasonFuture.complete(reason);
            }
        });
        final CompletableFuture<Message> successfulMessageFuture = new CompletableFuture<>();
        listener.subscribe(Capability.create("eth", 63), (capability, message) -> {
            if (message.getData().getCode() == LargeMessageData.VALID_ETH_MESSAGE_CODE) {
                successfulMessageFuture.complete(message);
            }
        });
        listener.start();
        connector.start();
        final EnodeURL listenerEnode = listener.getLocalEnode().get();
        final Bytes listenId = listenerEnode.getNodeId();
        final int listenPort = listenerEnode.getListeningPort().get();
        final PeerConnection peerConnection = connector.connect(createPeer(listenId, listenPort)).get(30000L, TimeUnit.SECONDS);
        // When
        peerConnection.sendForProtocol("eth", largeMessageData);
        // Then
        CompletableFuture.anyOf(disconnectReasonFuture, successfulMessageFuture).thenAccept(successOrFailure -> {
            if (successOrFailure instanceof DisconnectReason) {
                fail("listener disconnected due to " + ((DisconnectReason) successOrFailure).name());
            } else {
                final Message receivedMessage = (Message) successOrFailure;
                assertThat(receivedMessage.getData().getData()).isEqualTo(largeMessageData.getData());
            }
        }).get(30L, TimeUnit.SECONDS);
    }
}
Also used : ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) EnodeURLImpl(org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl) Arrays(java.util.Arrays) InMemoryKeyValueStorageProvider(org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider) ArgumentMatchers.eq(org.mockito.ArgumentMatchers.eq) Assertions.assertThat(org.assertj.core.api.Assertions.assertThat) SubProtocol(org.hyperledger.besu.ethereum.p2p.rlpx.wire.SubProtocol) RunWith(org.junit.runner.RunWith) Peer(org.hyperledger.besu.ethereum.p2p.peers.Peer) CompletableFuture(java.util.concurrent.CompletableFuture) NoOpMetricsSystem(org.hyperledger.besu.metrics.noop.NoOpMetricsSystem) Bytes(org.apache.tuweni.bytes.Bytes) Fail.fail(org.assertj.core.api.Fail.fail) TLSConfiguration(org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.TLSConfiguration) AbstractMessageData(org.hyperledger.besu.ethereum.p2p.rlpx.wire.AbstractMessageData) InetAddress(java.net.InetAddress) Assertions.assertThatThrownBy(org.assertj.core.api.Assertions.assertThatThrownBy) DefaultPeer(org.hyperledger.besu.ethereum.p2p.peers.DefaultPeer) PeerConnection(org.hyperledger.besu.ethereum.p2p.rlpx.connections.PeerConnection) IncompatiblePeerException(org.hyperledger.besu.ethereum.p2p.network.exceptions.IncompatiblePeerException) After(org.junit.After) DiscoveryConfiguration(org.hyperledger.besu.ethereum.p2p.config.DiscoveryConfiguration) Assertions(org.assertj.core.api.Assertions) Path(java.nio.file.Path) DisconnectReason(org.hyperledger.besu.ethereum.p2p.rlpx.wire.messages.DisconnectMessage.DisconnectReason) RlpxConfiguration(org.hyperledger.besu.ethereum.p2p.config.RlpxConfiguration) NodeKeyUtils(org.hyperledger.besu.crypto.NodeKeyUtils) Charsets(com.google.common.base.Charsets) NetworkingConfiguration(org.hyperledger.besu.ethereum.p2p.config.NetworkingConfiguration) Files(java.nio.file.Files) PeerPermissionsDenylist(org.hyperledger.besu.ethereum.p2p.permissions.PeerPermissionsDenylist) Vertx(io.vertx.core.Vertx) KeyStoreWrapper(org.hyperledger.besu.pki.keystore.KeyStoreWrapper) IOException(java.io.IOException) Test(org.junit.Test) Mockito.when(org.mockito.Mockito.when) File(java.io.File) EnodeURL(org.hyperledger.besu.plugin.data.EnodeURL) TimeUnit(java.util.concurrent.TimeUnit) Message(org.hyperledger.besu.ethereum.p2p.rlpx.wire.Message) Optional(java.util.Optional) PeerPermissions(org.hyperledger.besu.ethereum.p2p.permissions.PeerPermissions) Capability(org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability) Collections(java.util.Collections) MockitoJUnitRunner(org.mockito.junit.MockitoJUnitRunner) Mockito.mock(org.mockito.Mockito.mock) NodeKey(org.hyperledger.besu.crypto.NodeKey) Message(org.hyperledger.besu.ethereum.p2p.rlpx.wire.Message) PeerConnection(org.hyperledger.besu.ethereum.p2p.rlpx.connections.PeerConnection) EnodeURL(org.hyperledger.besu.plugin.data.EnodeURL) Bytes(org.apache.tuweni.bytes.Bytes) CompletableFuture(java.util.concurrent.CompletableFuture) DisconnectReason(org.hyperledger.besu.ethereum.p2p.rlpx.wire.messages.DisconnectMessage.DisconnectReason) NodeKey(org.hyperledger.besu.crypto.NodeKey) Test(org.junit.Test)

Example 3 with Message

use of org.hyperledger.besu.ethereum.p2p.rlpx.wire.Message in project besu by hyperledger.

the class IbftControllerTest method startsNewBlockHeightManagerAndReplaysFutureMessages.

@Test
public void startsNewBlockHeightManagerAndReplaysFutureMessages() {
    final ConsensusRoundIdentifier roundIdentifierHeight6 = new ConsensusRoundIdentifier(6, 0);
    setupPrepare(futureRoundIdentifier, validator);
    setupProposal(roundIdentifierHeight6, validator);
    setupCommit(futureRoundIdentifier, validator);
    setupRoundChange(futureRoundIdentifier, validator);
    final List<Message> height2Msgs = newArrayList(prepareMessage, commitMessage, roundChangeMessage);
    when(blockHeightManager.getChainHeight()).thenReturn(5L);
    when(futureMessageBuffer.retrieveMessagesForHeight(5L)).thenReturn(height2Msgs);
    constructIbftController();
    ibftController.start();
    verify(futureMessageBuffer).retrieveMessagesForHeight(5L);
    verify(futureMessageBuffer, never()).retrieveMessagesForHeight(6L);
    verify(blockHeightManagerFactory).create(chainHeadBlockHeader);
    verify(blockHeightManager, atLeastOnce()).getChainHeight();
    verify(blockHeightManager, never()).handleProposalPayload(proposal);
    verify(blockHeightManager).handlePreparePayload(prepare);
    verify(ibftGossip).send(prepareMessage);
    verify(blockHeightManager).handleCommitPayload(commit);
    verify(ibftGossip).send(commitMessage);
    verify(blockHeightManager).handleRoundChangePayload(roundChange);
    verify(ibftGossip).send(roundChangeMessage);
}
Also used : ConsensusRoundIdentifier(org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier) DefaultMessage(org.hyperledger.besu.ethereum.p2p.rlpx.wire.DefaultMessage) Message(org.hyperledger.besu.ethereum.p2p.rlpx.wire.Message) Test(org.junit.Test)

Example 4 with Message

use of org.hyperledger.besu.ethereum.p2p.rlpx.wire.Message in project besu by hyperledger.

the class MockNetworkTest method exchangeMessages.

@Test
public void exchangeMessages() throws Exception {
    final Capability cap = Capability.create("eth", 63);
    final MockNetwork network = new MockNetwork(Arrays.asList(cap));
    final Peer one = DefaultPeer.fromEnodeURL(EnodeURLImpl.builder().nodeId(randomId()).ipAddress("192.168.1.2").discoveryPort(1234).listeningPort(4321).build());
    final Peer two = DefaultPeer.fromEnodeURL(EnodeURLImpl.builder().nodeId(randomId()).ipAddress("192.168.1.3").discoveryPort(1234).listeningPort(4321).build());
    try (final P2PNetwork network1 = network.setup(one);
        final P2PNetwork network2 = network.setup(two)) {
        final CompletableFuture<Message> messageFuture = new CompletableFuture<>();
        network1.subscribe(cap, (capability, msg) -> messageFuture.complete(msg));
        final Predicate<PeerConnection> isPeerOne = peerConnection -> peerConnection.getPeerInfo().getNodeId().equals(one.getId());
        final Predicate<PeerConnection> isPeerTwo = peerConnection -> peerConnection.getPeerInfo().getNodeId().equals(two.getId());
        Assertions.assertThat(network1.getPeers().stream().filter(isPeerTwo).findFirst()).isNotPresent();
        Assertions.assertThat(network2.getPeers().stream().filter(isPeerOne).findFirst()).isNotPresent();
        // Validate Connect Behaviour
        final CompletableFuture<PeerConnection> peer2Future = new CompletableFuture<>();
        network1.subscribeConnect(peer2Future::complete);
        final CompletableFuture<PeerConnection> peer1Future = new CompletableFuture<>();
        network2.subscribeConnect(peer1Future::complete);
        network1.connect(two).get();
        Assertions.assertThat(peer1Future.get().getPeerInfo().getNodeId()).isEqualTo(one.getId());
        Assertions.assertThat(peer2Future.get().getPeerInfo().getNodeId()).isEqualTo(two.getId());
        Assertions.assertThat(network1.getPeers().stream().filter(isPeerTwo).findFirst()).isPresent();
        final Optional<PeerConnection> optionalConnection = network2.getPeers().stream().filter(isPeerOne).findFirst();
        Assertions.assertThat(optionalConnection).isPresent();
        // Validate Message Exchange
        final int size = 128;
        final byte[] data = new byte[size];
        ThreadLocalRandom.current().nextBytes(data);
        final int code = 0x74;
        final PeerConnection connection = optionalConnection.get();
        connection.send(cap, new RawMessage(code, Bytes.wrap(data)));
        final Message receivedMessage = messageFuture.get();
        final MessageData receivedMessageData = receivedMessage.getData();
        Assertions.assertThat(receivedMessageData.getData()).isEqualTo(Bytes.wrap(data));
        Assertions.assertThat(receivedMessage.getConnection().getPeerInfo().getNodeId()).isEqualTo(two.getId());
        Assertions.assertThat(receivedMessageData.getSize()).isEqualTo(size);
        Assertions.assertThat(receivedMessageData.getCode()).isEqualTo(code);
        // Validate Disconnect Behaviour
        final CompletableFuture<DisconnectReason> peer1DisconnectFuture = new CompletableFuture<>();
        final CompletableFuture<DisconnectReason> peer2DisconnectFuture = new CompletableFuture<>();
        network2.subscribeDisconnect((peer, reason, initiatedByPeer) -> peer1DisconnectFuture.complete(reason));
        network1.subscribeDisconnect((peer, reason, initiatedByPeer) -> peer2DisconnectFuture.complete(reason));
        connection.disconnect(DisconnectReason.CLIENT_QUITTING);
        Assertions.assertThat(peer1DisconnectFuture.get()).isEqualTo(DisconnectReason.REQUESTED);
        Assertions.assertThat(peer2DisconnectFuture.get()).isEqualTo(DisconnectReason.CLIENT_QUITTING);
        Assertions.assertThat(network1.getPeers().stream().filter(isPeerTwo).findFirst()).isNotPresent();
        Assertions.assertThat(network2.getPeers().stream().filter(isPeerOne).findFirst()).isNotPresent();
    }
}
Also used : EnodeURLImpl(org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl) Arrays(java.util.Arrays) Predicate(java.util.function.Predicate) RawMessage(org.hyperledger.besu.ethereum.p2p.rlpx.wire.RawMessage) Peer(org.hyperledger.besu.ethereum.p2p.peers.Peer) CompletableFuture(java.util.concurrent.CompletableFuture) Test(org.junit.Test) Bytes(org.apache.tuweni.bytes.Bytes) P2PNetwork(org.hyperledger.besu.ethereum.p2p.network.P2PNetwork) Message(org.hyperledger.besu.ethereum.p2p.rlpx.wire.Message) MessageData(org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData) DefaultPeer(org.hyperledger.besu.ethereum.p2p.peers.DefaultPeer) PeerConnection(org.hyperledger.besu.ethereum.p2p.rlpx.connections.PeerConnection) ThreadLocalRandom(java.util.concurrent.ThreadLocalRandom) Optional(java.util.Optional) Assertions(org.assertj.core.api.Assertions) Capability(org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability) DisconnectReason(org.hyperledger.besu.ethereum.p2p.rlpx.wire.messages.DisconnectMessage.DisconnectReason) Capability(org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability) RawMessage(org.hyperledger.besu.ethereum.p2p.rlpx.wire.RawMessage) Message(org.hyperledger.besu.ethereum.p2p.rlpx.wire.Message) PeerConnection(org.hyperledger.besu.ethereum.p2p.rlpx.connections.PeerConnection) MessageData(org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData) Peer(org.hyperledger.besu.ethereum.p2p.peers.Peer) DefaultPeer(org.hyperledger.besu.ethereum.p2p.peers.DefaultPeer) P2PNetwork(org.hyperledger.besu.ethereum.p2p.network.P2PNetwork) CompletableFuture(java.util.concurrent.CompletableFuture) DisconnectReason(org.hyperledger.besu.ethereum.p2p.rlpx.wire.messages.DisconnectMessage.DisconnectReason) RawMessage(org.hyperledger.besu.ethereum.p2p.rlpx.wire.RawMessage) Test(org.junit.Test)

Example 5 with Message

use of org.hyperledger.besu.ethereum.p2p.rlpx.wire.Message in project besu by hyperledger.

the class PeerConnectionEvents method dispatchMessage.

@Override
public void dispatchMessage(final Capability capability, final PeerConnection connection, final MessageData message) {
    final Message msg = new DefaultMessage(connection, message);
    messageSubscribers.getOrDefault(capability, Subscribers.none()).forEach(s -> s.onMessage(capability, msg));
}
Also used : DefaultMessage(org.hyperledger.besu.ethereum.p2p.rlpx.wire.DefaultMessage) DefaultMessage(org.hyperledger.besu.ethereum.p2p.rlpx.wire.DefaultMessage) Message(org.hyperledger.besu.ethereum.p2p.rlpx.wire.Message)

Aggregations

Message (org.hyperledger.besu.ethereum.p2p.rlpx.wire.Message)9 DefaultMessage (org.hyperledger.besu.ethereum.p2p.rlpx.wire.DefaultMessage)5 Test (org.junit.Test)5 Optional (java.util.Optional)4 PeerConnection (org.hyperledger.besu.ethereum.p2p.rlpx.connections.PeerConnection)4 Capability (org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability)4 MessageData (org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData)4 DisconnectReason (org.hyperledger.besu.ethereum.p2p.rlpx.wire.messages.DisconnectMessage.DisconnectReason)4 Bytes (org.apache.tuweni.bytes.Bytes)3 ImmutableList (com.google.common.collect.ImmutableList)2 BigInteger (java.math.BigInteger)2 Arrays (java.util.Arrays)2 Collections (java.util.Collections)2 List (java.util.List)2 Map (java.util.Map)2 CompletableFuture (java.util.concurrent.CompletableFuture)2 Assertions (org.assertj.core.api.Assertions)2 ConsensusRoundIdentifier (org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier)2 DefaultPeer (org.hyperledger.besu.ethereum.p2p.peers.DefaultPeer)2 EnodeURLImpl (org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl)2