Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds backwards compatibility in UsingPrecompile contract. #11236

Merged
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
f3c3193
added `getEpochInfoOfEpoch(uint256)` to get epoch info of specific ep…
soloseng Oct 2, 2024
6d059e9
updated natspec
soloseng Oct 2, 2024
7a4f8a4
PR feedback
soloseng Oct 3, 2024
2e30ff6
Use constant
soloseng Oct 3, 2024
fca97c1
breakup test; added more
soloseng Oct 3, 2024
ae767fe
++ registry to precompile contract
soloseng Oct 4, 2024
9e5043e
Merge branch 'soloseng/epoch-of-block' into soloseng/backward-compati…
soloseng Oct 4, 2024
dd39947
added elected to epoch info
soloseng Oct 4, 2024
ece3579
numberValidatorsInSet backwards compatibility
soloseng Oct 4, 2024
accf227
validator address & validatorSigner address from set
soloseng Oct 4, 2024
6b7cf95
support `getEpochNumber()` backwards compatibility in UsingRegistry
soloseng Oct 4, 2024
feeb9e3
using `getEpochByBlockNumber` instead of `getEpochByNumber`
soloseng Oct 4, 2024
f22201d
limit span of loop only to L2 blocks
soloseng Oct 4, 2024
69a84e6
use binary search instead of blind loop
soloseng Oct 4, 2024
fd36439
++ natspec
soloseng Oct 4, 2024
50bec5c
added getEpochNumberOfBlock() backwards compatibility support
soloseng Oct 4, 2024
6732448
++ electedSigners
soloseng Oct 8, 2024
d786a56
make usingPrecompile onlyL1 contract
soloseng Oct 8, 2024
eaeeb8b
++ precompile override contract
soloseng Oct 8, 2024
1dcd131
fix epoch manager bug and mock
soloseng Oct 8, 2024
b6ac1f2
using precompileOverride in validators contract
soloseng Oct 8, 2024
6205b5f
wording
soloseng Oct 8, 2024
d84205d
using indexed function when querying specific validator accounts or s…
soloseng Oct 8, 2024
162d850
Merge branch 'release/core-contracts/12' into soloseng/UsingRegistry-…
soloseng Oct 8, 2024
35316a0
fixed failing test
soloseng Oct 9, 2024
a0c976a
using independent mapping for elected accounts and signers
soloseng Oct 9, 2024
86f74d9
removed old elected list
soloseng Oct 10, 2024
681a858
support 0.5.13 contracts using precompiles
soloseng Oct 10, 2024
6648ad4
-- registry import
soloseng Oct 10, 2024
f0a4fc3
++ registry in PrecompilesOverride
soloseng Oct 10, 2024
ae1577f
++ more tests
soloseng Oct 10, 2024
17566dc
increase gaslimit
soloseng Oct 10, 2024
23b0aa3
moved election history update to epoch processing start.
soloseng Oct 10, 2024
f645c26
unused var
soloseng Oct 10, 2024
96e45a4
clean up
soloseng Oct 10, 2024
04d46ee
fixed e2e test
soloseng Oct 11, 2024
a4f380f
simplify code
soloseng Oct 11, 2024
de140aa
Merge branch 'release/core-contracts/12' into soloseng/UsingRegistry-…
soloseng Oct 11, 2024
1e52b15
Merge branch 'release/core-contracts/12' into soloseng/UsingRegistry-…
martinvol Oct 14, 2024
f3b7a51
Removed support for election historical data after that it's unlikely…
soloseng Oct 14, 2024
c15fc93
PR feedback
soloseng Oct 14, 2024
78ea07f
-- spacing
soloseng Oct 14, 2024
954b346
reorder state var
soloseng Oct 14, 2024
baf0e79
stat var reorder
soloseng Oct 14, 2024
0c14aa0
small fix
soloseng Oct 14, 2024
c67c70b
delete electedSigners at end of epochprocessing
soloseng Oct 14, 2024
0fb94bc
CI fix
soloseng Oct 15, 2024
3dcb696
added comment
pahor167 Oct 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
275 changes: 248 additions & 27 deletions packages/protocol/contracts-0.8/common/EpochManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,18 @@ contract EpochManager is

uint256 public firstKnownEpoch;
uint256 internal currentEpochNumber;
address[] internal electedAccounts;
soloseng marked this conversation as resolved.
Show resolved Hide resolved
address[] internal electedSigners;
address public oracleAddress;
address[] public elected;

