Skip to content

Commit

Permalink
Change how we update chain creation params (matter-labs#502)
Browse files Browse the repository at this point in the history
  • Loading branch information
StanislavBreadless authored May 31, 2024
1 parent 16ae765 commit fe0b7f4
Show file tree
Hide file tree
Showing 14 changed files with 327 additions and 129 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ max_number_of_chains = 100
create2_factory_salt = "0x00000000000000000000000000000000000000000000000000000000000000ff"
create2_factory_addr = "0x0000000000000000000000000000000000000000"
validator_timelock_execution_delay = 0
genesis_root = "0x0000000000000000000000000000000000000000000000000000000000000000"
genesis_rollup_leaf_index = 0
genesis_batch_commitment = "0x0000000000000000000000000000000000000000000000000000000000000000"
genesis_root = "0x1000000000000000000000000000000000000000000000000000000000000000"
genesis_rollup_leaf_index = 1
genesis_batch_commitment = "0x1000000000000000000000000000000000000000000000000000000000000000"
latest_protocol_version = 0
recursion_node_level_vk_hash = "0x0000000000000000000000000000000000000000000000000000000000000000"
recursion_leaf_level_vk_hash = "0x0000000000000000000000000000000000000000000000000000000000000000"
Expand Down
14 changes: 9 additions & 5 deletions l1-contracts-foundry/script/DeployL1.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {MailboxFacet} from "contracts/state-transition/chain-deps/facets/Mailbox
import {GettersFacet} from "contracts/state-transition/chain-deps/facets/Getters.sol";
import {DiamondInit} from "contracts/state-transition/chain-deps/DiamondInit.sol";
import {StateTransitionManager} from "contracts/state-transition/StateTransitionManager.sol";
import {StateTransitionManagerInitializeData} from "contracts/state-transition/IStateTransitionManager.sol";
import {StateTransitionManagerInitializeData, ChainCreationParams} from "contracts/state-transition/IStateTransitionManager.sol";
import {IStateTransitionManager} from "contracts/state-transition/IStateTransitionManager.sol";
import {Diamond} from "contracts/state-transition/libraries/Diamond.sol";
import {InitializeDataNewChain as DiamondInitializeDataNewChain} from "contracts/state-transition/chain-interfaces/IDiamondInit.sol";
Expand Down Expand Up @@ -428,14 +428,18 @@ contract DeployL1Script is Script {

config.contracts.diamondCutData = abi.encode(diamondCut);

StateTransitionManagerInitializeData memory diamondInitData = StateTransitionManagerInitializeData({
owner: config.ownerAddress,
validatorTimelock: addresses.validatorTimelock,
ChainCreationParams memory chainCreationParams = ChainCreationParams({
genesisUpgrade: addresses.stateTransition.genesisUpgrade,
genesisBatchHash: config.contracts.genesisRoot,
genesisIndexRepeatedStorageChanges: uint64(config.contracts.genesisRollupLeafIndex),
genesisBatchCommitment: config.contracts.genesisBatchCommitment,
diamondCut: diamondCut,
diamondCut: diamondCut
});

StateTransitionManagerInitializeData memory diamondInitData = StateTransitionManagerInitializeData({
owner: config.ownerAddress,
validatorTimelock: addresses.validatorTimelock,
chainCreationParams: chainCreationParams,
protocolVersion: config.contracts.latestProtocolVersion
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,28 @@ import {FeeParams} from "./chain-deps/ZkSyncHyperchainStorage.sol";
/// @dev We use struct instead of raw parameters in `initialize` function to prevent "Stack too deep" error
/// @param owner The address who can manage non-critical updates in the contract
/// @param validatorTimelock The address that serves as consensus, i.e. can submit blocks to be processed
/// @param chainCreationParams The struct that contains the fields that define how a new chain should be created
/// @param protocolVersion The initial protocol version on the newly deployed chain
struct StateTransitionManagerInitializeData {
address owner;
address validatorTimelock;
ChainCreationParams chainCreationParams;
uint256 protocolVersion;
}

/// @notice The struct that contains the fields that define how a new chain should be created
/// within this STM.
/// @param genesisUpgrade The address that is used in the diamond cut initialize address on chain creation
/// @param genesisBatchHash Batch hash of the genesis (initial) batch
/// @param genesisIndexRepeatedStorageChanges The serial number of the shortcut storage key for the genesis batch
/// @param genesisBatchCommitment The zk-proof commitment for the genesis batch
/// @param diamondCut The diamond cut for the first upgrade transaction on the newly deployed chain
/// @param protocolVersion The initial protocol version on the newly deployed chain
struct StateTransitionManagerInitializeData {
address owner;
address validatorTimelock;
struct ChainCreationParams {
address genesisUpgrade;
bytes32 genesisBatchHash;
uint64 genesisIndexRepeatedStorageChanges;
bytes32 genesisBatchCommitment;
Diamond.DiamondCutData diamondCut;
uint256 protocolVersion;
}

interface IStateTransitionManager {
Expand All @@ -48,8 +55,14 @@ interface IStateTransitionManager {
/// @notice ValidatorTimelock changed
event NewValidatorTimelock(address indexed oldValidatorTimelock, address indexed newValidatorTimelock);

/// @notice InitialCutHash changed
event NewInitialCutHash(bytes32 indexed oldInitialCutHash, bytes32 indexed newInitialCutHash);
/// @notice chain creation parameters changed
event NewChainCreationParams(
address genesisUpgrade,
bytes32 genesisBatchHash,
uint64 genesisIndexRepeatedStorageChanges,
bytes32 genesisBatchCommitment,
bytes32 newInitialCutHash
);

/// @notice new UpgradeCutHash
event NewUpgradeCutHash(uint256 indexed protocolVersion, bytes32 indexed upgradeCutHash);
Expand Down Expand Up @@ -85,10 +98,10 @@ interface IStateTransitionManager {

function initialize(StateTransitionManagerInitializeData calldata _initializeData) external;

function setInitialCutHash(Diamond.DiamondCutData calldata _diamondCut) external;

function setValidatorTimelock(address _validatorTimelock) external;

function setChainCreationParams(ChainCreationParams calldata _chainCreationParams) external;

function getChainAdmin(uint256 _chainId) external view returns (address);

function createNewChain(
Expand Down
56 changes: 39 additions & 17 deletions l1-contracts/contracts/state-transition/StateTransitionManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {IAdmin} from "./chain-interfaces/IAdmin.sol";
import {IDefaultUpgrade} from "../upgrades/IDefaultUpgrade.sol";
import {IDiamondInit} from "./chain-interfaces/IDiamondInit.sol";
import {IExecutor} from "./chain-interfaces/IExecutor.sol";
import {IStateTransitionManager, StateTransitionManagerInitializeData} from "./IStateTransitionManager.sol";
import {IStateTransitionManager, StateTransitionManagerInitializeData, ChainCreationParams} from "./IStateTransitionManager.sol";
import {ISystemContext} from "./l2-deps/ISystemContext.sol";
import {IZkSyncHyperchain} from "./chain-interfaces/IZkSyncHyperchain.sol";
import {FeeParams} from "./chain-deps/ZkSyncHyperchainStorage.sol";
Expand Down Expand Up @@ -72,6 +72,10 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own
constructor(address _bridgehub, uint256 _maxNumberOfHyperchains) reentrancyGuardInitializer {
BRIDGE_HUB = _bridgehub;
MAX_NUMBER_OF_HYPERCHAINS = _maxNumberOfHyperchains;

// While this does not provide a protection in the production, it is needed for local testing
// Length of the L2Log encoding should not be equal to the length of other L2Logs' tree nodes preimages
assert(L2_TO_L1_LOG_SERIALIZE_SIZE != 2 * 32);
}

/// @notice only the bridgehub can call
Expand Down Expand Up @@ -124,28 +128,54 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own
require(_initializeData.owner != address(0), "STM: owner zero");
_transferOwnership(_initializeData.owner);

genesisUpgrade = _initializeData.genesisUpgrade;
protocolVersion = _initializeData.protocolVersion;
protocolVersionDeadline[_initializeData.protocolVersion] = type(uint256).max;
validatorTimelock = _initializeData.validatorTimelock;

_setChainCreationParams(_initializeData.chainCreationParams);
}

/// @notice Updates the parameters with which a new chain is created
/// @param _chainCreationParams The new chain creation parameters
function _setChainCreationParams(ChainCreationParams calldata _chainCreationParams) internal {
require(_chainCreationParams.genesisUpgrade != address(0), "STM: genesisUpgrade zero");
require(_chainCreationParams.genesisBatchHash != bytes32(0), "STM: genesisBatchHash zero");
require(
_chainCreationParams.genesisIndexRepeatedStorageChanges != uint64(0),
"STM: genesisIndexRepeatedStorageChanges zero"
);
require(_chainCreationParams.genesisBatchCommitment != bytes32(0), "STM: genesisBatchCommitment zero");

genesisUpgrade = _chainCreationParams.genesisUpgrade;

// We need to initialize the state hash because it is used in the commitment of the next batch
IExecutor.StoredBatchInfo memory batchZero = IExecutor.StoredBatchInfo({
batchNumber: 0,
batchHash: _initializeData.genesisBatchHash,
indexRepeatedStorageChanges: _initializeData.genesisIndexRepeatedStorageChanges,
batchHash: _chainCreationParams.genesisBatchHash,
indexRepeatedStorageChanges: _chainCreationParams.genesisIndexRepeatedStorageChanges,
numberOfLayer1Txs: 0,
priorityOperationsHash: EMPTY_STRING_KECCAK,
l2LogsTreeRoot: DEFAULT_L2_LOGS_TREE_ROOT_HASH,
timestamp: 0,
commitment: _initializeData.genesisBatchCommitment
commitment: _chainCreationParams.genesisBatchCommitment
});
storedBatchZero = keccak256(abi.encode(batchZero));
initialCutHash = keccak256(abi.encode(_initializeData.diamondCut));
bytes32 newInitialCutHash = keccak256(abi.encode(_chainCreationParams.diamondCut));
initialCutHash = newInitialCutHash;

emit NewChainCreationParams({
genesisUpgrade: _chainCreationParams.genesisUpgrade,
genesisBatchHash: _chainCreationParams.genesisBatchHash,
genesisIndexRepeatedStorageChanges: _chainCreationParams.genesisIndexRepeatedStorageChanges,
genesisBatchCommitment: _chainCreationParams.genesisBatchCommitment,
newInitialCutHash: newInitialCutHash
});
}

// While this does not provide a protection in the production, it is needed for local testing
// Length of the L2Log encoding should not be equal to the length of other L2Logs' tree nodes preimages
assert(L2_TO_L1_LOG_SERIALIZE_SIZE != 2 * 32);
/// @notice Updates the parameters with which a new chain is created
/// @param _chainCreationParams The new chain creation parameters
function setChainCreationParams(ChainCreationParams calldata _chainCreationParams) external onlyOwner {
_setChainCreationParams(_chainCreationParams);
}

/// @notice Starts the transfer of admin rights. Only the current admin can propose a new pending one.
Expand Down Expand Up @@ -181,14 +211,6 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own
emit NewValidatorTimelock(oldValidatorTimelock, _validatorTimelock);
}

/// @dev set initial cutHash
function setInitialCutHash(Diamond.DiamondCutData calldata _diamondCut) external onlyOwner {
bytes32 oldInitialCutHash = initialCutHash;
bytes32 newCutHash = keccak256(abi.encode(_diamondCut));
initialCutHash = newCutHash;
emit NewInitialCutHash(oldInitialCutHash, newCutHash);
}

/// @dev set New Version with upgrade from old version
function setNewVersionUpgrade(
Diamond.DiamondCutData calldata _cutData,
Expand Down
6 changes: 3 additions & 3 deletions l1-contracts/src.ts/deploy-test-process.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ const testnetTokenPath = `${testConfigPath}/hardhat.json`;

export async function loadDefaultEnvVarsForTests(deployWallet: Wallet) {
process.env.CONTRACTS_GENESIS_PROTOCOL_SEMANTIC_VERSION = "0.21.0";
process.env.CONTRACTS_GENESIS_ROOT = ethers.constants.HashZero;
process.env.CONTRACTS_GENESIS_ROLLUP_LEAF_INDEX = "0";
process.env.CONTRACTS_GENESIS_BATCH_COMMITMENT = ethers.constants.HashZero;
process.env.CONTRACTS_GENESIS_ROOT = "0x0000000000000000000000000000000000000000000000000000000000000001";
process.env.CONTRACTS_GENESIS_ROLLUP_LEAF_INDEX = "1";
process.env.CONTRACTS_GENESIS_BATCH_COMMITMENT = "0x0000000000000000000000000000000000000000000000000000000000000001";
// process.env.CONTRACTS_GENESIS_UPGRADE_ADDR = ADDRESS_ONE;
process.env.CONTRACTS_PRIORITY_TX_MAX_GAS_LIMIT = "72000000";
process.env.CONTRACTS_FRI_RECURSION_NODE_LEVEL_VK_HASH = ethers.constants.HashZero;
Expand Down
60 changes: 19 additions & 41 deletions l1-contracts/src.ts/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
packSemver,
readBatchBootloaderBytecode,
readSystemContractsBytecode,
SYSTEM_CONFIG,
unpackStringSemVer,
} from "../scripts/utils";
import { getTokens } from "./deploy-token";
Expand All @@ -22,6 +21,7 @@ import {
PubdataPricingMode,
hashL2Bytecode,
DIAMOND_CUT_DATA_ABI_STRING,
compileInitialCutHash,
} from "./utils";
import { IBridgehubFactory } from "../typechain/IBridgehubFactory";
import { IGovernanceFactory } from "../typechain/IGovernanceFactory";
Expand All @@ -35,7 +35,7 @@ import { L1SharedBridgeFactory } from "../typechain/L1SharedBridgeFactory";
import { SingletonFactoryFactory } from "../typechain/SingletonFactoryFactory";
import { ValidatorTimelockFactory } from "../typechain/ValidatorTimelockFactory";
import type { FacetCut } from "./diamondCut";
import { diamondCut, getCurrentFacetCutsForAdd } from "./diamondCut";
import { getCurrentFacetCutsForAdd } from "./diamondCut";

import { ERC20Factory } from "../typechain";
import type { Contract, Overrides } from "@ethersproject/contracts";
Expand Down Expand Up @@ -98,43 +98,17 @@ export class Deployer {
recursionCircuitsSetVksHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
};
const priorityTxMaxGasLimit = getNumberFromEnv("CONTRACTS_PRIORITY_TX_MAX_GAS_LIMIT");
const DiamondInit = new Interface(hardhat.artifacts.readArtifactSync("DiamondInit").abi);

const feeParams = {
pubdataPricingMode: PubdataPricingMode.Rollup,
batchOverheadL1Gas: SYSTEM_CONFIG.priorityTxBatchOverheadL1Gas,
maxPubdataPerBatch: SYSTEM_CONFIG.priorityTxPubdataPerBatch,
priorityTxMaxPubdata: SYSTEM_CONFIG.priorityTxMaxPubdata,
maxL2GasPerBatch: SYSTEM_CONFIG.priorityTxMaxGasPerBatch,
minimalL2GasPrice: SYSTEM_CONFIG.priorityTxMinimalGasPrice,
};

const diamondInitCalldata = DiamondInit.encodeFunctionData("initialize", [
// these first values are set in the contract
{
chainId: "0x0000000000000000000000000000000000000000000000000000000000000001",
bridgehub: "0x0000000000000000000000000000000000001234",
stateTransitionManager: "0x0000000000000000000000000000000000002234",
protocolVersion: "0x0000000000000000000000000000000000002234",
admin: "0x0000000000000000000000000000000000003234",
validatorTimelock: "0x0000000000000000000000000000000000004234",
baseToken: "0x0000000000000000000000000000000000004234",
baseTokenBridge: "0x0000000000000000000000000000000000004234",
storedBatchZero: "0x0000000000000000000000000000000000000000000000000000000000005432",
verifier: this.addresses.StateTransition.Verifier,
verifierParams,
l2BootloaderBytecodeHash: L2_BOOTLOADER_BYTECODE_HASH,
l2DefaultAccountBytecodeHash: L2_DEFAULT_ACCOUNT_BYTECODE_HASH,
priorityTxMaxGasLimit,
feeParams,
blobVersionedHashRetriever: this.addresses.BlobVersionedHashRetriever,
},
]);

return diamondCut(
return compileInitialCutHash(
facetCuts,
verifierParams,
L2_BOOTLOADER_BYTECODE_HASH,
L2_DEFAULT_ACCOUNT_BYTECODE_HASH,
this.addresses.StateTransition.Verifier,
this.addresses.BlobVersionedHashRetriever,
+priorityTxMaxGasLimit,
this.addresses.StateTransition.DiamondInit,
"0x" + diamondInitCalldata.slice(2 + (4 + 9 * 32) * 2)
false
);
}

Expand Down Expand Up @@ -317,15 +291,19 @@ export class Deployer {

const stateTransitionManager = new Interface(hardhat.artifacts.readArtifactSync("StateTransitionManager").abi);

const chainCreationParams = {
genesisUpgrade: this.addresses.StateTransition.GenesisUpgrade,
genesisBatchHash,
genesisIndexRepeatedStorageChanges: genesisRollupLeafIndex,
genesisBatchCommitment,
diamondCut,
};

const initCalldata = stateTransitionManager.encodeFunctionData("initialize", [
{
owner: this.addresses.Governance,
validatorTimelock: this.addresses.ValidatorTimeLock,
genesisUpgrade: this.addresses.StateTransition.GenesisUpgrade,
genesisBatchHash,
genesisIndexRepeatedStorageChanges: genesisRollupLeafIndex,
genesisBatchCommitment,
diamondCut,
chainCreationParams,
protocolVersion,
},
]);
Expand Down
Loading

0 comments on commit fe0b7f4

Please sign in to comment.