diff --git a/consensus/ibft/src/integration-test/java/tech/pegasys/pantheon/consensus/ibft/support/TestContextFactory.java b/consensus/ibft/src/integration-test/java/tech/pegasys/pantheon/consensus/ibft/support/TestContextFactory.java index bb5414f0a6..179b585c35 100644 --- a/consensus/ibft/src/integration-test/java/tech/pegasys/pantheon/consensus/ibft/support/TestContextFactory.java +++ b/consensus/ibft/src/integration-test/java/tech/pegasys/pantheon/consensus/ibft/support/TestContextFactory.java @@ -44,6 +44,7 @@ import tech.pegasys.pantheon.consensus.ibft.statemachine.IbftRoundFactory; import tech.pegasys.pantheon.consensus.ibft.validation.MessageValidatorFactory; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.ethereum.ProtocolContext; +import tech.pegasys.pantheon.ethereum.chain.MinedBlockObserver; import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain; import tech.pegasys.pantheon.ethereum.core.Address; import tech.pegasys.pantheon.ethereum.core.AddressHelpers; @@ -59,6 +60,7 @@ import tech.pegasys.pantheon.ethereum.core.Wei; import tech.pegasys.pantheon.ethereum.db.WorldStateArchive; import tech.pegasys.pantheon.ethereum.mainnet.BlockHeaderValidator; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; +import tech.pegasys.pantheon.util.Subscribers; import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.uint.UInt256; @@ -258,13 +260,16 @@ public class TestContextFactory { // Disable Gossiping for integration tests. final IbftGossip gossiper = mock(IbftGossip.class); + final Subscribers minedBlockObservers = new Subscribers<>(); + final IbftController ibftController = new IbftController( blockChain, finalState, new IbftBlockHeightManagerFactory( finalState, - new IbftRoundFactory(finalState, protocolContext, protocolSchedule), + new IbftRoundFactory( + finalState, protocolContext, protocolSchedule, minedBlockObservers), messageValidatorFactory, protocolContext), new HashMap<>(), diff --git a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftFinalState.java b/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftFinalState.java index 68a916f575..9e8c4d79b1 100644 --- a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftFinalState.java +++ b/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftFinalState.java @@ -67,8 +67,8 @@ public class IbftFinalState { this.blockCreatorFactory = blockCreatorFactory; this.messageFactory = messageFactory; this.ibftContextBlockHeaderValidator = ibftContextBlockHeaderValidator; - this.messageTransmitter = new IbftMessageTransmitter(messageFactory, peers); this.clock = clock; + this.messageTransmitter = new IbftMessageTransmitter(messageFactory, peers); } public int getQuorumSize() { diff --git a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftRoundFactory.java b/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftRoundFactory.java index ed8fda0549..c5a45c3fea 100644 --- a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftRoundFactory.java +++ b/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftRoundFactory.java @@ -24,22 +24,22 @@ import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; import tech.pegasys.pantheon.util.Subscribers; public class IbftRoundFactory { - private final IbftFinalState finalState; - private final IbftBlockCreatorFactory blockCreatorFactory; private final ProtocolContext protocolContext; private final ProtocolSchedule protocolSchedule; - private final Subscribers minedBlockObservers = new Subscribers<>(); + private final Subscribers minedBlockObservers; public IbftRoundFactory( final IbftFinalState finalState, final ProtocolContext protocolContext, - final ProtocolSchedule protocolSchedule) { + final ProtocolSchedule protocolSchedule, + final Subscribers minedBlockObservers) { this.finalState = finalState; this.blockCreatorFactory = finalState.getBlockCreatorFactory(); this.protocolContext = protocolContext; this.protocolSchedule = protocolSchedule; + this.minedBlockObservers = minedBlockObservers; } public IbftRound createNewRound(final BlockHeader parentHeader, final int round) { diff --git a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftRoundTest.java b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftRoundTest.java index 59b0b811df..395df36321 100644 --- a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftRoundTest.java +++ b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/statemachine/IbftRoundTest.java @@ -68,14 +68,14 @@ public class IbftRoundTest { private final KeyPair localNodeKeys = KeyPair.generate(); private final ConsensusRoundIdentifier roundIdentifier = new ConsensusRoundIdentifier(1, 1); private final MessageFactory messageFactory = new MessageFactory(localNodeKeys); + private final Subscribers subscribers = new Subscribers<>(); private ProtocolContext protocolContext; @Mock private MutableBlockchain blockChain; @Mock private WorldStateArchive worldStateArchive; @Mock private BlockImporter blockImporter; - @Mock private Subscribers subscribers; @Mock private IbftMessageTransmitter transmitter; - + @Mock private MinedBlockObserver minedBlockObserver; @Mock private IbftBlockCreator blockCreator; @Mock private MessageValidator messageValidator; @@ -117,6 +117,8 @@ public class IbftRoundTest { when(blockCreator.createBlock(anyLong())).thenReturn(proposedBlock); when(blockImporter.importBlock(any(), any(), any())).thenReturn(true); + + subscribers.subscribe(minedBlockObserver); } @Test @@ -355,4 +357,21 @@ public class IbftRoundTest { messageFactory.createSignedPreparePayload(roundIdentifier, proposedBlock.getHash())); assertThat(roundState.isPrepared()).isTrue(); } + + @Test + public void creatingNewBlockNotifiesBlockMiningObservers() { + final RoundState roundState = new RoundState(roundIdentifier, 1, messageValidator); + final IbftRound round = + new IbftRound( + roundState, + blockCreator, + protocolContext, + blockImporter, + subscribers, + localNodeKeys, + messageFactory, + transmitter); + round.createAndSendProposalMessage(15); + verify(minedBlockObserver).blockMined(any()); + } } diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftPantheonController.java b/pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftPantheonController.java index 100870cb51..be9178866f 100644 --- a/pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftPantheonController.java +++ b/pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftPantheonController.java @@ -46,6 +46,7 @@ import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.ethereum.ProtocolContext; import tech.pegasys.pantheon.ethereum.blockcreation.MiningCoordinator; import tech.pegasys.pantheon.ethereum.chain.GenesisState; +import tech.pegasys.pantheon.ethereum.chain.MinedBlockObserver; import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain; import tech.pegasys.pantheon.ethereum.core.Hash; import tech.pegasys.pantheon.ethereum.core.MiningParameters; @@ -73,6 +74,7 @@ import tech.pegasys.pantheon.ethereum.storage.StorageProvider; import tech.pegasys.pantheon.ethereum.worldstate.WorldStateStorage; import tech.pegasys.pantheon.metrics.MetricCategory; import tech.pegasys.pantheon.metrics.MetricsSystem; +import tech.pegasys.pantheon.util.Subscribers; import java.io.IOException; import java.time.Clock; @@ -204,6 +206,9 @@ public class IbftPantheonController implements PantheonController { IbftBlockHeaderValidationRulesetFactory.ibftProposedBlockValidator( ibftConfig.getBlockPeriodSeconds()); + final Subscribers minedBlockObservers = new Subscribers<>(); + minedBlockObservers.subscribe(ethProtocolManager); + final IbftFinalState finalState = new IbftFinalState( voteTally, @@ -234,7 +239,8 @@ public class IbftPantheonController implements PantheonController { finalState, new IbftBlockHeightManagerFactory( finalState, - new IbftRoundFactory(finalState, protocolContext, protocolSchedule), + new IbftRoundFactory( + finalState, protocolContext, protocolSchedule, minedBlockObservers), messageValidatorFactory, protocolContext));