Add 2/3n Commit count for IBFT blocks (#1906)

This allows Besu to interop with an Quorum IBFT-1 network which has been updated to use a 2/3 validator threshold, rather than 2F+1.

Signed-off-by: Trent Mohay <trent.mohay@consensys.net>
pull/1965/head
Trent Mohay 4 years ago committed by GitHub
parent a4ffec24bc
commit e2963d69af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      besu/src/main/java/org/hyperledger/besu/controller/IbftLegacyBesuControllerBuilder.java
  2. 43
      config/src/main/java/org/hyperledger/besu/config/BftConfigOptions.java
  3. 2
      config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java
  4. 71
      config/src/main/java/org/hyperledger/besu/config/IbftLegacyConfigOptions.java
  5. 6
      config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java
  6. 4
      config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java
  7. 4
      config/src/test/java/org/hyperledger/besu/config/BftConfigOptionsTest.java
  8. 2
      config/src/test/java/org/hyperledger/besu/config/GenesisConfigOptionsTest.java
  9. 13
      consensus/ibftlegacy/src/main/java/org/hyperledger/besu/consensus/ibftlegacy/IbftBlockHeaderValidationRulesetFactory.java
  10. 15
      consensus/ibftlegacy/src/main/java/org/hyperledger/besu/consensus/ibftlegacy/IbftProtocolSchedule.java
  11. 20
      consensus/ibftlegacy/src/main/java/org/hyperledger/besu/consensus/ibftlegacy/headervalidationrules/IbftExtraDataValidationRule.java
  12. 4
      consensus/ibftlegacy/src/test/java/org/hyperledger/besu/consensus/ibftlegacy/IbftBlockHeaderValidationRulesetFactoryTest.java
  13. 49
      consensus/ibftlegacy/src/test/java/org/hyperledger/besu/consensus/ibftlegacy/headervalidationrules/BftExtraDataValidationRuleTest.java

@ -14,7 +14,7 @@
*/
package org.hyperledger.besu.controller;
import org.hyperledger.besu.config.BftConfigOptions;
import org.hyperledger.besu.config.IbftLegacyConfigOptions;
import org.hyperledger.besu.consensus.common.BlockInterface;
import org.hyperledger.besu.consensus.common.EpochManager;
import org.hyperledger.besu.consensus.common.VoteProposer;
@ -83,7 +83,7 @@ public class IbftLegacyBesuControllerBuilder extends BesuControllerBuilder {
@Override
protected BftContext createConsensusContext(
final Blockchain blockchain, final WorldStateArchive worldStateArchive) {
final BftConfigOptions ibftConfig =
final IbftLegacyConfigOptions ibftConfig =
genesisConfig.getConfigOptions(genesisConfigOverrides).getIbftLegacyConfigOptions();
final EpochManager epochManager = new EpochManager(ibftConfig.getEpochLength());
final VoteTallyCache voteTallyCache =

@ -38,52 +38,51 @@ public class BftConfigOptions {
private static final int DEFAULT_FUTURE_MESSAGES_LIMIT = 1000;
private static final int DEFAULT_FUTURE_MESSAGES_MAX_DISTANCE = 10;
private final ObjectNode ibftConfigRoot;
private final ObjectNode bftConfigRoot;
BftConfigOptions(final ObjectNode ibftConfigRoot) {
this.ibftConfigRoot = ibftConfigRoot;
BftConfigOptions(final ObjectNode bftConfigRoot) {
this.bftConfigRoot = bftConfigRoot;
}
public long getEpochLength() {
return JsonUtil.getLong(ibftConfigRoot, "epochlength", DEFAULT_EPOCH_LENGTH);
return JsonUtil.getLong(bftConfigRoot, "epochlength", DEFAULT_EPOCH_LENGTH);
}
public int getBlockPeriodSeconds() {
return JsonUtil.getInt(ibftConfigRoot, "blockperiodseconds", DEFAULT_BLOCK_PERIOD_SECONDS);
return JsonUtil.getInt(bftConfigRoot, "blockperiodseconds", DEFAULT_BLOCK_PERIOD_SECONDS);
}
public int getRequestTimeoutSeconds() {
return JsonUtil.getInt(ibftConfigRoot, "requesttimeoutseconds", DEFAULT_ROUND_EXPIRY_SECONDS);
return JsonUtil.getInt(bftConfigRoot, "requesttimeoutseconds", DEFAULT_ROUND_EXPIRY_SECONDS);
}
public int getGossipedHistoryLimit() {
return JsonUtil.getInt(ibftConfigRoot, "gossipedhistorylimit", DEFAULT_GOSSIPED_HISTORY_LIMIT);
return JsonUtil.getInt(bftConfigRoot, "gossipedhistorylimit", DEFAULT_GOSSIPED_HISTORY_LIMIT);
}
public int getMessageQueueLimit() {
return JsonUtil.getInt(ibftConfigRoot, "messagequeuelimit", DEFAULT_MESSAGE_QUEUE_LIMIT);
return JsonUtil.getInt(bftConfigRoot, "messagequeuelimit", DEFAULT_MESSAGE_QUEUE_LIMIT);
}
public int getDuplicateMessageLimit() {
return JsonUtil.getInt(
ibftConfigRoot, "duplicatemessagelimit", DEFAULT_DUPLICATE_MESSAGE_LIMIT);
return JsonUtil.getInt(bftConfigRoot, "duplicatemessagelimit", DEFAULT_DUPLICATE_MESSAGE_LIMIT);
}
public int getFutureMessagesLimit() {
return JsonUtil.getInt(ibftConfigRoot, "futuremessageslimit", DEFAULT_FUTURE_MESSAGES_LIMIT);
return JsonUtil.getInt(bftConfigRoot, "futuremessageslimit", DEFAULT_FUTURE_MESSAGES_LIMIT);
}
public int getFutureMessagesMaxDistance() {
return JsonUtil.getInt(
ibftConfigRoot, "futuremessagesmaxdistance", DEFAULT_FUTURE_MESSAGES_MAX_DISTANCE);
bftConfigRoot, "futuremessagesmaxdistance", DEFAULT_FUTURE_MESSAGES_MAX_DISTANCE);
}
public Optional<String> getMiningBeneficiary() {
return JsonUtil.getString(ibftConfigRoot, "miningbeneficiary");
return JsonUtil.getString(bftConfigRoot, "miningbeneficiary");
}
public BigInteger getBlockRewardWei() {
final Optional<String> configFileContent = JsonUtil.getString(ibftConfigRoot, "blockreward");
final Optional<String> configFileContent = JsonUtil.getString(bftConfigRoot, "blockreward");
if (configFileContent.isEmpty()) {
return BigInteger.ZERO;
@ -97,28 +96,28 @@ public class BftConfigOptions {
Map<String, Object> asMap() {
final ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
if (ibftConfigRoot.has("epochlength")) {
if (bftConfigRoot.has("epochlength")) {
builder.put("epochLength", getEpochLength());
}
if (ibftConfigRoot.has("blockperiodseconds")) {
if (bftConfigRoot.has("blockperiodseconds")) {
builder.put("blockPeriodSeconds", getBlockPeriodSeconds());
}
if (ibftConfigRoot.has("requesttimeoutseconds")) {
if (bftConfigRoot.has("requesttimeoutseconds")) {
builder.put("requestTimeoutSeconds", getRequestTimeoutSeconds());
}
if (ibftConfigRoot.has("gossipedhistorylimit")) {
if (bftConfigRoot.has("gossipedhistorylimit")) {
builder.put("gossipedHistoryLimit", getGossipedHistoryLimit());
}
if (ibftConfigRoot.has("messagequeuelimit")) {
if (bftConfigRoot.has("messagequeuelimit")) {
builder.put("messageQueueLimit", getMessageQueueLimit());
}
if (ibftConfigRoot.has("duplicatemessagelimit")) {
if (bftConfigRoot.has("duplicatemessagelimit")) {
builder.put("duplicateMessageLimit", getDuplicateMessageLimit());
}
if (ibftConfigRoot.has("futuremessageslimit")) {
if (bftConfigRoot.has("futuremessageslimit")) {
builder.put("futureMessagesLimit", getFutureMessagesLimit());
}
if (ibftConfigRoot.has("futuremessagesmaxdistance")) {
if (bftConfigRoot.has("futuremessagesmaxdistance")) {
builder.put("futureMessagesMaxDistance", getFutureMessagesMaxDistance());
}
return builder.build();

@ -35,7 +35,7 @@ public interface GenesisConfigOptions {
String getConsensusEngine();
BftConfigOptions getIbftLegacyConfigOptions();
IbftLegacyConfigOptions getIbftLegacyConfigOptions();
CliqueConfigOptions getCliqueConfigOptions();

@ -0,0 +1,71 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.config;
import java.util.Map;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.ImmutableMap;
public class IbftLegacyConfigOptions {
public static final IbftLegacyConfigOptions DEFAULT =
new IbftLegacyConfigOptions(JsonUtil.createEmptyObjectNode());
private static final long DEFAULT_EPOCH_LENGTH = 30_000;
private static final int DEFAULT_BLOCK_PERIOD_SECONDS = 1;
private static final int DEFAULT_ROUND_EXPIRY_SECONDS = 1;
private static final long DEFAULT_CEIL_2N_BY_3_BLOCK = 0L;
private final ObjectNode ibftConfigRoot;
IbftLegacyConfigOptions(final ObjectNode ibftConfigRoot) {
this.ibftConfigRoot = ibftConfigRoot;
}
public long getEpochLength() {
return JsonUtil.getLong(ibftConfigRoot, "epochlength", DEFAULT_EPOCH_LENGTH);
}
public int getBlockPeriodSeconds() {
return JsonUtil.getInt(ibftConfigRoot, "blockperiodseconds", DEFAULT_BLOCK_PERIOD_SECONDS);
}
public int getRequestTimeoutSeconds() {
return JsonUtil.getInt(ibftConfigRoot, "requesttimeoutseconds", DEFAULT_ROUND_EXPIRY_SECONDS);
}
public long getCeil2Nby3Block() {
return JsonUtil.getLong(ibftConfigRoot, "ceil2nby3block", DEFAULT_CEIL_2N_BY_3_BLOCK);
}
Map<String, Object> asMap() {
final ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
if (ibftConfigRoot.has("epochlength")) {
builder.put("epochLength", getEpochLength());
}
if (ibftConfigRoot.has("blockperiodseconds")) {
builder.put("blockPeriodSeconds", getBlockPeriodSeconds());
}
if (ibftConfigRoot.has("requesttimeoutseconds")) {
builder.put("requestTimeoutSeconds", getRequestTimeoutSeconds());
}
if (ibftConfigRoot.has("ceil2nby3block")) {
builder.put("ceil2nby3block", getCeil2Nby3Block());
}
return builder.build();
}
}

@ -133,10 +133,10 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
}
@Override
public BftConfigOptions getIbftLegacyConfigOptions() {
public IbftLegacyConfigOptions getIbftLegacyConfigOptions() {
return JsonUtil.getObjectNode(configRoot, IBFT_LEGACY_CONFIG_KEY)
.map(BftConfigOptions::new)
.orElse(BftConfigOptions.DEFAULT);
.map(IbftLegacyConfigOptions::new)
.orElse(IbftLegacyConfigOptions.DEFAULT);
}
@Override

@ -85,8 +85,8 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
}
@Override
public BftConfigOptions getIbftLegacyConfigOptions() {
return BftConfigOptions.DEFAULT;
public IbftLegacyConfigOptions getIbftLegacyConfigOptions() {
return IbftLegacyConfigOptions.DEFAULT;
}
@Override

@ -184,8 +184,8 @@ public class BftConfigOptionsTest {
final ObjectNode rootNode = JsonUtil.createEmptyObjectNode();
final ObjectNode configNode = JsonUtil.createEmptyObjectNode();
final ObjectNode options = JsonUtil.objectNodeFromMap(ibftConfigOptions);
configNode.set("ibft", options);
configNode.set("ibft2", options);
rootNode.set("config", configNode);
return GenesisConfigFile.fromConfig(rootNode).getConfigOptions().getIbftLegacyConfigOptions();
return GenesisConfigFile.fromConfig(rootNode).getConfigOptions().getBftConfigOptions();
}
}

@ -55,7 +55,7 @@ public class GenesisConfigOptionsTest {
public void shouldNotUseIbftLegacyIfIbftNotPresent() {
final GenesisConfigOptions config = fromConfigOptions(emptyMap());
assertThat(config.isIbftLegacy()).isFalse();
assertThat(config.getIbftLegacyConfigOptions()).isSameAs(BftConfigOptions.DEFAULT);
assertThat(config.getIbftLegacyConfigOptions()).isSameAs(IbftLegacyConfigOptions.DEFAULT);
}
@Test

@ -35,11 +35,12 @@ public class IbftBlockHeaderValidationRulesetFactory {
* part of the BlockChain (i.e. not proposed blocks, which do not contain commit seals)
*
* @param secondsBetweenBlocks the minimum number of seconds which must elapse between blocks.
* @param ceil2nBy3Block the block after which 2/3n commit seals must exist, rather than 2F+1
* @return BlockHeaderValidator configured for assessing ibft block headers
*/
public static BlockHeaderValidator.Builder ibftBlockHeaderValidator(
final long secondsBetweenBlocks) {
return createValidator(secondsBetweenBlocks, true);
final long secondsBetweenBlocks, final long ceil2nBy3Block) {
return createValidator(secondsBetweenBlocks, true, ceil2nBy3Block);
}
/**
@ -51,11 +52,13 @@ public class IbftBlockHeaderValidationRulesetFactory {
*/
public static BlockHeaderValidator.Builder ibftProposedBlockValidator(
final long secondsBetweenBlocks) {
return createValidator(secondsBetweenBlocks, false);
return createValidator(secondsBetweenBlocks, false, 0);
}
private static BlockHeaderValidator.Builder createValidator(
final long secondsBetweenBlocks, final boolean validateCommitSeals) {
final long secondsBetweenBlocks,
final boolean validateCommitSeals,
final long ceil2nBy3Block) {
return new BlockHeaderValidator.Builder()
.addRule(new AncestryValidationRule())
.addRule(new GasUsageValidationRule())
@ -72,6 +75,6 @@ public class IbftBlockHeaderValidationRulesetFactory {
new ConstantFieldValidationRule<>(
"Difficulty", BlockHeader::getDifficulty, UInt256.ONE))
.addRule(new VoteValidationRule())
.addRule(new IbftExtraDataValidationRule(validateCommitSeals));
.addRule(new IbftExtraDataValidationRule(validateCommitSeals, ceil2nBy3Block));
}
}

@ -16,8 +16,8 @@ package org.hyperledger.besu.consensus.ibftlegacy;
import static org.hyperledger.besu.consensus.ibftlegacy.IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator;
import org.hyperledger.besu.config.BftConfigOptions;
import org.hyperledger.besu.config.GenesisConfigOptions;
import org.hyperledger.besu.config.IbftLegacyConfigOptions;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockBodyValidator;
@ -38,13 +38,15 @@ public class IbftProtocolSchedule {
final GenesisConfigOptions config,
final PrivacyParameters privacyParameters,
final boolean isRevertReasonEnabled) {
final BftConfigOptions ibftConfig = config.getIbftLegacyConfigOptions();
final IbftLegacyConfigOptions ibftConfig = config.getIbftLegacyConfigOptions();
final long blockPeriod = ibftConfig.getBlockPeriodSeconds();
return new ProtocolScheduleBuilder(
config,
DEFAULT_CHAIN_ID,
builder -> applyIbftChanges(blockPeriod, builder, config.isQuorum()),
builder ->
applyIbftChanges(
blockPeriod, builder, config.isQuorum(), ibftConfig.getCeil2Nby3Block()),
privacyParameters,
isRevertReasonEnabled,
config.isQuorum())
@ -59,10 +61,11 @@ public class IbftProtocolSchedule {
private static ProtocolSpecBuilder applyIbftChanges(
final long secondsBetweenBlocks,
final ProtocolSpecBuilder builder,
final boolean goQuorumMode) {
final boolean goQuorumMode,
final long ceil2nBy3Block) {
return builder
.blockHeaderValidatorBuilder(ibftBlockHeaderValidator(secondsBetweenBlocks))
.ommerHeaderValidatorBuilder(ibftBlockHeaderValidator(secondsBetweenBlocks))
.blockHeaderValidatorBuilder(ibftBlockHeaderValidator(secondsBetweenBlocks, ceil2nBy3Block))
.ommerHeaderValidatorBuilder(ibftBlockHeaderValidator(secondsBetweenBlocks, ceil2nBy3Block))
.blockBodyValidatorBuilder(MainnetBlockBodyValidator::new)
.blockValidatorBuilder(MainnetProtocolSpecs.blockValidatorBuilder(goQuorumMode))
.blockImporterBuilder(MainnetBlockImporter::new)

@ -16,6 +16,7 @@ package org.hyperledger.besu.consensus.ibftlegacy.headervalidationrules;
import org.hyperledger.besu.consensus.common.ValidatorProvider;
import org.hyperledger.besu.consensus.common.bft.BftContext;
import org.hyperledger.besu.consensus.common.bft.BftHelpers;
import org.hyperledger.besu.consensus.ibftlegacy.IbftBlockHashing;
import org.hyperledger.besu.consensus.ibftlegacy.IbftExtraData;
import org.hyperledger.besu.consensus.ibftlegacy.IbftHelpers;
@ -44,9 +45,11 @@ public class IbftExtraDataValidationRule implements AttachedBlockHeaderValidatio
private static final Logger LOG = LogManager.getLogger();
private final boolean validateCommitSeals;
private final long ceil2nBy3Block;
public IbftExtraDataValidationRule(final boolean validateCommitSeals) {
public IbftExtraDataValidationRule(final boolean validateCommitSeals, final long ceil2nBy3Block) {
this.validateCommitSeals = validateCommitSeals;
this.ceil2nBy3Block = ceil2nBy3Block;
}
@Override
@ -72,7 +75,13 @@ public class IbftExtraDataValidationRule implements AttachedBlockHeaderValidatio
if (validateCommitSeals) {
final List<Address> committers =
IbftBlockHashing.recoverCommitterAddresses(header, ibftExtraData);
if (!validateCommitters(committers, storedValidators)) {
final int minimumSealsRequired =
header.getNumber() < ceil2nBy3Block
? IbftHelpers.calculateRequiredValidatorQuorum(storedValidators.size())
: BftHelpers.calculateRequiredValidatorQuorum(storedValidators.size());
if (!validateCommitters(committers, storedValidators, minimumSealsRequired)) {
return false;
}
}
@ -113,10 +122,9 @@ public class IbftExtraDataValidationRule implements AttachedBlockHeaderValidatio
}
private boolean validateCommitters(
final Collection<Address> committers, final Collection<Address> storedValidators) {
final int minimumSealsRequired =
IbftHelpers.calculateRequiredValidatorQuorum(storedValidators.size());
final Collection<Address> committers,
final Collection<Address> storedValidators,
final int minimumSealsRequired) {
if (committers.size() < minimumSealsRequired) {
LOG.info(
"Invalid block header: Insufficient committers to seal block. (Required {}, received {})",

@ -68,7 +68,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
final BlockHeader blockHeader = buildBlockHeader(2, proposerKeyPair, validators, parentHeader);
final BlockHeaderValidator validator =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5).build();
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, 0).build();
assertThat(
validator.validateHeader(
@ -91,7 +91,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
final BlockHeader blockHeader = buildBlockHeader(2, proposerKeyPair, validators, null);
final BlockHeaderValidator validator =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5).build();
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, 0).build();
assertThat(
validator.validateHeader(

@ -105,7 +105,7 @@ public class BftExtraDataValidationRuleTest {
new ProtocolContext(null, null, setupContextWithValidators(validators));
final IbftExtraDataValidationRule extraDataValidationRule =
new IbftExtraDataValidationRule(true);
new IbftExtraDataValidationRule(true, 0);
BlockHeader header = createProposedBlockHeader(proposerKeyPair, validators);
@ -131,7 +131,7 @@ public class BftExtraDataValidationRuleTest {
new ProtocolContext(null, null, setupContextWithValidators(validators));
final IbftExtraDataValidationRule extraDataValidationRule =
new IbftExtraDataValidationRule(true);
new IbftExtraDataValidationRule(true, 0);
final BlockHeader header = createProposedBlockHeader(proposerKeyPair, validators);
@ -158,7 +158,7 @@ public class BftExtraDataValidationRuleTest {
new ProtocolContext(null, null, setupContextWithValidators(validators));
final IbftExtraDataValidationRule extraDataValidationRule =
new IbftExtraDataValidationRule(true);
new IbftExtraDataValidationRule(true, 0);
BlockHeader header = createProposedBlockHeader(proposerKeyPair, validators);
@ -187,7 +187,7 @@ public class BftExtraDataValidationRuleTest {
new ProtocolContext(null, null, setupContextWithValidators(validators));
final IbftExtraDataValidationRule extraDataValidationRule =
new IbftExtraDataValidationRule(true);
new IbftExtraDataValidationRule(true, 0);
BlockHeader header = createProposedBlockHeader(proposerKeyPair, validators);
@ -214,7 +214,7 @@ public class BftExtraDataValidationRuleTest {
new ProtocolContext(null, null, setupContextWithValidators(validators));
final IbftExtraDataValidationRule extraDataValidationRule =
new IbftExtraDataValidationRule(true);
new IbftExtraDataValidationRule(true, 0);
// Add another validator to the list reported in the IbftExtraData (note, as the
final List<Address> extraDataValidators =
@ -253,35 +253,35 @@ public class BftExtraDataValidationRuleTest {
final ProtocolContext context =
new ProtocolContext(null, null, setupContextWithValidators(validators));
final IbftExtraDataValidationRule extraDataValidationRule =
new IbftExtraDataValidationRule(true);
new IbftExtraDataValidationRule(true, 0);
assertThat(extraDataValidationRule.validate(header, null, context)).isFalse();
}
@Test
public void ratioOfCommittersToValidatorsAffectValidation() {
assertThat(subExecution(4, 4)).isEqualTo(true);
assertThat(subExecution(4, 3)).isEqualTo(true);
assertThat(subExecution(4, 2)).isEqualTo(false);
assertThat(subExecution(4, 4, false)).isEqualTo(true);
assertThat(subExecution(4, 3, false)).isEqualTo(true);
assertThat(subExecution(4, 2, false)).isEqualTo(false);
assertThat(subExecution(5, 3)).isEqualTo(true);
assertThat(subExecution(5, 2)).isEqualTo(false);
assertThat(subExecution(5, 3, false)).isEqualTo(true);
assertThat(subExecution(5, 2, false)).isEqualTo(false);
assertThat(subExecution(6, 4)).isEqualTo(true);
assertThat(subExecution(6, 3)).isEqualTo(true);
assertThat(subExecution(6, 2)).isEqualTo(false);
assertThat(subExecution(6, 4, false)).isEqualTo(true);
assertThat(subExecution(6, 3, false)).isEqualTo(true);
assertThat(subExecution(6, 2, false)).isEqualTo(false);
assertThat(subExecution(7, 5)).isEqualTo(true);
assertThat(subExecution(7, 4)).isEqualTo(false);
assertThat(subExecution(7, 5, false)).isEqualTo(true);
assertThat(subExecution(7, 4, false)).isEqualTo(false);
assertThat(subExecution(9, 5)).isEqualTo(true);
assertThat(subExecution(9, 4)).isEqualTo(false);
assertThat(subExecution(9, 5, false)).isEqualTo(true);
assertThat(subExecution(9, 4, false)).isEqualTo(false);
assertThat(subExecution(10, 7)).isEqualTo(true);
assertThat(subExecution(10, 6)).isEqualTo(false);
assertThat(subExecution(10, 7, false)).isEqualTo(true);
assertThat(subExecution(10, 6, false)).isEqualTo(false);
assertThat(subExecution(12, 7)).isEqualTo(true);
assertThat(subExecution(12, 6)).isEqualTo(false);
assertThat(subExecution(12, 7, false)).isEqualTo(true);
assertThat(subExecution(12, 6, false)).isEqualTo(false);
// The concern in the above is that when using 6 validators, only 1/2 the validators are
// required to seal a block. All other combinations appear to be safe they always have >50%
@ -289,7 +289,8 @@ public class BftExtraDataValidationRuleTest {
}
private boolean subExecution(final int validatorCount, final int committerCount) {
private boolean subExecution(
final int validatorCount, final int committerCount, final boolean useTwoThirds) {
final BlockHeaderTestFixture builder = new BlockHeaderTestFixture();
builder.number(1); // must NOT be block 0, as that should not contain seals at all
final KeyPair proposerKeyPair = KeyPair.generate();
@ -318,7 +319,7 @@ public class BftExtraDataValidationRuleTest {
final ProtocolContext context =
new ProtocolContext(null, null, setupContextWithValidators(validators));
final IbftExtraDataValidationRule extraDataValidationRule =
new IbftExtraDataValidationRule(true);
new IbftExtraDataValidationRule(true, useTwoThirds ? 0 : 2);
return extraDataValidationRule.validate(header, null, context);
}

Loading…
Cancel
Save