Skip to content

Commit

Permalink
Packed protocol version (#492)
Browse files Browse the repository at this point in the history
Co-authored-by: perekopskiy <mikeson.dp@gmail.com>
Co-authored-by: Vlad Bochok <41153528+vladbochok@users.noreply.github.com>
Co-authored-by: perekopskiy <53865202+perekopskiy@users.noreply.github.com>
  • Loading branch information
4 people authored May 29, 2024
1 parent 5312fd4 commit 8cc766e
Show file tree
Hide file tree
Showing 16 changed files with 455 additions and 79 deletions.
5 changes: 3 additions & 2 deletions l1-contracts/contracts/common/Config.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,11 @@ uint256 constant PRIORITY_OPERATION_L2_TX_TYPE = 255;
/// @dev Denotes the type of the zkSync transaction that is used for system upgrades.
uint256 constant SYSTEM_UPGRADE_L2_TX_TYPE = 254;

/// @dev The maximal allowed difference between protocol versions in an upgrade. The 100 gap is needed
/// @dev The maximal allowed difference between protocol minor versions in an upgrade. The 100 gap is needed
/// in case a protocol version has been tested on testnet, but then not launched on mainnet, e.g.
/// due to a bug found.
uint256 constant MAX_ALLOWED_PROTOCOL_VERSION_DELTA = 100;
/// We are allowed to jump at most 100 minor versions at a time. The major version is always expected to be 0.
uint256 constant MAX_ALLOWED_MINOR_VERSION_DELTA = 100;

/// @dev The amount of time in seconds the validator has to process the priority transaction
/// NOTE: The constant is set to zero for the Alpha release period
Expand Down
48 changes: 48 additions & 0 deletions l1-contracts/contracts/common/libraries/SemVer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.24;

/// @dev The number of bits dedicated to the "patch" portion of the protocol version.
/// This also defines the bit starting from which the "minor" part is located.
uint256 constant SEMVER_MINOR_OFFSET = 32;

/// @dev The number of bits dedicated to the "patch" and "minor" portions of the protocol version.
/// This also defines the bit starting from which the "major" part is located.
/// Note, that currently, only major version of "0" is supported.
uint256 constant SEMVER_MAJOR_OFFSET = 64;

/**
* @author Matter Labs
* @custom:security-contact security@matterlabs.dev
* @notice The library for managing SemVer for the protocol version.
*/
library SemVer {
/// @notice Unpacks the SemVer version from a single uint256 into major, minor and patch components.
/// @param _packedProtocolVersion The packed protocol version.
/// @return major The major version.
/// @return minor The minor version.
/// @return patch The patch version.
function unpackSemVer(
uint96 _packedProtocolVersion
) internal pure returns (uint32 major, uint32 minor, uint32 patch) {
patch = uint32(_packedProtocolVersion);
minor = uint32(_packedProtocolVersion >> SEMVER_MINOR_OFFSET);
major = uint32(_packedProtocolVersion >> SEMVER_MAJOR_OFFSET);
}

/// @notice Packs the SemVer version from the major, minor and patch components into a single uint96.
/// @param _major The major version.
/// @param _minor The minor version.
/// @param _patch The patch version.
/// @return packedProtocolVersion The packed protocol version.
function packSemVer(
uint32 _major,
uint32 _minor,
uint32 _patch
) internal pure returns (uint96 packedProtocolVersion) {
packedProtocolVersion =
uint96(_patch) |
(uint96(_minor) << SEMVER_MINOR_OFFSET) |
(uint96(_major) << SEMVER_MAJOR_OFFSET);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,17 @@ contract CustomUpgradeTest is BaseZkSyncUpgrade {
/// @notice The main function that will be called by the upgrade proxy.
/// @param _proposedUpgrade The upgrade to be executed.
function upgrade(ProposedUpgrade calldata _proposedUpgrade) public override returns (bytes32) {
_setNewProtocolVersion(_proposedUpgrade.newProtocolVersion);
(uint32 newMinorVersion, bool isPatchOnly) = _setNewProtocolVersion(_proposedUpgrade.newProtocolVersion);
_upgradeL1Contract(_proposedUpgrade.l1ContractsUpgradeCalldata);
_upgradeVerifier(_proposedUpgrade.verifier, _proposedUpgrade.verifierParams);
_setBaseSystemContracts(_proposedUpgrade.bootloaderHash, _proposedUpgrade.defaultAccountHash);
_setBaseSystemContracts(_proposedUpgrade.bootloaderHash, _proposedUpgrade.defaultAccountHash, isPatchOnly);

bytes32 txHash;
txHash = _setL2SystemContractUpgrade(
_proposedUpgrade.l2ProtocolUpgradeTx,
_proposedUpgrade.factoryDeps,
_proposedUpgrade.newProtocolVersion
newMinorVersion,
isPatchOnly
);

_postUpgrade(_proposedUpgrade.postUpgradeCalldata);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,6 @@ interface IStateTransitionManager {
uint256 _oldProtocolVersion,
Diamond.DiamondCutData calldata _diamondCut
) external;

function getSemverProtocolVersion() external view returns (uint32, uint32, uint32);
}
22 changes: 17 additions & 5 deletions l1-contracts/contracts/state-transition/StateTransitionManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
pragma solidity 0.8.24;

import {EnumerableMap} from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol";
import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";

import {Diamond} from "./libraries/Diamond.sol";
import {DiamondProxy} from "./chain-deps/DiamondProxy.sol";
Expand All @@ -21,6 +22,7 @@ import {ProposedUpgrade} from "../upgrades/BaseZkSyncUpgrade.sol";
import {ReentrancyGuard} from "../common/ReentrancyGuard.sol";
import {REQUIRED_L2_GAS_PRICE_PER_PUBDATA, L2_TO_L1_LOG_SERIALIZE_SIZE, DEFAULT_L2_LOGS_TREE_ROOT_HASH, EMPTY_STRING_KECCAK, SYSTEM_UPGRADE_L2_TX_TYPE, PRIORITY_TX_MAX_GAS_LIMIT} from "../common/Config.sol";
import {VerifierParams} from "./chain-interfaces/IVerifier.sol";
import {SemVer} from "../common/libraries/SemVer.sol";

/// @title State Transition Manager contract
/// @author Matter Labs
Expand All @@ -47,7 +49,7 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own
/// @dev The genesisUpgrade contract address, used to setChainId
address public genesisUpgrade;

/// @dev The current protocolVersion
/// @dev The current packed protocolVersion. To access human-readable version, use `getSemverProtocolVersion` function.
uint256 public protocolVersion;

/// @dev The timestamp when protocolVersion can be last used
Expand Down Expand Up @@ -84,6 +86,12 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own
_;
}

/// @return The tuple of (major, minor, patch) protocol version.
function getSemverProtocolVersion() external view returns (uint32, uint32, uint32) {
// slither-disable-next-line unused-return
return SemVer.unpackSemVer(SafeCast.toUint96(protocolVersion));
}

/// @notice Returns all the registered hyperchain addresses
function getAllHyperchains() public view override returns (address[] memory chainAddresses) {
uint256[] memory keys = hyperchainMap.keys();
Expand Down Expand Up @@ -280,6 +288,10 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own
uint256[] memory uintEmptyArray;
bytes[] memory bytesEmptyArray;

uint256 cachedProtocolVersion = protocolVersion;
// slither-disable-next-line unused-return
(, uint32 minorVersion, ) = SemVer.unpackSemVer(SafeCast.toUint96(cachedProtocolVersion));

L2CanonicalTransaction memory l2ProtocolUpgradeTx = L2CanonicalTransaction({
txType: SYSTEM_UPGRADE_L2_TX_TYPE,
from: uint256(uint160(L2_FORCE_DEPLOYER_ADDR)),
Expand All @@ -289,8 +301,8 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own
maxFeePerGas: uint256(0),
maxPriorityFeePerGas: uint256(0),
paymaster: uint256(0),
// Note, that the protocol version is used as "nonce" for system upgrade transactions
nonce: protocolVersion,
// Note, that the `minor` of the protocol version is used as "nonce" for system upgrade transactions
nonce: uint256(minorVersion),
value: 0,
reserved: [uint256(0), 0, 0, 0],
data: systemContextCalldata,
Expand All @@ -314,7 +326,7 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own
l1ContractsUpgradeCalldata: new bytes(0),
postUpgradeCalldata: new bytes(0),
upgradeTimestamp: 0,
newProtocolVersion: protocolVersion
newProtocolVersion: cachedProtocolVersion
});

Diamond.FacetCut[] memory emptyArray;
Expand All @@ -325,7 +337,7 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own
});

IAdmin(_chainContract).executeUpgrade(cutData);
emit SetChainIdUpgrade(_chainContract, l2ProtocolUpgradeTx, protocolVersion);
emit SetChainIdUpgrade(_chainContract, l2ProtocolUpgradeTx, cachedProtocolVersion);
}

/// @dev used to register already deployed hyperchain contracts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

pragma solidity 0.8.24;

import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";

import {ZkSyncHyperchainBase} from "./ZkSyncHyperchainBase.sol";
import {PubdataPricingMode} from "../ZkSyncHyperchainStorage.sol";
import {VerifierParams} from "../../../state-transition/chain-interfaces/IVerifier.sol";
Expand All @@ -10,6 +12,7 @@ import {PriorityQueue, PriorityOperation} from "../../../state-transition/librar
import {UncheckedMath} from "../../../common/libraries/UncheckedMath.sol";
import {IGetters} from "../../chain-interfaces/IGetters.sol";
import {ILegacyGetters} from "../../chain-interfaces/ILegacyGetters.sol";
import {SemVer} from "../../../common/libraries/SemVer.sol";

// While formally the following import is not used, it is needed to inherit documentation from it
import {IZkSyncHyperchainBase} from "../../chain-interfaces/IZkSyncHyperchainBase.sol";
Expand Down Expand Up @@ -143,6 +146,12 @@ contract GettersFacet is ZkSyncHyperchainBase, IGetters, ILegacyGetters {
return s.protocolVersion;
}

/// @inheritdoc IGetters
function getSemverProtocolVersion() external view returns (uint32, uint32, uint32) {
// slither-disable-next-line unused-return
return SemVer.unpackSemVer(SafeCast.toUint96(s.protocolVersion));
}

/// @inheritdoc IGetters
function getL2SystemContractsUpgradeTxHash() external view returns (bytes32) {
return s.l2SystemContractsUpgradeTxHash;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,12 @@ interface IGetters is IZkSyncHyperchainBase {
/// @return Whether the diamond is frozen or not
function isDiamondStorageFrozen() external view returns (bool);

/// @return The current protocol version
/// @return The current packed protocol version. To access human-readable version, use `getSemverProtocolVersion` function.
function getProtocolVersion() external view returns (uint256);

/// @return The tuple of (major, minor, patch) protocol version.
function getSemverProtocolVersion() external view returns (uint32, uint32, uint32);

/// @return The upgrade system contract transaction hash, 0 if the upgrade is not initialized
function getL2SystemContractsUpgradeTxHash() external view returns (bytes32);

Expand Down
Loading

0 comments on commit 8cc766e

Please sign in to comment.