/** @return True if any requests were processed */ public boolean respond(final Responder responder) { // Respond to queued messages final List<OutgoingMessage> currentMessages = new ArrayList<>(outgoingMessages); outgoingMessages.clear(); for (final OutgoingMessage msg : currentMessages) { final Optional<MessageData> maybeResponse = responder.respond(msg.capability, msg.messageData); maybeResponse.ifPresent( (response) -> ethProtocolManager.processMessage( msg.capability, new DefaultMessage(peerConnection, response))); } return currentMessages.size() > 0; }
private void setupRoundChange( final ConsensusRoundIdentifier roundIdentifier, final Address validator) { when(signedRoundChange.getPayload()).thenReturn(roundChangePayload); when(signedRoundChange.getAuthor()).thenReturn(validator); when(roundChangePayload.getRoundIdentifier()).thenReturn(roundIdentifier); when(roundChangeMessageData.getCode()).thenReturn(IbftV2.ROUND_CHANGE); when(roundChangeMessageData.decode()).thenReturn(signedRoundChange); roundChangeMessage = new DefaultMessage(null, roundChangeMessageData); } }
private void setupCommit( final ConsensusRoundIdentifier roundIdentifier, final Address validator) { when(signedCommit.getPayload()).thenReturn(commitPayload); when(signedCommit.getAuthor()).thenReturn(validator); when(commitPayload.getRoundIdentifier()).thenReturn(roundIdentifier); when(commitMessageData.getCode()).thenReturn(IbftV2.COMMIT); when(commitMessageData.decode()).thenReturn(signedCommit); commitMessage = new DefaultMessage(null, commitMessageData); }
private void setupProposal( final ConsensusRoundIdentifier roundIdentifier, final Address validator) { when(signedProposal.getPayload()).thenReturn(proposalPayload); when(signedProposal.getAuthor()).thenReturn(validator); when(proposalPayload.getRoundIdentifier()).thenReturn(roundIdentifier); when(proposalMessageData.getCode()).thenReturn(IbftV2.PROPOSAL); when(proposalMessageData.decode()).thenReturn(signedProposal); proposalMessage = new DefaultMessage(null, proposalMessageData); }
private void setupPrepare( final ConsensusRoundIdentifier roundIdentifier, final Address validator) { when(signedPrepare.getPayload()).thenReturn(preparePayload); when(signedPrepare.getAuthor()).thenReturn(validator); when(preparePayload.getRoundIdentifier()).thenReturn(roundIdentifier); when(prepareMessageData.getCode()).thenReturn(IbftV2.PREPARE); when(prepareMessageData.decode()).thenReturn(signedPrepare); prepareMessage = new DefaultMessage(null, prepareMessageData); }
private void setupNewRound( final ConsensusRoundIdentifier roundIdentifier, final Address validator) { when(signedNewRound.getPayload()).thenReturn(newRoundPayload); when(signedNewRound.getAuthor()).thenReturn(validator); when(newRoundPayload.getRoundIdentifier()).thenReturn(roundIdentifier); when(newRoundMessageData.getCode()).thenReturn(IbftV2.NEW_ROUND); when(newRoundMessageData.decode()).thenReturn(signedNewRound); newRoundMessage = new DefaultMessage(null, newRoundMessageData); }
public static void broadcastMessage( final EthProtocolManager ethProtocolManager, final RespondingEthPeer peer, final MessageData message) { ethProtocolManager.processMessage( EthProtocol.ETH63, new DefaultMessage(peer.getPeerConnection(), message)); }
private <P extends Payload> void assertRebroadcastToAllExceptSignerAndSender( final Function<KeyPair, SignedData<P>> createPayload, final Function<SignedData<P>, MessageData> createMessageData) { final KeyPair keypair = KeyPair.generate(); final SignedData<P> payload = createPayload.apply(keypair); final MessageData messageData = createMessageData.apply(payload); final Message message = new DefaultMessage(peerConnection, messageData); ibftGossip.send(message); verify(validatorMulticaster) .send(messageData, newArrayList(senderAddress, payload.getAuthor())); }
@Test public void disconnectOnFailureToSendStatusMessage() { try (final EthProtocolManager ethManager = new EthProtocolManager(blockchain, protocolContext.getWorldStateArchive(), 1, true, 1, 1)) { final MessageData messageData = BlockHeadersMessage.create(Collections.singletonList(blockchain.getBlockHeader(1).get())); final MockPeerConnection peer = setupPeerWithoutStatusExchange(ethManager, (cap, msg, conn) -> {}); ethManager.processMessage(EthProtocol.ETH63, new DefaultMessage(peer, messageData)); assertThat(peer.isDisconnected()).isTrue(); } }
@Test public void disconnectOnUnsolicitedMessage() { try (final EthProtocolManager ethManager = new EthProtocolManager(blockchain, protocolContext.getWorldStateArchive(), 1, true, 1, 1)) { final MessageData messageData = BlockHeadersMessage.create(Collections.singletonList(blockchain.getBlockHeader(1).get())); final MockPeerConnection peer = setupPeer(ethManager, (cap, msg, conn) -> {}); ethManager.processMessage(EthProtocol.ETH63, new DefaultMessage(peer, messageData)); assertThat(peer.isDisconnected()).isTrue(); } }
}; final PeerConnection peer = setupPeer(ethManager, onSend); ethManager.processMessage(EthProtocol.ETH63, new DefaultMessage(peer, messageData)); done.get();
@Test public void respondToGetHeadersReversed() throws ExecutionException, InterruptedException { final CompletableFuture<Void> done = new CompletableFuture<>(); try (final EthProtocolManager ethManager = new EthProtocolManager(blockchain, protocolContext.getWorldStateArchive(), 1, true, 1, 1)) { final long endBlock = 10L; final int blockCount = 5; final MessageData messageData = GetBlockHeadersMessage.create(endBlock, blockCount, 0, true); final PeerSendHandler onSend = (cap, message, conn) -> { if (message.getCode() == EthPV62.STATUS) { // Ignore status message return; } assertThat(message.getCode()).isEqualTo(EthPV62.BLOCK_HEADERS); final BlockHeadersMessage headersMsg = BlockHeadersMessage.readFrom(message); final List<BlockHeader> headers = Lists.newArrayList(headersMsg.getHeaders(protocolSchedule)); assertThat(headers.size()).isEqualTo(blockCount); for (int i = 0; i < blockCount; i++) { assertThat(headers.get(i).getNumber()).isEqualTo(endBlock - i); } done.complete(null); }; final PeerConnection peer = setupPeer(ethManager, onSend); ethManager.processMessage(EthProtocol.ETH63, new DefaultMessage(peer, messageData)); done.get(); } }
}; final PeerConnection peer = setupPeer(ethManager, onSend); ethManager.processMessage(EthProtocol.ETH63, new DefaultMessage(peer, messageData)); done.get();
@Test public void respondToGetHeadersPartial() throws ExecutionException, InterruptedException { final CompletableFuture<Void> done = new CompletableFuture<>(); try (final EthProtocolManager ethManager = new EthProtocolManager(blockchain, protocolContext.getWorldStateArchive(), 1, true, 1, 1)) { final long startBlock = blockchain.getChainHeadBlockNumber() - 1L; final int blockCount = 5; final MessageData messageData = GetBlockHeadersMessage.create(startBlock, blockCount, 0, false); final PeerSendHandler onSend = (cap, message, conn) -> { if (message.getCode() == EthPV62.STATUS) { // Ignore status message return; } assertThat(message.getCode()).isEqualTo(EthPV62.BLOCK_HEADERS); final BlockHeadersMessage headersMsg = BlockHeadersMessage.readFrom(message); final List<BlockHeader> headers = Lists.newArrayList(headersMsg.getHeaders(protocolSchedule)); assertThat(headers.size()).isEqualTo(2); for (int i = 0; i < 2; i++) { assertThat(headers.get(i).getNumber()).isEqualTo(startBlock + i); } done.complete(null); }; final PeerConnection peer = setupPeer(ethManager, onSend); ethManager.processMessage(EthProtocol.ETH63, new DefaultMessage(peer, messageData)); done.get(); } }
@Test public void respondToGetHeadersEmpty() throws ExecutionException, InterruptedException { final CompletableFuture<Void> done = new CompletableFuture<>(); try (final EthProtocolManager ethManager = new EthProtocolManager(blockchain, protocolContext.getWorldStateArchive(), 1, true, 1, 1)) { final long startBlock = blockchain.getChainHeadBlockNumber() + 1; final int blockCount = 5; final MessageData messageData = GetBlockHeadersMessage.create(startBlock, blockCount, 0, false); final PeerSendHandler onSend = (cap, message, conn) -> { if (message.getCode() == EthPV62.STATUS) { // Ignore status message return; } assertThat(message.getCode()).isEqualTo(EthPV62.BLOCK_HEADERS); final BlockHeadersMessage headersMsg = BlockHeadersMessage.readFrom(message); final List<BlockHeader> headers = Lists.newArrayList(headersMsg.getHeaders(protocolSchedule)); assertThat(headers.size()).isEqualTo(0); done.complete(null); }; final PeerConnection peer = setupPeer(ethManager, onSend); ethManager.processMessage(EthProtocol.ETH63, new DefaultMessage(peer, messageData)); done.get(); } }
@Test public void disconnectOnWrongChainId() { try (final EthProtocolManager ethManager = new EthProtocolManager(blockchain, protocolContext.getWorldStateArchive(), 1, true, 1, 1)) { final MessageData messageData = BlockHeadersMessage.create(Collections.singletonList(blockchain.getBlockHeader(1).get())); final MockPeerConnection peer = setupPeerWithoutStatusExchange(ethManager, (cap, msg, conn) -> {}); // Send status message with wrong chain final StatusMessage statusMessage = StatusMessage.create( EthVersion.V63, 2222, blockchain.getChainHead().getTotalDifficulty(), blockchain.getChainHeadHash(), blockchain.getBlockHeader(BlockHeader.GENESIS_BLOCK_NUMBER).get().getHash()); ethManager.processMessage(EthProtocol.ETH63, new DefaultMessage(peer, statusMessage)); ethManager.processMessage(EthProtocol.ETH63, new DefaultMessage(peer, messageData)); assertThat(peer.isDisconnected()).isTrue(); } }
@Test public void disconnectOnWrongGenesisHash() { try (final EthProtocolManager ethManager = new EthProtocolManager(blockchain, protocolContext.getWorldStateArchive(), 1, true, 1, 1)) { final MessageData messageData = BlockHeadersMessage.create(Collections.singletonList(blockchain.getBlockHeader(1).get())); final MockPeerConnection peer = setupPeerWithoutStatusExchange(ethManager, (cap, msg, conn) -> {}); // Send status message with wrong chain final StatusMessage statusMessage = StatusMessage.create( EthVersion.V63, 1, blockchain.getChainHead().getTotalDifficulty(), gen.hash(), blockchain.getBlockHeader(BlockHeader.GENESIS_BLOCK_NUMBER).get().getHash()); ethManager.processMessage(EthProtocol.ETH63, new DefaultMessage(peer, statusMessage)); ethManager.processMessage(EthProtocol.ETH63, new DefaultMessage(peer, messageData)); assertThat(peer.isDisconnected()).isTrue(); } }
ethManager.processMessage(EthProtocol.ETH63, new DefaultMessage(peer, transactionMessage));
private MockPeerConnection setupPeer( final EthProtocolManager ethManager, final PeerSendHandler onSend) { final MockPeerConnection peer = setupPeerWithoutStatusExchange(ethManager, onSend); final StatusMessage statusMessage = StatusMessage.create( EthVersion.V63, 1, blockchain.getChainHead().getTotalDifficulty(), blockchain.getChainHeadHash(), blockchain.getBlockHeader(BlockHeader.GENESIS_BLOCK_NUMBER).get().getHash()); ethManager.processMessage(EthProtocol.ETH63, new DefaultMessage(peer, statusMessage)); return peer; }
@Test(expected = ConditionTimeoutException.class) public void doNotDisconnectOnValidMessage() { try (final EthProtocolManager ethManager = new EthProtocolManager(blockchain, protocolContext.getWorldStateArchive(), 1, true, 1, 1)) { final MessageData messageData = GetBlockBodiesMessage.create(Collections.singletonList(gen.hash())); final MockPeerConnection peer = setupPeer(ethManager, (cap, msg, conn) -> {}); ethManager.processMessage(EthProtocol.ETH63, new DefaultMessage(peer, messageData)); Awaitility.await() .catchUncaughtExceptions() .atMost(200, TimeUnit.MILLISECONDS) .until(peer::isDisconnected); } }