diff --git a/consensus/ibft/build.gradle b/consensus/ibft/build.gradle index 37c2faaa51..227a6e1508 100644 --- a/consensus/ibft/build.gradle +++ b/consensus/ibft/build.gradle @@ -36,11 +36,12 @@ dependencies { testImplementation project( path: ':ethereum:core', configuration: 'testSupportArtifacts') - testImplementation group: 'org.powermock', name: 'powermock-api-mockito2', version: '2.0.0-beta.5' - testImplementation group: 'org.powermock', name: 'powermock-module-junit4', version: '2.0.0-beta.5' testImplementation group: 'junit', name: 'junit', version: '4.12' testImplementation "org.awaitility:awaitility:3.1.2" testImplementation "org.assertj:assertj-core:3.10.0" testImplementation 'org.mockito:mockito-core' } + + +artifacts { testSupportArtifacts testSupportJar } diff --git a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/Ibft2VoteType.java b/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftVoteType.java similarity index 82% rename from consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/Ibft2VoteType.java rename to consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftVoteType.java index d505679abe..89a0f6985b 100644 --- a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/Ibft2VoteType.java +++ b/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftVoteType.java @@ -16,13 +16,13 @@ import tech.pegasys.pantheon.ethereum.rlp.RLPException; import tech.pegasys.pantheon.ethereum.rlp.RLPInput; import tech.pegasys.pantheon.ethereum.rlp.RLPOutput; -public enum Ibft2VoteType { +public enum IbftVoteType { ADD((byte) 0xFF), DROP((byte) 0x00); private final byte voteValue; - Ibft2VoteType(final byte voteValue) { + IbftVoteType(final byte voteValue) { this.voteValue = voteValue; } @@ -30,15 +30,15 @@ public enum Ibft2VoteType { return voteValue; } - public static Ibft2VoteType readFrom(final RLPInput rlpInput) { + public static IbftVoteType readFrom(final RLPInput rlpInput) { byte encodedByteValue = rlpInput.readByte(); - for (final Ibft2VoteType voteType : values()) { + for (final IbftVoteType voteType : values()) { if (voteType.voteValue == encodedByteValue) { return voteType; } } - throw new RLPException("Invalid Ibft2VoteType RLP encoding"); + throw new RLPException("Invalid IbftVoteType RLP encoding"); } public void writeTo(final RLPOutput rlpOutput) { diff --git a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/Vote.java b/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/Vote.java index 0faf37aa01..01b04c1806 100644 --- a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/Vote.java +++ b/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/Vote.java @@ -20,19 +20,19 @@ import com.google.common.base.Objects; public class Vote { private final Address recipient; - private final Ibft2VoteType voteType; + private final IbftVoteType voteType; - private Vote(final Address recipient, final Ibft2VoteType voteType) { + private Vote(final Address recipient, final IbftVoteType voteType) { this.recipient = recipient; this.voteType = voteType; } public static Vote authVote(final Address address) { - return new Vote(address, Ibft2VoteType.ADD); + return new Vote(address, IbftVoteType.ADD); } public static Vote dropVote(final Address address) { - return new Vote(address, Ibft2VoteType.DROP); + return new Vote(address, IbftVoteType.DROP); } public Address getRecipient() { @@ -40,11 +40,11 @@ public class Vote { } public boolean isAuth() { - return voteType.equals(Ibft2VoteType.ADD); + return voteType.equals(IbftVoteType.ADD); } public boolean isDrop() { - return voteType.equals(Ibft2VoteType.DROP); + return voteType.equals(IbftVoteType.DROP); } @Override @@ -64,7 +64,7 @@ public class Vote { return Objects.hashCode(recipient, voteType); } - public Ibft2VoteType getVoteType() { + public IbftVoteType getVoteType() { return voteType; } @@ -79,7 +79,7 @@ public class Vote { rlpInput.enterList(); final Address recipient = Address.readFrom(rlpInput); - final Ibft2VoteType vote = Ibft2VoteType.readFrom(rlpInput); + final IbftVoteType vote = IbftVoteType.readFrom(rlpInput); rlpInput.leaveList(); return new Vote(recipient, vote); diff --git a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/VoteTallyUpdater.java b/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/VoteTallyUpdater.java index 31e3485dcd..3c1b38485a 100644 --- a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/VoteTallyUpdater.java +++ b/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/VoteTallyUpdater.java @@ -12,55 +12,18 @@ */ package tech.pegasys.pantheon.consensus.ibft; -import tech.pegasys.pantheon.consensus.common.EpochManager; import tech.pegasys.pantheon.consensus.common.VoteTally; -import tech.pegasys.pantheon.consensus.common.VoteType; import tech.pegasys.pantheon.ethereum.chain.Blockchain; -import tech.pegasys.pantheon.ethereum.core.Address; import tech.pegasys.pantheon.ethereum.core.BlockHeader; -import tech.pegasys.pantheon.util.bytes.BytesValue; - -import java.util.List; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -/** - * Provides the logic to extract vote tally state from the blockchain and update it as blocks are - * added. - */ -public class VoteTallyUpdater { - - private static final Logger LOG = LogManager.getLogger(); - private static final Address NO_VOTE_SUBJECT = Address.wrap(BytesValue.wrap(new byte[20])); - - private final EpochManager epochManager; - - public VoteTallyUpdater(final EpochManager epochManager) { - this.epochManager = epochManager; - } +public interface VoteTallyUpdater { /** * Create a new VoteTally based on the current blockchain state. * * @param blockchain the blockchain to load the current state from * @return a VoteTally reflecting the state of the blockchain head */ - public VoteTally buildVoteTallyFromBlockchain(final Blockchain blockchain) { - final long chainHeadBlockNumber = blockchain.getChainHeadBlockNumber(); - final long epochBlockNumber = epochManager.getLastEpochBlock(chainHeadBlockNumber); - LOG.info("Loading validator voting state starting from block {}", epochBlockNumber); - final BlockHeader epochBlock = blockchain.getBlockHeader(epochBlockNumber).get(); - final List
initialValidators = - IbftExtraData.decode(epochBlock.getExtraData()).getValidators(); - final VoteTally voteTally = new VoteTally(initialValidators); - for (long blockNumber = epochBlockNumber + 1; - blockNumber <= chainHeadBlockNumber; - blockNumber++) { - updateForBlock(blockchain.getBlockHeader(blockNumber).get(), voteTally); - } - return voteTally; - } + VoteTally buildVoteTallyFromBlockchain(final Blockchain blockchain); /** * Update the vote tally to reflect changes caused by appending a new block to the chain. @@ -68,17 +31,5 @@ public class VoteTallyUpdater { * @param header the header of the block being added * @param voteTally the vote tally to update */ - public void updateForBlock(final BlockHeader header, final VoteTally voteTally) { - final Address candidate = header.getCoinbase(); - if (epochManager.isEpochBlock(header.getNumber())) { - voteTally.discardOutstandingVotes(); - return; - } - - if (!candidate.equals(NO_VOTE_SUBJECT)) { - final IbftExtraData ibftExtraData = IbftExtraData.decode(header.getExtraData()); - final Address proposer = IbftBlockHashing.recoverProposerAddress(header, ibftExtraData); - voteTally.addVote(proposer, candidate, VoteType.fromNonce(header.getNonce()).get()); - } - } + void updateForBlock(final BlockHeader header, final VoteTally voteTally); } diff --git a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/blockcreation/IbftBlockCreator.java b/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/blockcreation/IbftBlockCreator.java index 69877056dc..b9aefff145 100644 --- a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/blockcreation/IbftBlockCreator.java +++ b/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/blockcreation/IbftBlockCreator.java @@ -12,42 +12,20 @@ */ package tech.pegasys.pantheon.consensus.ibft.blockcreation; -import tech.pegasys.pantheon.consensus.ibft.IbftBlockHashing; import tech.pegasys.pantheon.consensus.ibft.IbftContext; -import tech.pegasys.pantheon.consensus.ibft.IbftExtraData; -import tech.pegasys.pantheon.consensus.ibft.IbftHelpers; -import tech.pegasys.pantheon.crypto.SECP256K1; -import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.ethereum.ProtocolContext; import tech.pegasys.pantheon.ethereum.blockcreation.AbstractBlockCreator; import tech.pegasys.pantheon.ethereum.core.Address; -import tech.pegasys.pantheon.ethereum.core.BlockHashFunction; import tech.pegasys.pantheon.ethereum.core.BlockHeader; -import tech.pegasys.pantheon.ethereum.core.BlockHeaderBuilder; -import tech.pegasys.pantheon.ethereum.core.Hash; import tech.pegasys.pantheon.ethereum.core.PendingTransactions; import tech.pegasys.pantheon.ethereum.core.SealableBlockHeader; -import tech.pegasys.pantheon.ethereum.core.Util; import tech.pegasys.pantheon.ethereum.core.Wei; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; -import tech.pegasys.pantheon.ethereum.mainnet.ScheduleBasedBlockHashFunction; import java.util.function.Function; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -/** - * Responsible for producing a Block which conforms to IBFT validation rules (other than missing - * commit seals). Transactions and associated Hashes (stateroot, receipts etc.) are loaded into the - * Block in the base class as part of the transaction selection process. - */ +// TODO: Just a placeholder. Implementation is required. public class IbftBlockCreator extends AbstractBlockCreator { - - private static final Logger LOG = LogManager.getLogger(); - - private final KeyPair nodeKeys; - public IbftBlockCreator( final Address coinbase, final ExtraDataCalculator extraDataCalculator, @@ -55,8 +33,8 @@ public class IbftBlockCreator extends AbstractBlockCreator { final ProtocolContext protocolContext, final ProtocolSchedule protocolSchedule, final Function gasLimitCalculator, - final KeyPair nodeKeys, final Wei minTransactionGasPrice, + final Address miningBeneficiary, final BlockHeader parentHeader) { super( coinbase, @@ -66,54 +44,12 @@ public class IbftBlockCreator extends AbstractBlockCreator { protocolSchedule, gasLimitCalculator, minTransactionGasPrice, - Util.publicKeyToAddress(nodeKeys.getPublicKey()), + miningBeneficiary, parentHeader); - this.nodeKeys = nodeKeys; } - /** - * Responsible for signing (hash of) the block (including MixHash and Nonce), and then injecting - * the seal into the extraData. This is called after a suitable set of transactions have been - * identified, and all resulting hashes have been inserted into the passed-in SealableBlockHeader. - * - * @param sealableBlockHeader A block header containing StateRoots, TransactionHashes etc. - * @return The blockhead which is to be added to the block being proposed. - */ @Override protected BlockHeader createFinalBlockHeader(final SealableBlockHeader sealableBlockHeader) { - - final BlockHashFunction blockHashFunction = - ScheduleBasedBlockHashFunction.create(protocolSchedule); - - final BlockHeaderBuilder builder = - BlockHeaderBuilder.create() - .populateFrom(sealableBlockHeader) - .mixHash(IbftHelpers.EXPECTED_MIX_HASH) - .nonce(0) - .blockHashFunction(blockHashFunction); - - final IbftExtraData sealedExtraData = constructSignedExtraData(builder.buildBlockHeader()); - - // Replace the extraData in the BlockHeaderBuilder, and return header. - return builder.extraData(sealedExtraData.encode()).buildBlockHeader(); - } - - /** - * Produces an IbftExtraData object with a populated proposerSeal. The signature in the block is - * generated from the Hash of the header (minus proposer and committer seals) and the nodeKeys. - * - * @param headerToSign An almost fully populated header (proposer and committer seals are empty) - * @return Extra data containing the same vanity data and validators as extraData, however - * proposerSeal will also be populated. - */ - private IbftExtraData constructSignedExtraData(final BlockHeader headerToSign) { - final IbftExtraData extraData = IbftExtraData.decode(headerToSign.getExtraData()); - final Hash hashToSign = - IbftBlockHashing.calculateDataHashForProposerSeal(headerToSign, extraData); - return new IbftExtraData( - extraData.getVanityData(), - extraData.getSeals(), - SECP256K1.sign(hashToSign, nodeKeys), - extraData.getValidators()); + return null; } } diff --git a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/IbftProtocolContextFixture.java b/consensus/ibft/src/test-support/java/tech/pegasys/pantheon/consensus/ibft/IbftProtocolContextFixture.java similarity index 100% rename from consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/IbftProtocolContextFixture.java rename to consensus/ibft/src/test-support/java/tech/pegasys/pantheon/consensus/ibft/IbftProtocolContextFixture.java diff --git a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/IbftBlockImporterTest.java b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/IbftBlockImporterTest.java index 4fcf4cb945..9eefe49f97 100644 --- a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/IbftBlockImporterTest.java +++ b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/IbftBlockImporterTest.java @@ -29,8 +29,6 @@ import tech.pegasys.pantheon.ethereum.core.BlockImporter; import tech.pegasys.pantheon.ethereum.db.WorldStateArchive; import tech.pegasys.pantheon.ethereum.mainnet.HeaderValidationMode; -import java.util.Collections; - import org.junit.Test; public class IbftBlockImporterTest { @@ -54,9 +52,7 @@ public class IbftBlockImporterTest { public void voteTallyNotUpdatedWhenBlockImportFails() { final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture(); final Block block = - new Block( - headerBuilder.buildHeader(), - new BlockBody(Collections.emptyList(), Collections.emptyList())); + new Block(headerBuilder.buildHeader(), new BlockBody(emptyList(), emptyList())); when(delegate.importBlock(context, block, HeaderValidationMode.FULL, HeaderValidationMode.FULL)) .thenReturn(false); @@ -70,14 +66,12 @@ public class IbftBlockImporterTest { public void voteTallyNotUpdatedWhenFastBlockImportFails() { final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture(); final Block block = - new Block( - headerBuilder.buildHeader(), - new BlockBody(Collections.emptyList(), Collections.emptyList())); + new Block(headerBuilder.buildHeader(), new BlockBody(emptyList(), emptyList())); when(delegate.fastImportBlock(context, block, emptyList(), HeaderValidationMode.LIGHT)) .thenReturn(false); - importer.fastImportBlock(context, block, Collections.emptyList(), HeaderValidationMode.LIGHT); + importer.fastImportBlock(context, block, emptyList(), HeaderValidationMode.LIGHT); verifyZeroInteractions(voteTallyUpdater); } @@ -86,8 +80,7 @@ public class IbftBlockImporterTest { public void voteTallyUpdatedWhenBlockImportSucceeds() { final Block block = new Block( - new BlockHeaderTestFixture().buildHeader(), - new BlockBody(Collections.emptyList(), Collections.emptyList())); + new BlockHeaderTestFixture().buildHeader(), new BlockBody(emptyList(), emptyList())); when(delegate.importBlock(context, block, HeaderValidationMode.FULL, HeaderValidationMode.FULL)) .thenReturn(true); @@ -101,13 +94,12 @@ public class IbftBlockImporterTest { public void voteTallyUpdatedWhenFastBlockImportSucceeds() { final Block block = new Block( - new BlockHeaderTestFixture().buildHeader(), - new BlockBody(Collections.emptyList(), Collections.emptyList())); + new BlockHeaderTestFixture().buildHeader(), new BlockBody(emptyList(), emptyList())); when(delegate.fastImportBlock(context, block, emptyList(), HeaderValidationMode.LIGHT)) .thenReturn(true); - importer.fastImportBlock(context, block, Collections.emptyList(), HeaderValidationMode.LIGHT); + importer.fastImportBlock(context, block, emptyList(), HeaderValidationMode.LIGHT); verify(voteTallyUpdater).updateForBlock(block.getHeader(), voteTally); } diff --git a/consensus/ibftlegacy/build.gradle b/consensus/ibftlegacy/build.gradle new file mode 100644 index 0000000000..4b25aa1db0 --- /dev/null +++ b/consensus/ibftlegacy/build.gradle @@ -0,0 +1,33 @@ +apply plugin: 'java-library' + +jar { + baseName 'pantheon-ibftlegacy' + manifest { + attributes('Implementation-Title': baseName, + 'Implementation-Version': project.version) + } +} + +dependencies { + implementation project(':consensus:common') + implementation project(':consensus:ibft') + implementation project(':crypto') + implementation project(':ethereum:core') + implementation project(':ethereum:eth') + implementation project(':ethereum:jsonrpc') + implementation project(':ethereum:rlp') + implementation project(':ethereum:p2p') + implementation project(':services:kvstore') + + implementation 'com.google.guava:guava' + implementation 'io.vertx:vertx-core' + + testImplementation project( path: ':ethereum:core', configuration: 'testSupportArtifacts') + testImplementation project( path: ':consensus:ibft', configuration: 'testSupportArtifacts') + + testImplementation group: 'junit', name: 'junit', version: '4.12' + testImplementation "org.awaitility:awaitility:3.1.2" + + testImplementation "org.assertj:assertj-core:3.10.0" + testImplementation 'org.mockito:mockito-core' +} diff --git a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftBlockHashing.java b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftBlockHashing.java similarity index 99% rename from consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftBlockHashing.java rename to consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftBlockHashing.java index 9e7fd0fea3..737f6343ae 100644 --- a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftBlockHashing.java +++ b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftBlockHashing.java @@ -10,7 +10,7 @@ * 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; +package tech.pegasys.pantheon.consensus.ibftlegacy; import tech.pegasys.pantheon.crypto.SECP256K1.Signature; import tech.pegasys.pantheon.ethereum.core.Address; diff --git a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftBlockHeaderValidationRulesetFactory.java b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftBlockHeaderValidationRulesetFactory.java similarity index 94% rename from consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftBlockHeaderValidationRulesetFactory.java rename to consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftBlockHeaderValidationRulesetFactory.java index 69bdb79b78..dcf64a1996 100644 --- a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftBlockHeaderValidationRulesetFactory.java +++ b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftBlockHeaderValidationRulesetFactory.java @@ -10,10 +10,11 @@ * 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; +package tech.pegasys.pantheon.consensus.ibftlegacy; import tech.pegasys.pantheon.consensus.common.headervalidationrules.VoteValidationRule; -import tech.pegasys.pantheon.consensus.ibft.headervalidationrules.IbftExtraDataValidationRule; +import tech.pegasys.pantheon.consensus.ibft.IbftContext; +import tech.pegasys.pantheon.consensus.ibftlegacy.headervalidationrules.IbftExtraDataValidationRule; import tech.pegasys.pantheon.ethereum.core.BlockHeader; import tech.pegasys.pantheon.ethereum.core.Hash; import tech.pegasys.pantheon.ethereum.mainnet.BlockHeaderValidator; diff --git a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftExtraData.java b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftExtraData.java similarity index 98% rename from consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftExtraData.java rename to consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftExtraData.java index 71e532818d..c5a55c199a 100644 --- a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftExtraData.java +++ b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftExtraData.java @@ -10,7 +10,7 @@ * 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; +package tech.pegasys.pantheon.consensus.ibftlegacy; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; diff --git a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftHelpers.java b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftHelpers.java similarity index 94% rename from consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftHelpers.java rename to consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftHelpers.java index 59891a36ae..e9acf83490 100644 --- a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftHelpers.java +++ b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftHelpers.java @@ -10,7 +10,7 @@ * 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; +package tech.pegasys.pantheon.consensus.ibftlegacy; import tech.pegasys.pantheon.ethereum.core.Hash; diff --git a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftProtocolSchedule.java b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftProtocolSchedule.java similarity index 94% rename from consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftProtocolSchedule.java rename to consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftProtocolSchedule.java index 2c97dd9a3d..6320777123 100644 --- a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftProtocolSchedule.java +++ b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftProtocolSchedule.java @@ -10,8 +10,9 @@ * 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; +package tech.pegasys.pantheon.consensus.ibftlegacy; +import tech.pegasys.pantheon.consensus.ibft.IbftContext; import tech.pegasys.pantheon.ethereum.mainnet.MutableProtocolSchedule; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; diff --git a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftProtocolSpecs.java b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftProtocolSpecs.java similarity index 88% rename from consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftProtocolSpecs.java rename to consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftProtocolSpecs.java index 1b3efcb77c..468fb3f1e1 100644 --- a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftProtocolSpecs.java +++ b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftProtocolSpecs.java @@ -10,11 +10,13 @@ * 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; +package tech.pegasys.pantheon.consensus.ibftlegacy; -import static tech.pegasys.pantheon.consensus.ibft.IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator; +import static tech.pegasys.pantheon.consensus.ibftlegacy.IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator; import tech.pegasys.pantheon.consensus.common.EpochManager; +import tech.pegasys.pantheon.consensus.ibft.IbftBlockImporter; +import tech.pegasys.pantheon.consensus.ibft.IbftContext; import tech.pegasys.pantheon.ethereum.core.Wei; import tech.pegasys.pantheon.ethereum.mainnet.MainnetBlockBodyValidator; import tech.pegasys.pantheon.ethereum.mainnet.MainnetBlockImporter; @@ -51,7 +53,7 @@ public class IbftProtocolSpecs { new IbftBlockImporter( new MainnetBlockImporter<>( blockHeaderValidator, blockBodyValidator, blockProcessor), - new VoteTallyUpdater(epochManager)), + new IbftVoteTallyUpdater(epochManager)), (time, parent, protocolContext) -> BigInteger.ONE) .blockReward(Wei.ZERO) .blockHashFunction(IbftBlockHashing::calculateHashOfIbftBlockOnChain) diff --git a/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftVoteTallyUpdater.java b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftVoteTallyUpdater.java new file mode 100644 index 0000000000..928c26284b --- /dev/null +++ b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftVoteTallyUpdater.java @@ -0,0 +1,87 @@ +/* + * Copyright 2018 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.ibftlegacy; + +import tech.pegasys.pantheon.consensus.common.EpochManager; +import tech.pegasys.pantheon.consensus.common.VoteTally; +import tech.pegasys.pantheon.consensus.common.VoteType; +import tech.pegasys.pantheon.consensus.ibft.VoteTallyUpdater; +import tech.pegasys.pantheon.ethereum.chain.Blockchain; +import tech.pegasys.pantheon.ethereum.core.Address; +import tech.pegasys.pantheon.ethereum.core.BlockHeader; +import tech.pegasys.pantheon.util.bytes.BytesValue; + +import java.util.List; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +/** + * Provides the logic to extract vote tally state from the blockchain and update it as blocks are + * added. + */ +public class IbftVoteTallyUpdater implements VoteTallyUpdater { + + private static final Logger LOG = LogManager.getLogger(); + private static final Address NO_VOTE_SUBJECT = Address.wrap(BytesValue.wrap(new byte[20])); + + private final EpochManager epochManager; + + public IbftVoteTallyUpdater(final EpochManager epochManager) { + this.epochManager = epochManager; + } + + /** + * Create a new VoteTally based on the current blockchain state. + * + * @param blockchain the blockchain to load the current state from + * @return a VoteTally reflecting the state of the blockchain head + */ + @Override + public VoteTally buildVoteTallyFromBlockchain(final Blockchain blockchain) { + final long chainHeadBlockNumber = blockchain.getChainHeadBlockNumber(); + final long epochBlockNumber = epochManager.getLastEpochBlock(chainHeadBlockNumber); + LOG.info("Loading validator voting state starting from block {}", epochBlockNumber); + final BlockHeader epochBlock = blockchain.getBlockHeader(epochBlockNumber).get(); + final List
initialValidators = + IbftExtraData.decode(epochBlock.getExtraData()).getValidators(); + final VoteTally voteTally = new VoteTally(initialValidators); + for (long blockNumber = epochBlockNumber + 1; + blockNumber <= chainHeadBlockNumber; + blockNumber++) { + updateForBlock(blockchain.getBlockHeader(blockNumber).get(), voteTally); + } + return voteTally; + } + + /** + * Update the vote tally to reflect changes caused by appending a new block to the chain. + * + * @param header the header of the block being added + * @param voteTally the vote tally to update + */ + @Override + public void updateForBlock(final BlockHeader header, final VoteTally voteTally) { + final Address candidate = header.getCoinbase(); + if (epochManager.isEpochBlock(header.getNumber())) { + voteTally.discardOutstandingVotes(); + return; + } + + if (!candidate.equals(NO_VOTE_SUBJECT)) { + final IbftExtraData ibftExtraData = IbftExtraData.decode(header.getExtraData()); + final Address proposer = IbftBlockHashing.recoverProposerAddress(header, ibftExtraData); + voteTally.addVote(proposer, candidate, VoteType.fromNonce(header.getNonce()).get()); + } + } +} diff --git a/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/blockcreation/IbftBlockCreator.java b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/blockcreation/IbftBlockCreator.java new file mode 100644 index 0000000000..da8709bd37 --- /dev/null +++ b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/blockcreation/IbftBlockCreator.java @@ -0,0 +1,119 @@ +/* + * Copyright 2018 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.ibftlegacy.blockcreation; + +import tech.pegasys.pantheon.consensus.ibft.IbftContext; +import tech.pegasys.pantheon.consensus.ibftlegacy.IbftBlockHashing; +import tech.pegasys.pantheon.consensus.ibftlegacy.IbftExtraData; +import tech.pegasys.pantheon.consensus.ibftlegacy.IbftHelpers; +import tech.pegasys.pantheon.crypto.SECP256K1; +import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; +import tech.pegasys.pantheon.ethereum.ProtocolContext; +import tech.pegasys.pantheon.ethereum.blockcreation.AbstractBlockCreator; +import tech.pegasys.pantheon.ethereum.core.Address; +import tech.pegasys.pantheon.ethereum.core.BlockHashFunction; +import tech.pegasys.pantheon.ethereum.core.BlockHeader; +import tech.pegasys.pantheon.ethereum.core.BlockHeaderBuilder; +import tech.pegasys.pantheon.ethereum.core.Hash; +import tech.pegasys.pantheon.ethereum.core.PendingTransactions; +import tech.pegasys.pantheon.ethereum.core.SealableBlockHeader; +import tech.pegasys.pantheon.ethereum.core.Util; +import tech.pegasys.pantheon.ethereum.core.Wei; +import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; +import tech.pegasys.pantheon.ethereum.mainnet.ScheduleBasedBlockHashFunction; + +import java.util.function.Function; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +/** + * Responsible for producing a Block which conforms to IBFT validation rules (other than missing + * commit seals). Transactions and associated Hashes (stateroot, receipts etc.) are loaded into the + * Block in the base class as part of the transaction selection process. + */ +public class IbftBlockCreator extends AbstractBlockCreator { + + private static final Logger LOG = LogManager.getLogger(); + + private final KeyPair nodeKeys; + + public IbftBlockCreator( + final Address coinbase, + final ExtraDataCalculator extraDataCalculator, + final PendingTransactions pendingTransactions, + final ProtocolContext protocolContext, + final ProtocolSchedule protocolSchedule, + final Function gasLimitCalculator, + final KeyPair nodeKeys, + final Wei minTransactionGasPrice, + final BlockHeader parentHeader) { + super( + coinbase, + extraDataCalculator, + pendingTransactions, + protocolContext, + protocolSchedule, + gasLimitCalculator, + minTransactionGasPrice, + Util.publicKeyToAddress(nodeKeys.getPublicKey()), + parentHeader); + this.nodeKeys = nodeKeys; + } + + /** + * Responsible for signing (hash of) the block (including MixHash and Nonce), and then injecting + * the seal into the extraData. This is called after a suitable set of transactions have been + * identified, and all resulting hashes have been inserted into the passed-in SealableBlockHeader. + * + * @param sealableBlockHeader A block header containing StateRoots, TransactionHashes etc. + * @return The blockhead which is to be added to the block being proposed. + */ + @Override + protected BlockHeader createFinalBlockHeader(final SealableBlockHeader sealableBlockHeader) { + + final BlockHashFunction blockHashFunction = + ScheduleBasedBlockHashFunction.create(protocolSchedule); + + final BlockHeaderBuilder builder = + BlockHeaderBuilder.create() + .populateFrom(sealableBlockHeader) + .mixHash(IbftHelpers.EXPECTED_MIX_HASH) + .nonce(0) + .blockHashFunction(blockHashFunction); + + final IbftExtraData sealedExtraData = constructSignedExtraData(builder.buildBlockHeader()); + + // Replace the extraData in the BlockHeaderBuilder, and return header. + return builder.extraData(sealedExtraData.encode()).buildBlockHeader(); + } + + /** + * Produces an IbftExtraData object with a populated proposerSeal. The signature in the block is + * generated from the Hash of the header (minus proposer and committer seals) and the nodeKeys. + * + * @param headerToSign An almost fully populated header (proposer and committer seals are empty) + * @return Extra data containing the same vanity data and validators as extraData, however + * proposerSeal will also be populated. + */ + private IbftExtraData constructSignedExtraData(final BlockHeader headerToSign) { + final IbftExtraData extraData = IbftExtraData.decode(headerToSign.getExtraData()); + final Hash hashToSign = + IbftBlockHashing.calculateDataHashForProposerSeal(headerToSign, extraData); + return new IbftExtraData( + extraData.getVanityData(), + extraData.getSeals(), + SECP256K1.sign(hashToSign, nodeKeys), + extraData.getValidators()); + } +} diff --git a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/blockcreation/IbftExtraDataCalculator.java b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/blockcreation/IbftExtraDataCalculator.java similarity index 92% rename from consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/blockcreation/IbftExtraDataCalculator.java rename to consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/blockcreation/IbftExtraDataCalculator.java index c93f893245..b94cf5cab1 100644 --- a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/blockcreation/IbftExtraDataCalculator.java +++ b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/blockcreation/IbftExtraDataCalculator.java @@ -10,10 +10,10 @@ * 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.blockcreation; +package tech.pegasys.pantheon.consensus.ibftlegacy.blockcreation; import tech.pegasys.pantheon.consensus.common.ValidatorProvider; -import tech.pegasys.pantheon.consensus.ibft.IbftExtraData; +import tech.pegasys.pantheon.consensus.ibftlegacy.IbftExtraData; import tech.pegasys.pantheon.ethereum.blockcreation.AbstractBlockCreator.ExtraDataCalculator; import tech.pegasys.pantheon.ethereum.core.BlockHeader; import tech.pegasys.pantheon.util.bytes.BytesValue; diff --git a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/blockcreation/ProposerSelector.java b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/blockcreation/ProposerSelector.java similarity index 97% rename from consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/blockcreation/ProposerSelector.java rename to consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/blockcreation/ProposerSelector.java index 97e3eb2122..506110323c 100644 --- a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/blockcreation/ProposerSelector.java +++ b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/blockcreation/ProposerSelector.java @@ -10,14 +10,14 @@ * 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.blockcreation; +package tech.pegasys.pantheon.consensus.ibftlegacy.blockcreation; import static com.google.common.base.Preconditions.checkArgument; import tech.pegasys.pantheon.consensus.common.ValidatorProvider; 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.ibftlegacy.IbftBlockHashing; +import tech.pegasys.pantheon.consensus.ibftlegacy.IbftExtraData; import tech.pegasys.pantheon.ethereum.chain.Blockchain; import tech.pegasys.pantheon.ethereum.core.Address; import tech.pegasys.pantheon.ethereum.core.BlockHeader; diff --git a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/headervalidationrules/IbftExtraDataValidationRule.java b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/headervalidationrules/IbftExtraDataValidationRule.java similarity index 92% rename from consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/headervalidationrules/IbftExtraDataValidationRule.java rename to consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/headervalidationrules/IbftExtraDataValidationRule.java index e014a997d5..a756c9bae7 100644 --- a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/headervalidationrules/IbftExtraDataValidationRule.java +++ b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/headervalidationrules/IbftExtraDataValidationRule.java @@ -10,14 +10,13 @@ * 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.headervalidationrules; - -import static tech.pegasys.pantheon.consensus.ibft.IbftHelpers.calculateRequiredValidatorQuorum; +package tech.pegasys.pantheon.consensus.ibftlegacy.headervalidationrules; import tech.pegasys.pantheon.consensus.common.ValidatorProvider; -import tech.pegasys.pantheon.consensus.ibft.IbftBlockHashing; import tech.pegasys.pantheon.consensus.ibft.IbftContext; -import tech.pegasys.pantheon.consensus.ibft.IbftExtraData; +import tech.pegasys.pantheon.consensus.ibftlegacy.IbftBlockHashing; +import tech.pegasys.pantheon.consensus.ibftlegacy.IbftExtraData; +import tech.pegasys.pantheon.consensus.ibftlegacy.IbftHelpers; import tech.pegasys.pantheon.ethereum.ProtocolContext; import tech.pegasys.pantheon.ethereum.core.Address; import tech.pegasys.pantheon.ethereum.core.BlockHeader; @@ -112,7 +111,8 @@ public class IbftExtraDataValidationRule implements AttachedBlockHeaderValidatio private boolean validateCommitters( final Collection
committers, final Collection
storedValidators) { - final int minimumSealsRequired = calculateRequiredValidatorQuorum(storedValidators.size()); + final int minimumSealsRequired = + IbftHelpers.calculateRequiredValidatorQuorum(storedValidators.size()); if (committers.size() < minimumSealsRequired) { LOG.trace( "Insufficient committers to seal block. (Required {}, received {})", diff --git a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/protocol/Istanbul64Protocol.java b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/protocol/Istanbul64Protocol.java similarity index 97% rename from consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/protocol/Istanbul64Protocol.java rename to consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/protocol/Istanbul64Protocol.java index 6cb08040b7..eff7cf3a88 100644 --- a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/protocol/Istanbul64Protocol.java +++ b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/protocol/Istanbul64Protocol.java @@ -10,7 +10,7 @@ * 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.protocol; +package tech.pegasys.pantheon.consensus.ibftlegacy.protocol; import tech.pegasys.pantheon.ethereum.eth.messages.EthPV62; import tech.pegasys.pantheon.ethereum.eth.messages.EthPV63; diff --git a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/protocol/Istanbul64ProtocolManager.java b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/protocol/Istanbul64ProtocolManager.java similarity index 97% rename from consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/protocol/Istanbul64ProtocolManager.java rename to consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/protocol/Istanbul64ProtocolManager.java index c09388fab4..f83e57d63b 100644 --- a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/protocol/Istanbul64ProtocolManager.java +++ b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/protocol/Istanbul64ProtocolManager.java @@ -10,7 +10,7 @@ * 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.protocol; +package tech.pegasys.pantheon.consensus.ibftlegacy.protocol; import tech.pegasys.pantheon.ethereum.chain.Blockchain; import tech.pegasys.pantheon.ethereum.eth.EthProtocol; diff --git a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/IbftBlockHashingTest.java b/consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftBlockHashingTest.java similarity index 97% rename from consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/IbftBlockHashingTest.java rename to consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftBlockHashingTest.java index 470f115c89..e0ce8d451f 100644 --- a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/IbftBlockHashingTest.java +++ b/consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftBlockHashingTest.java @@ -10,7 +10,7 @@ * 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; +package tech.pegasys.pantheon.consensus.ibftlegacy; import static org.assertj.core.api.Assertions.assertThat; @@ -25,6 +25,7 @@ import tech.pegasys.pantheon.util.uint.UInt256; import java.util.Arrays; import java.util.List; +import org.assertj.core.api.Assertions; import org.junit.Test; public class IbftBlockHashingTest { @@ -58,7 +59,7 @@ public class IbftBlockHashingTest { @Test public void readValidatorListFromExtraData() { final IbftExtraData ibftExtraData = IbftExtraData.decode(header.getExtraData()); - assertThat(ibftExtraData.getValidators()).isEqualTo(VALIDATORS_IN_HEADER); + Assertions.assertThat(ibftExtraData.getValidators()).isEqualTo(VALIDATORS_IN_HEADER); } @Test diff --git a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/IbftBlockHeaderValidationRulesetFactoryTest.java b/consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftBlockHeaderValidationRulesetFactoryTest.java similarity index 90% rename from consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/IbftBlockHeaderValidationRulesetFactoryTest.java rename to consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftBlockHeaderValidationRulesetFactoryTest.java index f8d71a081d..94202bf803 100644 --- a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/IbftBlockHeaderValidationRulesetFactoryTest.java +++ b/consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftBlockHeaderValidationRulesetFactoryTest.java @@ -10,14 +10,15 @@ * 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; +package tech.pegasys.pantheon.consensus.ibftlegacy; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; -import static tech.pegasys.pantheon.consensus.ibft.IbftProtocolContextFixture.protocolContext; import tech.pegasys.pantheon.consensus.common.VoteType; +import tech.pegasys.pantheon.consensus.ibft.IbftContext; +import tech.pegasys.pantheon.consensus.ibft.IbftProtocolContextFixture; import tech.pegasys.pantheon.crypto.SECP256K1; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.crypto.SECP256K1.Signature; @@ -53,7 +54,10 @@ public class IbftBlockHeaderValidationRulesetFactoryTest { assertThat( validator.validateHeader( - blockHeader, parentHeader, protocolContext(validators), HeaderValidationMode.FULL)) + blockHeader, + parentHeader, + IbftProtocolContextFixture.protocolContext(validators), + HeaderValidationMode.FULL)) .isTrue(); } @@ -73,7 +77,10 @@ public class IbftBlockHeaderValidationRulesetFactoryTest { assertThat( validator.validateHeader( - blockHeader, parentHeader, protocolContext(validators), HeaderValidationMode.FULL)) + blockHeader, + parentHeader, + IbftProtocolContextFixture.protocolContext(validators), + HeaderValidationMode.FULL)) .isFalse(); } diff --git a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/IbftExtraDataTest.java b/consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftExtraDataTest.java similarity index 91% rename from consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/IbftExtraDataTest.java rename to consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftExtraDataTest.java index 56fb6d132a..c42fbca575 100644 --- a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/IbftExtraDataTest.java +++ b/consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftExtraDataTest.java @@ -10,7 +10,7 @@ * 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; +package tech.pegasys.pantheon.consensus.ibftlegacy; import static org.assertj.core.api.Assertions.assertThat; @@ -26,6 +26,7 @@ import java.util.List; import java.util.Random; import com.google.common.collect.Lists; +import org.assertj.core.api.Assertions; import org.bouncycastle.util.encoders.Hex; import org.junit.Test; @@ -52,10 +53,10 @@ public class IbftExtraDataTest { final IbftExtraData extraData = IbftExtraData.decode(bufferToInject); - assertThat(extraData.getVanityData()).isEqualTo(vanity_data); + Assertions.assertThat(extraData.getVanityData()).isEqualTo(vanity_data); assertThat(extraData.getProposerSeal()).isEqualTo(proposerSeal); - assertThat(extraData.getSeals()).isEqualTo(committerSeals); - assertThat(extraData.getValidators()).isEqualTo(validators); + Assertions.assertThat(extraData.getSeals()).isEqualTo(committerSeals); + Assertions.assertThat(extraData.getValidators()).isEqualTo(validators); } @Test @@ -83,10 +84,10 @@ public class IbftExtraDataTest { final IbftExtraData extraData = IbftExtraData.decode(bufferToInject); - assertThat(extraData.getVanityData()).isEqualTo(vanity_data); + Assertions.assertThat(extraData.getVanityData()).isEqualTo(vanity_data); assertThat(extraData.getProposerSeal()).isEqualTo(proposerSeal); - assertThat(extraData.getSeals()).isEqualTo(committerSeals); - assertThat(extraData.getValidators()).isEqualTo(validators); + Assertions.assertThat(extraData.getSeals()).isEqualTo(committerSeals); + Assertions.assertThat(extraData.getValidators()).isEqualTo(validators); } @Test(expected = RLPException.class) diff --git a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/VoteTallyUpdaterTest.java b/consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftVoteTallyUpdaterTest.java similarity index 97% rename from consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/VoteTallyUpdaterTest.java rename to consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftVoteTallyUpdaterTest.java index 4122f1f233..ab05a7d7c3 100644 --- a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/VoteTallyUpdaterTest.java +++ b/consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftVoteTallyUpdaterTest.java @@ -10,7 +10,7 @@ * 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; +package tech.pegasys.pantheon.consensus.ibftlegacy; import static java.util.Arrays.asList; import static java.util.Collections.emptyList; @@ -41,7 +41,7 @@ import java.util.Optional; import org.junit.Test; -public class VoteTallyUpdaterTest { +public class IbftVoteTallyUpdaterTest { private static final long EPOCH_LENGTH = 30_000; public static final Signature INVALID_SEAL = @@ -55,7 +55,8 @@ public class VoteTallyUpdaterTest { private final Address validator1 = Address.fromHexString("00dae27b350bae20c5652124af5d8b5cba001ec1"); - private final VoteTallyUpdater updater = new VoteTallyUpdater(new EpochManager(EPOCH_LENGTH)); + private final IbftVoteTallyUpdater updater = + new IbftVoteTallyUpdater(new EpochManager(EPOCH_LENGTH)); @Test public void voteTallyUpdatedWithVoteFromBlock() { diff --git a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/blockcreation/IbftBlockCreatorTest.java b/consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/blockcreation/IbftBlockCreatorTest.java similarity index 94% rename from consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/blockcreation/IbftBlockCreatorTest.java rename to consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/blockcreation/IbftBlockCreatorTest.java index ab96801d7c..c8a5ab34d5 100644 --- a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/blockcreation/IbftBlockCreatorTest.java +++ b/consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/blockcreation/IbftBlockCreatorTest.java @@ -10,7 +10,7 @@ * 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.blockcreation; +package tech.pegasys.pantheon.consensus.ibftlegacy.blockcreation; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -20,10 +20,10 @@ import static tech.pegasys.pantheon.ethereum.core.InMemoryWorldState.createInMem import tech.pegasys.pantheon.consensus.common.VoteProposer; import tech.pegasys.pantheon.consensus.common.VoteTally; -import tech.pegasys.pantheon.consensus.ibft.IbftBlockHeaderValidationRulesetFactory; import tech.pegasys.pantheon.consensus.ibft.IbftContext; -import tech.pegasys.pantheon.consensus.ibft.IbftExtraData; -import tech.pegasys.pantheon.consensus.ibft.IbftProtocolSchedule; +import tech.pegasys.pantheon.consensus.ibftlegacy.IbftBlockHeaderValidationRulesetFactory; +import tech.pegasys.pantheon.consensus.ibftlegacy.IbftExtraData; +import tech.pegasys.pantheon.consensus.ibftlegacy.IbftProtocolSchedule; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.ethereum.ProtocolContext; import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain; diff --git a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/blockcreation/ProposerSelectorTest.java b/consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/blockcreation/ProposerSelectorTest.java similarity index 98% rename from consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/blockcreation/ProposerSelectorTest.java rename to consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/blockcreation/ProposerSelectorTest.java index b47e14c851..7d7a447e7a 100644 --- a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/blockcreation/ProposerSelectorTest.java +++ b/consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/blockcreation/ProposerSelectorTest.java @@ -10,7 +10,7 @@ * 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.blockcreation; +package tech.pegasys.pantheon.consensus.ibftlegacy.blockcreation; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.anyLong; @@ -19,8 +19,8 @@ import static org.mockito.Mockito.when; import tech.pegasys.pantheon.consensus.common.VoteTally; 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.ibftlegacy.IbftBlockHashing; +import tech.pegasys.pantheon.consensus.ibftlegacy.IbftExtraData; import tech.pegasys.pantheon.crypto.SECP256K1; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.crypto.SECP256K1.Signature; diff --git a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/headervalidationrules/IbftExtraDataValidationRuleTest.java b/consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/headervalidationrules/IbftExtraDataValidationRuleTest.java similarity index 97% rename from consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/headervalidationrules/IbftExtraDataValidationRuleTest.java rename to consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/headervalidationrules/IbftExtraDataValidationRuleTest.java index c29e7f9256..b01e1a0409 100644 --- a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/headervalidationrules/IbftExtraDataValidationRuleTest.java +++ b/consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/headervalidationrules/IbftExtraDataValidationRuleTest.java @@ -10,16 +10,16 @@ * 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.headervalidationrules; +package tech.pegasys.pantheon.consensus.ibftlegacy.headervalidationrules; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; import tech.pegasys.pantheon.consensus.common.VoteTally; -import tech.pegasys.pantheon.consensus.ibft.IbftBlockHashing; import tech.pegasys.pantheon.consensus.ibft.IbftContext; -import tech.pegasys.pantheon.consensus.ibft.IbftExtraData; +import tech.pegasys.pantheon.consensus.ibftlegacy.IbftBlockHashing; +import tech.pegasys.pantheon.consensus.ibftlegacy.IbftExtraData; import tech.pegasys.pantheon.crypto.SECP256K1; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.crypto.SECP256K1.Signature; @@ -37,6 +37,7 @@ import java.util.List; import java.util.stream.Collectors; import com.google.common.collect.Lists; +import org.assertj.core.api.Assertions; import org.junit.Test; public class IbftExtraDataValidationRuleTest { @@ -141,7 +142,7 @@ public class IbftExtraDataValidationRuleTest { // Note that no committer seals are in the header's IBFT extra data. final IbftExtraData headerExtraData = IbftExtraData.decode(header.getExtraData()); - assertThat(headerExtraData.getSeals().size()).isEqualTo(0); + Assertions.assertThat(headerExtraData.getSeals().size()).isEqualTo(0); assertThat(extraDataValidationRule.validate(header, null, context)).isFalse(); } diff --git a/pantheon/build.gradle b/pantheon/build.gradle index 332ac1fb9b..f266b5ad64 100644 --- a/pantheon/build.gradle +++ b/pantheon/build.gradle @@ -26,6 +26,7 @@ dependencies { implementation project(':consensus:common') implementation project(':consensus:clique') implementation project(':consensus:ibft') + implementation project(':consensus:ibftlegacy') implementation project(':consensus:clique') implementation project(':ethereum:eth') implementation project(':ethereum:core') 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 eb16d35b91..6565f9e49d 100644 --- a/pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftPantheonController.java +++ b/pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftPantheonController.java @@ -21,14 +21,14 @@ import tech.pegasys.pantheon.consensus.ibft.IbftChainObserver; import tech.pegasys.pantheon.consensus.ibft.IbftContext; import tech.pegasys.pantheon.consensus.ibft.IbftEventQueue; import tech.pegasys.pantheon.consensus.ibft.IbftProcessor; -import tech.pegasys.pantheon.consensus.ibft.IbftProtocolSchedule; import tech.pegasys.pantheon.consensus.ibft.IbftStateMachine; -import tech.pegasys.pantheon.consensus.ibft.VoteTallyUpdater; import tech.pegasys.pantheon.consensus.ibft.blockcreation.IbftBlockMiner; import tech.pegasys.pantheon.consensus.ibft.protocol.IbftProtocolManager; import tech.pegasys.pantheon.consensus.ibft.protocol.IbftSubProtocol; -import tech.pegasys.pantheon.consensus.ibft.protocol.Istanbul64Protocol; -import tech.pegasys.pantheon.consensus.ibft.protocol.Istanbul64ProtocolManager; +import tech.pegasys.pantheon.consensus.ibftlegacy.IbftProtocolSchedule; +import tech.pegasys.pantheon.consensus.ibftlegacy.IbftVoteTallyUpdater; +import tech.pegasys.pantheon.consensus.ibftlegacy.protocol.Istanbul64Protocol; +import tech.pegasys.pantheon.consensus.ibftlegacy.protocol.Istanbul64ProtocolManager; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.ethereum.ProtocolContext; import tech.pegasys.pantheon.ethereum.blockcreation.AbstractMiningCoordinator; @@ -129,7 +129,7 @@ public class IbftPantheonController implements PantheonController