diff --git a/consensus/common/src/test-support/java/org/hyperledger/besu/consensus/common/bft/BftContextBuilder.java b/consensus/common/src/test-support/java/org/hyperledger/besu/consensus/common/bft/BftContextBuilder.java index 890045bf365..0a848c737cc 100644 --- a/consensus/common/src/test-support/java/org/hyperledger/besu/consensus/common/bft/BftContextBuilder.java +++ b/consensus/common/src/test-support/java/org/hyperledger/besu/consensus/common/bft/BftContextBuilder.java @@ -73,12 +73,20 @@ public static T setupContextWithBftExtraDataEncoder( final Class contextClazz, final Collection
validators, final BftExtraDataCodec bftExtraDataCodec) { + return setupContextWithBftBlockInterface( + contextClazz, validators, new BftBlockInterface(bftExtraDataCodec)); + } + + public static T setupContextWithBftBlockInterface( + final Class contextClazz, + final Collection
validators, + final BftBlockInterface bftBlockInterface) { final T bftContext = mock(contextClazz, withSettings().strictness(Strictness.LENIENT)); final ValidatorProvider mockValidatorProvider = mock(ValidatorProvider.class, withSettings().strictness(Strictness.LENIENT)); when(bftContext.getValidatorProvider()).thenReturn(mockValidatorProvider); when(mockValidatorProvider.getValidatorsAfterBlock(any())).thenReturn(validators); - when(bftContext.getBlockInterface()).thenReturn(new BftBlockInterface(bftExtraDataCodec)); + when(bftContext.getBlockInterface()).thenReturn(bftBlockInterface); when(bftContext.as(any())).thenReturn(bftContext); return bftContext; diff --git a/consensus/qbft-core/build.gradle b/consensus/qbft-core/build.gradle index aab093f53ef..db00ec82655 100644 --- a/consensus/qbft-core/build.gradle +++ b/consensus/qbft-core/build.gradle @@ -55,7 +55,6 @@ dependencies { testImplementation project(path: ':config', configuration: 'testSupportArtifacts') testImplementation project(path: ':consensus:common', configuration: 'testArtifacts') testImplementation project(path: ':consensus:common', configuration: 'testSupportArtifacts') - testImplementation project(':consensus:qbft') testImplementation project(':ethereum:core') testImplementation project(path: ':ethereum:core', configuration: 'testSupportArtifacts') testImplementation project(':crypto:algorithms') diff --git a/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/ProposalTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/ProposalTest.java index 885bd03c2d9..52946270031 100644 --- a/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/ProposalTest.java +++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/ProposalTest.java @@ -16,11 +16,9 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.hyperledger.besu.consensus.common.bft.BftExtraData; import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; import org.hyperledger.besu.consensus.qbft.core.messagedata.QbftV1; import org.hyperledger.besu.consensus.qbft.core.payload.PreparePayload; import org.hyperledger.besu.consensus.qbft.core.payload.PreparedRoundMetadata; @@ -38,19 +36,18 @@ import java.util.List; import java.util.Optional; -import org.apache.tuweni.bytes.Bytes32; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +@ExtendWith(MockitoExtension.class) public class ProposalTest { - private static final BftExtraDataCodec bftExtraDataCodec = new QbftExtraDataCodec(); - - private static final BftExtraData extraData = - new BftExtraData( - Bytes32.ZERO, Collections.emptyList(), Optional.empty(), 1, Collections.emptyList()); + @Mock private BftExtraDataCodec bftExtraDataCodec; private static final Block BLOCK = new Block( - new BlockHeaderTestFixture().extraData(bftExtraDataCodec.encode(extraData)).buildHeader(), + new BlockHeaderTestFixture().buildHeader(), new BlockBody( Collections.emptyList(), Collections.emptyList(), diff --git a/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/RoundChangeTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/RoundChangeTest.java index cf415b3bef1..1f38cb787eb 100644 --- a/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/RoundChangeTest.java +++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/RoundChangeTest.java @@ -16,11 +16,9 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.hyperledger.besu.consensus.common.bft.BftExtraData; import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; import org.hyperledger.besu.consensus.qbft.core.messagedata.QbftV1; import org.hyperledger.besu.consensus.qbft.core.payload.PreparePayload; import org.hyperledger.besu.consensus.qbft.core.payload.PreparedRoundMetadata; @@ -37,20 +35,18 @@ import java.util.List; import java.util.Optional; -import org.apache.tuweni.bytes.Bytes32; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +@ExtendWith(MockitoExtension.class) public class RoundChangeTest { - private static final BftExtraDataCodec bftExtraDataCodec = new QbftExtraDataCodec(); - private static final BftExtraData extraData = - new BftExtraData( - Bytes32.ZERO, Collections.emptyList(), Optional.empty(), 1, Collections.emptyList()); + @Mock private BftExtraDataCodec bftExtraDataCodec; private static final Block BLOCK = new Block( - new BlockHeaderTestFixture() - .extraData(new QbftExtraDataCodec().encode(extraData)) - .buildHeader(), + new BlockHeaderTestFixture().buildHeader(), new BlockBody(Collections.emptyList(), Collections.emptyList())); @Test diff --git a/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftBlockHeightManagerTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftBlockHeightManagerTest.java index 2788dfc0505..d77a28867bb 100644 --- a/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftBlockHeightManagerTest.java +++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftBlockHeightManagerTest.java @@ -43,7 +43,6 @@ import org.hyperledger.besu.consensus.common.bft.events.RoundExpiry; import org.hyperledger.besu.consensus.common.bft.network.ValidatorMulticaster; import org.hyperledger.besu.consensus.common.bft.statemachine.BftFinalState; -import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; import org.hyperledger.besu.consensus.qbft.core.messagedata.RoundChangeMessageData; import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit; import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; @@ -107,7 +106,6 @@ public class QbftBlockHeightManagerTest { private final NodeKey nodeKey = NodeKeyUtils.generate(); private final MessageFactory messageFactory = new MessageFactory(nodeKey); private final BlockHeaderTestFixture headerTestFixture = new BlockHeaderTestFixture(); - private final BftExtraDataCodec bftExtraDataCodec = new QbftExtraDataCodec(); @Mock private BftFinalState finalState; @Mock private QbftMessageTransmitter messageTransmitter; @@ -122,6 +120,7 @@ public class QbftBlockHeightManagerTest { @Mock private FutureRoundProposalMessageValidator futureRoundProposalMessageValidator; @Mock private ValidatorMulticaster validatorMulticaster; @Mock private BlockHeader parentHeader; + @Mock private BftExtraDataCodec bftExtraDataCodec; @Captor private ArgumentCaptor sentMessageArgCaptor; @@ -133,11 +132,6 @@ public class QbftBlockHeightManagerTest { private Block createdBlock; private void buildCreatedBlock() { - - final BftExtraData extraData = - new BftExtraData(Bytes.wrap(new byte[32]), emptyList(), Optional.empty(), 0, validators); - - headerTestFixture.extraData(bftExtraDataCodec.encode(extraData)); final BlockHeader header = headerTestFixture.buildHeader(); createdBlock = new Block(header, new BlockBody(emptyList(), emptyList())); } @@ -175,8 +169,7 @@ public void setup() { new ProtocolContext( blockchain, null, - setupContextWithBftExtraDataEncoder( - BftContext.class, validators, new QbftExtraDataCodec()), + setupContextWithBftExtraDataEncoder(BftContext.class, validators, bftExtraDataCodec), new BadBlockManager()); final ProtocolScheduleBuilder protocolScheduleBuilder = @@ -234,6 +227,12 @@ BftContext.class, validators, new QbftExtraDataCodec()), bftExtraDataCodec, parentHeader); }); + + when(bftExtraDataCodec.decode(any())) + .thenReturn( + new BftExtraData( + Bytes.wrap(new byte[32]), emptyList(), Optional.empty(), 0, validators)); + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); } @Test diff --git a/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftControllerTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftControllerTest.java index 6a1b18fa709..d6e6fb9fc6f 100644 --- a/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftControllerTest.java +++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftControllerTest.java @@ -35,7 +35,6 @@ import org.hyperledger.besu.consensus.common.bft.events.RoundExpiry; import org.hyperledger.besu.consensus.common.bft.statemachine.BftFinalState; import org.hyperledger.besu.consensus.common.bft.statemachine.FutureMessageBuffer; -import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; import org.hyperledger.besu.consensus.qbft.core.messagedata.CommitMessageData; import org.hyperledger.besu.consensus.qbft.core.messagedata.PrepareMessageData; import org.hyperledger.besu.consensus.qbft.core.messagedata.ProposalMessageData; @@ -68,14 +67,13 @@ @ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.LENIENT) public class QbftControllerTest { - private static final BftExtraDataCodec bftExtraDataCodec = new QbftExtraDataCodec(); - @Mock private Blockchain blockChain; @Mock private BftFinalState bftFinalState; @Mock private QbftBlockHeightManagerFactory blockHeightManagerFactory; @Mock private BlockHeader chainHeadBlockHeader; @Mock private BlockHeader nextBlock; @Mock private BaseQbftBlockHeightManager blockHeightManager; + @Mock private BftExtraDataCodec bftExtraDataCodec; @Mock private Proposal proposal; private Message proposalMessage; diff --git a/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftRoundTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftRoundTest.java index 9e61d582a3c..e63ee14bae6 100644 --- a/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftRoundTest.java +++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftRoundTest.java @@ -18,7 +18,7 @@ import static java.util.Collections.singletonList; import static java.util.Optional.empty; import static org.assertj.core.api.Assertions.assertThat; -import static org.hyperledger.besu.consensus.common.bft.BftContextBuilder.setupContextWithBftExtraDataEncoder; +import static org.hyperledger.besu.consensus.common.bft.BftContextBuilder.setupContextWithBftBlockInterface; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; @@ -29,6 +29,7 @@ import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; +import org.hyperledger.besu.consensus.common.bft.BftBlockInterface; import org.hyperledger.besu.consensus.common.bft.BftContext; import org.hyperledger.besu.consensus.common.bft.BftExtraData; import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; @@ -37,7 +38,6 @@ import org.hyperledger.besu.consensus.common.bft.RoundTimer; import org.hyperledger.besu.consensus.common.bft.blockcreation.BftBlockCreator; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; import org.hyperledger.besu.consensus.qbft.core.messagewrappers.RoundChange; import org.hyperledger.besu.consensus.qbft.core.network.QbftMessageTransmitter; import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; @@ -91,7 +91,6 @@ public class QbftRoundTest { private final MessageFactory messageFactory = new MessageFactory(nodeKey); private final MessageFactory messageFactory2 = new MessageFactory(nodeKey2); private final Subscribers subscribers = Subscribers.create(); - private final BftExtraDataCodec bftExtraDataCodec = new QbftExtraDataCodec(); private ProtocolContext protocolContext; @Mock private BftProtocolSchedule protocolSchedule; @@ -105,11 +104,12 @@ public class QbftRoundTest { @Mock private ProtocolSpec protocolSpec; @Mock private BlockImporter blockImporter; @Mock private BlockHeader parentHeader; + @Mock private BftExtraDataCodec bftExtraDataCodec; + @Mock private BftBlockInterface bftBlockInteface; @Captor private ArgumentCaptor blockCaptor; private Block proposedBlock; - private BftExtraData proposedExtraData; private final SECPSignature remoteCommitSeal = SignatureAlgorithmFactory.getInstance() @@ -121,18 +121,14 @@ public void setup() { new ProtocolContext( blockChain, worldStateArchive, - setupContextWithBftExtraDataEncoder( - BftContext.class, emptyList(), new QbftExtraDataCodec()), + setupContextWithBftBlockInterface(BftContext.class, emptyList(), bftBlockInteface), new BadBlockManager()); when(messageValidator.validateProposal(any())).thenReturn(true); when(messageValidator.validatePrepare(any())).thenReturn(true); when(messageValidator.validateCommit(any())).thenReturn(true); - proposedExtraData = - new BftExtraData(Bytes.wrap(new byte[32]), emptyList(), empty(), 0, emptyList()); final BlockHeaderTestFixture headerTestFixture = new BlockHeaderTestFixture(); - headerTestFixture.extraData(new QbftExtraDataCodec().encode(proposedExtraData)); headerTestFixture.number(1); final BlockHeader header = headerTestFixture.buildHeader(); @@ -149,6 +145,16 @@ BftContext.class, emptyList(), new QbftExtraDataCodec()), when(blockImporter.importBlock(any(), any(), any())) .thenReturn(new BlockImportResult(BlockImportResult.BlockImportStatus.IMPORTED)); + BftExtraData bftExtraData = + new BftExtraData(Bytes.wrap(new byte[32]), emptyList(), empty(), 0, emptyList()); + when(bftExtraDataCodec.decode(any())).thenReturn(bftExtraData); + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.encodeWithoutCommitSealsAndRoundNumber(any())).thenReturn(Bytes.EMPTY); + when(bftBlockInteface.replaceRoundInBlock( + eq(proposedBlock), eq(roundIdentifier.getRoundNumber()), any())) + .thenReturn(proposedBlock); + subscribers.subscribe(minedBlockObserver); } @@ -187,6 +193,9 @@ public void onReceptionOfValidProposalSendsAPrepareToNetworkPeers() { bftExtraDataCodec, parentHeader); + when(bftBlockInteface.replaceRoundInBlock(eq(proposedBlock), eq(0), any())) + .thenReturn(proposedBlock); + round.handleProposalMessage( messageFactory.createProposal( roundIdentifier, proposedBlock, Collections.emptyList(), Collections.emptyList())); @@ -256,10 +265,6 @@ public void aProposalMessageWithTheSameBlockIsSentUponReceptionOfARoundChangeWit verify(transmitter, times(1)) .multicastPrepare(eq(roundIdentifier), eq(blockCaptor.getValue().getHash())); - final BftExtraData proposedExtraData = - new QbftExtraDataCodec().decode(blockCaptor.getValue().getHeader()); - assertThat(proposedExtraData.getRound()).isEqualTo(roundIdentifier.getRoundNumber()); - // Inject a single Prepare message, and confirm the roundState has gone to Prepared (which // indicates the block has entered the roundState (note: all msgs are deemed valid due to mocks) round.handlePrepareMessage( @@ -326,6 +331,9 @@ public void blockIsOnlyImportedOnceWhenCommitsAreReceivedBeforeProposal() { bftExtraDataCodec, parentHeader); + when(bftBlockInteface.replaceRoundInBlock(eq(proposedBlock), eq(0), any())) + .thenReturn(proposedBlock); + round.handleCommitMessage( messageFactory.createCommit(roundIdentifier, proposedBlock.getHash(), remoteCommitSeal)); @@ -352,12 +360,17 @@ public void blockIsImportedOnlyOnceIfQuorumCommitsAreReceivedPriorToProposal() { bftExtraDataCodec, parentHeader); + when(bftBlockInteface.replaceRoundInBlock(eq(proposedBlock), eq(0), any())) + .thenReturn(proposedBlock); + round.handleCommitMessage( messageFactory.createCommit(roundIdentifier, proposedBlock.getHash(), remoteCommitSeal)); round.handleProposalMessage( messageFactory.createProposal( roundIdentifier, proposedBlock, Collections.emptyList(), Collections.emptyList())); + + // TODO add assertions } @Test @@ -382,6 +395,9 @@ public void exceptionDuringNodeKeySigningDoesNotEscape() { bftExtraDataCodec, parentHeader); + when(bftBlockInteface.replaceRoundInBlock(eq(proposedBlock), eq(0), any())) + .thenReturn(proposedBlock); + round.handleProposalMessage( messageFactory.createProposal( roundIdentifier, proposedBlock, Collections.emptyList(), Collections.emptyList())); diff --git a/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/ProposalPayloadValidatorTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/ProposalPayloadValidatorTest.java index 4984a950c21..0cc93a4c46d 100644 --- a/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/ProposalPayloadValidatorTest.java +++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/ProposalPayloadValidatorTest.java @@ -17,15 +17,16 @@ import static java.util.Collections.emptyList; import static org.assertj.core.api.Assertions.assertThat; import static org.hyperledger.besu.consensus.common.bft.BftContextBuilder.setupContextWithBftExtraDataEncoder; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import org.hyperledger.besu.consensus.common.bft.BftContext; +import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundHelpers; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.ProposedBlockHelpers; -import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal; import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; import org.hyperledger.besu.cryptoservices.NodeKey; @@ -43,6 +44,7 @@ import java.util.Optional; +import org.apache.tuweni.bytes.Bytes; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -55,6 +57,7 @@ public class ProposalPayloadValidatorTest { @Mock private BlockValidator blockValidator; @Mock private MutableBlockchain blockChain; @Mock private WorldStateArchive worldStateArchive; + @Mock private BftExtraDataCodec bftExtraDataCodec; private ProtocolContext protocolContext; private static final int CHAIN_HEIGHT = 3; @@ -66,7 +69,6 @@ public class ProposalPayloadValidatorTest { private final MessageFactory messageFactory = new MessageFactory(nodeKey); final ConsensusRoundIdentifier roundIdentifier = ConsensusRoundHelpers.createFrom(targetRound, 1, 0); - final QbftExtraDataCodec bftExtraDataCodec = new QbftExtraDataCodec(); @BeforeEach public void setup() { @@ -80,6 +82,7 @@ public void setup() { @Test public void validationPassesWhenProposerAndRoundMatchAndBlockIsValid() { + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); final ProposalPayloadValidator payloadValidator = new ProposalPayloadValidator( expectedProposer, roundIdentifier, blockValidator, protocolContext); @@ -101,6 +104,7 @@ public void validationPassesWhenProposerAndRoundMatchAndBlockIsValid() { @Test public void validationPassesWhenBlockRoundDoesNotMatchProposalRound() { + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); final ProposalPayloadValidator payloadValidator = new ProposalPayloadValidator( expectedProposer, roundIdentifier, blockValidator, protocolContext); @@ -126,6 +130,7 @@ public void validationPassesWhenBlockRoundDoesNotMatchProposalRound() { @Test public void validationFailsWhenBlockFailsValidation() { + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); final ConsensusRoundIdentifier roundIdentifier = ConsensusRoundHelpers.createFrom(targetRound, 1, 0); @@ -199,6 +204,8 @@ public void validationFailsWhenMessageMismatchesExpectedHeight() { @Test public void validationFailsForBlockWithIncorrectHeight() { + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); + final ProposalPayloadValidator payloadValidator = new ProposalPayloadValidator( expectedProposer, roundIdentifier, blockValidator, protocolContext); diff --git a/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/ProposalValidatorTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/ProposalValidatorTest.java index ea680866546..c5c2627427d 100644 --- a/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/ProposalValidatorTest.java +++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/ProposalValidatorTest.java @@ -25,13 +25,14 @@ import static org.mockito.Mockito.when; import org.hyperledger.besu.consensus.common.bft.BftContext; +import org.hyperledger.besu.consensus.common.bft.BftExtraData; +import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; import org.hyperledger.besu.consensus.common.bft.BftHelpers; import org.hyperledger.besu.consensus.common.bft.BftProtocolSchedule; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundHelpers; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.ProposedBlockHelpers; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal; import org.hyperledger.besu.consensus.qbft.core.messagewrappers.RoundChange; @@ -54,6 +55,7 @@ import java.util.Map; import java.util.Optional; +import org.apache.tuweni.bytes.Bytes; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -91,10 +93,10 @@ public RoundSpecificItems( @Mock private WorldStateArchive worldStateArchive; @Mock private BftProtocolSchedule protocolSchedule; @Mock private ProtocolSpec protocolSpec; + @Mock private BftExtraDataCodec bftExtraDataCodec; private ProtocolContext protocolContext; private final Map roundItems = new HashMap<>(); - final QbftExtraDataCodec bftExtraDataEncoder = new QbftExtraDataCodec(); @BeforeEach public void setup() { @@ -102,7 +104,7 @@ public void setup() { new ProtocolContext( blockChain, worldStateArchive, - setupContextWithBftExtraDataEncoder(BftContext.class, emptyList(), bftExtraDataEncoder), + setupContextWithBftExtraDataEncoder(BftContext.class, emptyList(), bftExtraDataCodec), new BadBlockManager()); // typically tests require the blockValidation to be successful @@ -118,6 +120,7 @@ public void setup() { when(protocolSpec.getBlockValidator()).thenReturn(blockValidator); + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); roundItems.put(ROUND_ID.ZERO, createRoundSpecificItems(0)); roundItems.put(ROUND_ID.ONE, createRoundSpecificItems(1)); } @@ -127,7 +130,7 @@ private RoundSpecificItems createRoundSpecificItems(final int roundNumber) { return new RoundSpecificItems( ProposedBlockHelpers.createProposalBlock( - validators.getNodeAddresses(), roundIdentifier, bftExtraDataEncoder), + validators.getNodeAddresses(), roundIdentifier, bftExtraDataCodec), roundIdentifier, new ProposalValidator( protocolContext, @@ -136,7 +139,7 @@ private RoundSpecificItems createRoundSpecificItems(final int roundNumber) { validators.getNodeAddresses(), roundIdentifier, validators.getNode(0).getAddress(), - bftExtraDataEncoder)); + bftExtraDataCodec)); } // NOTE: tests herein assume the ProposalPayloadValidator works as expected, so other than @@ -177,6 +180,10 @@ public void validationFailsIfBlockIsInvalid() { @Test public void validationFailsIfRoundZeroHasNonEmptyPrepares() { + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.decode(any())) + .thenReturn(new BftExtraData(Bytes.EMPTY, emptyList(), Optional.empty(), 0, emptyList())); + final Prepare prepareMsg = validators .getMessageFactory(1) @@ -350,6 +357,10 @@ public void validationFailsIfBlockHashInLatestPreparedMetadataDoesNotMatchPropos roundChanges.add(preparedRoundChange); + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.decode(any())) + .thenReturn(new BftExtraData(Bytes.EMPTY, emptyList(), Optional.empty(), 0, emptyList())); + final Proposal proposal = validators .getMessageFactory(0) @@ -395,6 +406,10 @@ public void validationFailsIfPreparesAreNonEmptyButNoRoundChangeHasPreparedMetad @Test public void validationFailsIfPiggybackedPreparePayloadIsFromNonValidator() { + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.decode(any())) + .thenReturn(new BftExtraData(Bytes.EMPTY, emptyList(), Optional.empty(), 0, emptyList())); + final RoundSpecificItems roundItem = roundItems.get(ROUND_ID.ONE); final List> roundChanges = createPreparedRoundZeroRoundChanges(); @@ -418,6 +433,10 @@ public void validationFailsIfPiggybackedPreparePayloadIsFromNonValidator() { @Test public void validationFailsIfPiggybackedPreparePayloadHasDuplicatedAuthors() { + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.decode(any())) + .thenReturn(new BftExtraData(Bytes.EMPTY, emptyList(), Optional.empty(), 0, emptyList())); + final RoundSpecificItems roundItem = roundItems.get(ROUND_ID.ONE); final List> roundChanges = createPreparedRoundZeroRoundChanges(); @@ -440,6 +459,10 @@ public void validationFailsIfPiggybackedPreparePayloadHasDuplicatedAuthors() { @Test public void validationFailsIfInsufficientPiggybackedPreparePayloads() { + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.decode(any())) + .thenReturn(new BftExtraData(Bytes.EMPTY, emptyList(), Optional.empty(), 0, emptyList())); + final RoundSpecificItems roundItem = roundItems.get(ROUND_ID.ONE); final List> roundChanges = createPreparedRoundZeroRoundChanges(); @@ -461,6 +484,10 @@ public void validationFailsIfInsufficientPiggybackedPreparePayloads() { @Test public void validationFailsIfPreparePayloadsDoNotMatchMetadataInRoundChanges() { + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.decode(any())) + .thenReturn(new BftExtraData(Bytes.EMPTY, emptyList(), Optional.empty(), 0, emptyList())); + final RoundSpecificItems roundItem = roundItems.get(ROUND_ID.ONE); final List> roundChanges = createPreparedRoundZeroRoundChanges(); @@ -483,6 +510,10 @@ public void validationFailsIfPreparePayloadsDoNotMatchMetadataInRoundChanges() { @Test public void validationFailsIfPreparePayloadsDoNotMatchBlockHashInRoundChanges() { + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.decode(any())) + .thenReturn(new BftExtraData(Bytes.EMPTY, emptyList(), Optional.empty(), 0, emptyList())); + final RoundSpecificItems roundItem = roundItems.get(ROUND_ID.ONE); final List> roundChanges = createPreparedRoundZeroRoundChanges(); @@ -505,6 +536,10 @@ public void validationFailsIfPreparePayloadsDoNotMatchBlockHashInRoundChanges() @Test public void validationFailsIfTwoRoundChangesArePreparedOnSameRoundDifferentBlock() { + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.decode(any())) + .thenReturn(new BftExtraData(Bytes.EMPTY, emptyList(), Optional.empty(), 0, emptyList())); + final RoundSpecificItems roundItem = roundItems.get(ROUND_ID.ONE); final List> roundChanges = createPreparedRoundZeroRoundChanges(); diff --git a/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/RoundChangeMessageValidatorTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/RoundChangeMessageValidatorTest.java index 67fce5fbfb0..573caa4bad5 100644 --- a/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/RoundChangeMessageValidatorTest.java +++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/RoundChangeMessageValidatorTest.java @@ -25,13 +25,13 @@ import static org.mockito.Mockito.when; import org.hyperledger.besu.consensus.common.bft.BftContext; +import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; import org.hyperledger.besu.consensus.common.bft.BftHelpers; import org.hyperledger.besu.consensus.common.bft.BftProtocolSchedule; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundHelpers; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.ProposedBlockHelpers; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; import org.hyperledger.besu.consensus.qbft.core.messagewrappers.RoundChange; import org.hyperledger.besu.consensus.qbft.core.payload.PreparedRoundMetadata; import org.hyperledger.besu.consensus.qbft.core.payload.RoundChangePayload; @@ -51,6 +51,7 @@ import java.util.Optional; import java.util.stream.Collectors; +import org.apache.tuweni.bytes.Bytes; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -66,6 +67,7 @@ public class RoundChangeMessageValidatorTest { @Mock private BftProtocolSchedule protocolSchedule; @Mock private BlockValidator blockValidator; @Mock private ProtocolSpec protocolSpec; + @Mock private BftExtraDataCodec bftExtraDataCodec; private ProtocolContext protocolContext; private RoundChangeMessageValidator messageValidator; @@ -76,7 +78,6 @@ public class RoundChangeMessageValidatorTest { new ConsensusRoundIdentifier(CHAIN_HEIGHT, 3); private final ConsensusRoundIdentifier roundIdentifier = ConsensusRoundHelpers.createFrom(targetRound, 0, -1); - private final QbftExtraDataCodec bftExtraDataEncoder = new QbftExtraDataCodec(); @BeforeEach public void setup() { @@ -84,7 +85,7 @@ public void setup() { new ProtocolContext( blockChain, worldStateArchive, - setupContextWithBftExtraDataEncoder(BftContext.class, emptyList(), bftExtraDataEncoder), + setupContextWithBftExtraDataEncoder(BftContext.class, emptyList(), bftExtraDataCodec), new BadBlockManager()); lenient().when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec); @@ -116,6 +117,8 @@ public void roundChangeWithValidPiggyBackDataIsValid() { when(payloadValidator.validate(any())).thenReturn(true); when(blockValidator.validateAndProcessBlock(any(), any(), any(), any())) .thenReturn(new BlockProcessingResult(Optional.empty())); + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); messageValidator = new RoundChangeMessageValidator( payloadValidator, @@ -127,7 +130,7 @@ public void roundChangeWithValidPiggyBackDataIsValid() { final Block block = ProposedBlockHelpers.createProposalBlock( - Collections.emptyList(), roundIdentifier, bftExtraDataEncoder); + Collections.emptyList(), roundIdentifier, bftExtraDataCodec); final PreparedCertificate prepCert = createPreparedCertificate( block, roundIdentifier, toArray(validators.getNodes(), QbftNode.class)); @@ -142,6 +145,8 @@ public void roundChangeWithBlockRoundMismatchingPreparesIsValid() { when(payloadValidator.validate(any())).thenReturn(true); when(blockValidator.validateAndProcessBlock(any(), any(), any(), any())) .thenReturn(new BlockProcessingResult(Optional.empty())); + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); messageValidator = new RoundChangeMessageValidator( payloadValidator, @@ -153,7 +158,7 @@ public void roundChangeWithBlockRoundMismatchingPreparesIsValid() { final Block block = ProposedBlockHelpers.createProposalBlock( - Collections.emptyList(), roundIdentifier, bftExtraDataEncoder); + Collections.emptyList(), roundIdentifier, bftExtraDataCodec); final PreparedCertificate prepCert = createPreparedCertificate( block, @@ -212,6 +217,8 @@ public void insufficientPiggyBackedPrepareMessagesIsInvalid() { when(payloadValidator.validate(any())).thenReturn(true); when(blockValidator.validateAndProcessBlock(any(), any(), any(), any())) .thenReturn(new BlockProcessingResult(Optional.empty())); + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); messageValidator = new RoundChangeMessageValidator( payloadValidator, @@ -223,7 +230,7 @@ public void insufficientPiggyBackedPrepareMessagesIsInvalid() { final Block block = ProposedBlockHelpers.createProposalBlock( - Collections.emptyList(), roundIdentifier, bftExtraDataEncoder); + Collections.emptyList(), roundIdentifier, bftExtraDataCodec); final PreparedCertificate prepCert = createPreparedCertificate( block, roundIdentifier, validators.getNode(0), validators.getNode(1)); @@ -238,6 +245,8 @@ public void prepareFromNonValidatorFails() { when(payloadValidator.validate(any())).thenReturn(true); when(blockValidator.validateAndProcessBlock(any(), any(), any(), any())) .thenReturn(new BlockProcessingResult(Optional.empty())); + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); messageValidator = new RoundChangeMessageValidator( payloadValidator, @@ -251,7 +260,7 @@ public void prepareFromNonValidatorFails() { final Block block = ProposedBlockHelpers.createProposalBlock( - Collections.emptyList(), roundIdentifier, bftExtraDataEncoder); + Collections.emptyList(), roundIdentifier, bftExtraDataCodec); final PreparedCertificate prepCert = createPreparedCertificate( block, roundIdentifier, validators.getNode(0), validators.getNode(1), nonValidator); @@ -266,6 +275,8 @@ public void validationFailsIfPreparedMetadataContainsDifferentRoundToBlock() { when(payloadValidator.validate(any())).thenReturn(true); when(blockValidator.validateAndProcessBlock(any(), any(), any(), any())) .thenReturn(new BlockProcessingResult(Optional.empty())); + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); messageValidator = new RoundChangeMessageValidator( payloadValidator, @@ -277,7 +288,7 @@ public void validationFailsIfPreparedMetadataContainsDifferentRoundToBlock() { final Block block = ProposedBlockHelpers.createProposalBlock( - Collections.emptyList(), roundIdentifier, bftExtraDataEncoder); + Collections.emptyList(), roundIdentifier, bftExtraDataCodec); final PreparedCertificate prepCert = new PreparedCertificate( block, @@ -300,6 +311,8 @@ public void validationFailsIfPreparesContainsDifferentRoundToBlock() { when(payloadValidator.validate(any())).thenReturn(true); when(blockValidator.validateAndProcessBlock(any(), any(), any(), any())) .thenReturn(new BlockProcessingResult(Optional.empty())); + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); messageValidator = new RoundChangeMessageValidator( payloadValidator, @@ -311,7 +324,7 @@ public void validationFailsIfPreparesContainsDifferentRoundToBlock() { final Block block = ProposedBlockHelpers.createProposalBlock( - Collections.emptyList(), roundIdentifier, bftExtraDataEncoder); + Collections.emptyList(), roundIdentifier, bftExtraDataCodec); final PreparedCertificate prepCert = new PreparedCertificate( block, @@ -336,6 +349,8 @@ public void validationFailsIfPreparesContainsWrongHeight() { when(payloadValidator.validate(any())).thenReturn(true); when(blockValidator.validateAndProcessBlock(any(), any(), any(), any())) .thenReturn(new BlockProcessingResult(Optional.empty())); + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); messageValidator = new RoundChangeMessageValidator( payloadValidator, @@ -347,7 +362,7 @@ public void validationFailsIfPreparesContainsWrongHeight() { final Block block = ProposedBlockHelpers.createProposalBlock( - Collections.emptyList(), roundIdentifier, bftExtraDataEncoder); + Collections.emptyList(), roundIdentifier, bftExtraDataCodec); final PreparedCertificate prepCert = new PreparedCertificate( block, @@ -372,6 +387,8 @@ public void validationFailsIfPreparesHaveDuplicateAuthors() { when(payloadValidator.validate(any())).thenReturn(true); when(blockValidator.validateAndProcessBlock(any(), any(), any(), any())) .thenReturn(new BlockProcessingResult(Optional.empty())); + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); messageValidator = new RoundChangeMessageValidator( payloadValidator, @@ -383,7 +400,7 @@ public void validationFailsIfPreparesHaveDuplicateAuthors() { final Block block = ProposedBlockHelpers.createProposalBlock( - Collections.emptyList(), roundIdentifier, bftExtraDataEncoder); + Collections.emptyList(), roundIdentifier, bftExtraDataCodec); final PreparedCertificate prepCert = createPreparedCertificate( block,