Skip to content

Commit

Permalink
Add deactivation procedure for minAverageUptime
Browse files Browse the repository at this point in the history
  • Loading branch information
thaarok committed Nov 7, 2024
1 parent cff29d5 commit d215bbb
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 11 deletions.
12 changes: 7 additions & 5 deletions contracts/sfc/ConstantsManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@ contract ConstantsManager is Ownable {
uint256 public targetGasPowerPerSecond;
uint256 public gasPriceBalancingCounterweight;

// the number of epochs for counting the average uptime of validators
uint32 public averageUptimeEpochsWindow;
// Epoch threshold for stop counting alive epochs (avoid diminishing impact of new uptimes).
// Is also the minimum number of epochs necessary for deactivation of offline validators.
uint32 public averageUptimeEpochsThreshold;

// minimum average uptime
// Minimum average uptime in Q1.30 format; acceptable bounds [0,0.9]
// Zero to disable validators deactivation by this metric.
uint32 public minAverageUptime;

/**
Expand Down Expand Up @@ -160,14 +162,14 @@ contract ConstantsManager is Ownable {
gasPriceBalancingCounterweight = v;
}

function updateAverageUptimeEpochsWindow(uint32 v) external virtual onlyOwner {
function updateAverageUptimeEpochsThreshold(uint32 v) external virtual onlyOwner {
if (v < 10) {
revert ValueTooSmall();
}
if (v > 87600) {
revert ValueTooLarge();
}
averageUptimeEpochsWindow = v;
averageUptimeEpochsThreshold = v;
}

function updateMinAverageUptime(uint32 v) external virtual onlyOwner {
Expand Down
4 changes: 2 additions & 2 deletions contracts/sfc/NetworkInitializer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ contract NetworkInitializer {
consts.updateOfflinePenaltyThresholdBlocksNum(1000);
consts.updateTargetGasPowerPerSecond(2000000);
consts.updateGasPriceBalancingCounterweight(3600);
consts.updateAverageUptimeEpochsWindow(20);
consts.updateMinAverageUptime(0);
consts.updateAverageUptimeEpochsThreshold(100);
consts.updateMinAverageUptime(0); // check disabled by default
consts.transferOwnership(_owner);

ISFC(_sfc).initialize(sealedEpoch, totalSupply, _auth, address(consts), _owner);
Expand Down
21 changes: 17 additions & 4 deletions contracts/sfc/SFC.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ contract SFC is Initializable, Ownable, Version {
uint256 internal constant OK_STATUS = 0;
uint256 internal constant WITHDRAWN_BIT = 1;
uint256 internal constant OFFLINE_BIT = 1 << 3;
uint256 internal constant OFFLINE_AVG_BIT = 1 << 4;
uint256 internal constant DOUBLESIGN_BIT = 1 << 7;
uint256 internal constant CHEATER_MASK = DOUBLESIGN_BIT;

Expand Down Expand Up @@ -929,16 +930,28 @@ contract SFC is Initializable, Ownable, Version {
) internal {
for (uint256 i = 0; i < validatorIDs.length; i++) {
uint256 validatorID = validatorIDs[i];
// compute normalised uptime as a percentage in the Q1.30 fixed-point format
uint256 normalisedUptime = (uptimes[i] * (1 << 30)) / epochDuration;
if (normalisedUptime > 1 << 30) {
normalisedUptime = 1 << 30;
}
AverageUptime memory previousAverage = prevSnapshot.averageUptime[validatorID];
snapshot.averageUptime[validatorID] = _addElementIntoAverageUptime(normalisedUptime, previousAverage);
AverageUptime memory previous = prevSnapshot.averageUptime[validatorID];
AverageUptime memory current = _addElementIntoAverageUptime(uint32(normalisedUptime), previous);
snapshot.averageUptime[validatorID] = current;

// remove validator if average uptime drops below min average uptime
// (by setting minAverageUptime to zero, this check is ignored)
if (current.averageUptime < c.minAverageUptime() && current.epochs >= c.averageUptimeEpochsThreshold()) {
_setValidatorDeactivated(validatorID, OFFLINE_AVG_BIT);
_syncValidator(validatorID, false);
}
}
}

function _addElementIntoAverageUptime(uint32 newValue, AverageUptime memory prev) private returns (AverageUptime memory) {
function _addElementIntoAverageUptime(
uint32 newValue,
AverageUptime memory prev
) private view returns (AverageUptime memory) {
AverageUptime memory cur;
if (prev.epochs == 0) {
// the only element for the average
Expand All @@ -963,7 +976,7 @@ contract SFC is Initializable, Ownable, Version {
if (cur.averageUptime > 1 << 30) {
cur.averageUptime = 1 << 30;
}
if (prev.epochs < c.averageUptimeEpochsWindow()) {
if (prev.epochs < c.averageUptimeEpochsThreshold()) {
cur.epochs = prev.epochs + 1;
} else {
cur.epochs = prev.epochs;
Expand Down

0 comments on commit d215bbb

Please sign in to comment.