Skip to content

Commit

Permalink
Added log for validator selection mode transition (hyperledger#2909)
Browse files Browse the repository at this point in the history
* Added log for validator selection mode transition

Signed-off-by: Lucas Saldanha <lucascrsaldanha@gmail.com>
  • Loading branch information
lucassaldanha authored and garyschulte committed Oct 22, 2021
1 parent 210ceaa commit 9f83517
Show file tree
Hide file tree
Showing 10 changed files with 331 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
import org.hyperledger.besu.consensus.qbft.validator.ForkingValidatorProvider;
import org.hyperledger.besu.consensus.qbft.validator.TransactionValidatorProvider;
import org.hyperledger.besu.consensus.qbft.validator.ValidatorContractController;
import org.hyperledger.besu.consensus.qbft.validator.ValidatorModeTransitionLogger;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.methods.JsonRpcMethods;
Expand Down Expand Up @@ -219,7 +220,8 @@ protected MiningCoordinator createMiningCoordinator(
messageFactory,
bftExtraDataCodec().get()),
messageValidatorFactory,
messageFactory),
messageFactory,
new ValidatorModeTransitionLogger(qbftForksSchedule)),
gossiper,
duplicateMessageTracker,
futureMessageBuffer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public JsonQbftConfigOptions(final ObjectNode bftConfigRoot) {

@Override
public Optional<String> getValidatorContractAddress() {
return JsonUtil.getString(bftConfigRoot, VALIDATOR_CONTRACT_ADDRESS);
return JsonUtil.getString(bftConfigRoot, VALIDATOR_CONTRACT_ADDRESS).map(String::toLowerCase);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,8 @@ public interface QbftConfigOptions extends BftConfigOptions {
default boolean isValidatorContractMode() {
return getValidatorContractAddress().isPresent();
}

default boolean isValidatorBlockHeaderMode() {
return !isValidatorContractMode();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
* the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/

package org.hyperledger.besu.config;

import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.besu.config.JsonQbftConfigOptions.VALIDATOR_CONTRACT_ADDRESS;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.junit.Test;

public class JsonQbftConfigOptionsTest {

final ObjectMapper objectMapper = new ObjectMapper();

@Test
public void getValidatorContractAddressNormalization() {
final ObjectNode objectNode =
objectMapper.createObjectNode().put(VALIDATOR_CONTRACT_ADDRESS, "0xABC");

final JsonQbftConfigOptions configOptions = new JsonQbftConfigOptions(objectNode);

assertThat(configOptions.getValidatorContractAddress()).hasValue("0xabc");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
import org.hyperledger.besu.consensus.qbft.validator.ForkingValidatorProvider;
import org.hyperledger.besu.consensus.qbft.validator.TransactionValidatorProvider;
import org.hyperledger.besu.consensus.qbft.validator.ValidatorContractController;
import org.hyperledger.besu.consensus.qbft.validator.ValidatorModeTransitionLogger;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
Expand Down Expand Up @@ -500,7 +501,8 @@ private static ControllerAndState createControllerAndFinalState(
messageFactory,
BFT_EXTRA_DATA_ENCODER),
messageValidatorFactory,
messageFactory),
messageFactory,
new ValidatorModeTransitionLogger(forksSchedule)),
gossiper,
duplicateMessageTracker,
futureMessageBuffer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ public class MutableQbftConfigOptions extends MutableBftConfigOptions implements

public MutableQbftConfigOptions(final QbftConfigOptions qbftConfigOptions) {
super(qbftConfigOptions);
this.validatorContractAddress = qbftConfigOptions.getValidatorContractAddress();
this.validatorContractAddress =
qbftConfigOptions.getValidatorContractAddress().map(String::toLowerCase);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.hyperledger.besu.consensus.common.bft.statemachine.BftFinalState;
import org.hyperledger.besu.consensus.qbft.payload.MessageFactory;
import org.hyperledger.besu.consensus.qbft.validation.MessageValidatorFactory;
import org.hyperledger.besu.consensus.qbft.validator.ValidatorModeTransitionLogger;
import org.hyperledger.besu.ethereum.core.BlockHeader;

public class QbftBlockHeightManagerFactory {
Expand All @@ -26,19 +27,24 @@ public class QbftBlockHeightManagerFactory {
private final BftFinalState finalState;
private final MessageValidatorFactory messageValidatorFactory;
private final MessageFactory messageFactory;
private final ValidatorModeTransitionLogger validatorModeTransitionLogger;

public QbftBlockHeightManagerFactory(
final BftFinalState finalState,
final QbftRoundFactory roundFactory,
final MessageValidatorFactory messageValidatorFactory,
final MessageFactory messageFactory) {
final MessageFactory messageFactory,
final ValidatorModeTransitionLogger validatorModeTransitionLogger) {
this.roundFactory = roundFactory;
this.finalState = finalState;
this.messageValidatorFactory = messageValidatorFactory;
this.messageFactory = messageFactory;
this.validatorModeTransitionLogger = validatorModeTransitionLogger;
}

public BaseQbftBlockHeightManager create(final BlockHeader parentHeader) {
validatorModeTransitionLogger.logTransitionChange(parentHeader);

if (finalState.isLocalNodeValidator()) {
return createFullBlockHeightManager(parentHeader);
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/

package org.hyperledger.besu.consensus.qbft.validator;

import org.hyperledger.besu.config.QbftConfigOptions;
import org.hyperledger.besu.consensus.common.bft.BftForkSpec;
import org.hyperledger.besu.consensus.common.bft.BftForksSchedule;
import org.hyperledger.besu.ethereum.core.BlockHeader;

import java.util.function.Consumer;

import com.google.common.annotations.VisibleForTesting;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class ValidatorModeTransitionLogger {

private static final Logger LOG = LogManager.getLogger();

private final BftForksSchedule<QbftConfigOptions> bftForksSchedule;
private final Consumer<String> msgConsumer;

public ValidatorModeTransitionLogger(final BftForksSchedule<QbftConfigOptions> bftForksSchedule) {
this.bftForksSchedule = bftForksSchedule;
this.msgConsumer = LOG::info;
}

@VisibleForTesting
ValidatorModeTransitionLogger(
final BftForksSchedule<QbftConfigOptions> bftForksSchedule,
final Consumer<String> msgConsumer) {
this.bftForksSchedule = bftForksSchedule;
this.msgConsumer = msgConsumer;
}

public void logTransitionChange(final BlockHeader parentHeader) {
final BftForkSpec<QbftConfigOptions> currentForkSpec =
bftForksSchedule.getFork(parentHeader.getNumber());
final BftForkSpec<QbftConfigOptions> nextForkSpec =
bftForksSchedule.getFork(parentHeader.getNumber() + 1L);

final QbftConfigOptions currentConfigOptions = currentForkSpec.getConfigOptions();
final QbftConfigOptions nextConfigOptions = nextForkSpec.getConfigOptions();

if (hasChangedConfig(currentConfigOptions, nextConfigOptions)) {
msgConsumer.accept(
String.format(
"Transitioning validator selection mode from %s to %s",
parseConfigToLog(currentConfigOptions), parseConfigToLog(nextConfigOptions)));
}
}

private boolean hasChangedConfig(
final QbftConfigOptions currentConfig, final QbftConfigOptions nextConfig) {
return !currentConfig
.getValidatorContractAddress()
.equals(nextConfig.getValidatorContractAddress());
}

private String parseConfigToLog(final QbftConfigOptions configOptions) {
if (configOptions.getValidatorContractAddress().isPresent()) {
return String.format(
"contract (address: %s)", configOptions.getValidatorContractAddress().get());
} else {
return "blockheader";
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
* the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/

package org.hyperledger.besu.consensus.qbft;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import org.hyperledger.besu.config.QbftConfigOptions;

import java.util.Optional;

import org.junit.Test;

public class MutableQbftConfigOptionsTest {

private final QbftConfigOptions qbftConfigOptions = mock(QbftConfigOptions.class);

@Test
public void getValidatorContractAddressNormalization() {
when(qbftConfigOptions.getValidatorContractAddress()).thenReturn(Optional.of("0xABC"));

final MutableQbftConfigOptions mutableQbftConfigOptions =
new MutableQbftConfigOptions(qbftConfigOptions);

assertThat(mutableQbftConfigOptions.getValidatorContractAddress()).hasValue("0xabc");
}
}
Loading

0 comments on commit 9f83517

Please sign in to comment.