Skip to content

Commit

Permalink
Merge pull request #6 from DMDcoin/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
SurfingNerd authored Sep 17, 2024
2 parents 9ba1d34 + 5ec5b9d commit 9d380fd
Show file tree
Hide file tree
Showing 17 changed files with 666 additions and 241 deletions.
25 changes: 19 additions & 6 deletions contracts/BlockRewardHbbft.sol
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,10 @@ contract BlockRewardHbbft is
for (uint256 i = 0; i < governancePotShareNominatorParams.length; i++) {
governancePotShareNominatorParams[i] = 10 + i;
}

initAllowedChangeableParameter(
"setGovernancePotShareNominator(uint256)",
"governancePotShareNominatorParams()",
"governancePotShareNominator()",
governancePotShareNominatorParams
);
}
Expand Down Expand Up @@ -252,11 +252,9 @@ contract BlockRewardHbbft is
IStakingHbbft stakingContract = IStakingHbbft(validatorSetContract.getStakingContract());

// If this is the last block of the epoch i.e. master key has been generated.
if (_isEpochEndBlock || earlyEpochEnd) {
if (_isEpochEndBlock) {
rewardsNative = _closeEpoch(stakingContract);

earlyEpochEnd = false;

emit CoinsRewarded(rewardsNative);
} else {
_closeBlock(stakingContract);
Expand Down Expand Up @@ -451,9 +449,15 @@ contract BlockRewardHbbft is
}
}

if ((isPhaseTransition || toBeUpscaled) && validatorSetContract.getPendingValidators().length == 0) {
bool validatorSetChangeTrigger = isPhaseTransition || toBeUpscaled || earlyEpochEnd;

if (validatorSetChangeTrigger && validatorSetContract.getPendingValidators().length == 0) {
// Choose new validators
validatorSetContract.newValidatorSet();

// in any case we reset early epoch end flag because
// the validator set change already in progress
earlyEpochEnd = false;
} else if (block.timestamp >= stakingContract.stakingFixedEpochEndTime()) {
validatorSetContract.handleFailedKeyGeneration();
}
Expand Down Expand Up @@ -482,6 +486,8 @@ contract BlockRewardHbbft is
// Indicates whether the validator is entitled to share the rewartds or not.
bool[] memory isRewardedValidator = new bool[](validators.length);

uint256 currentEpochStartTime = stakingContract.stakingEpochStartTime();

// Number of validators that are being rewarded.
uint256 numRewardedValidators = 0;

Expand All @@ -495,6 +501,13 @@ contract BlockRewardHbbft is
continue;
}

// validator who is unavailable or set himself available (because it was unavailable)
// in current epoch, should not get rewards for it.
uint256 availableSince = validatorSetContract.validatorAvailableSince(validators[i]);
if (availableSince == 0 || availableSince >= currentEpochStartTime) {
continue;
}

isRewardedValidator[i] = true;
++numRewardedValidators;
}
Expand Down
31 changes: 23 additions & 8 deletions contracts/ConnectivityTrackerHbbft.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,14 @@ contract ConnectivityTrackerHbbft is Initializable, OwnableUpgradeable, IConnect
mapping(uint256 => EnumerableSet.AddressSet) private _flaggedValidators;
mapping(uint256 => mapping(address => EnumerableSet.AddressSet)) private _reporters;

mapping(address => uint256) private _disconnectTimestamp;
/// @custom:oz-renamed-from _disconnectTimestamp
mapping(address => uint256) private _unused;
mapping(uint256 => bool) private _epochPenaltiesSent;

IBonusScoreSystem public bonusScoreContract;

mapping(uint256 => mapping(address => uint256)) private _disconnectTimestamp;

