Skip to content

Commit

Permalink
Enable epoch manager in devchain
Browse files Browse the repository at this point in the history
  • Loading branch information
pahor167 committed Sep 16, 2024
1 parent fe91831 commit 2c5a95f
Show file tree
Hide file tree
Showing 13 changed files with 148 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import "../../contracts/governance/interfaces/IEpochRewards.sol";

contract EpochManagerEnabler is Initializable, UsingPrecompiles, UsingRegistry {
uint256 public lastKnownEpochNumber;
uint256 public lastKnownFirstBlockOfEpoch;
address[] public lastKnownElectedAccounts;

/**
Expand All @@ -33,10 +34,11 @@ contract EpochManagerEnabler is Initializable, UsingPrecompiles, UsingRegistry {
*/
function initEpochManager() external onlyL2 {
require(lastKnownEpochNumber != 0, "lastKnownEpochNumber not set.");
require(lastKnownFirstBlockOfEpoch != 0, "lastKnownFirstBlockOfEpoch not set.");
require(lastKnownElectedAccounts.length > 0, "lastKnownElectedAccounts not set.");
getEpochManager().initializeSystem(
lastKnownEpochNumber,
_getFirstBlockOfEpoch(lastKnownEpochNumber),
lastKnownFirstBlockOfEpoch,
lastKnownElectedAccounts
);
}
Expand All @@ -48,8 +50,8 @@ contract EpochManagerEnabler is Initializable, UsingPrecompiles, UsingRegistry {
lastKnownEpochNumber = getEpochNumber();

uint256 numberElectedValidators = numberValidatorsInCurrentSet();

lastKnownElectedAccounts = new address[](numberElectedValidators);
lastKnownFirstBlockOfEpoch = _getFirstBlockOfEpoch(lastKnownEpochNumber);

for (uint256 i = 0; i < numberElectedValidators; i++) {
// TODO: document how much gas this takes for 110 signers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ pragma solidity >=0.5.13 <0.9.0;
interface IEpochManagerEnabler {
function initEpochManager() external;
function getEpochNumber() external returns (uint256);
function captureEpochAndValidators() external;
}
20 changes: 20 additions & 0 deletions packages/protocol/migrations_sol/Migration.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import "@celo-contracts/common/interfaces/IFeeHandler.sol";
import "@celo-contracts/common/interfaces/IFeeHandlerInitializer.sol";
import "@celo-contracts/common/interfaces/IFeeCurrencyWhitelist.sol";
import "@celo-contracts/common/interfaces/IAccounts.sol";
import "@celo-contracts/common/interfaces/IEpochManagerEnabler.sol";
import "@celo-contracts/governance/interfaces/ILockedGoldInitializer.sol";
import "@celo-contracts/governance/interfaces/IValidatorsInitializer.sol";
import "@celo-contracts/governance/interfaces/IElectionInitializer.sol";
Expand Down Expand Up @@ -249,6 +250,12 @@ contract Migration is Script, UsingRegistry, MigrationsConstants {
// Functions with broadcast with different addresses
// Validators needs to lock, which can be only used by the msg.sender
electValidators(json);

vm.startBroadcast(DEPLOYER_ACCOUNT);

captureEpochManagerEnablerValidators();

vm.stopBroadcast();
}

/**
Expand Down Expand Up @@ -944,6 +951,7 @@ contract Migration is Script, UsingRegistry, MigrationsConstants {
abi.encodeWithSelector(IEpochManagerEnablerInitializer.initialize.selector, REGISTRY_ADDRESS)
);
}

function migrateScoreManager() public {
deployProxiedContract(
"ScoreManager",
Expand Down Expand Up @@ -1293,4 +1301,16 @@ contract Migration is Script, UsingRegistry, MigrationsConstants {
}
}
}

function captureEpochManagerEnablerValidators() public {
address numberValidatorsInCurrentSetPrecompileAddress = 0x00000000000000000000000000000000000000f9;
numberValidatorsInCurrentSetPrecompileAddress.call(abi.encodeWithSignature("setNumberOfValidators()"));

address validatorSignerAddressFromCurrentSetPrecompileAddress = 0x00000000000000000000000000000000000000fa;
validatorSignerAddressFromCurrentSetPrecompileAddress.call(abi.encodeWithSignature("setValidators()"));

address epochManagerEnabler = registry.getAddressForString("EpochManagerEnabler");
IEpochManagerEnabler epochManagerEnablerContract = IEpochManagerEnabler(epochManagerEnabler);
epochManagerEnablerContract.captureEpochAndValidators();
}
}
12 changes: 6 additions & 6 deletions packages/protocol/migrations_sol/MigrationL2.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import "forge-std/console.sol";

import "@celo-contracts/common/FixidityLib.sol";
import "@celo-contracts-8/common/UsingRegistry.sol";
import "../../contracts/common/interfaces/IEpochManagerEnabler.sol";

contract MigrationL2 is Script, MigrationsConstants, UsingRegistry {
using FixidityLib for FixidityLib.Fraction;
Expand Down Expand Up @@ -36,13 +37,12 @@ contract MigrationL2 is Script, MigrationsConstants, UsingRegistry {
}

function initializeEpochManagerSystem() public {
console.log("Initialize Epoch Manager System");
console.log("Initializing EpochManager system");
address[] memory firstElected = getValidators().getRegisteredValidators();
IEpochManager epochManager = getEpochManager();
address epochManagerEnabler = epochManager.epochManagerEnabler();
vm.stopBroadcast();
vm.prank(epochManagerEnabler);
epochManager.initializeSystem(1, 1, firstElected);
vm.startBroadcast(DEPLOYER_ACCOUNT);
address epochManagerEnablerAddress = epochManager.epochManagerEnabler();

IEpochManagerEnabler epochManagerEnabler = IEpochManagerEnabler(epochManagerEnablerAddress);
epochManagerEnabler.initEpochManager();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ echo "Migration script total elapsed time: $ELAPSED_TIME seconds"
# this helps to make sure that devchain state is actually being saved
sleep 1

# Rename devchain artifact and remove unused directory
mv $ANVIL_FOLDER/state.json $TMP_FOLDER/$L1_DEVCHAIN_FILE_NAME
rm -rf $ANVIL_FOLDER
if [[ "${KEEP_DEVCHAIN_FOLDER:-}" == "true" ]]; then
cp $ANVIL_FOLDER/state.json $TMP_FOLDER/$L1_DEVCHAIN_FILE_NAME
echo "Keeping devchain folder as per flag."
else
# Rename devchain artifact and remove unused directory
mv $ANVIL_FOLDER/state.json $TMP_FOLDER/$L1_DEVCHAIN_FILE_NAME
rm -rf $ANVIL_FOLDER
fi
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@ set -euo pipefail
# Read environment variables and constants
source $PWD/scripts/foundry/constants.sh

export KEEP_DEVCHAIN_FOLDER=true

# Generate and run L1 devchain
echo "Generating and running L1 devchain before activating L2..."
source $PWD/scripts/foundry/create_and_migrate_anvil_devchain.sh

# Backup L1 state before applying L2 migrations so it can be published to NPM
cp $TMP_FOLDER/$L1_DEVCHAIN_FILE_NAME $TMP_FOLDER/backup_$L1_DEVCHAIN_FILE_NAME

# Activate L2 by deploying arbitrary bytecode to the proxy admin address.
# Note: This can't be done from the migration script
ARBITRARY_BYTECODE=$(cast format-bytes32-string "L2 is activated")
Expand Down Expand Up @@ -50,12 +49,8 @@ forge script \
$NON_INTERACTIVE \
--rpc-url $ANVIL_RPC_URL || { echo "Migration script failed"; exit 1; }

# Save L2 state so it can published to NPM
cp $TMP_FOLDER/$L1_DEVCHAIN_FILE_NAME $TMP_FOLDER/$L2_DEVCHAIN_FILE_NAME
# # Save L2 state so it can published to NPM
mv $ANVIL_FOLDER/state.json $TMP_FOLDER/$L2_DEVCHAIN_FILE_NAME
echo "Saved anvil L2 state to $TMP_FOLDER/$L2_DEVCHAIN_FILE_NAME"

# Restore L1 state from backup so it can be published to NPM as well
cp $TMP_FOLDER/backup_$L1_DEVCHAIN_FILE_NAME $TMP_FOLDER/$L1_DEVCHAIN_FILE_NAME

# Delete backup
rm $TMP_FOLDER/backup_$L1_DEVCHAIN_FILE_NAME
rm -rf $ANVIL_FOLDER
10 changes: 9 additions & 1 deletion packages/protocol/scripts/foundry/deploy_precompiles.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,12 @@ cast rpc anvil_setCode --rpc-url $ANVIL_RPC_URL $EpochSizeAddress $EpochSizeByte

ProofOfPossesionAddress=0x00000000000000000000000000000000000000fb
ProofOfPossesionBytecode=`cat ./out/ProofOfPossesionPrecompile.sol/ProofOfPossesionPrecompile.json | jq -r '.deployedBytecode.object'`
cast rpc anvil_setCode --rpc-url $ANVIL_RPC_URL $ProofOfPossesionAddress $ProofOfPossesionBytecode
cast rpc anvil_setCode --rpc-url $ANVIL_RPC_URL $ProofOfPossesionAddress $ProofOfPossesionBytecode

NumberValidatorsInCurrentSetPrecompileAddress=0x00000000000000000000000000000000000000f9
NumberValidatorsInCurrentSetPrecompileBytecode=`cat ./out/NumberValidatorsInCurrentSetPrecompile.sol/NumberValidatorsInCurrentSetPrecompile.json | jq -r '.deployedBytecode.object'`
cast rpc anvil_setCode --rpc-url $ANVIL_RPC_URL $NumberValidatorsInCurrentSetPrecompileAddress $NumberValidatorsInCurrentSetPrecompileBytecode

ValidatorSignerAddressFromCurrentSetAddress=0x00000000000000000000000000000000000000fa
ValidatorSignerAddressFromCurrentSetBytecode=`cat ./out/ValidatorSignerAddressFromCurrentSetPrecompile.sol/ValidatorSignerAddressFromCurrentSetPrecompile.json | jq -r '.deployedBytecode.object'`
cast rpc anvil_setCode --rpc-url $ANVIL_RPC_URL $ValidatorSignerAddressFromCurrentSetAddress $ValidatorSignerAddressFromCurrentSetBytecode
1 change: 1 addition & 0 deletions packages/protocol/scripts/foundry/start_anvil.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ cp $PWD/migrations_sol/README.md $TMP_FOLDER/README.md
if nc -z localhost $ANVIL_PORT; then
echo "Port already used"
kill $(lsof -t -i:$ANVIL_PORT)
sleep 5
echo "Killed previous Anvil"
fi

Expand Down
2 changes: 2 additions & 0 deletions packages/protocol/test-sol/devchain/ImportPrecompiles.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@ pragma solidity >=0.8.7 <0.8.20;
// this file only exists so that foundry compiles this contracts
import "@test-sol/precompiles/ProofOfPossesionPrecompile.sol";
import "@test-sol/precompiles/EpochSizePrecompile.sol";
import "@test-sol/precompiles/NumberValidatorsInCurrentSetPrecompile.sol";
import "@test-sol/precompiles/ValidatorSignerAddressFromCurrentSetPrecompile.sol";

contract ImportPrecompiles {}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import "celo-foundry-8/Test.sol";
import { Utils08 } from "@test-sol/utils08.sol";
import { TestConstants } from "@test-sol/constants.sol";
import { MigrationsConstants } from "@migrations-sol/constants.sol";
import { FeeCurrencyDirectory } from "@celo-contracts-8/common/FeeCurrencyDirectory.sol";

import "@celo-contracts/common/interfaces/IRegistry.sol";
import "@celo-contracts/common/interfaces/IProxy.sol";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// TODO move this to test folder
pragma solidity >=0.8.7 <0.8.20;

import "forge-std/console.sol";
import "@celo-contracts/common/interfaces/IRegistry.sol";
import "@celo-contracts/governance/interfaces/IValidators.sol";

contract NumberValidatorsInCurrentSetPrecompile {
address constant ADDRESS = address(0xff - 6);

uint256 public NumberOfValidators = 1;

address internal constant registryAddress = 0x000000000000000000000000000000000000ce10;

receive() external payable {}

fallback(bytes calldata) external payable returns (bytes memory) {
return abi.encodePacked(NumberOfValidators);
}

function setNumberOfValidators() external{
IRegistry registry = IRegistry(registryAddress);
address validatorsAddress = registry.getAddressForString("Validators");
IValidators validatorsContract = IValidators(validatorsAddress);
address[] memory registeredValidators = validatorsContract.getRegisteredValidators();
NumberOfValidators = registeredValidators.length;
}

function getAddress() public pure returns (address) {
return ADDRESS;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// TODO move this to test folder
pragma solidity >=0.8.7 <0.8.20;

import "forge-std/console.sol";
import "@celo-contracts/common/interfaces/IRegistry.sol";
import "@celo-contracts/governance/interfaces/IValidators.sol";

contract ValidatorSignerAddressFromCurrentSetPrecompile {
address constant ADDRESS = address(0xff - 5);

uint256 public constant EPOCH_SIZE = 100;

address[] validators;

address internal constant registryAddress = 0x000000000000000000000000000000000000ce10;

receive() external payable {}

fallback(bytes calldata input) external payable returns (bytes memory) {
uint256 index = getUint256FromBytes(input, 0);
return abi.encodePacked(uint256(uint160(validators[index])));
}

function getAddress() public pure returns (address) {
return ADDRESS;
}

function getUint256FromBytes(bytes memory bs, uint256 start) internal pure returns (uint256) {
return uint256(getBytes32FromBytes(bs, start));
}

function setValidators() external{
IRegistry registry = IRegistry(registryAddress);
address validatorsAddress = registry.getAddressForString("Validators");
IValidators validatorsContract = IValidators(validatorsAddress);
address[] memory registeredValidators = validatorsContract.getRegisteredValidators();
for (uint256 i = 0; i < registeredValidators.length; i++) {
validators.push(registeredValidators[i]);
}
}

/**
* @notice Converts bytes to bytes32.
* @param bs byte[] data
* @param start offset into byte data to convert
* @return bytes32 data
*/
function getBytes32FromBytes(bytes memory bs, uint256 start) internal pure returns (bytes32) {
require(bs.length >= start + 32, "slicing out of range");
bytes32 x;
assembly {
x := mload(add(bs, add(start, 32)))
}
return x;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@ pragma solidity >=0.8.7 <0.8.20;
// this file only exists so that foundry compiles this contracts
import "@test-sol/precompiles/ProofOfPossesionPrecompile.sol";
import "@test-sol/precompiles/EpochSizePrecompile.sol";
import "@test-sol/precompiles/NumberValidatorsInCurrentSetPrecompile.sol";
import "@test-sol/precompiles/ValidatorSignerAddressFromCurrentSetPrecompile.sol";

contract ImportPrecompiles {}

0 comments on commit 2c5a95f

Please sign in to comment.