mirror of https://github.com/hyperledger/besu
Ibft Int Testing - Local Node is proposer (#527)
parent
fbd933fe07
commit
c4b25b75f1
@ -0,0 +1,42 @@ |
||||
/* |
||||
* Copyright 2019 ConsenSys AG. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations under the License. |
||||
*/ |
||||
package tech.pegasys.pantheon.consensus.ibft.support; |
||||
|
||||
import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier; |
||||
import tech.pegasys.pantheon.consensus.ibft.IbftBlockHashing; |
||||
import tech.pegasys.pantheon.consensus.ibft.IbftExtraData; |
||||
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.CommitPayload; |
||||
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.MessageFactory; |
||||
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.SignedData; |
||||
import tech.pegasys.pantheon.crypto.SECP256K1; |
||||
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; |
||||
import tech.pegasys.pantheon.crypto.SECP256K1.Signature; |
||||
import tech.pegasys.pantheon.ethereum.core.Block; |
||||
|
||||
public class TestHelpers { |
||||
|
||||
public static SignedData<CommitPayload> createSignedCommentPayload( |
||||
final Block block, final KeyPair signingKeyPair, final ConsensusRoundIdentifier roundId) { |
||||
|
||||
final IbftExtraData extraData = IbftExtraData.decode(block.getHeader().getExtraData()); |
||||
|
||||
final Signature commitSeal = |
||||
SECP256K1.sign( |
||||
IbftBlockHashing.calculateDataHashForCommittedSeal(block.getHeader(), extraData), |
||||
signingKeyPair); |
||||
|
||||
final MessageFactory messageFactory = new MessageFactory(signingKeyPair); |
||||
|
||||
return messageFactory.createSignedCommitPayload(roundId, block.getHash(), commitSeal); |
||||
} |
||||
} |
@ -0,0 +1,106 @@ |
||||
/* |
||||
* Copyright 2019 ConsenSys AG. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations under the License. |
||||
*/ |
||||
package tech.pegasys.pantheon.consensus.ibft.tests; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static tech.pegasys.pantheon.consensus.ibft.support.MessageReceptionHelpers.assertPeersReceivedExactly; |
||||
import static tech.pegasys.pantheon.consensus.ibft.support.MessageReceptionHelpers.assertPeersReceivedNoMessages; |
||||
import static tech.pegasys.pantheon.consensus.ibft.support.TestHelpers.createSignedCommentPayload; |
||||
|
||||
import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier; |
||||
import tech.pegasys.pantheon.consensus.ibft.ibftevent.BlockTimerExpiry; |
||||
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.CommitPayload; |
||||
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.MessageFactory; |
||||
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.ProposalPayload; |
||||
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.SignedData; |
||||
import tech.pegasys.pantheon.consensus.ibft.support.RoundSpecificNodeRoles; |
||||
import tech.pegasys.pantheon.consensus.ibft.support.TestContext; |
||||
import tech.pegasys.pantheon.consensus.ibft.support.TestContextFactory; |
||||
import tech.pegasys.pantheon.ethereum.core.Block; |
||||
|
||||
import java.time.Clock; |
||||
import java.time.Instant; |
||||
import java.time.ZoneId; |
||||
|
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
|
||||
/** |
||||
* These tests assume the basic function of the Ibft Round State Machine has been proven via the |
||||
* LocalNodeIsNotProposerTest. |
||||
*/ |
||||
public class LocalNodeIsProposerTest { |
||||
|
||||
final long blockTimeStamp = 100; |
||||
private final Clock fixedClock = |
||||
Clock.fixed(Instant.ofEpochSecond(blockTimeStamp), ZoneId.systemDefault()); |
||||
|
||||
// Local node will propose the first block
|
||||
private final TestContext context = TestContextFactory.createTestEnvironment(4, 1, fixedClock); |
||||
private final ConsensusRoundIdentifier roundId = new ConsensusRoundIdentifier(1, 0); |
||||
private final RoundSpecificNodeRoles roles = context.getRoundSpecificRoles(roundId); |
||||
|
||||
private final MessageFactory localNodeMessageFactory = context.getLocalNodeMessageFactory(); |
||||
|
||||
private Block expectedProposedBlock; |
||||
private SignedData<ProposalPayload> expectedTxProposal; |
||||
private SignedData<CommitPayload> expectedTxCommit; |
||||
|
||||
@Before |
||||
public void setup() { |
||||
expectedProposedBlock = context.createBlockForProposal(0, blockTimeStamp); |
||||
expectedTxProposal = |
||||
localNodeMessageFactory.createSignedProposalPayload(roundId, expectedProposedBlock); |
||||
|
||||
expectedTxCommit = |
||||
createSignedCommentPayload( |
||||
expectedProposedBlock, context.getLocalNodeParams().getNodeKeyPair(), roundId); |
||||
|
||||
// Start the Controller, and trigger "block timer" to send proposal.
|
||||
context.getController().start(); |
||||
context.getController().handleBlockTimerExpiry(new BlockTimerExpiry(roundId)); |
||||
} |
||||
|
||||
@Test |
||||
public void basicCase() { |
||||
assertPeersReceivedExactly(roles.getAllPeers(), expectedTxProposal); |
||||
|
||||
// NOTE: In these test roles.getProposer() will return NULL.
|
||||
roles.getNonProposingPeer(0).injectPrepare(roundId, expectedProposedBlock.getHash()); |
||||
assertPeersReceivedNoMessages(roles.getAllPeers()); |
||||
|
||||
roles.getNonProposingPeer(1).injectPrepare(roundId, expectedProposedBlock.getHash()); |
||||
assertPeersReceivedExactly(roles.getAllPeers(), expectedTxCommit); |
||||
|
||||
roles.getNonProposingPeer(1).injectCommit(roundId, expectedProposedBlock.getHash()); |
||||
assertThat(context.getBlockchain().getChainHeadBlockNumber()).isEqualTo(0); |
||||
assertPeersReceivedNoMessages(roles.getAllPeers()); |
||||
|
||||
roles.getNonProposingPeer(2).injectCommit(roundId, expectedProposedBlock.getHash()); |
||||
assertThat(context.getBlockchain().getChainHeadBlockNumber()).isEqualTo(1); |
||||
assertPeersReceivedNoMessages(roles.getAllPeers()); |
||||
} |
||||
|
||||
@Test |
||||
public void importsToChainWithoutReceivingPrepareMessages() { |
||||
assertPeersReceivedExactly(roles.getAllPeers(), expectedTxProposal); |
||||
|
||||
roles.getNonProposingPeer(1).injectCommit(roundId, expectedProposedBlock.getHash()); |
||||
assertThat(context.getBlockchain().getChainHeadBlockNumber()).isEqualTo(0); |
||||
assertPeersReceivedNoMessages(roles.getAllPeers()); |
||||
|
||||
roles.getNonProposingPeer(2).injectCommit(roundId, expectedProposedBlock.getHash()); |
||||
assertThat(context.getBlockchain().getChainHeadBlockNumber()).isEqualTo(1); |
||||
assertPeersReceivedNoMessages(roles.getAllPeers()); |
||||
} |
||||
} |
Loading…
Reference in new issue