@ -12,6 +12,7 @@
* /
* /
package tech.pegasys.pantheon.consensus.ibft.validation ;
package tech.pegasys.pantheon.consensus.ibft.validation ;
import static java.util.Optional.empty ;
import static org.assertj.core.api.Assertions.assertThat ;
import static org.assertj.core.api.Assertions.assertThat ;
import static org.mockito.ArgumentMatchers.any ;
import static org.mockito.ArgumentMatchers.any ;
import static org.mockito.Mockito.mock ;
import static org.mockito.Mockito.mock ;
@ -27,6 +28,8 @@ import tech.pegasys.pantheon.consensus.ibft.payload.ProposalPayload;
import tech.pegasys.pantheon.consensus.ibft.payload.SignedData ;
import tech.pegasys.pantheon.consensus.ibft.payload.SignedData ;
import tech.pegasys.pantheon.crypto.SECP256K1 ;
import tech.pegasys.pantheon.crypto.SECP256K1 ;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair ;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair ;
import tech.pegasys.pantheon.ethereum.BlockValidator ;
import tech.pegasys.pantheon.ethereum.BlockValidator.BlockProcessingOutputs ;
import tech.pegasys.pantheon.ethereum.ProtocolContext ;
import tech.pegasys.pantheon.ethereum.ProtocolContext ;
import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain ;
import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain ;
import tech.pegasys.pantheon.ethereum.core.Address ;
import tech.pegasys.pantheon.ethereum.core.Address ;
@ -35,7 +38,6 @@ import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.core.Hash ;
import tech.pegasys.pantheon.ethereum.core.Hash ;
import tech.pegasys.pantheon.ethereum.core.Util ;
import tech.pegasys.pantheon.ethereum.core.Util ;
import tech.pegasys.pantheon.ethereum.db.WorldStateArchive ;
import tech.pegasys.pantheon.ethereum.db.WorldStateArchive ;
import tech.pegasys.pantheon.ethereum.mainnet.BlockHeaderValidator ;
import tech.pegasys.pantheon.util.bytes.BytesValue ;
import tech.pegasys.pantheon.util.bytes.BytesValue ;
import java.util.Collections ;
import java.util.Collections ;
@ -61,7 +63,7 @@ public class MessageValidatorTest {
private final List < Address > validators = Lists . newArrayList ( ) ;
private final List < Address > validators = Lists . newArrayList ( ) ;
@Mock private BlockHeader Validator < IbftContext > header Validator;
@Mock private BlockValidator < IbftContext > block Validator;
private final BlockHeader parentHeader = mock ( BlockHeader . class ) ;
private final BlockHeader parentHeader = mock ( BlockHeader . class ) ;
private final ConsensusRoundIdentifier roundIdentifier = new ConsensusRoundIdentifier ( 2 , 0 ) ;
private final ConsensusRoundIdentifier roundIdentifier = new ConsensusRoundIdentifier ( 2 , 0 ) ;
private MessageValidator validator ;
private MessageValidator validator ;
@ -82,30 +84,27 @@ public class MessageValidatorTest {
validators ,
validators ,
Util . publicKeyToAddress ( proposerKey . getPublicKey ( ) ) ,
Util . publicKeyToAddress ( proposerKey . getPublicKey ( ) ) ,
roundIdentifier ,
roundIdentifier ,
header Validator,
block Validator,
protocolContext ,
protocolContext ,
parentHeader ) ;
parentHeader ) ;
when ( block . getHash ( ) ) . thenReturn ( Hash . fromHexStringLenient ( "1" ) ) ;
when ( block . getHash ( ) ) . thenReturn ( Hash . fromHexStringLenient ( "1" ) ) ;
when ( headerValidator . validateHeader ( any ( ) , any ( ) , any ( ) , any ( ) ) ) . thenReturn ( true ) ;
when ( blockValidator . validateAndProcessBlock ( any ( ) , any ( ) , any ( ) , any ( ) ) )
. thenReturn ( Optional . of ( new BlockProcessingOutputs ( null , null ) ) ) ;
insertRoundToBlockHeader ( 0 ) ;
insertRoundToBlockHeader ( 0 ) ;
}
}
private void insertRoundToBlockHeader ( final int round ) {
private void insertRoundToBlockHeader ( final int round ) {
final IbftExtraData extraData =
final IbftExtraData extraData =
new IbftExtraData (
new IbftExtraData (
BytesValue . wrap ( new byte [ 32 ] ) ,
BytesValue . wrap ( new byte [ 32 ] ) , Collections . emptyList ( ) , empty ( ) , round , validators ) ;
Collections . emptyList ( ) ,
Optional . empty ( ) ,
round ,
validators ) ;
final BlockHeader header = mock ( BlockHeader . class ) ;
final BlockHeader header = mock ( BlockHeader . class ) ;
when ( header . getExtraData ( ) ) . thenReturn ( extraData . encode ( ) ) ;
when ( header . getExtraData ( ) ) . thenReturn ( extraData . encode ( ) ) ;
when ( block . getHeader ( ) ) . thenReturn ( header ) ;
when ( block . getHeader ( ) ) . thenReturn ( header ) ;
}
}
@Test
@Test
public void receivingAPrepareMessageBeforePrePrepare Fails ( ) {
public void receivingAPrepareMessageBeforeProposal Fails ( ) {
final SignedData < PreparePayload > prepareMsg =
final SignedData < PreparePayload > prepareMsg =
proposerMessageFactory . createSignedPreparePayload ( roundIdentifier , Hash . ZERO ) ;
proposerMessageFactory . createSignedPreparePayload ( roundIdentifier , Hash . ZERO ) ;
@ -113,7 +112,7 @@ public class MessageValidatorTest {
}
}
@Test
@Test
public void receivingACommitMessageBeforePreprepare Fails ( ) {
public void receivingACommitMessageBeforeProposal Fails ( ) {
final SignedData < CommitPayload > commitMsg =
final SignedData < CommitPayload > commitMsg =
proposerMessageFactory . createSignedCommitPayload (
proposerMessageFactory . createSignedCommitPayload (
roundIdentifier , Hash . ZERO , SECP256K1 . sign ( Hash . ZERO , proposerKey ) ) ;
roundIdentifier , Hash . ZERO , SECP256K1 . sign ( Hash . ZERO , proposerKey ) ) ;
@ -122,55 +121,49 @@ public class MessageValidatorTest {
}
}
@Test
@Test
public void receivingPreprepare MessageFromNonProposerFails ( ) {
public void receivingProposal MessageFromNonProposerFails ( ) {
final SignedData < ProposalPayload > preprepare Msg =
final SignedData < ProposalPayload > proposal Msg =
validatorMessageFactory . createSignedProposalPayload ( roundIdentifier , mock ( Block . class ) ) ;
validatorMessageFactory . createSignedProposalPayload ( roundIdentifier , mock ( Block . class ) ) ;
assertThat ( validator . addSignedProposalPayload ( preprepare Msg ) ) . isFalse ( ) ;
assertThat ( validator . addSignedProposalPayload ( proposal Msg ) ) . isFalse ( ) ;
}
}
@Test
@Test
public void receivingPreprepare MessageWithIllegalBlockFails ( ) {
public void receivingProposal MessageWithIllegalBlockFails ( ) {
when ( headerValidator . validateHeader ( any ( ) , any ( ) , any ( ) , any ( ) ) ) . thenReturn ( false ) ;
when ( blockValidator . validateAndProcessBlock ( any ( ) , any ( ) , any ( ) , any ( ) ) ) . thenReturn ( empty ( ) ) ;
final SignedData < ProposalPayload > preprepare Msg =
final SignedData < ProposalPayload > proposal Msg =
proposerMessageFactory . createSignedProposalPayload ( roundIdentifier , mock ( Block . class ) ) ;
proposerMessageFactory . createSignedProposalPayload ( roundIdentifier , mock ( Block . class ) ) ;
assertThat ( validator . addSignedProposalPayload ( preprepare Msg ) ) . isFalse ( ) ;
assertThat ( validator . addSignedProposalPayload ( proposal Msg ) ) . isFalse ( ) ;
}
}
@Test
@Test
public void receivingPrepareFromProposerFails ( ) {
public void receivingPrepareFromProposerFails ( ) {
when ( headerValidator . validateHeader ( any ( ) , any ( ) , any ( ) , any ( ) ) ) . thenReturn ( true ) ;
final SignedData < ProposalPayload > proposalMsg =
final SignedData < ProposalPayload > preprepareMsg =
proposerMessageFactory . createSignedProposalPayload ( roundIdentifier , block ) ;
proposerMessageFactory . createSignedProposalPayload ( roundIdentifier , block ) ;
final SignedData < PreparePayload > prepareMsg =
final SignedData < PreparePayload > prepareMsg =
proposerMessageFactory . createSignedPreparePayload ( roundIdentifier , block . getHash ( ) ) ;
proposerMessageFactory . createSignedPreparePayload ( roundIdentifier , block . getHash ( ) ) ;
assertThat ( validator . addSignedProposalPayload ( preprepare Msg ) ) . isTrue ( ) ;
assertThat ( validator . addSignedProposalPayload ( proposal Msg ) ) . isTrue ( ) ;
assertThat ( validator . validatePrepareMessage ( prepareMsg ) ) . isFalse ( ) ;
assertThat ( validator . validatePrepareMessage ( prepareMsg ) ) . isFalse ( ) ;
}
}
@Test
@Test
public void receivingPrepareFromNonValidatorFails ( ) {
public void receivingPrepareFromNonValidatorFails ( ) {
when ( headerValidator . validateHeader ( any ( ) , any ( ) , any ( ) , any ( ) ) ) . thenReturn ( true ) ;
final SignedData < ProposalPayload > proposalMsg =
final SignedData < ProposalPayload > preprepareMsg =
proposerMessageFactory . createSignedProposalPayload ( roundIdentifier , block ) ;
proposerMessageFactory . createSignedProposalPayload ( roundIdentifier , block ) ;
final SignedData < PreparePayload > prepareMsg =
final SignedData < PreparePayload > prepareMsg =
nonValidatorMessageFactory . createSignedPreparePayload ( roundIdentifier , block . getHash ( ) ) ;
nonValidatorMessageFactory . createSignedPreparePayload ( roundIdentifier , block . getHash ( ) ) ;
assertThat ( validator . addSignedProposalPayload ( preprepare Msg ) ) . isTrue ( ) ;
assertThat ( validator . addSignedProposalPayload ( proposal Msg ) ) . isTrue ( ) ;
assertThat ( validator . validatePrepareMessage ( prepareMsg ) ) . isFalse ( ) ;
assertThat ( validator . validatePrepareMessage ( prepareMsg ) ) . isFalse ( ) ;
}
}
@Test
@Test
public void receivingMessagesWithDifferentRoundIdFromPreprepareFails ( ) {
public void receivingMessagesWithDifferentRoundIdFromProposalFails ( ) {
when ( headerValidator . validateHeader ( any ( ) , any ( ) , any ( ) , any ( ) ) ) . thenReturn ( true ) ;
final SignedData < ProposalPayload > proposalMsg =
final SignedData < ProposalPayload > preprepareMsg =
proposerMessageFactory . createSignedProposalPayload ( roundIdentifier , block ) ;
proposerMessageFactory . createSignedProposalPayload ( roundIdentifier , block ) ;
final ConsensusRoundIdentifier invalidRoundIdentifier =
final ConsensusRoundIdentifier invalidRoundIdentifier =
@ -182,44 +175,38 @@ public class MessageValidatorTest {
validatorMessageFactory . createSignedCommitPayload (
validatorMessageFactory . createSignedCommitPayload (
invalidRoundIdentifier , block . getHash ( ) , SECP256K1 . sign ( block . getHash ( ) , proposerKey ) ) ;
invalidRoundIdentifier , block . getHash ( ) , SECP256K1 . sign ( block . getHash ( ) , proposerKey ) ) ;
assertThat ( validator . addSignedProposalPayload ( preprepare Msg ) ) . isTrue ( ) ;
assertThat ( validator . addSignedProposalPayload ( proposal Msg ) ) . isTrue ( ) ;
assertThat ( validator . validatePrepareMessage ( prepareMsg ) ) . isFalse ( ) ;
assertThat ( validator . validatePrepareMessage ( prepareMsg ) ) . isFalse ( ) ;
assertThat ( validator . validateCommmitMessage ( commitMsg ) ) . isFalse ( ) ;
assertThat ( validator . validateCommmitMessage ( commitMsg ) ) . isFalse ( ) ;
}
}
@Test
@Test
public void receivingPrepareNonProposerValidatorWithCorrectRoundIsSuccessful ( ) {
public void receivingPrepareNonProposerValidatorWithCorrectRoundIsSuccessful ( ) {
when ( headerValidator . validateHeader ( any ( ) , any ( ) , any ( ) , any ( ) ) ) . thenReturn ( true ) ;
final SignedData < ProposalPayload > proposalMsg =
final SignedData < ProposalPayload > preprepareMsg =
proposerMessageFactory . createSignedProposalPayload ( roundIdentifier , block ) ;
proposerMessageFactory . createSignedProposalPayload ( roundIdentifier , block ) ;
final SignedData < PreparePayload > prepareMsg =
final SignedData < PreparePayload > prepareMsg =
validatorMessageFactory . createSignedPreparePayload ( roundIdentifier , block . getHash ( ) ) ;
validatorMessageFactory . createSignedPreparePayload ( roundIdentifier , block . getHash ( ) ) ;
assertThat ( validator . addSignedProposalPayload ( preprepare Msg ) ) . isTrue ( ) ;
assertThat ( validator . addSignedProposalPayload ( proposal Msg ) ) . isTrue ( ) ;
assertThat ( validator . validatePrepareMessage ( prepareMsg ) ) . isTrue ( ) ;
assertThat ( validator . validatePrepareMessage ( prepareMsg ) ) . isTrue ( ) ;
}
}
@Test
@Test
public void receivingACommitMessageWithAnInvalidCommitSealFails ( ) {
public void receivingACommitMessageWithAnInvalidCommitSealFails ( ) {
when ( headerValidator . validateHeader ( any ( ) , any ( ) , any ( ) , any ( ) ) ) . thenReturn ( true ) ;
final SignedData < ProposalPayload > proposalMsg =
final SignedData < ProposalPayload > preprepareMsg =
proposerMessageFactory . createSignedProposalPayload ( roundIdentifier , block ) ;
proposerMessageFactory . createSignedProposalPayload ( roundIdentifier , block ) ;
final SignedData < CommitPayload > commitMsg =
final SignedData < CommitPayload > commitMsg =
proposerMessageFactory . createSignedCommitPayload (
proposerMessageFactory . createSignedCommitPayload (
roundIdentifier , block . getHash ( ) , SECP256K1 . sign ( block . getHash ( ) , nonValidatorKey ) ) ;
roundIdentifier , block . getHash ( ) , SECP256K1 . sign ( block . getHash ( ) , nonValidatorKey ) ) ;
assertThat ( validator . addSignedProposalPayload ( preprepare Msg ) ) . isTrue ( ) ;
assertThat ( validator . addSignedProposalPayload ( proposal Msg ) ) . isTrue ( ) ;
assertThat ( validator . validateCommmitMessage ( commitMsg ) ) . isFalse ( ) ;
assertThat ( validator . validateCommmitMessage ( commitMsg ) ) . isFalse ( ) ;
}
}
@Test
@Test
public void commitMessageContainingValidSealFromValidatorIsSuccessful ( ) {
public void commitMessageContainingValidSealFromValidatorIsSuccessful ( ) {
when ( headerValidator . validateHeader ( any ( ) , any ( ) , any ( ) , any ( ) ) ) . thenReturn ( true ) ;
final SignedData < ProposalPayload > proposalMsg =
final SignedData < ProposalPayload > preprepareMsg =
proposerMessageFactory . createSignedProposalPayload ( roundIdentifier , block ) ;
proposerMessageFactory . createSignedProposalPayload ( roundIdentifier , block ) ;
final SignedData < CommitPayload > proposerCommitMsg =
final SignedData < CommitPayload > proposerCommitMsg =
@ -230,58 +217,52 @@ public class MessageValidatorTest {
validatorMessageFactory . createSignedCommitPayload (
validatorMessageFactory . createSignedCommitPayload (
roundIdentifier , block . getHash ( ) , SECP256K1 . sign ( block . getHash ( ) , validatorKey ) ) ;
roundIdentifier , block . getHash ( ) , SECP256K1 . sign ( block . getHash ( ) , validatorKey ) ) ;
assertThat ( validator . addSignedProposalPayload ( preprepare Msg ) ) . isTrue ( ) ;
assertThat ( validator . addSignedProposalPayload ( proposal Msg ) ) . isTrue ( ) ;
assertThat ( validator . validateCommmitMessage ( proposerCommitMsg ) ) . isTrue ( ) ;
assertThat ( validator . validateCommmitMessage ( proposerCommitMsg ) ) . isTrue ( ) ;
assertThat ( validator . validateCommmitMessage ( validatorCommitMsg ) ) . isTrue ( ) ;
assertThat ( validator . validateCommmitMessage ( validatorCommitMsg ) ) . isTrue ( ) ;
}
}
@Test
@Test
public void subsequentPreprepareHasDifferentSenderFails ( ) {
public void subsequentProposalHasDifferentSenderFails ( ) {
when ( headerValidator . validateHeader ( any ( ) , any ( ) , any ( ) , any ( ) ) ) . thenReturn ( true ) ;
final SignedData < ProposalPayload > proposalMsg =
final SignedData < ProposalPayload > preprepareMsg =
proposerMessageFactory . createSignedProposalPayload ( roundIdentifier , block ) ;
proposerMessageFactory . createSignedProposalPayload ( roundIdentifier , block ) ;
assertThat ( validator . addSignedProposalPayload ( preprepare Msg ) ) . isTrue ( ) ;
assertThat ( validator . addSignedProposalPayload ( proposalMsg ) ) . isTrue ( ) ;
final SignedData < ProposalPayload > secondPreprepare Msg =
final SignedData < ProposalPayload > secondProposal Msg =
validatorMessageFactory . createSignedProposalPayload ( roundIdentifier , block ) ;
validatorMessageFactory . createSignedProposalPayload ( roundIdentifier , block ) ;
assertThat ( validator . addSignedProposalPayload ( secondPreprepare Msg ) ) . isFalse ( ) ;
assertThat ( validator . addSignedProposalPayload ( secondProposal Msg ) ) . isFalse ( ) ;
}
}
@Test
@Test
public void subsequentPreprepareHasDifferentContentFails ( ) {
public void subsequentProposalHasDifferentContentFails ( ) {
final SignedData < ProposalPayload > proposalMsg =
final SignedData < ProposalPayload > preprepareMsg =
proposerMessageFactory . createSignedProposalPayload ( roundIdentifier , block ) ;
proposerMessageFactory . createSignedProposalPayload ( roundIdentifier , block ) ;
assertThat ( validator . addSignedProposalPayload ( preprepare Msg ) ) . isTrue ( ) ;
assertThat ( validator . addSignedProposalPayload ( proposal Msg ) ) . isTrue ( ) ;
final ConsensusRoundIdentifier newRoundIdentifier = new ConsensusRoundIdentifier ( 3 , 0 ) ;
final ConsensusRoundIdentifier newRoundIdentifier = new ConsensusRoundIdentifier ( 3 , 0 ) ;
final SignedData < ProposalPayload > secondPreprepare Msg =
final SignedData < ProposalPayload > secondProposal Msg =
proposerMessageFactory . createSignedProposalPayload ( newRoundIdentifier , block ) ;
proposerMessageFactory . createSignedProposalPayload ( newRoundIdentifier , block ) ;
assertThat ( validator . addSignedProposalPayload ( secondPreprepare Msg ) ) . isFalse ( ) ;
assertThat ( validator . addSignedProposalPayload ( secondProposal Msg ) ) . isFalse ( ) ;
}
}
@Test
@Test
public void subsequentPreprepareHasIdenticalSenderAndContentIsSuccessful ( ) {
public void subsequentProposalHasIdenticalSenderAndContentIsSuccessful ( ) {
when ( headerValidator . validateHeader ( any ( ) , any ( ) , any ( ) , any ( ) ) ) . thenReturn ( true ) ;
final SignedData < ProposalPayload > proposalMsg =
final SignedData < ProposalPayload > preprepareMsg =
proposerMessageFactory . createSignedProposalPayload ( roundIdentifier , block ) ;
proposerMessageFactory . createSignedProposalPayload ( roundIdentifier , block ) ;
assertThat ( validator . addSignedProposalPayload ( preprepare Msg ) ) . isTrue ( ) ;
assertThat ( validator . addSignedProposalPayload ( proposalMsg ) ) . isTrue ( ) ;
final SignedData < ProposalPayload > secondPreprepare Msg =
final SignedData < ProposalPayload > secondProposal Msg =
proposerMessageFactory . createSignedProposalPayload ( roundIdentifier , block ) ;
proposerMessageFactory . createSignedProposalPayload ( roundIdentifier , block ) ;
assertThat ( validator . addSignedProposalPayload ( secondPreprepare Msg ) ) . isTrue ( ) ;
assertThat ( validator . addSignedProposalPayload ( secondProposal Msg ) ) . isTrue ( ) ;
}
}
@Test
@Test
public void blockRoundMisMatchWithMessageRoundFails ( ) {
public void blockRoundMisMatchWithMessageRoundFails ( ) {
insertRoundToBlockHeader ( roundIdentifier . getRoundNumber ( ) + 1 ) ;
insertRoundToBlockHeader ( roundIdentifier . getRoundNumber ( ) + 1 ) ;
when ( headerValidator . validateHeader ( any ( ) , any ( ) , any ( ) , any ( ) ) ) . thenReturn ( true ) ;
final SignedData < ProposalPayload > proposalMsg =
final SignedData < ProposalPayload > preprepareMsg =
proposerMessageFactory . createSignedProposalPayload ( roundIdentifier , block ) ;
proposerMessageFactory . createSignedProposalPayload ( roundIdentifier , block ) ;
assertThat ( validator . addSignedProposalPayload ( preprepare Msg ) ) . isFalse ( ) ;
assertThat ( validator . addSignedProposalPayload ( proposal Msg ) ) . isFalse ( ) ;
}
}
}
}