mirror of
https://github.com/vacp2p/linea-besu.git
synced 2026-01-09 21:17:54 -05:00
QBFT + shanghai support (#6353)
* Refactored version of QBFT/shanghai Signed-off-by: Matthew Whitehead <matthew1001@gmail.com> * More refactoring Signed-off-by: Matthew Whitehead <matthew1001@gmail.com> * Add equivalent IBFT fixes. Update QBFT and IBFT round tests Signed-off-by: Matthew Whitehead <matthew1001@gmail.com> * Update the change log Signed-off-by: Matthew Whitehead <matthew1001@gmail.com> * Remove old comments Signed-off-by: Matthew Whitehead <matthew1001@gmail.com> * Add shanghai contract validator test Signed-off-by: Matthew Whitehead <matthew1001@gmail.com> * Add shanghai acceptance test Signed-off-by: Matthew Whitehead <matthew1001@gmail.com> * Add Shanghai to the combined protocol schedule test, update IBFT message validator creation Signed-off-by: Matthew Whitehead <matthew1001@gmail.com> * Fix merge Signed-off-by: Matthew Whitehead <matthew1001@gmail.com> * Update tests to use shanghai time > 0 Signed-off-by: Matthew Whitehead <matthew1001@gmail.com> * Address PR comments Signed-off-by: Matthew Whitehead <matthew1001@gmail.com> * Refactor unit tests Signed-off-by: Matthew Whitehead <matthew1001@gmail.com> * Refactor unit tests Signed-off-by: Matthew Whitehead <matthew1001@gmail.com> * IbftRoundTests update Signed-off-by: Matthew Whitehead <matthew1001@gmail.com> * Address PR comments Signed-off-by: Matthew Whitehead <matthew1001@gmail.com> * Remove unnecessary class type check Signed-off-by: Matthew Whitehead <matthew1001@gmail.com> --------- Signed-off-by: Matthew Whitehead <matthew1001@gmail.com> Signed-off-by: Matt Whitehead <matthew1001@gmail.com> Signed-off-by: Matt Whitehead <matthew.whitehead@kaleido.io>
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
- Introduce caching mechanism to optimize Keccak hash calculations for account storage slots during block processing [#6452](https://github.com/hyperledger/besu/pull/6452)
|
||||
- Added configuration options for `pragueTime` to genesis file for Prague fork development [#6473](https://github.com/hyperledger/besu/pull/6473)
|
||||
- Moving trielog storage to RocksDB's blobdb to improve write amplications [#6289](https://github.com/hyperledger/besu/pull/6289)
|
||||
- Support for `shanghaiTime` fork and Shanghai EVM smart contracts in QBFT/IBFT chains [#6353](https://github.com/hyperledger/besu/pull/6353)
|
||||
|
||||
### Bug fixes
|
||||
- Fix the way an advertised host configured with `--p2p-host` is treated when communicating with the originator of a PING packet [#6225](https://github.com/hyperledger/besu/pull/6225)
|
||||
|
||||
@@ -150,6 +150,36 @@ public class BftMiningAcceptanceTest extends ParameterizedBftTestBase {
|
||||
cluster.verify(receiver.balanceEquals(3));
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{index}: {0}")
|
||||
@MethodSource("factoryFunctions")
|
||||
public void shouldMineOnSingleNodeWithFreeGas_Shanghai(
|
||||
final String testName, final BftAcceptanceTestParameterization nodeFactory) throws Exception {
|
||||
setUp(testName, nodeFactory);
|
||||
final BesuNode minerNode = nodeFactory.createNode(besu, "miner1");
|
||||
updateGenesisConfigToShanghai(minerNode, true);
|
||||
|
||||
cluster.start(minerNode);
|
||||
|
||||
cluster.verify(blockchain.reachesHeight(minerNode, 1));
|
||||
|
||||
final Account sender = accounts.createAccount("account1");
|
||||
final Account receiver = accounts.createAccount("account2");
|
||||
|
||||
minerNode.execute(accountTransactions.createTransfer(sender, 50, Amount.ZERO));
|
||||
cluster.verify(sender.balanceEquals(50));
|
||||
|
||||
minerNode.execute(accountTransactions.create1559Transfer(sender, 50, 4, Amount.ZERO));
|
||||
cluster.verify(sender.balanceEquals(100));
|
||||
|
||||
minerNode.execute(
|
||||
accountTransactions.createIncrementalTransfers(sender, receiver, 1, Amount.ZERO));
|
||||
cluster.verify(receiver.balanceEquals(1));
|
||||
|
||||
minerNode.execute(
|
||||
accountTransactions.create1559IncrementalTransfers(sender, receiver, 2, 4, Amount.ZERO));
|
||||
cluster.verify(receiver.balanceEquals(3));
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{index}: {0}")
|
||||
@MethodSource("factoryFunctions")
|
||||
public void shouldMineOnMultipleNodes(
|
||||
@@ -245,4 +275,16 @@ public class BftMiningAcceptanceTest extends ParameterizedBftTestBase {
|
||||
config.put("zeroBaseFee", zeroBaseFeeEnabled);
|
||||
minerNode.setGenesisConfig(genesisConfigNode.toString());
|
||||
}
|
||||
|
||||
private static void updateGenesisConfigToShanghai(
|
||||
final BesuNode minerNode, final boolean zeroBaseFeeEnabled) {
|
||||
final Optional<String> genesisConfig =
|
||||
minerNode.getGenesisConfigProvider().create(List.of(minerNode));
|
||||
final ObjectNode genesisConfigNode = JsonUtil.objectNodeFromString(genesisConfig.orElseThrow());
|
||||
final ObjectNode config = (ObjectNode) genesisConfigNode.get("config");
|
||||
config.remove("berlinBlock");
|
||||
config.put("shanghaiTime", 100);
|
||||
config.put("zeroBaseFee", zeroBaseFeeEnabled);
|
||||
minerNode.setGenesisConfig(genesisConfigNode.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,14 +53,22 @@ public class CombinedProtocolScheduleFactory {
|
||||
protocolSchedule.getScheduledProtocolSpecs().stream()
|
||||
.filter(protocolSpecMatchesConsensusBlockRange(spec.getBlock(), endBlock))
|
||||
.forEach(
|
||||
s ->
|
||||
combinedProtocolSchedule.putBlockNumberMilestone(s.fork().milestone(), s.spec()));
|
||||
s -> {
|
||||
if (s instanceof ScheduledProtocolSpec.TimestampProtocolSpec) {
|
||||
combinedProtocolSchedule.putTimestampMilestone(s.fork().milestone(), s.spec());
|
||||
} else if (s instanceof ScheduledProtocolSpec.BlockNumberProtocolSpec) {
|
||||
combinedProtocolSchedule.putBlockNumberMilestone(s.fork().milestone(), s.spec());
|
||||
} else {
|
||||
throw new IllegalStateException(
|
||||
"Unexpected milestone: " + s + " for milestone: " + s.fork().milestone());
|
||||
}
|
||||
});
|
||||
|
||||
// When moving to a new consensus mechanism we want to use the last milestone but created by
|
||||
// our consensus mechanism's BesuControllerBuilder so any additional rules are applied
|
||||
if (spec.getBlock() > 0) {
|
||||
combinedProtocolSchedule.putBlockNumberMilestone(
|
||||
spec.getBlock(), protocolSchedule.getByBlockNumber(spec.getBlock()));
|
||||
spec.getBlock(), protocolSchedule.getByBlockNumberOrTimestamp(spec.getBlock(), 0L));
|
||||
}
|
||||
}
|
||||
return combinedProtocolSchedule;
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecAdapters;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecBuilder;
|
||||
import org.hyperledger.besu.ethereum.mainnet.WithdrawalsValidator;
|
||||
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
|
||||
import org.hyperledger.besu.evm.internal.EvmConfiguration;
|
||||
|
||||
@@ -116,6 +117,9 @@ public abstract class BaseBftProtocolScheduleBuilder {
|
||||
.skipZeroBlockRewards(true)
|
||||
.blockHeaderFunctions(BftBlockHeaderFunctions.forOnchainBlock(bftExtraDataCodec))
|
||||
.blockReward(Wei.of(configOptions.getBlockRewardWei()))
|
||||
.withdrawalsValidator(
|
||||
new WithdrawalsValidator
|
||||
.ProhibitedWithdrawals()) // QBFT/IBFT doesn't support withdrawals
|
||||
.miningBeneficiaryCalculator(
|
||||
header -> configOptions.getMiningBeneficiary().orElseGet(header::getCoinbase));
|
||||
}
|
||||
|
||||
@@ -39,12 +39,13 @@ public class BftProtocolSchedule extends DefaultProtocolSchedule {
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up ProtocolSpec by block number
|
||||
* Look up ProtocolSpec by block number or timestamp
|
||||
*
|
||||
* @param number block number
|
||||
* @return the protocol spec for that block number
|
||||
* @param timestamp block timestamp
|
||||
* @return the protocol spec for that block number or timestamp
|
||||
*/
|
||||
public ProtocolSpec getByBlockNumber(final long number) {
|
||||
public ProtocolSpec getByBlockNumberOrTimestamp(final long number, final long timestamp) {
|
||||
checkArgument(number >= 0, "number must be non-negative");
|
||||
checkArgument(
|
||||
!protocolSpecs.isEmpty(), "At least 1 milestone must be provided to the protocol schedule");
|
||||
@@ -53,12 +54,19 @@ public class BftProtocolSchedule extends DefaultProtocolSchedule {
|
||||
"There must be a milestone starting from block 0");
|
||||
// protocolSpecs is sorted in descending block order, so the first one we find that's lower than
|
||||
// the requested level will be the most appropriate spec
|
||||
ProtocolSpec theSpec = null;
|
||||
for (final ScheduledProtocolSpec s : protocolSpecs) {
|
||||
if (number >= s.fork().milestone()) {
|
||||
return s.spec();
|
||||
if ((s instanceof ScheduledProtocolSpec.BlockNumberProtocolSpec)
|
||||
&& (number >= s.fork().milestone())) {
|
||||
theSpec = s.spec();
|
||||
break;
|
||||
} else if ((s instanceof ScheduledProtocolSpec.TimestampProtocolSpec)
|
||||
&& (timestamp >= s.fork().milestone())) {
|
||||
theSpec = s.spec();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return theSpec;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -60,18 +60,20 @@ public class CombinedProtocolScheduleFactoryTest {
|
||||
final BftProtocolSchedule combinedProtocolSchedule =
|
||||
combinedProtocolScheduleFactory.create(consensusSchedule, Optional.of(BigInteger.TEN));
|
||||
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumber(0L).getName()).isEqualTo("Frontier");
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumber(0L))
|
||||
.isSameAs(protocolSchedule.getByBlockNumber(0L));
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(0L, 0L).getName())
|
||||
.isEqualTo("Frontier");
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(0L, 0L))
|
||||
.isSameAs(protocolSchedule.getByBlockNumberOrTimestamp(0L, 0L));
|
||||
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumber(5L).getName()).isEqualTo("Homestead");
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumber(5L))
|
||||
.isSameAs(protocolSchedule.getByBlockNumber(5L));
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(5L, 0L).getName())
|
||||
.isEqualTo("Homestead");
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(5L, 0L))
|
||||
.isSameAs(protocolSchedule.getByBlockNumberOrTimestamp(5L, 0L));
|
||||
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumber(10L).getName())
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(10L, 0L).getName())
|
||||
.isEqualTo("Constantinople");
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumber(10L))
|
||||
.isSameAs(protocolSchedule.getByBlockNumber(10L));
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(10L, 0L))
|
||||
.isSameAs(protocolSchedule.getByBlockNumberOrTimestamp(10L, 0L));
|
||||
|
||||
assertThat(
|
||||
new MilestoneStreamingProtocolSchedule(combinedProtocolSchedule)
|
||||
@@ -88,63 +90,78 @@ public class CombinedProtocolScheduleFactoryTest {
|
||||
genesisConfigOptions.byzantiumBlock(105L);
|
||||
genesisConfigOptions.berlinBlock(110L);
|
||||
genesisConfigOptions.londonBlock(220L);
|
||||
genesisConfigOptions.shanghaiTime(1000000050L);
|
||||
genesisConfigOptions.chainId(BigInteger.TEN);
|
||||
|
||||
final BftProtocolSchedule protocolSchedule1 = createProtocolSchedule(genesisConfigOptions);
|
||||
final BftProtocolSchedule protocolSchedule2 = createProtocolSchedule(genesisConfigOptions);
|
||||
final BftProtocolSchedule protocolSchedule3 = createProtocolSchedule(genesisConfigOptions);
|
||||
final BftProtocolSchedule protocolSchedule4 = createProtocolSchedule(genesisConfigOptions);
|
||||
|
||||
final NavigableSet<ForkSpec<ProtocolSchedule>> consensusSchedule =
|
||||
new TreeSet<>(ForkSpec.COMPARATOR);
|
||||
consensusSchedule.add(new ForkSpec<>(0, protocolSchedule1));
|
||||
consensusSchedule.add(new ForkSpec<>(100L, protocolSchedule2));
|
||||
consensusSchedule.add(new ForkSpec<>(200L, protocolSchedule3));
|
||||
consensusSchedule.add(new ForkSpec<>(1000000000L, protocolSchedule4));
|
||||
|
||||
final BftProtocolSchedule combinedProtocolSchedule =
|
||||
combinedProtocolScheduleFactory.create(consensusSchedule, Optional.of(BigInteger.TEN));
|
||||
|
||||
// consensus schedule 1
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumber(0L).getName()).isEqualTo("Frontier");
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumber(0L))
|
||||
.isSameAs(protocolSchedule1.getByBlockNumber(0L));
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(0L, 0L).getName())
|
||||
.isEqualTo("Frontier");
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(0L, 0L))
|
||||
.isSameAs(protocolSchedule1.getByBlockNumberOrTimestamp(0L, 0L));
|
||||
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumber(5L).getName()).isEqualTo("Homestead");
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumber(5L))
|
||||
.isSameAs(protocolSchedule1.getByBlockNumber(5L));
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumber(10L).getName())
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(5L, 0L).getName())
|
||||
.isEqualTo("Homestead");
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(5L, 0L))
|
||||
.isSameAs(protocolSchedule1.getByBlockNumberOrTimestamp(5L, 0L));
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(10L, 0L).getName())
|
||||
.isEqualTo("Constantinople");
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumber(10L))
|
||||
.isSameAs(protocolSchedule1.getByBlockNumber(10L));
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(10L, 0L))
|
||||
.isSameAs(protocolSchedule1.getByBlockNumberOrTimestamp(10L, 0L));
|
||||
|
||||
// consensus schedule 2 migration block
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumber(100L).getName())
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(100L, 0L).getName())
|
||||
.isEqualTo("Constantinople");
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumber(100L))
|
||||
.isSameAs(protocolSchedule2.getByBlockNumber(10L));
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(100L, 0L))
|
||||
.isSameAs(protocolSchedule2.getByBlockNumberOrTimestamp(10L, 0L));
|
||||
|
||||
// consensus schedule 2
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumber(105L).getName()).isEqualTo("Byzantium");
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumber(105L))
|
||||
.isSameAs(protocolSchedule2.getByBlockNumber(105L));
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumber(110L).getName()).isEqualTo("Berlin");
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumber(110L))
|
||||
.isSameAs(protocolSchedule2.getByBlockNumber(110L));
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(105L, 0L).getName())
|
||||
.isEqualTo("Byzantium");
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(105L, 0L))
|
||||
.isSameAs(protocolSchedule2.getByBlockNumberOrTimestamp(105L, 0L));
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(110L, 0L).getName())
|
||||
.isEqualTo("Berlin");
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(110L, 0L))
|
||||
.isSameAs(protocolSchedule2.getByBlockNumberOrTimestamp(110L, 0L));
|
||||
|
||||
// consensus schedule 3 migration block
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumber(200L).getName()).isEqualTo("Berlin");
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumber(200L))
|
||||
.isSameAs(protocolSchedule3.getByBlockNumber(110L));
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(200L, 0L).getName())
|
||||
.isEqualTo("Berlin");
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(200L, 0L))
|
||||
.isSameAs(protocolSchedule3.getByBlockNumberOrTimestamp(110L, 0L));
|
||||
|
||||
// consensus schedule 3
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumber(220L).getName()).isEqualTo("London");
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumber(220L))
|
||||
.isSameAs(protocolSchedule3.getByBlockNumber(220L));
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(220L, 0L).getName())
|
||||
.isEqualTo("London");
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(220L, 0L))
|
||||
.isSameAs(protocolSchedule3.getByBlockNumberOrTimestamp(220L, 0L));
|
||||
|
||||
// consensus schedule 4
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(0L, 1000000050L).getName())
|
||||
.isEqualTo("Shanghai");
|
||||
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(220L, 1000000050L))
|
||||
.isSameAs(protocolSchedule4.getByBlockNumberOrTimestamp(220L, 1000000050L));
|
||||
|
||||
assertThat(
|
||||
new MilestoneStreamingProtocolSchedule(combinedProtocolSchedule)
|
||||
.streamMilestoneBlocks()
|
||||
.collect(Collectors.toList()))
|
||||
.isEqualTo(List.of(0L, 5L, 10L, 100L, 105L, 110L, 200L, 220L));
|
||||
.isEqualTo(List.of(0L, 5L, 10L, 100L, 105L, 110L, 200L, 220L, 1000000000L, 1000000050L));
|
||||
}
|
||||
|
||||
private BftProtocolSchedule createProtocolSchedule(
|
||||
|
||||
@@ -24,6 +24,7 @@ import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.hyperledger.besu.consensus.common.bft.BftExtraData;
|
||||
import org.hyperledger.besu.consensus.common.bft.BftProtocolSchedule;
|
||||
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
|
||||
import org.hyperledger.besu.consensus.common.bft.RoundTimer;
|
||||
import org.hyperledger.besu.consensus.common.bft.blockcreation.BftBlockCreator;
|
||||
@@ -48,6 +49,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
|
||||
import org.hyperledger.besu.ethereum.core.BlockImporter;
|
||||
import org.hyperledger.besu.ethereum.mainnet.BlockImportResult;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
|
||||
import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleException;
|
||||
import org.hyperledger.besu.util.Subscribers;
|
||||
@@ -74,6 +76,8 @@ public class IbftRoundIntegrationTest {
|
||||
private final Subscribers<MinedBlockObserver> subscribers = Subscribers.create();
|
||||
private ProtocolContext protocolContext;
|
||||
|
||||
@Mock private BftProtocolSchedule protocolSchedule;
|
||||
@Mock private ProtocolSpec protocolSpec;
|
||||
@Mock private MutableBlockchain blockChain;
|
||||
@Mock private WorldStateArchive worldStateArchive;
|
||||
@Mock private BlockImporter blockImporter;
|
||||
@@ -112,6 +116,9 @@ public class IbftRoundIntegrationTest {
|
||||
final BlockHeader header = headerTestFixture.buildHeader();
|
||||
proposedBlock = new Block(header, new BlockBody(emptyList(), emptyList()));
|
||||
|
||||
when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec);
|
||||
when(protocolSpec.getBlockImporter()).thenReturn(blockImporter);
|
||||
|
||||
when(blockImporter.importBlock(any(), any(), any())).thenReturn(new BlockImportResult(true));
|
||||
|
||||
protocolContext =
|
||||
@@ -131,7 +138,7 @@ public class IbftRoundIntegrationTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
nodeKey,
|
||||
throwingMessageFactory,
|
||||
@@ -158,7 +165,7 @@ public class IbftRoundIntegrationTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
nodeKey,
|
||||
throwingMessageFactory,
|
||||
|
||||
@@ -40,6 +40,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.BlockImporter;
|
||||
import org.hyperledger.besu.ethereum.mainnet.BlockImportResult;
|
||||
import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleException;
|
||||
import org.hyperledger.besu.util.Subscribers;
|
||||
|
||||
@@ -57,7 +58,7 @@ public class IbftRound {
|
||||
private final RoundState roundState;
|
||||
private final BlockCreator blockCreator;
|
||||
private final ProtocolContext protocolContext;
|
||||
private final BlockImporter blockImporter;
|
||||
private final ProtocolSchedule protocolSchedule;
|
||||
private final NodeKey nodeKey;
|
||||
private final MessageFactory messageFactory; // used only to create stored local msgs
|
||||
private final IbftMessageTransmitter transmitter;
|
||||
@@ -69,7 +70,7 @@ public class IbftRound {
|
||||
* @param roundState the round state
|
||||
* @param blockCreator the block creator
|
||||
* @param protocolContext the protocol context
|
||||
* @param blockImporter the block importer
|
||||
* @param protocolSchedule the protocol schedule
|
||||
* @param observers the observers
|
||||
* @param nodeKey the node key
|
||||
* @param messageFactory the message factory
|
||||
@@ -81,7 +82,7 @@ public class IbftRound {
|
||||
final RoundState roundState,
|
||||
final BlockCreator blockCreator,
|
||||
final ProtocolContext protocolContext,
|
||||
final BlockImporter blockImporter,
|
||||
final ProtocolSchedule protocolSchedule,
|
||||
final Subscribers<MinedBlockObserver> observers,
|
||||
final NodeKey nodeKey,
|
||||
final MessageFactory messageFactory,
|
||||
@@ -91,7 +92,7 @@ public class IbftRound {
|
||||
this.roundState = roundState;
|
||||
this.blockCreator = blockCreator;
|
||||
this.protocolContext = protocolContext;
|
||||
this.blockImporter = blockImporter;
|
||||
this.protocolSchedule = protocolSchedule;
|
||||
this.observers = observers;
|
||||
this.nodeKey = nodeKey;
|
||||
this.messageFactory = messageFactory;
|
||||
@@ -312,6 +313,8 @@ public class IbftRound {
|
||||
blockToImport.getHash());
|
||||
}
|
||||
LOG.trace("Importing block with extraData={}", extraData);
|
||||
final BlockImporter blockImporter =
|
||||
protocolSchedule.getByBlockHeader(blockToImport.getHeader()).getBlockImporter();
|
||||
final BlockImportResult result =
|
||||
blockImporter.importBlock(protocolContext, blockToImport, HeaderValidationMode.FULL);
|
||||
if (!result.isImported()) {
|
||||
|
||||
@@ -99,9 +99,8 @@ public class IbftRoundFactory {
|
||||
*/
|
||||
public IbftRound createNewRoundWithState(
|
||||
final BlockHeader parentHeader, final RoundState roundState) {
|
||||
final ConsensusRoundIdentifier roundIdentifier = roundState.getRoundIdentifier();
|
||||
final BlockCreator blockCreator =
|
||||
blockCreatorFactory.create(parentHeader, roundIdentifier.getRoundNumber());
|
||||
blockCreatorFactory.create(parentHeader, roundState.getRoundIdentifier().getRoundNumber());
|
||||
|
||||
final IbftMessageTransmitter messageTransmitter =
|
||||
new IbftMessageTransmitter(messageFactory, finalState.getValidatorMulticaster());
|
||||
@@ -110,7 +109,7 @@ public class IbftRoundFactory {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
protocolSchedule.getByBlockNumber(roundIdentifier.getSequenceNumber()).getBlockImporter(),
|
||||
protocolSchedule,
|
||||
minedBlockObservers,
|
||||
finalState.getNodeKey(),
|
||||
messageFactory,
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.hyperledger.besu.ethereum.BlockValidator;
|
||||
import org.hyperledger.besu.ethereum.ProtocolContext;
|
||||
import org.hyperledger.besu.ethereum.core.Block;
|
||||
import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -38,7 +39,7 @@ public class MessageValidator {
|
||||
|
||||
private final SignedDataValidator signedDataValidator;
|
||||
private final ProposalBlockConsistencyValidator proposalConsistencyValidator;
|
||||
private final BlockValidator blockValidator;
|
||||
private final ProtocolSchedule protocolSchedule;
|
||||
private final ProtocolContext protocolContext;
|
||||
private final RoundChangeCertificateValidator roundChangeCertificateValidator;
|
||||
|
||||
@@ -47,19 +48,19 @@ public class MessageValidator {
|
||||
*
|
||||
* @param signedDataValidator the signed data validator
|
||||
* @param proposalConsistencyValidator the proposal consistency validator
|
||||
* @param blockValidator the block validator
|
||||
* @param protocolSchedule the protocol schedule
|
||||
* @param protocolContext the protocol context
|
||||
* @param roundChangeCertificateValidator the round change certificate validator
|
||||
*/
|
||||
public MessageValidator(
|
||||
final SignedDataValidator signedDataValidator,
|
||||
final ProposalBlockConsistencyValidator proposalConsistencyValidator,
|
||||
final BlockValidator blockValidator,
|
||||
final ProtocolContext protocolContext,
|
||||
final ProtocolSchedule protocolSchedule,
|
||||
final RoundChangeCertificateValidator roundChangeCertificateValidator) {
|
||||
this.signedDataValidator = signedDataValidator;
|
||||
this.proposalConsistencyValidator = proposalConsistencyValidator;
|
||||
this.blockValidator = blockValidator;
|
||||
this.protocolSchedule = protocolSchedule;
|
||||
this.protocolContext = protocolContext;
|
||||
this.roundChangeCertificateValidator = roundChangeCertificateValidator;
|
||||
}
|
||||
@@ -93,6 +94,10 @@ public class MessageValidator {
|
||||
}
|
||||
|
||||
private boolean validateBlock(final Block block) {
|
||||
|
||||
final BlockValidator blockValidator =
|
||||
protocolSchedule.getByBlockHeader(block.getHeader()).getBlockValidator();
|
||||
|
||||
final var validationResult =
|
||||
blockValidator.validateAndProcessBlock(
|
||||
protocolContext, block, HeaderValidationMode.LIGHT, HeaderValidationMode.FULL);
|
||||
|
||||
@@ -22,7 +22,6 @@ import org.hyperledger.besu.consensus.common.bft.BftProtocolSchedule;
|
||||
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
|
||||
import org.hyperledger.besu.consensus.common.bft.blockcreation.ProposerSelector;
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.ethereum.BlockValidator;
|
||||
import org.hyperledger.besu.ethereum.ProtocolContext;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
|
||||
@@ -80,8 +79,6 @@ public class MessageValidatorFactory {
|
||||
*/
|
||||
public MessageValidator createMessageValidator(
|
||||
final ConsensusRoundIdentifier roundIdentifier, final BlockHeader parentHeader) {
|
||||
final BlockValidator blockValidator =
|
||||
protocolSchedule.getByBlockNumber(roundIdentifier.getSequenceNumber()).getBlockValidator();
|
||||
final Collection<Address> validators = getValidatorsAfterBlock(parentHeader);
|
||||
|
||||
final BftBlockInterface bftBlockInterface =
|
||||
@@ -90,8 +87,8 @@ public class MessageValidatorFactory {
|
||||
return new MessageValidator(
|
||||
createSignedDataValidator(roundIdentifier, parentHeader),
|
||||
new ProposalBlockConsistencyValidator(),
|
||||
blockValidator,
|
||||
protocolContext,
|
||||
protocolSchedule,
|
||||
new RoundChangeCertificateValidator(
|
||||
validators,
|
||||
(ri) -> createSignedDataValidator(ri, parentHeader),
|
||||
|
||||
@@ -110,7 +110,7 @@ public class IbftProtocolScheduleTest {
|
||||
final BlockHeader blockHeader,
|
||||
final int block) {
|
||||
return schedule
|
||||
.getByBlockNumber(block)
|
||||
.getByBlockNumberOrTimestamp(block, blockHeader.getTimestamp())
|
||||
.getBlockHeaderValidator()
|
||||
.validateHeader(
|
||||
blockHeader, parentHeader, protocolContext(validators), HeaderValidationMode.LIGHT);
|
||||
|
||||
@@ -31,8 +31,10 @@ import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.hyperledger.besu.config.StubGenesisConfigOptions;
|
||||
import org.hyperledger.besu.consensus.common.bft.BftExtraData;
|
||||
import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec;
|
||||
import org.hyperledger.besu.consensus.common.bft.BftProtocolSchedule;
|
||||
import org.hyperledger.besu.consensus.common.bft.BlockTimer;
|
||||
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
|
||||
import org.hyperledger.besu.consensus.common.bft.RoundTimer;
|
||||
@@ -61,13 +63,19 @@ import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.ProtocolContext;
|
||||
import org.hyperledger.besu.ethereum.blockcreation.BlockCreator.BlockCreationResult;
|
||||
import org.hyperledger.besu.ethereum.blockcreation.txselection.TransactionSelectionResults;
|
||||
import org.hyperledger.besu.ethereum.chain.DefaultBlockchain;
|
||||
import org.hyperledger.besu.ethereum.core.Block;
|
||||
import org.hyperledger.besu.ethereum.core.BlockBody;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
|
||||
import org.hyperledger.besu.ethereum.core.BlockImporter;
|
||||
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
|
||||
import org.hyperledger.besu.ethereum.core.Util;
|
||||
import org.hyperledger.besu.ethereum.mainnet.DefaultProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecAdapters;
|
||||
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData;
|
||||
import org.hyperledger.besu.evm.internal.EvmConfiguration;
|
||||
import org.hyperledger.besu.util.Subscribers;
|
||||
|
||||
import java.math.BigInteger;
|
||||
@@ -75,6 +83,7 @@ import java.time.Clock;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
@@ -101,8 +110,8 @@ public class IbftBlockHeightManagerTest {
|
||||
@Mock private Clock clock;
|
||||
@Mock private MessageValidatorFactory messageValidatorFactory;
|
||||
@Mock private BftBlockCreator blockCreator;
|
||||
@Mock private BlockImporter blockImporter;
|
||||
@Mock private BlockTimer blockTimer;
|
||||
@Mock private DefaultBlockchain blockchain;
|
||||
@Mock private RoundTimer roundTimer;
|
||||
@Mock private FutureRoundProposalMessageValidator futureRoundProposalMessageValidator;
|
||||
@Mock private ValidatorMulticaster validatorMulticaster;
|
||||
@@ -158,7 +167,21 @@ public class IbftBlockHeightManagerTest {
|
||||
.thenReturn(messageValidator);
|
||||
|
||||
protocolContext =
|
||||
new ProtocolContext(null, null, setupContextWithValidators(validators), Optional.empty());
|
||||
new ProtocolContext(
|
||||
blockchain, null, setupContextWithValidators(validators), Optional.empty());
|
||||
|
||||
final ProtocolScheduleBuilder protocolScheduleBuilder =
|
||||
new ProtocolScheduleBuilder(
|
||||
new StubGenesisConfigOptions(),
|
||||
BigInteger.ONE,
|
||||
ProtocolSpecAdapters.create(0, Function.identity()),
|
||||
new PrivacyParameters(),
|
||||
false,
|
||||
EvmConfiguration.DEFAULT);
|
||||
|
||||
ProtocolSchedule protocolSchedule =
|
||||
new BftProtocolSchedule(
|
||||
(DefaultProtocolSchedule) protocolScheduleBuilder.createProtocolSchedule());
|
||||
|
||||
// Ensure the created IbftRound has the valid ConsensusRoundIdentifier;
|
||||
when(roundFactory.createNewRound(any(), anyInt()))
|
||||
@@ -171,7 +194,7 @@ public class IbftBlockHeightManagerTest {
|
||||
createdRoundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
Subscribers.create(),
|
||||
nodeKey,
|
||||
messageFactory,
|
||||
@@ -189,7 +212,7 @@ public class IbftBlockHeightManagerTest {
|
||||
providedRoundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
Subscribers.create(),
|
||||
nodeKey,
|
||||
messageFactory,
|
||||
|
||||
@@ -32,6 +32,7 @@ import static org.mockito.Mockito.when;
|
||||
import org.hyperledger.besu.consensus.common.bft.BftBlockHashing;
|
||||
import org.hyperledger.besu.consensus.common.bft.BftExtraData;
|
||||
import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec;
|
||||
import org.hyperledger.besu.consensus.common.bft.BftProtocolSchedule;
|
||||
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
|
||||
import org.hyperledger.besu.consensus.common.bft.RoundTimer;
|
||||
import org.hyperledger.besu.consensus.common.bft.blockcreation.BftBlockCreator;
|
||||
@@ -56,6 +57,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
|
||||
import org.hyperledger.besu.ethereum.core.BlockImporter;
|
||||
import org.hyperledger.besu.ethereum.mainnet.BlockImportResult;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
|
||||
import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleException;
|
||||
import org.hyperledger.besu.util.Subscribers;
|
||||
@@ -83,14 +85,16 @@ public class IbftRoundTest {
|
||||
private final BftExtraDataCodec bftExtraDataCodec = new IbftExtraDataCodec();
|
||||
private ProtocolContext protocolContext;
|
||||
|
||||
@Mock private BftProtocolSchedule protocolSchedule;
|
||||
@Mock private MutableBlockchain blockChain;
|
||||
@Mock private WorldStateArchive worldStateArchive;
|
||||
@Mock private BlockImporter blockImporter;
|
||||
@Mock private IbftMessageTransmitter transmitter;
|
||||
@Mock private MinedBlockObserver minedBlockObserver;
|
||||
@Mock private BftBlockCreator blockCreator;
|
||||
@Mock private MessageValidator messageValidator;
|
||||
@Mock private RoundTimer roundTimer;
|
||||
@Mock private ProtocolSpec protocolSpec;
|
||||
@Mock private BlockImporter blockImporter;
|
||||
|
||||
@Captor private ArgumentCaptor<Block> blockCaptor;
|
||||
|
||||
@@ -127,9 +131,12 @@ public class IbftRoundTest {
|
||||
.when(blockCreator.createBlock(anyLong()))
|
||||
.thenReturn(new BlockCreationResult(proposedBlock, new TransactionSelectionResults()));
|
||||
|
||||
lenient().when(protocolSpec.getBlockImporter()).thenReturn(blockImporter);
|
||||
lenient().when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec);
|
||||
|
||||
lenient()
|
||||
.when(blockImporter.importBlock(any(), any(), any()))
|
||||
.thenReturn(new BlockImportResult(true));
|
||||
.thenReturn(new BlockImportResult(BlockImportResult.BlockImportStatus.IMPORTED));
|
||||
|
||||
subscribers.subscribe(minedBlockObserver);
|
||||
}
|
||||
@@ -141,7 +148,7 @@ public class IbftRoundTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
nodeKey,
|
||||
messageFactory,
|
||||
@@ -159,7 +166,7 @@ public class IbftRoundTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
nodeKey,
|
||||
messageFactory,
|
||||
@@ -181,7 +188,7 @@ public class IbftRoundTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
nodeKey,
|
||||
messageFactory,
|
||||
@@ -204,7 +211,7 @@ public class IbftRoundTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
nodeKey,
|
||||
messageFactory,
|
||||
@@ -227,7 +234,7 @@ public class IbftRoundTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
nodeKey,
|
||||
messageFactory,
|
||||
@@ -271,7 +278,7 @@ public class IbftRoundTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
nodeKey,
|
||||
messageFactory,
|
||||
@@ -308,7 +315,7 @@ public class IbftRoundTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
nodeKey,
|
||||
messageFactory,
|
||||
@@ -332,7 +339,7 @@ public class IbftRoundTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
nodeKey,
|
||||
messageFactory,
|
||||
@@ -379,7 +386,7 @@ public class IbftRoundTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
nodeKey,
|
||||
messageFactory,
|
||||
@@ -413,7 +420,7 @@ public class IbftRoundTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
nodeKey,
|
||||
messageFactory,
|
||||
@@ -434,7 +441,7 @@ public class IbftRoundTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
nodeKey,
|
||||
messageFactory,
|
||||
@@ -460,7 +467,7 @@ public class IbftRoundTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
nodeKey,
|
||||
messageFactory,
|
||||
@@ -490,7 +497,7 @@ public class IbftRoundTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
throwingNodeKey,
|
||||
throwingMessageFactory,
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.hyperledger.besu.consensus.ibft.validation;
|
||||
import static java.util.Collections.emptyList;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.lenient;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -26,6 +27,7 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.hyperledger.besu.consensus.common.bft.BftContext;
|
||||
import org.hyperledger.besu.consensus.common.bft.BftProtocolSchedule;
|
||||
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
|
||||
import org.hyperledger.besu.consensus.common.bft.ProposedBlockHelpers;
|
||||
import org.hyperledger.besu.consensus.ibft.messagewrappers.Commit;
|
||||
@@ -42,6 +44,7 @@ import org.hyperledger.besu.ethereum.ProtocolContext;
|
||||
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
|
||||
import org.hyperledger.besu.ethereum.core.AddressHelpers;
|
||||
import org.hyperledger.besu.ethereum.core.Block;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
|
||||
|
||||
import java.util.List;
|
||||
@@ -66,6 +69,8 @@ public class MessageValidatorTest {
|
||||
private final ProposalBlockConsistencyValidator proposalBlockConsistencyValidator =
|
||||
mock(ProposalBlockConsistencyValidator.class);
|
||||
|
||||
@Mock private BftProtocolSchedule protocolSchedule;
|
||||
@Mock private ProtocolSpec protocolSpec;
|
||||
@Mock private BlockValidator blockValidator;
|
||||
private ProtocolContext protocolContext;
|
||||
private final RoundChangeCertificateValidator roundChangeCertificateValidator =
|
||||
@@ -101,6 +106,12 @@ public class MessageValidatorTest {
|
||||
mockBftCtx,
|
||||
Optional.empty());
|
||||
|
||||
lenient()
|
||||
.when(protocolSchedule.getByBlockNumberOrTimestamp(anyLong(), anyLong()))
|
||||
.thenReturn(protocolSpec);
|
||||
|
||||
when(protocolSpec.getBlockValidator()).thenReturn(blockValidator);
|
||||
when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec);
|
||||
when(blockValidator.validateAndProcessBlock(any(), any(), any(), any()))
|
||||
.thenReturn(new BlockProcessingResult(Optional.empty()));
|
||||
|
||||
@@ -115,8 +126,8 @@ public class MessageValidatorTest {
|
||||
new MessageValidator(
|
||||
signedDataValidator,
|
||||
proposalBlockConsistencyValidator,
|
||||
blockValidator,
|
||||
protocolContext,
|
||||
protocolSchedule,
|
||||
roundChangeCertificateValidator);
|
||||
}
|
||||
|
||||
|
||||
@@ -147,6 +147,7 @@ public class TestContextBuilder {
|
||||
private static final MetricsSystem metricsSystem = new NoOpMetricsSystem();
|
||||
private boolean useValidatorContract;
|
||||
private boolean useLondonMilestone = false;
|
||||
private boolean useShanghaiMilestone = false;
|
||||
private boolean useZeroBaseFee = false;
|
||||
public static final int EPOCH_LENGTH = 10_000;
|
||||
public static final int BLOCK_TIMER_SEC = 3;
|
||||
@@ -215,6 +216,11 @@ public class TestContextBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public TestContextBuilder useShanghaiMilestone(final boolean useShanghaiMilestone) {
|
||||
this.useShanghaiMilestone = useShanghaiMilestone;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TestContextBuilder useZeroBaseFee(final boolean useZeroBaseFee) {
|
||||
this.useZeroBaseFee = useZeroBaseFee;
|
||||
return this;
|
||||
@@ -285,6 +291,7 @@ public class TestContextBuilder {
|
||||
synchronizerUpdater,
|
||||
useValidatorContract,
|
||||
useLondonMilestone,
|
||||
useShanghaiMilestone,
|
||||
useZeroBaseFee,
|
||||
qbftForks);
|
||||
|
||||
@@ -365,6 +372,7 @@ public class TestContextBuilder {
|
||||
final SynchronizerUpdater synchronizerUpdater,
|
||||
final boolean useValidatorContract,
|
||||
final boolean useLondonMilestone,
|
||||
final boolean useShanghaiMilestone,
|
||||
final boolean useZeroBaseFee,
|
||||
final List<QbftFork> qbftForks) {
|
||||
|
||||
@@ -390,6 +398,8 @@ public class TestContextBuilder {
|
||||
|
||||
if (useLondonMilestone) {
|
||||
genesisConfigOptions.londonBlock(0);
|
||||
} else if (useShanghaiMilestone) {
|
||||
genesisConfigOptions.shanghaiTime(10);
|
||||
} else {
|
||||
genesisConfigOptions.berlinBlock(0);
|
||||
}
|
||||
|
||||
@@ -140,6 +140,33 @@ public class ValidatorContractTest {
|
||||
assertThat(validatorProvider.getValidatorsForBlock(block1)).containsExactly(NODE_ADDRESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retrievesValidatorsFromValidatorContract_ShanghaiFork_ZeroBaseFee() {
|
||||
// Using Shanghai on a free gas network
|
||||
final TestContext context =
|
||||
new TestContextBuilder()
|
||||
.indexOfFirstLocallyProposedBlock(0)
|
||||
.nodeParams(
|
||||
List.of(new NodeParams(NODE_ADDRESS, NodeKeyUtils.createFrom(NODE_PRIVATE_KEY))))
|
||||
.clock(TestClock.fixed())
|
||||
.genesisFile(
|
||||
Resources.getResource("genesis_validator_contract_shanghai.json").getFile())
|
||||
.useValidatorContract(true)
|
||||
.useShanghaiMilestone(true)
|
||||
.useZeroBaseFee(true)
|
||||
.buildAndStart();
|
||||
|
||||
createNewBlockAsProposerFixedTime(
|
||||
context, 1,
|
||||
266L); // 10s ahead of genesis timestamp in genesis_validator_contract_shanghai.json
|
||||
|
||||
final ValidatorProvider validatorProvider = context.getValidatorProvider();
|
||||
final BlockHeader genesisBlock = context.getBlockchain().getBlockHeader(0).get();
|
||||
final BlockHeader block1 = context.getBlockchain().getBlockHeader(1).get();
|
||||
assertThat(validatorProvider.getValidatorsForBlock(genesisBlock)).containsExactly(NODE_ADDRESS);
|
||||
assertThat(validatorProvider.getValidatorsForBlock(block1)).containsExactly(NODE_ADDRESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void transitionsFromBlockHeaderModeToValidatorContractMode() {
|
||||
final List<QbftFork> qbftForks =
|
||||
@@ -397,6 +424,24 @@ public class ValidatorContractTest {
|
||||
.handleNewBlockEvent(new NewChainHead(context.getBlockchain().getChainHeadHeader()));
|
||||
}
|
||||
|
||||
private void createNewBlockAsProposerFixedTime(
|
||||
final TestContext context, final long blockNumber, final long timestamp) {
|
||||
ConsensusRoundIdentifier roundId = new ConsensusRoundIdentifier(blockNumber, 0);
|
||||
|
||||
// trigger proposal
|
||||
context.getController().handleBlockTimerExpiry(new BlockTimerExpiry(roundId));
|
||||
|
||||
// peers commit proposed block
|
||||
Block proposedBlock = context.createBlockForProposalFromChainHead(timestamp);
|
||||
RoundSpecificPeers peers = context.roundSpecificPeers(roundId);
|
||||
peers.commitForNonProposing(roundId, proposedBlock);
|
||||
|
||||
assertThat(context.getCurrentChainHeight()).isEqualTo(blockNumber);
|
||||
context
|
||||
.getController()
|
||||
.handleNewBlockEvent(new NewChainHead(context.getBlockchain().getChainHeadHeader()));
|
||||
}
|
||||
|
||||
private void remotePeerProposesNewBlock(final TestContext context, final long blockNumber) {
|
||||
ConsensusRoundIdentifier roundId = new ConsensusRoundIdentifier(blockNumber, 0);
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import org.hyperledger.besu.consensus.common.bft.BftExtraData;
|
||||
import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec;
|
||||
import org.hyperledger.besu.consensus.common.bft.BftProtocolSchedule;
|
||||
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
|
||||
import org.hyperledger.besu.consensus.common.bft.RoundTimer;
|
||||
import org.hyperledger.besu.consensus.common.bft.blockcreation.BftBlockCreator;
|
||||
@@ -50,6 +51,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
|
||||
import org.hyperledger.besu.ethereum.core.BlockImporter;
|
||||
import org.hyperledger.besu.ethereum.mainnet.BlockImportResult;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
|
||||
import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleException;
|
||||
import org.hyperledger.besu.util.Subscribers;
|
||||
@@ -77,6 +79,8 @@ public class QbftRoundIntegrationTest {
|
||||
private final BftExtraDataCodec bftExtraDataCodec = new QbftExtraDataCodec();
|
||||
private ProtocolContext protocolContext;
|
||||
|
||||
@Mock private BftProtocolSchedule protocolSchedule;
|
||||
@Mock private ProtocolSpec protocolSpec;
|
||||
@Mock private MutableBlockchain blockChain;
|
||||
@Mock private WorldStateArchive worldStateArchive;
|
||||
@Mock private BlockImporter blockImporter;
|
||||
@@ -115,6 +119,9 @@ public class QbftRoundIntegrationTest {
|
||||
final BlockHeader header = headerTestFixture.buildHeader();
|
||||
proposedBlock = new Block(header, new BlockBody(emptyList(), emptyList()));
|
||||
|
||||
when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec);
|
||||
when(protocolSpec.getBlockImporter()).thenReturn(blockImporter);
|
||||
|
||||
when(blockImporter.importBlock(any(), any(), any())).thenReturn(new BlockImportResult(true));
|
||||
|
||||
protocolContext =
|
||||
@@ -135,7 +142,7 @@ public class QbftRoundIntegrationTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
nodeKey,
|
||||
throwingMessageFactory,
|
||||
@@ -163,7 +170,7 @@ public class QbftRoundIntegrationTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
nodeKey,
|
||||
throwingMessageFactory,
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"nonce": "0x0",
|
||||
"timestamp": "0x100",
|
||||
"extraData": "0xe5a00000000000000000000000000000000000000000000000000000000000000000c0c080c0",
|
||||
"gasLimit": "0x29b92700",
|
||||
"difficulty": "0x1",
|
||||
"mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365",
|
||||
"coinbase": "0x0000000000000000000000000000000000000000",
|
||||
"alloc": {
|
||||
"64d9be4177f418bcf4e56adad85f33e3a64efe22": {
|
||||
"balance": "0x446c3b15f9926687d2c40534fdb564000000000000"
|
||||
},
|
||||
"9f66f8a0f0a6537e4a36aa1799673ea7ae97a166": {
|
||||
"balance": "0x446c3b15f9926687d2c40534fdb564000000000000"
|
||||
},
|
||||
"a7f25969fb6f3d5ac09a88862c90b5ff664557a7": {
|
||||
"balance": "0x446c3b15f9926687d2c40534fdb564000000000000"
|
||||
},
|
||||
"f4bbfd32c11c9d63e9b4c77bb225810f840342df": {
|
||||
"balance": "0x446c3b15f9926687d2c40534fdb564000000000000"
|
||||
},
|
||||
"0x0000000000000000000000000000000000008888": {
|
||||
"comment": "validator smart contract. This is compiled from validator_contract.sol using solc --evm-version shanghai --bin-runtime validator_contract.sol",
|
||||
"balance": "0",
|
||||
"code": "608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063b7ab4db51461002d575b5f80fd5b61003561004b565b60405161004291906101bc565b60405180910390f35b60605f8054806020026020016040519081016040528092919081815260200182805480156100cb57602002820191905f5260205f20905b815f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610082575b5050505050905090565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610127826100fe565b9050919050565b6101378161011d565b82525050565b5f610148838361012e565b60208301905092915050565b5f602082019050919050565b5f61016a826100d5565b61017481856100df565b935061017f836100ef565b805f5b838110156101af578151610196888261013d565b97506101a183610154565b925050600181019050610182565b5085935050505092915050565b5f6020820190508181035f8301526101d48184610160565b90509291505056fea2646970667358221220b52fc648d3af2856c13132ebd193317528087a330aea868fcf843abcf9d9dc6d64736f6c63430008140033",
|
||||
"storage": {
|
||||
"0000000000000000000000000000000000000000000000000000000000000000": "0000000000000000000000000000000000000000000000000000000000000001",
|
||||
"290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563": "000000000000000000000000eac51e3fe1afc9894f0dfeab8ceb471899b932df"
|
||||
}
|
||||
},
|
||||
"0x0000000000000000000000000000000000009999": {
|
||||
"comment": "validator smart contract. This is compiled from validator_contract.sol using solc --evm-version shanghai --bin-runtime validator_contract.sol",
|
||||
"balance": "0",
|
||||
"code": "608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063b7ab4db51461002d575b5f80fd5b61003561004b565b60405161004291906101bc565b60405180910390f35b60605f8054806020026020016040519081016040528092919081815260200182805480156100cb57602002820191905f5260205f20905b815f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610082575b5050505050905090565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610127826100fe565b9050919050565b6101378161011d565b82525050565b5f610148838361012e565b60208301905092915050565b5f602082019050919050565b5f61016a826100d5565b61017481856100df565b935061017f836100ef565b805f5b838110156101af578151610196888261013d565b97506101a183610154565b925050600181019050610182565b5085935050505092915050565b5f6020820190508181035f8301526101d48184610160565b90509291505056fea2646970667358221220b52fc648d3af2856c13132ebd193317528087a330aea868fcf843abcf9d9dc6d64736f6c63430008140033",
|
||||
"storage": {
|
||||
"0000000000000000000000000000000000000000000000000000000000000000": "0000000000000000000000000000000000000000000000000000000000000002",
|
||||
"290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563": "000000000000000000000000e98d92560fac3069ccff53ef348ded26a51d4b68",
|
||||
"290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e564": "000000000000000000000000eac51e3fe1afc9894f0dfeab8ceb471899b932df"
|
||||
}
|
||||
}
|
||||
},
|
||||
"number": "0x0",
|
||||
"gasUsed": "0x0",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"baseFeePerGas": "0x7"
|
||||
}
|
||||
@@ -44,6 +44,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.BlockImporter;
|
||||
import org.hyperledger.besu.ethereum.mainnet.BlockImportResult;
|
||||
import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleException;
|
||||
import org.hyperledger.besu.util.Subscribers;
|
||||
|
||||
@@ -65,8 +66,9 @@ public class QbftRound {
|
||||
protected final BlockCreator blockCreator;
|
||||
/** The Protocol context. */
|
||||
protected final ProtocolContext protocolContext;
|
||||
/** The Protocol schedule. */
|
||||
protected final ProtocolSchedule protocolSchedule;
|
||||
|
||||
private final BlockImporter blockImporter;
|
||||
private final NodeKey nodeKey;
|
||||
private final MessageFactory messageFactory; // used only to create stored local msgs
|
||||
private final QbftMessageTransmitter transmitter;
|
||||
@@ -79,7 +81,7 @@ public class QbftRound {
|
||||
* @param roundState the round state
|
||||
* @param blockCreator the block creator
|
||||
* @param protocolContext the protocol context
|
||||
* @param blockImporter the block importer
|
||||
* @param protocolSchedule the protocol schedule
|
||||
* @param observers the observers
|
||||
* @param nodeKey the node key
|
||||
* @param messageFactory the message factory
|
||||
@@ -91,7 +93,7 @@ public class QbftRound {
|
||||
final RoundState roundState,
|
||||
final BlockCreator blockCreator,
|
||||
final ProtocolContext protocolContext,
|
||||
final BlockImporter blockImporter,
|
||||
final ProtocolSchedule protocolSchedule,
|
||||
final Subscribers<MinedBlockObserver> observers,
|
||||
final NodeKey nodeKey,
|
||||
final MessageFactory messageFactory,
|
||||
@@ -101,7 +103,7 @@ public class QbftRound {
|
||||
this.roundState = roundState;
|
||||
this.blockCreator = blockCreator;
|
||||
this.protocolContext = protocolContext;
|
||||
this.blockImporter = blockImporter;
|
||||
this.protocolSchedule = protocolSchedule;
|
||||
this.observers = observers;
|
||||
this.nodeKey = nodeKey;
|
||||
this.messageFactory = messageFactory;
|
||||
@@ -341,7 +343,10 @@ public class QbftRound {
|
||||
getRoundIdentifier(),
|
||||
blockToImport.getHash());
|
||||
}
|
||||
|
||||
LOG.trace("Importing proposed block with extraData={}", extraData);
|
||||
final BlockImporter blockImporter =
|
||||
protocolSchedule.getByBlockHeader(blockToImport.getHeader()).getBlockImporter();
|
||||
final BlockImportResult result =
|
||||
blockImporter.importBlock(protocolContext, blockToImport, HeaderValidationMode.FULL);
|
||||
if (!result.isImported()) {
|
||||
|
||||
@@ -99,7 +99,6 @@ public class QbftRoundFactory {
|
||||
*/
|
||||
public QbftRound createNewRoundWithState(
|
||||
final BlockHeader parentHeader, final RoundState roundState) {
|
||||
final ConsensusRoundIdentifier roundIdentifier = roundState.getRoundIdentifier();
|
||||
final BlockCreator blockCreator = blockCreatorFactory.create(parentHeader, 0);
|
||||
|
||||
// TODO(tmm): Why is this created everytime?!
|
||||
@@ -110,7 +109,7 @@ public class QbftRoundFactory {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
protocolSchedule.getByBlockNumber(roundIdentifier.getSequenceNumber()).getBlockImporter(),
|
||||
protocolSchedule,
|
||||
minedBlockObservers,
|
||||
finalState.getNodeKey(),
|
||||
messageFactory,
|
||||
|
||||
@@ -23,7 +23,6 @@ import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
|
||||
import org.hyperledger.besu.consensus.common.bft.blockcreation.ProposerSelector;
|
||||
import org.hyperledger.besu.consensus.qbft.validation.MessageValidator.SubsequentMessageValidator;
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.ethereum.BlockValidator;
|
||||
import org.hyperledger.besu.ethereum.ProtocolContext;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
|
||||
@@ -78,16 +77,13 @@ public class MessageValidatorFactory {
|
||||
final RoundChangePayloadValidator roundChangePayloadValidator =
|
||||
new RoundChangePayloadValidator(validatorsForHeight, chainHeight);
|
||||
|
||||
final BlockValidator blockValidator =
|
||||
protocolSchedule.getByBlockNumber(chainHeight).getBlockValidator();
|
||||
|
||||
return new RoundChangeMessageValidator(
|
||||
roundChangePayloadValidator,
|
||||
BftHelpers.calculateRequiredValidatorQuorum(validatorsForHeight.size()),
|
||||
chainHeight,
|
||||
validatorsForHeight,
|
||||
blockValidator,
|
||||
protocolContext);
|
||||
protocolContext,
|
||||
protocolSchedule);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,13 +97,11 @@ public class MessageValidatorFactory {
|
||||
final ConsensusRoundIdentifier roundIdentifier, final BlockHeader parentHeader) {
|
||||
|
||||
final Collection<Address> validatorsForHeight = getValidatorsAfterBlock(parentHeader);
|
||||
final BlockValidator blockValidator =
|
||||
protocolSchedule.getByBlockNumber(roundIdentifier.getSequenceNumber()).getBlockValidator();
|
||||
|
||||
final ProposalValidator proposalValidator =
|
||||
new ProposalValidator(
|
||||
blockValidator,
|
||||
protocolContext,
|
||||
protocolSchedule,
|
||||
BftHelpers.calculateRequiredValidatorQuorum(validatorsForHeight.size()),
|
||||
validatorsForHeight,
|
||||
roundIdentifier,
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
*/
|
||||
package org.hyperledger.besu.consensus.qbft.validation;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import org.hyperledger.besu.consensus.common.bft.BftBlockInterface;
|
||||
import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec;
|
||||
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
|
||||
@@ -144,6 +146,8 @@ public class ProposalPayloadValidator {
|
||||
}
|
||||
|
||||
private boolean validateBlock(final Block block) {
|
||||
checkState(blockValidator != null, "block validation not possible, no block validator.");
|
||||
|
||||
final var validationResult =
|
||||
blockValidator.validateAndProcessBlock(
|
||||
protocolContext, block, HeaderValidationMode.LIGHT, HeaderValidationMode.FULL);
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.BlockValidator;
|
||||
import org.hyperledger.besu.ethereum.ProtocolContext;
|
||||
import org.hyperledger.besu.ethereum.core.Block;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
@@ -49,8 +50,8 @@ public class ProposalValidator {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ProposalValidator.class);
|
||||
private static final String ERROR_PREFIX = "Invalid Proposal Payload";
|
||||
|
||||
private final BlockValidator blockValidator;
|
||||
private final ProtocolContext protocolContext;
|
||||
private final ProtocolSchedule protocolSchedule;
|
||||
private final int quorumMessageCount;
|
||||
private final Collection<Address> validators;
|
||||
private final ConsensusRoundIdentifier roundIdentifier;
|
||||
@@ -60,8 +61,8 @@ public class ProposalValidator {
|
||||
/**
|
||||
* Instantiates a new Proposal validator.
|
||||
*
|
||||
* @param blockValidator the block validator
|
||||
* @param protocolContext the protocol context
|
||||
* @param protocolSchedule the protocol schedule
|
||||
* @param quorumMessageCount the quorum message count
|
||||
* @param validators the validators
|
||||
* @param roundIdentifier the round identifier
|
||||
@@ -69,15 +70,15 @@ public class ProposalValidator {
|
||||
* @param bftExtraDataCodec the bft extra data codec
|
||||
*/
|
||||
public ProposalValidator(
|
||||
final BlockValidator blockValidator,
|
||||
final ProtocolContext protocolContext,
|
||||
final ProtocolSchedule protocolSchedule,
|
||||
final int quorumMessageCount,
|
||||
final Collection<Address> validators,
|
||||
final ConsensusRoundIdentifier roundIdentifier,
|
||||
final Address expectedProposer,
|
||||
final BftExtraDataCodec bftExtraDataCodec) {
|
||||
this.blockValidator = blockValidator;
|
||||
this.protocolContext = protocolContext;
|
||||
this.protocolSchedule = protocolSchedule;
|
||||
this.quorumMessageCount = quorumMessageCount;
|
||||
this.validators = validators;
|
||||
this.roundIdentifier = roundIdentifier;
|
||||
@@ -92,6 +93,8 @@ public class ProposalValidator {
|
||||
* @return the boolean
|
||||
*/
|
||||
public boolean validate(final Proposal msg) {
|
||||
final BlockValidator blockValidator =
|
||||
protocolSchedule.getByBlockHeader(msg.getBlock().getHeader()).getBlockValidator();
|
||||
|
||||
final ProposalPayloadValidator payloadValidator =
|
||||
new ProposalPayloadValidator(
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.hyperledger.besu.ethereum.BlockValidator;
|
||||
import org.hyperledger.besu.ethereum.ProtocolContext;
|
||||
import org.hyperledger.besu.ethereum.core.Block;
|
||||
import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@@ -45,8 +46,8 @@ public class RoundChangeMessageValidator {
|
||||
private final long quorumMessageCount;
|
||||
private final long chainHeight;
|
||||
private final Collection<Address> validators;
|
||||
private final BlockValidator blockValidator;
|
||||
private final ProtocolContext protocolContext;
|
||||
private final ProtocolSchedule protocolSchedule;
|
||||
|
||||
/**
|
||||
* Instantiates a new Round change message validator.
|
||||
@@ -55,22 +56,22 @@ public class RoundChangeMessageValidator {
|
||||
* @param quorumMessageCount the quorum message count
|
||||
* @param chainHeight the chain height
|
||||
* @param validators the validators
|
||||
* @param blockValidator the block validator
|
||||
* @param protocolContext the protocol context
|
||||
* @param protocolSchedule the protocol context
|
||||
*/
|
||||
public RoundChangeMessageValidator(
|
||||
final RoundChangePayloadValidator roundChangePayloadValidator,
|
||||
final long quorumMessageCount,
|
||||
final long chainHeight,
|
||||
final Collection<Address> validators,
|
||||
final BlockValidator blockValidator,
|
||||
final ProtocolContext protocolContext) {
|
||||
final ProtocolContext protocolContext,
|
||||
final ProtocolSchedule protocolSchedule) {
|
||||
this.roundChangePayloadValidator = roundChangePayloadValidator;
|
||||
this.quorumMessageCount = quorumMessageCount;
|
||||
this.chainHeight = chainHeight;
|
||||
this.validators = validators;
|
||||
this.blockValidator = blockValidator;
|
||||
this.protocolContext = protocolContext;
|
||||
this.protocolSchedule = protocolSchedule;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,6 +95,10 @@ public class RoundChangeMessageValidator {
|
||||
}
|
||||
|
||||
private boolean validateBlock(final Block block) {
|
||||
|
||||
final BlockValidator blockValidator =
|
||||
protocolSchedule.getByBlockHeader(block.getHeader()).getBlockValidator();
|
||||
|
||||
final var validationResult =
|
||||
blockValidator.validateAndProcessBlock(
|
||||
protocolContext, block, HeaderValidationMode.LIGHT, HeaderValidationMode.FULL);
|
||||
|
||||
@@ -144,7 +144,7 @@ public class QbftProtocolScheduleTest {
|
||||
final BlockHeader blockHeader,
|
||||
final int block) {
|
||||
return schedule
|
||||
.getByBlockNumber(block)
|
||||
.getByBlockNumberOrTimestamp(block, blockHeader.getTimestamp())
|
||||
.getBlockHeaderValidator()
|
||||
.validateHeader(
|
||||
blockHeader, parentHeader, protocolContext(validators), HeaderValidationMode.LIGHT);
|
||||
|
||||
@@ -31,8 +31,10 @@ import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.hyperledger.besu.config.StubGenesisConfigOptions;
|
||||
import org.hyperledger.besu.consensus.common.bft.BftExtraData;
|
||||
import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec;
|
||||
import org.hyperledger.besu.consensus.common.bft.BftProtocolSchedule;
|
||||
import org.hyperledger.besu.consensus.common.bft.BlockTimer;
|
||||
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
|
||||
import org.hyperledger.besu.consensus.common.bft.RoundTimer;
|
||||
@@ -60,20 +62,26 @@ import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.ProtocolContext;
|
||||
import org.hyperledger.besu.ethereum.blockcreation.BlockCreator.BlockCreationResult;
|
||||
import org.hyperledger.besu.ethereum.blockcreation.txselection.TransactionSelectionResults;
|
||||
import org.hyperledger.besu.ethereum.chain.DefaultBlockchain;
|
||||
import org.hyperledger.besu.ethereum.core.Block;
|
||||
import org.hyperledger.besu.ethereum.core.BlockBody;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
|
||||
import org.hyperledger.besu.ethereum.core.BlockImporter;
|
||||
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
|
||||
import org.hyperledger.besu.ethereum.core.Util;
|
||||
import org.hyperledger.besu.ethereum.mainnet.BlockImportResult;
|
||||
import org.hyperledger.besu.ethereum.mainnet.DefaultProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecAdapters;
|
||||
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData;
|
||||
import org.hyperledger.besu.evm.internal.EvmConfiguration;
|
||||
import org.hyperledger.besu.util.Subscribers;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.time.Clock;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
@@ -104,9 +112,9 @@ public class QbftBlockHeightManagerTest {
|
||||
@Mock private Clock clock;
|
||||
@Mock private MessageValidatorFactory messageValidatorFactory;
|
||||
@Mock private BftBlockCreator blockCreator;
|
||||
@Mock private BlockImporter blockImporter;
|
||||
@Mock private BlockTimer blockTimer;
|
||||
@Mock private RoundTimer roundTimer;
|
||||
@Mock private DefaultBlockchain blockchain;
|
||||
@Mock private FutureRoundProposalMessageValidator futureRoundProposalMessageValidator;
|
||||
@Mock private ValidatorMulticaster validatorMulticaster;
|
||||
|
||||
@@ -153,16 +161,28 @@ public class QbftBlockHeightManagerTest {
|
||||
when(messageValidatorFactory.createFutureRoundProposalMessageValidator(anyLong(), any()))
|
||||
.thenReturn(futureRoundProposalMessageValidator);
|
||||
when(messageValidatorFactory.createMessageValidator(any(), any())).thenReturn(messageValidator);
|
||||
when(blockImporter.importBlock(any(), any(), any())).thenReturn(new BlockImportResult(false));
|
||||
|
||||
protocolContext =
|
||||
new ProtocolContext(
|
||||
null,
|
||||
blockchain,
|
||||
null,
|
||||
setupContextWithBftExtraDataEncoder(
|
||||
QbftContext.class, validators, new QbftExtraDataCodec()),
|
||||
Optional.empty());
|
||||
|
||||
final ProtocolScheduleBuilder protocolScheduleBuilder =
|
||||
new ProtocolScheduleBuilder(
|
||||
new StubGenesisConfigOptions(),
|
||||
BigInteger.ONE,
|
||||
ProtocolSpecAdapters.create(0, Function.identity()),
|
||||
new PrivacyParameters(),
|
||||
false,
|
||||
EvmConfiguration.DEFAULT);
|
||||
|
||||
ProtocolSchedule protocolSchedule =
|
||||
new BftProtocolSchedule(
|
||||
(DefaultProtocolSchedule) protocolScheduleBuilder.createProtocolSchedule());
|
||||
|
||||
// Ensure the created QbftRound has the valid ConsensusRoundIdentifier;
|
||||
when(roundFactory.createNewRound(any(), anyInt()))
|
||||
.thenAnswer(
|
||||
@@ -174,7 +194,7 @@ public class QbftBlockHeightManagerTest {
|
||||
createdRoundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
Subscribers.create(),
|
||||
nodeKey,
|
||||
messageFactory,
|
||||
@@ -191,7 +211,7 @@ public class QbftBlockHeightManagerTest {
|
||||
providedRoundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
Subscribers.create(),
|
||||
nodeKey,
|
||||
messageFactory,
|
||||
|
||||
@@ -32,6 +32,7 @@ import static org.mockito.Mockito.when;
|
||||
import org.hyperledger.besu.consensus.common.bft.BftBlockHashing;
|
||||
import org.hyperledger.besu.consensus.common.bft.BftExtraData;
|
||||
import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec;
|
||||
import org.hyperledger.besu.consensus.common.bft.BftProtocolSchedule;
|
||||
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
|
||||
import org.hyperledger.besu.consensus.common.bft.RoundTimer;
|
||||
import org.hyperledger.besu.consensus.common.bft.blockcreation.BftBlockCreator;
|
||||
@@ -59,6 +60,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
|
||||
import org.hyperledger.besu.ethereum.core.BlockImporter;
|
||||
import org.hyperledger.besu.ethereum.mainnet.BlockImportResult;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
|
||||
import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleException;
|
||||
import org.hyperledger.besu.util.Subscribers;
|
||||
@@ -92,14 +94,16 @@ public class QbftRoundTest {
|
||||
private final BftExtraDataCodec bftExtraDataCodec = new QbftExtraDataCodec();
|
||||
private ProtocolContext protocolContext;
|
||||
|
||||
@Mock private BftProtocolSchedule protocolSchedule;
|
||||
@Mock private MutableBlockchain blockChain;
|
||||
@Mock private WorldStateArchive worldStateArchive;
|
||||
@Mock private BlockImporter blockImporter;
|
||||
@Mock private QbftMessageTransmitter transmitter;
|
||||
@Mock private MinedBlockObserver minedBlockObserver;
|
||||
@Mock private BftBlockCreator blockCreator;
|
||||
@Mock private MessageValidator messageValidator;
|
||||
@Mock private RoundTimer roundTimer;
|
||||
@Mock private ProtocolSpec protocolSpec;
|
||||
@Mock private BlockImporter blockImporter;
|
||||
|
||||
@Captor private ArgumentCaptor<Block> blockCaptor;
|
||||
|
||||
@@ -136,7 +140,11 @@ public class QbftRoundTest {
|
||||
when(blockCreator.createBlock(anyLong()))
|
||||
.thenReturn(new BlockCreationResult(proposedBlock, new TransactionSelectionResults()));
|
||||
|
||||
when(blockImporter.importBlock(any(), any(), any())).thenReturn(new BlockImportResult(true));
|
||||
when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec);
|
||||
when(protocolSpec.getBlockImporter()).thenReturn(blockImporter);
|
||||
|
||||
when(blockImporter.importBlock(any(), any(), any()))
|
||||
.thenReturn(new BlockImportResult(BlockImportResult.BlockImportStatus.IMPORTED));
|
||||
|
||||
subscribers.subscribe(minedBlockObserver);
|
||||
}
|
||||
@@ -148,7 +156,7 @@ public class QbftRoundTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
nodeKey,
|
||||
messageFactory,
|
||||
@@ -166,7 +174,7 @@ public class QbftRoundTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
nodeKey,
|
||||
messageFactory,
|
||||
@@ -189,7 +197,7 @@ public class QbftRoundTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
nodeKey,
|
||||
messageFactory,
|
||||
@@ -213,7 +221,7 @@ public class QbftRoundTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
nodeKey,
|
||||
messageFactory,
|
||||
@@ -226,7 +234,6 @@ public class QbftRoundTest {
|
||||
roundIdentifier, proposedBlock, Collections.emptyList(), Collections.emptyList());
|
||||
verify(transmitter, times(1)).multicastPrepare(roundIdentifier, proposedBlock.getHash());
|
||||
verify(transmitter, times(1)).multicastCommit(any(), any(), any());
|
||||
verify(blockImporter, times(1)).importBlock(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -237,7 +244,7 @@ public class QbftRoundTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
nodeKey,
|
||||
messageFactory,
|
||||
@@ -252,18 +259,15 @@ public class QbftRoundTest {
|
||||
|
||||
round.createAndSendProposalMessage(15);
|
||||
verify(transmitter, never()).multicastCommit(any(), any(), any());
|
||||
verify(blockImporter, never()).importBlock(any(), any(), any());
|
||||
|
||||
round.handlePrepareMessage(
|
||||
messageFactory2.createPrepare(roundIdentifier, proposedBlock.getHash()));
|
||||
|
||||
verify(transmitter, times(1))
|
||||
.multicastCommit(roundIdentifier, proposedBlock.getHash(), localCommitSeal);
|
||||
verify(blockImporter, never()).importBlock(any(), any(), any());
|
||||
|
||||
round.handleCommitMessage(
|
||||
messageFactory.createCommit(roundIdentifier, proposedBlock.getHash(), remoteCommitSeal));
|
||||
verify(blockImporter, times(1)).importBlock(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -274,7 +278,7 @@ public class QbftRoundTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
nodeKey,
|
||||
messageFactory,
|
||||
@@ -297,7 +301,7 @@ public class QbftRoundTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
nodeKey,
|
||||
messageFactory,
|
||||
@@ -345,7 +349,7 @@ public class QbftRoundTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
nodeKey,
|
||||
messageFactory,
|
||||
@@ -384,7 +388,7 @@ public class QbftRoundTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
nodeKey,
|
||||
messageFactory,
|
||||
@@ -405,7 +409,7 @@ public class QbftRoundTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
nodeKey,
|
||||
messageFactory,
|
||||
@@ -419,8 +423,6 @@ public class QbftRoundTest {
|
||||
round.handleProposalMessage(
|
||||
messageFactory.createProposal(
|
||||
roundIdentifier, proposedBlock, Collections.emptyList(), Collections.emptyList()));
|
||||
|
||||
verify(blockImporter, times(1)).importBlock(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -432,7 +434,7 @@ public class QbftRoundTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
nodeKey,
|
||||
messageFactory,
|
||||
@@ -446,8 +448,6 @@ public class QbftRoundTest {
|
||||
round.handleProposalMessage(
|
||||
messageFactory.createProposal(
|
||||
roundIdentifier, proposedBlock, Collections.emptyList(), Collections.emptyList()));
|
||||
|
||||
verify(blockImporter, times(1)).importBlock(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -463,7 +463,7 @@ public class QbftRoundTest {
|
||||
roundState,
|
||||
blockCreator,
|
||||
protocolContext,
|
||||
blockImporter,
|
||||
protocolSchedule,
|
||||
subscribers,
|
||||
throwingNodeKey,
|
||||
throwingMessageFactory,
|
||||
|
||||
@@ -25,6 +25,7 @@ import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.hyperledger.besu.consensus.common.bft.BftHelpers;
|
||||
import org.hyperledger.besu.consensus.common.bft.BftProtocolSchedule;
|
||||
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundHelpers;
|
||||
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
|
||||
import org.hyperledger.besu.consensus.common.bft.ProposedBlockHelpers;
|
||||
@@ -44,6 +45,7 @@ import org.hyperledger.besu.ethereum.ProtocolContext;
|
||||
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
|
||||
import org.hyperledger.besu.ethereum.core.Block;
|
||||
import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -86,6 +88,8 @@ public class ProposalValidatorTest {
|
||||
@Mock private BlockValidator blockValidator;
|
||||
@Mock private MutableBlockchain blockChain;
|
||||
@Mock private WorldStateArchive worldStateArchive;
|
||||
@Mock private BftProtocolSchedule protocolSchedule;
|
||||
@Mock private ProtocolSpec protocolSpec;
|
||||
private ProtocolContext protocolContext;
|
||||
|
||||
private final Map<ROUND_ID, RoundSpecificItems> roundItems = new HashMap<>();
|
||||
@@ -109,6 +113,10 @@ public class ProposalValidatorTest {
|
||||
eq(HeaderValidationMode.FULL)))
|
||||
.thenReturn(new BlockProcessingResult(Optional.empty()));
|
||||
|
||||
when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec);
|
||||
|
||||
when(protocolSpec.getBlockValidator()).thenReturn(blockValidator);
|
||||
|
||||
roundItems.put(ROUND_ID.ZERO, createRoundSpecificItems(0));
|
||||
roundItems.put(ROUND_ID.ONE, createRoundSpecificItems(1));
|
||||
}
|
||||
@@ -121,8 +129,8 @@ public class ProposalValidatorTest {
|
||||
validators.getNodeAddresses(), roundIdentifier, bftExtraDataEncoder),
|
||||
roundIdentifier,
|
||||
new ProposalValidator(
|
||||
blockValidator,
|
||||
protocolContext,
|
||||
protocolSchedule,
|
||||
BftHelpers.calculateRequiredValidatorQuorum(VALIDATOR_COUNT),
|
||||
validators.getNodeAddresses(),
|
||||
roundIdentifier,
|
||||
|
||||
@@ -20,11 +20,12 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hyperledger.besu.consensus.common.bft.BftContextBuilder.setupContextWithBftExtraDataEncoder;
|
||||
import static org.hyperledger.besu.consensus.qbft.validation.ValidationTestHelpers.createPreparePayloads;
|
||||
import static org.hyperledger.besu.consensus.qbft.validation.ValidationTestHelpers.createPreparedCertificate;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.lenient;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.hyperledger.besu.consensus.common.bft.BftHelpers;
|
||||
import org.hyperledger.besu.consensus.common.bft.BftProtocolSchedule;
|
||||
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundHelpers;
|
||||
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
|
||||
import org.hyperledger.besu.consensus.common.bft.ProposedBlockHelpers;
|
||||
@@ -42,7 +43,7 @@ import org.hyperledger.besu.ethereum.BlockValidator;
|
||||
import org.hyperledger.besu.ethereum.ProtocolContext;
|
||||
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
|
||||
import org.hyperledger.besu.ethereum.core.Block;
|
||||
import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -59,9 +60,11 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
||||
public class RoundChangeMessageValidatorTest {
|
||||
|
||||
@Mock private RoundChangePayloadValidator payloadValidator;
|
||||
@Mock private BlockValidator blockValidator;
|
||||
@Mock private MutableBlockchain blockChain;
|
||||
@Mock private WorldStateArchive worldStateArchive;
|
||||
@Mock private BftProtocolSchedule protocolSchedule;
|
||||
@Mock private BlockValidator blockValidator;
|
||||
@Mock private ProtocolSpec protocolSpec;
|
||||
private ProtocolContext protocolContext;
|
||||
|
||||
private RoundChangeMessageValidator messageValidator;
|
||||
@@ -83,6 +86,10 @@ public class RoundChangeMessageValidatorTest {
|
||||
setupContextWithBftExtraDataEncoder(
|
||||
QbftContext.class, emptyList(), bftExtraDataEncoder),
|
||||
Optional.empty());
|
||||
|
||||
lenient().when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec);
|
||||
|
||||
lenient().when(protocolSpec.getBlockValidator()).thenReturn(blockValidator);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -94,8 +101,8 @@ public class RoundChangeMessageValidatorTest {
|
||||
BftHelpers.calculateRequiredValidatorQuorum(VALIDATOR_COUNT),
|
||||
CHAIN_HEIGHT,
|
||||
validators.getNodeAddresses(),
|
||||
blockValidator,
|
||||
protocolContext);
|
||||
protocolContext,
|
||||
protocolSchedule);
|
||||
|
||||
for (int i = 0; i < VALIDATOR_COUNT; i++) {
|
||||
final RoundChange message =
|
||||
@@ -106,18 +113,17 @@ public class RoundChangeMessageValidatorTest {
|
||||
|
||||
@Test
|
||||
public void roundChangeWithValidPiggyBackDataIsValid() {
|
||||
when(blockValidator.validateAndProcessBlock(
|
||||
any(), any(), eq(HeaderValidationMode.LIGHT), eq(HeaderValidationMode.FULL)))
|
||||
.thenReturn(new BlockProcessingResult(Optional.empty()));
|
||||
when(payloadValidator.validate(any())).thenReturn(true);
|
||||
when(blockValidator.validateAndProcessBlock(any(), any(), any(), any()))
|
||||
.thenReturn(new BlockProcessingResult(Optional.empty()));
|
||||
messageValidator =
|
||||
new RoundChangeMessageValidator(
|
||||
payloadValidator,
|
||||
BftHelpers.calculateRequiredValidatorQuorum(VALIDATOR_COUNT),
|
||||
CHAIN_HEIGHT,
|
||||
validators.getNodeAddresses(),
|
||||
blockValidator,
|
||||
protocolContext);
|
||||
protocolContext,
|
||||
protocolSchedule);
|
||||
|
||||
final Block block =
|
||||
ProposedBlockHelpers.createProposalBlock(
|
||||
@@ -133,18 +139,17 @@ public class RoundChangeMessageValidatorTest {
|
||||
|
||||
@Test
|
||||
public void roundChangeWithBlockRoundMismatchingPreparesIsValid() {
|
||||
when(blockValidator.validateAndProcessBlock(
|
||||
any(), any(), eq(HeaderValidationMode.LIGHT), eq(HeaderValidationMode.FULL)))
|
||||
.thenReturn(new BlockProcessingResult(Optional.empty()));
|
||||
when(payloadValidator.validate(any())).thenReturn(true);
|
||||
when(blockValidator.validateAndProcessBlock(any(), any(), any(), any()))
|
||||
.thenReturn(new BlockProcessingResult(Optional.empty()));
|
||||
messageValidator =
|
||||
new RoundChangeMessageValidator(
|
||||
payloadValidator,
|
||||
BftHelpers.calculateRequiredValidatorQuorum(VALIDATOR_COUNT),
|
||||
CHAIN_HEIGHT,
|
||||
validators.getNodeAddresses(),
|
||||
blockValidator,
|
||||
protocolContext);
|
||||
protocolContext,
|
||||
protocolSchedule);
|
||||
|
||||
final Block block =
|
||||
ProposedBlockHelpers.createProposalBlock(
|
||||
@@ -162,18 +167,17 @@ public class RoundChangeMessageValidatorTest {
|
||||
|
||||
@Test
|
||||
public void blockIsInvalidFailsValidation() {
|
||||
when(blockValidator.validateAndProcessBlock(
|
||||
any(), any(), eq(HeaderValidationMode.LIGHT), eq(HeaderValidationMode.FULL)))
|
||||
.thenReturn(new BlockProcessingResult("Failed"));
|
||||
when(payloadValidator.validate(any())).thenReturn(true);
|
||||
when(blockValidator.validateAndProcessBlock(any(), any(), any(), any()))
|
||||
.thenReturn(BlockProcessingResult.FAILED);
|
||||
messageValidator =
|
||||
new RoundChangeMessageValidator(
|
||||
payloadValidator,
|
||||
BftHelpers.calculateRequiredValidatorQuorum(VALIDATOR_COUNT),
|
||||
CHAIN_HEIGHT,
|
||||
validators.getNodeAddresses(),
|
||||
blockValidator,
|
||||
protocolContext);
|
||||
protocolContext,
|
||||
protocolSchedule);
|
||||
|
||||
final Block block =
|
||||
ProposedBlockHelpers.createProposalBlock(Collections.emptyList(), roundIdentifier);
|
||||
@@ -195,8 +199,8 @@ public class RoundChangeMessageValidatorTest {
|
||||
BftHelpers.calculateRequiredValidatorQuorum(VALIDATOR_COUNT),
|
||||
CHAIN_HEIGHT,
|
||||
validators.getNodeAddresses(),
|
||||
blockValidator,
|
||||
protocolContext);
|
||||
protocolContext,
|
||||
protocolSchedule);
|
||||
|
||||
final RoundChange message =
|
||||
validators.getMessageFactory(0).createRoundChange(targetRound, Optional.empty());
|
||||
@@ -205,18 +209,17 @@ public class RoundChangeMessageValidatorTest {
|
||||
|
||||
@Test
|
||||
public void insufficientPiggyBackedPrepareMessagesIsInvalid() {
|
||||
when(blockValidator.validateAndProcessBlock(
|
||||
any(), any(), eq(HeaderValidationMode.LIGHT), eq(HeaderValidationMode.FULL)))
|
||||
.thenReturn(new BlockProcessingResult(Optional.empty()));
|
||||
when(payloadValidator.validate(any())).thenReturn(true);
|
||||
when(blockValidator.validateAndProcessBlock(any(), any(), any(), any()))
|
||||
.thenReturn(new BlockProcessingResult(Optional.empty()));
|
||||
messageValidator =
|
||||
new RoundChangeMessageValidator(
|
||||
payloadValidator,
|
||||
BftHelpers.calculateRequiredValidatorQuorum(VALIDATOR_COUNT),
|
||||
CHAIN_HEIGHT,
|
||||
validators.getNodeAddresses(),
|
||||
blockValidator,
|
||||
protocolContext);
|
||||
protocolContext,
|
||||
protocolSchedule);
|
||||
|
||||
final Block block =
|
||||
ProposedBlockHelpers.createProposalBlock(
|
||||
@@ -232,18 +235,17 @@ public class RoundChangeMessageValidatorTest {
|
||||
|
||||
@Test
|
||||
public void prepareFromNonValidatorFails() {
|
||||
when(blockValidator.validateAndProcessBlock(
|
||||
any(), any(), eq(HeaderValidationMode.LIGHT), eq(HeaderValidationMode.FULL)))
|
||||
.thenReturn(new BlockProcessingResult(Optional.empty()));
|
||||
when(payloadValidator.validate(any())).thenReturn(true);
|
||||
when(blockValidator.validateAndProcessBlock(any(), any(), any(), any()))
|
||||
.thenReturn(new BlockProcessingResult(Optional.empty()));
|
||||
messageValidator =
|
||||
new RoundChangeMessageValidator(
|
||||
payloadValidator,
|
||||
BftHelpers.calculateRequiredValidatorQuorum(VALIDATOR_COUNT),
|
||||
CHAIN_HEIGHT,
|
||||
validators.getNodeAddresses(),
|
||||
blockValidator,
|
||||
protocolContext);
|
||||
protocolContext,
|
||||
protocolSchedule);
|
||||
|
||||
final QbftNode nonValidator = QbftNode.create();
|
||||
|
||||
@@ -261,18 +263,17 @@ public class RoundChangeMessageValidatorTest {
|
||||
|
||||
@Test
|
||||
public void validationFailsIfPreparedMetadataContainsDifferentRoundToBlock() {
|
||||
when(blockValidator.validateAndProcessBlock(
|
||||
any(), any(), eq(HeaderValidationMode.LIGHT), eq(HeaderValidationMode.FULL)))
|
||||
.thenReturn(new BlockProcessingResult(Optional.empty()));
|
||||
when(payloadValidator.validate(any())).thenReturn(true);
|
||||
when(blockValidator.validateAndProcessBlock(any(), any(), any(), any()))
|
||||
.thenReturn(new BlockProcessingResult(Optional.empty()));
|
||||
messageValidator =
|
||||
new RoundChangeMessageValidator(
|
||||
payloadValidator,
|
||||
BftHelpers.calculateRequiredValidatorQuorum(VALIDATOR_COUNT),
|
||||
CHAIN_HEIGHT,
|
||||
validators.getNodeAddresses(),
|
||||
blockValidator,
|
||||
protocolContext);
|
||||
protocolContext,
|
||||
protocolSchedule);
|
||||
|
||||
final Block block =
|
||||
ProposedBlockHelpers.createProposalBlock(
|
||||
@@ -296,18 +297,17 @@ public class RoundChangeMessageValidatorTest {
|
||||
|
||||
@Test
|
||||
public void validationFailsIfPreparesContainsDifferentRoundToBlock() {
|
||||
when(blockValidator.validateAndProcessBlock(
|
||||
any(), any(), eq(HeaderValidationMode.LIGHT), eq(HeaderValidationMode.FULL)))
|
||||
.thenReturn(new BlockProcessingResult(Optional.empty()));
|
||||
when(payloadValidator.validate(any())).thenReturn(true);
|
||||
when(blockValidator.validateAndProcessBlock(any(), any(), any(), any()))
|
||||
.thenReturn(new BlockProcessingResult(Optional.empty()));
|
||||
messageValidator =
|
||||
new RoundChangeMessageValidator(
|
||||
payloadValidator,
|
||||
BftHelpers.calculateRequiredValidatorQuorum(VALIDATOR_COUNT),
|
||||
CHAIN_HEIGHT,
|
||||
validators.getNodeAddresses(),
|
||||
blockValidator,
|
||||
protocolContext);
|
||||
protocolContext,
|
||||
protocolSchedule);
|
||||
|
||||
final Block block =
|
||||
ProposedBlockHelpers.createProposalBlock(
|
||||
@@ -333,18 +333,17 @@ public class RoundChangeMessageValidatorTest {
|
||||
|
||||
@Test
|
||||
public void validationFailsIfPreparesContainsWrongHeight() {
|
||||
when(blockValidator.validateAndProcessBlock(
|
||||
any(), any(), eq(HeaderValidationMode.LIGHT), eq(HeaderValidationMode.FULL)))
|
||||
.thenReturn(new BlockProcessingResult(Optional.empty()));
|
||||
when(payloadValidator.validate(any())).thenReturn(true);
|
||||
when(blockValidator.validateAndProcessBlock(any(), any(), any(), any()))
|
||||
.thenReturn(new BlockProcessingResult(Optional.empty()));
|
||||
messageValidator =
|
||||
new RoundChangeMessageValidator(
|
||||
payloadValidator,
|
||||
BftHelpers.calculateRequiredValidatorQuorum(VALIDATOR_COUNT),
|
||||
CHAIN_HEIGHT,
|
||||
validators.getNodeAddresses(),
|
||||
blockValidator,
|
||||
protocolContext);
|
||||
protocolContext,
|
||||
protocolSchedule);
|
||||
|
||||
final Block block =
|
||||
ProposedBlockHelpers.createProposalBlock(
|
||||
@@ -370,18 +369,17 @@ public class RoundChangeMessageValidatorTest {
|
||||
|
||||
@Test
|
||||
public void validationFailsIfPreparesHaveDuplicateAuthors() {
|
||||
when(blockValidator.validateAndProcessBlock(
|
||||
any(), any(), eq(HeaderValidationMode.LIGHT), eq(HeaderValidationMode.FULL)))
|
||||
.thenReturn(new BlockProcessingResult(Optional.empty()));
|
||||
when(payloadValidator.validate(any())).thenReturn(true);
|
||||
when(blockValidator.validateAndProcessBlock(any(), any(), any(), any()))
|
||||
.thenReturn(new BlockProcessingResult(Optional.empty()));
|
||||
messageValidator =
|
||||
new RoundChangeMessageValidator(
|
||||
payloadValidator,
|
||||
BftHelpers.calculateRequiredValidatorQuorum(VALIDATOR_COUNT),
|
||||
CHAIN_HEIGHT,
|
||||
validators.getNodeAddresses(),
|
||||
blockValidator,
|
||||
protocolContext);
|
||||
protocolContext,
|
||||
protocolSchedule);
|
||||
|
||||
final Block block =
|
||||
ProposedBlockHelpers.createProposalBlock(
|
||||
@@ -402,18 +400,17 @@ public class RoundChangeMessageValidatorTest {
|
||||
|
||||
@Test
|
||||
public void validationFailsIfBlockExistsButNotPreparedMetadata() {
|
||||
when(blockValidator.validateAndProcessBlock(
|
||||
any(), any(), eq(HeaderValidationMode.LIGHT), eq(HeaderValidationMode.FULL)))
|
||||
.thenReturn(new BlockProcessingResult(Optional.empty()));
|
||||
when(payloadValidator.validate(any())).thenReturn(true);
|
||||
when(blockValidator.validateAndProcessBlock(any(), any(), any(), any()))
|
||||
.thenReturn(new BlockProcessingResult(Optional.empty()));
|
||||
messageValidator =
|
||||
new RoundChangeMessageValidator(
|
||||
payloadValidator,
|
||||
BftHelpers.calculateRequiredValidatorQuorum(VALIDATOR_COUNT),
|
||||
CHAIN_HEIGHT,
|
||||
validators.getNodeAddresses(),
|
||||
blockValidator,
|
||||
protocolContext);
|
||||
protocolContext,
|
||||
protocolSchedule);
|
||||
|
||||
final Block block =
|
||||
ProposedBlockHelpers.createProposalBlock(Collections.emptyList(), roundIdentifier);
|
||||
@@ -430,18 +427,17 @@ public class RoundChangeMessageValidatorTest {
|
||||
|
||||
@Test
|
||||
public void validationFailsIfBlockHashDoesNotMatchPreparedMetadata() {
|
||||
when(blockValidator.validateAndProcessBlock(
|
||||
any(), any(), eq(HeaderValidationMode.LIGHT), eq(HeaderValidationMode.FULL)))
|
||||
.thenReturn(new BlockProcessingResult(Optional.empty()));
|
||||
when(payloadValidator.validate(any())).thenReturn(true);
|
||||
when(blockValidator.validateAndProcessBlock(any(), any(), any(), any()))
|
||||
.thenReturn(new BlockProcessingResult(Optional.empty()));
|
||||
messageValidator =
|
||||
new RoundChangeMessageValidator(
|
||||
payloadValidator,
|
||||
BftHelpers.calculateRequiredValidatorQuorum(VALIDATOR_COUNT),
|
||||
CHAIN_HEIGHT,
|
||||
validators.getNodeAddresses(),
|
||||
blockValidator,
|
||||
protocolContext);
|
||||
protocolContext,
|
||||
protocolSchedule);
|
||||
|
||||
final Block block =
|
||||
ProposedBlockHelpers.createProposalBlock(Collections.emptyList(), roundIdentifier);
|
||||
|
||||
Reference in New Issue
Block a user