event SetMinReportAgeBlocks(uint256 _minReportAge);
event SetEarlyEpochEndToleranceLevel(uint256 _level);
event ReportMissingConnectivity(address indexed reporter, address indexed validator, uint256 indexed blockNumber);
Expand Down Expand Up @@ -118,8 +121,8 @@ contract ConnectivityTrackerHbbft is Initializable, OwnableUpgradeable, IConnect
// slither-disable-next-line unused-return
_reporters[epoch][validator].add(msg.sender);

if (isFaultyValidator(validator, epoch)) {
_disconnectTimestamp[validator] = block.timestamp;
if (isFaultyValidator(epoch, validator)) {
_markValidatorFaulty(epoch, validator);
}

_decideEarlyEpochEndNeeded(epoch);
Expand All @@ -142,12 +145,13 @@ contract ConnectivityTrackerHbbft is Initializable, OwnableUpgradeable, IConnect

// All reporters confirmed that this validator reconnected,
// decrease validator bonus score for bad performance based on disconnect time interval.
if (_disconnectTimestamp[validator] != 0) {
uint256 disconnectPeriod = block.timestamp - _disconnectTimestamp[validator];
uint256 disconnectTimestamp = _disconnectTimestamp[epoch][validator];
if (disconnectTimestamp != 0) {
uint256 disconnectPeriod = block.timestamp - disconnectTimestamp;

bonusScoreContract.penaliseBadPerformance(validator, disconnectPeriod);

delete _disconnectTimestamp[validator];
delete _disconnectTimestamp[epoch][validator];
}
}

Expand All @@ -166,7 +170,7 @@ contract ConnectivityTrackerHbbft is Initializable, OwnableUpgradeable, IConnect
address[] memory flaggedValidators = getFlaggedValidatorsByEpoch(epoch);

for (uint256 i = 0; i < flaggedValidators.length; ++i) {
if (!isFaultyValidator(flaggedValidators[i], epoch)) {
if (!isFaultyValidator(epoch, flaggedValidators[i])) {
continue;
}

Expand All @@ -183,7 +187,7 @@ contract ConnectivityTrackerHbbft is Initializable, OwnableUpgradeable, IConnect
return _reporters[epoch][validator].length();
}

function isFaultyValidator(address validator, uint256 epoch) public view returns (bool) {
function isFaultyValidator(uint256 epoch, address validator) public view returns (bool) {
return getValidatorConnectivityScore(epoch, validator) >= _getReportersThreshold(epoch);
}

Expand Down Expand Up @@ -269,6 +273,17 @@ contract ConnectivityTrackerHbbft is Initializable, OwnableUpgradeable, IConnect
emit NotifyEarlyEpochEnd(epoch, block.number);
}

function _markValidatorFaulty(uint256 epoch, address validator) private {
if (_disconnectTimestamp[epoch][validator] != 0) {
// validator already marked as faulty
return;
}

_disconnectTimestamp[epoch][validator] = block.timestamp;

validatorSetContract.notifyUnavailability(validator);
}

function _getReportersThreshold(uint256 epoch) private view returns (uint256) {
uint256 unflaggedValidatorsCount = validatorSetContract.getCurrentValidatorsCount() -
getFlaggedValidatorsCount(epoch);
Expand Down
40 changes: 29 additions & 11 deletions contracts/ValidatorSetHbbft.sol
Original file line number Diff line number Diff line change
Expand Up @@ -96,17 +96,21 @@ contract ValidatorSetHbbft is Initializable, OwnableUpgradeable, IValidatorSetHb

IBonusScoreSystem public bonusScoreSystem;

address public connectivityTracker;

// ================================================ Events ========================================================

event ValidatorAvailable(address validator, uint256 timestamp);

/// @dev Emitted by the `handleFailedKeyGeneration` function to signal that a specific validator was
/// marked as unavailable since he dit not contribute to the required key shares.
/// @dev Emitted by the `handleFailedKeyGeneration` and `notifyUnavailability` functions to signal that a specific
/// validator was marked as unavailable since he dit not contribute to the required key shares or 2/3 of other
/// validators reporter him as disconnected.
event ValidatorUnavailable(address validator, uint256 timestamp);

event SetMaxValidators(uint256 _count);
event SetValidatorInactivityThreshold(uint256 _value);
event SetBonusScoreContract(address _address);
event SetConnectivityTrackerContract(address _address);

error AnnounceBlockNumberTooOld();
error CantAnnounceAvailability();
Expand All @@ -132,17 +136,16 @@ contract ValidatorSetHbbft is Initializable, OwnableUpgradeable, IValidatorSetHb
_;
}

/// @dev Ensures the caller is the RandomHbbft contract address.
modifier onlyRandomContract() {
if (msg.sender != randomContract) {
/// @dev Ensures the caller is the StakingHbbft contract address.
modifier onlyStakingContract() {
if (msg.sender != address(stakingContract)) {
revert Unauthorized();
}
_;
}

/// @dev Ensures the caller is the StakingHbbft contract address.
modifier onlyStakingContract() {
if (msg.sender != address(stakingContract)) {
modifier onlyConnectivityTracker() {
if (msg.sender != connectivityTracker) {
revert Unauthorized();
}
_;
Expand Down Expand Up @@ -202,6 +205,7 @@ contract ValidatorSetHbbft is Initializable, OwnableUpgradeable, IValidatorSetHb
stakingContract = IStakingHbbft(_params.stakingContract);
keyGenHistoryContract = IKeyGenHistory(_params.keyGenHistoryContract);
bonusScoreSystem = IBonusScoreSystem(_params.bonusScoreContract);
connectivityTracker = _params.connectivityTrackerContract;
validatorInactivityThreshold = _params.validatorInactivityThreshold;

// Add initial validators to the `_currentValidators` array
Expand Down Expand Up @@ -274,6 +278,16 @@ contract ValidatorSetHbbft is Initializable, OwnableUpgradeable, IValidatorSetHb
emit SetBonusScoreContract(_address);
}

function setConnectivityTracker(address _address) external onlyOwner {
if (_address == address(0)) {
revert ZeroAddress();
}

connectivityTracker = _address;

emit SetConnectivityTrackerContract(_address);
}

/// @dev called by validators when a validator comes online after
/// getting marked as unavailable caused by a failed key generation.
function announceAvailability(uint256 _blockNumber, bytes32 _blockhash) external {
Expand Down Expand Up @@ -434,9 +448,13 @@ contract ValidatorSetHbbft is Initializable, OwnableUpgradeable, IValidatorSetHb
/// @dev Notifies hbbft validator set contract that a validator
/// asociated with the given `_stakingAddress` became
/// unavailable and must be flagged as unavailable.
/// @param _stakingAddress The address of the validator which became unavailable.
function notifyUnavailability(address _stakingAddress) external onlyStakingContract {
_writeValidatorAvailableSince(miningByStakingAddress[_stakingAddress], 0);
/// @param _miningAddress The address of the validator which became unavailable.
function notifyUnavailability(address _miningAddress) external onlyConnectivityTracker {
stakingContract.removePool(stakingByMiningAddress[_miningAddress]);

_writeValidatorAvailableSince(_miningAddress, 0);

emit ValidatorUnavailable(_miningAddress, block.timestamp);
}

/// @dev Binds a mining address to the specified staking address. Called by the `StakingHbbft.addPool` function
Expand Down
1 change: 1 addition & 0 deletions contracts/interfaces/IValidatorSetHbbft.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ interface IValidatorSetHbbft {
address stakingContract;
address keyGenHistoryContract;
address bonusScoreContract;
address connectivityTrackerContract;
uint256 validatorInactivityThreshold;
}

Expand Down
1 change: 1 addition & 0 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import "@typechain/hardhat";
import "hardhat-gas-reporter";
import "hardhat-contract-sizer";
import 'solidity-docgen';
import 'hardhat-tracer';

import './tasks/make_spec';

Expand Down
Loading

0 comments on commit 9d380fd

Please sign in to comment.