mapping(address => uint256) public processedGroups;

EpochProcessState public epochProcessing;
mapping(uint256 => Epoch) internal epochs;
mapping(uint256 => address[]) internal electedAccountsOfEpoch;
soloseng marked this conversation as resolved.
Show resolved Hide resolved
// Electeds in the L1 assumed signers can not change during the epoch
// so we keep a copy
mapping(uint256 => address[]) internal electedSignersOfEpoch;
soloseng marked this conversation as resolved.
Show resolved Hide resolved
mapping(address => uint256) public validatorPendingPayments;

/**
Expand Down Expand Up @@ -144,7 +149,11 @@ contract EpochManager is
uint256 firstEpochNumber,
uint256 firstEpochBlock,
address[] memory firstElected
) external onlyEpochManagerEnabler {
)
external
// address[] memory firstElectedSigners
onlyEpochManagerEnabler
{
require(
getCeloToken().balanceOf(registry.getAddressForOrDie(CELO_UNRELEASED_TREASURY_REGISTRY_ID)) >
0,
Expand All @@ -166,7 +175,11 @@ contract EpochManager is
_currentEpoch.firstBlock = firstEpochBlock;
_currentEpoch.startTimestamp = block.timestamp;

elected = firstElected;
electedAccounts = firstElected;

_setElectedSigners(firstElected);

updateElectionHistory();
}

/**
Expand All @@ -177,8 +190,8 @@ contract EpochManager is
function startNextEpochProcess() external nonReentrant onlySystemAlreadyInitialized {
require(isTimeForNextEpoch(), "Epoch is not ready to start");
require(!isOnEpochProcess(), "Epoch process is already started");
updateElectionHistory();
epochProcessing.status = EpochProcessStatus.Started;

epochs[currentEpochNumber].rewardsBlock = block.number;

// calculate rewards
Expand Down Expand Up @@ -227,8 +240,8 @@ contract EpochManager is
IValidators validators = getValidators();
IElection election = getElection();
IScoreReader scoreReader = getScoreReader();
for (uint i = 0; i < elected.length; i++) {
address group = validators.getValidatorsGroup(elected[i]);
for (uint i = 0; i < electedAccounts.length; i++) {
address group = validators.getValidatorsGroup(electedAccounts[i]);
if (processedGroups[group] == 0) {
toProcessGroups++;
uint256 groupScore = scoreReader.getGroupScore(group);
Expand All @@ -240,7 +253,7 @@ contract EpochManager is
);
processedGroups[group] = epochRewards == 0 ? type(uint256).max : epochRewards;
}
delete elected[i];
soloseng marked this conversation as resolved.
Show resolved Hide resolved
delete electedAccounts[i];
}

require(toProcessGroups == groups.length, "number of groups does not match");
Expand All @@ -264,8 +277,17 @@ contract EpochManager is
epochProcessing.totalRewardsCarbonFund
);
// run elections
elected = election.electValidatorAccounts();
_epochProcessing.status = EpochProcessStatus.NotStarted;

address[] memory _newlyElected = election.electValidatorAccounts();

electedAccounts = _newlyElected;

_setElectedSigners(_newlyElected);

EpochProcessState memory _epochProcessingEmpty;
epochProcessing = _epochProcessingEmpty;
pahor167 marked this conversation as resolved.
Show resolved Hide resolved

emit EpochProcessingEnded(currentEpochNumber - 1);
}

/**
Expand Down Expand Up @@ -321,11 +343,7 @@ contract EpochManager is
}

/**
* @notice Returns the info of the current epoch.
* @return firstEpoch The first block of the epoch.
* @return lastBlock The first block of the epoch.
* @return startTimestamp The starting timestamp of the epoch.
* @return rewardsBlock The reward block of the epoch.
* @notice Returns the epoch info of the specified epoch, for current epoch.
*/
function getCurrentEpoch()
external
Expand Down Expand Up @@ -371,10 +389,58 @@ contract EpochManager is
}

/**
* @return The list of currently elected validators.
* @return The number of elected accounts in the current set.
*/
function numberOfElectedInCurrentSet()
external
view
onlySystemAlreadyInitialized
returns (uint256)
{
return electedAccountsOfEpoch[currentEpochNumber].length;
}

/**
* @notice Returns the number of elected accounts in a specified set.
* @param _blockNumber The block number at which to retreive the set.
*/
function numberOfElectedInSet(
uint256 _blockNumber
) external view onlySystemAlreadyInitialized returns (uint256) {
(uint256 _epochNumber, , , , ) = _getEpochByBlockNumber(_blockNumber);
return electedAccountsOfEpoch[_epochNumber].length;
}

/**
* @notice Returns the currently elected account at a specified index.
* @param index The index of the currently elected account.
*/
function getElectedAccountByIndex(
uint256 index
) external view onlySystemAlreadyInitialized returns (address) {
return electedAccounts[index];
}

/**
* @return The list of the validator signers of elected validators.
*/
function getElectedSigners()
external
view
onlySystemAlreadyInitialized
returns (address[] memory)
{
return electedSigners;
}

/**
* @notice Returns the currently elected signer address at a specified index.
* @param index The index of the currently elected signer.
*/
function getElected() external view returns (address[] memory) {
return elected;
function getElectedSignerByIndex(
uint256 index
) external view onlySystemAlreadyInitialized returns (address) {
return electedSigners[index];
}

/**
Expand All @@ -397,6 +463,71 @@ contract EpochManager is
return epochs[epoch].lastBlock;
}

/**
* @notice Returns the epoch number of a specified blockNumber.
* @param _blockNumber Block number of the epoch info is retreived.
*/
function getEpochNumberOfBlock(
uint256 _blockNumber
) external view onlySystemAlreadyInitialized returns (uint256) {
(uint256 _epochNumber, , , , ) = _getEpochByBlockNumber(_blockNumber);
return _epochNumber;
}

/**
* @notice Returns the epoch info of a specified blockNumber.
* @param _blockNumber Block number of the epoch info is retreived.
* @return firstEpoch The first block of the given block number.
* @return lastBlock The first block of the given block number.
* @return startTimestamp The starting timestamp of the given block number.
* @return rewardsBlock The reward block of the given block number.
*/
function getEpochByBlockNumber(
uint256 _blockNumber
) external view onlySystemAlreadyInitialized returns (uint256, uint256, uint256, uint256) {
(
,
uint256 _firstBlock,
uint256 _lastBlock,
uint256 _startTimestamp,
uint256 _rewardsBlock
) = _getEpochByBlockNumber(_blockNumber);
return (_firstBlock, _lastBlock, _startTimestamp, _rewardsBlock);
}

/**
* @notice Returns the elected account address at a specified index of a specified block number.
* @param index The index of the elected account.
* @param _blockNumber The block number of interest.
*/
function getElectedAccountAddressFromSet(
uint256 index,
uint256 _blockNumber
) external view onlySystemAlreadyInitialized returns (address) {
if (_blockNumber == block.number) {
return electedAccounts[index];
}
(uint256 _epochNumber, , , , ) = _getEpochByBlockNumber(_blockNumber);
return electedAccountsOfEpoch[_epochNumber][index];
}

/**
* @notice Returns the elected signer address at a specified index of a specified block number.
* @param index The index of the elected signer.
* @param _blockNumber The block number of interest.
*/
function getElectedSignerAddressFromSet(
uint256 index,
uint256 _blockNumber
) external view onlySystemAlreadyInitialized returns (address) {
if (_blockNumber == block.number) {
return electedSigners[index];
}

(uint256 _epochNumber, , , , ) = _getEpochByBlockNumber(_blockNumber);
return electedSignersOfEpoch[_epochNumber][index];
}

/**
* @notice Returns the storage, major, minor, and patch version of the contract.
* @return Storage version of the contract.
Expand Down Expand Up @@ -433,6 +564,18 @@ contract EpochManager is
emit OracleAddressSet(newOracleAddress);
}

/**
* @return The list of currently elected validators.
*/
function getElectedAccounts()
public
view
onlySystemAlreadyInitialized
returns (address[] memory)
{
return electedAccounts;
}

/**
* @return Whether or not the next epoch can be processed.
*/
Expand All @@ -456,16 +599,16 @@ contract EpochManager is

/**
* @notice Returns the epoch info of a specified epoch.
* @param epochNumber Epoch number where epoch info is retreived.
* @return firstEpoch The first block of the epoch.
* @return lastBlock The first block of the epoch.
* @return startTimestamp The starting timestamp of the epoch.
* @return rewardsBlock The reward block of the epoch.
* @param epochNumber Epoch number where the epoch info is retreived.
* @return firstEpoch The first block of the given epoch.
* @return lastBlock The first block of the given epoch.
* @return startTimestamp The starting timestamp of the given epoch.
* @return rewardsBlock The reward block of the given epoch.
*/
function getEpochByNumber(
uint256 epochNumber
) public view onlySystemAlreadyInitialized returns (uint256, uint256, uint256, uint256) {
Epoch storage _epoch = epochs[epochNumber];
Epoch memory _epoch = epochs[epochNumber];
return (_epoch.firstBlock, _epoch.lastBlock, _epoch.startTimestamp, _epoch.rewardsBlock);
}

Expand All @@ -479,14 +622,14 @@ contract EpochManager is

EpochProcessState storage _epochProcessing = epochProcessing;

for (uint i = 0; i < elected.length; i++) {
uint256 validatorScore = scoreReader.getValidatorScore(elected[i]);
for (uint i = 0; i < electedAccounts.length; i++) {
uint256 validatorScore = scoreReader.getValidatorScore(electedAccounts[i]);
uint256 validatorReward = validators.computeEpochReward(
elected[i],
electedAccounts[i],
validatorScore,
_epochProcessing.perValidatorReward
);
validatorPendingPayments[elected[i]] += validatorReward;
validatorPendingPayments[electedAccounts[i]] += validatorReward;
totalRewards += validatorReward;
}
if (totalRewards == 0) {
Expand All @@ -506,4 +649,82 @@ contract EpochManager is
CELOequivalent
);
}

/**
* @notice Updates the list of elected validator signers.
*/
function _setElectedSigners(address[] memory _elected) internal {
require(electedAccounts.length > 0, "Elected list length cannot be zero.");
IAccounts accounts = getAccounts();
electedSigners = new address[](_elected.length);
for (uint i = 0; i < _elected.length; i++) {
electedSigners[i] = accounts.getValidatorSigner(_elected[i]);
}
}

/**
* @notice Returns the epoch info of a specified blockNumber.
* @param _blockNumber Block number of the epoch info is retreived.
* @return firstEpoch The first block of the given block number.
* @return lastBlock The first block of the given block number.
* @return startTimestamp The starting timestamp of the given block number.
* @return rewardsBlock The reward block of the given block number.
*/
function _getEpochByBlockNumber(
pahor167 marked this conversation as resolved.
Show resolved Hide resolved
uint256 _blockNumber
)
internal
view
onlySystemAlreadyInitialized
returns (uint256, uint256, uint256, uint256, uint256)
{
require(_blockNumber <= block.number, "Invalid blockNumber. Value too high.");

(uint256 _firstBlockOfFirstEpoch, , , ) = getEpochByNumber(firstKnownEpoch);

require(_blockNumber >= _firstBlockOfFirstEpoch, "Invalid blockNumber. Value too low.");

uint256 _firstBlockOfCurrentEpoch = epochs[currentEpochNumber].firstBlock;

if (_blockNumber >= _firstBlockOfCurrentEpoch) {
(
uint256 _firstBlock,
uint256 _lastBlock,
uint256 _startTimestamp,
uint256 _rewardsBlock
) = getEpochByNumber(currentEpochNumber);
return (currentEpochNumber, _firstBlock, _lastBlock, _startTimestamp, _rewardsBlock);
}

uint256 left = firstKnownEpoch;
uint256 right = currentEpochNumber - 1;

while (left <= right) {
uint256 mid = (left + right) / 2;
uint256 _epochFirstBlock = epochs[mid].firstBlock;
uint256 _epochLastBlock = epochs[mid].lastBlock;

if (_blockNumber >= _epochFirstBlock && _blockNumber <= _epochLastBlock) {
Epoch memory _epoch = epochs[mid];
return (
mid,
_epoch.firstBlock,
_epoch.lastBlock,
_epoch.startTimestamp,
_epoch.rewardsBlock
);
} else if (_blockNumber < _epochFirstBlock) {
right = mid - 1;
} else {
left = mid + 1;
}
}

revert("No matching epoch found for the given block number.");
}

function updateElectionHistory() private {
electedAccountsOfEpoch[currentEpochNumber] = electedAccounts;
electedSignersOfEpoch[currentEpochNumber] = electedSigners;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import "./interfaces/IEpochManagerEnablerInitializer.sol";

contract EpochManagerEnabler is
Initializable,
UsingPrecompiles,
UsingRegistry,
UsingPrecompiles,
IEpochManagerEnabler,
IEpochManagerEnablerInitializer
{
Expand Down
Loading
Loading