diff --git a/contracts/binding/build.rs b/contracts/binding/build.rs index 1c45e66a46..63de37f863 100644 --- a/contracts/binding/build.rs +++ b/contracts/binding/build.rs @@ -47,6 +47,7 @@ fn main() { "TopDownFinalityFacet", "XnetMessagingFacet", "GatewayMessengerFacet", + "SubnetActorActivityFacet", "SubnetActorCheckpointingFacet", "SubnetActorDiamond", "SubnetActorGetterFacet", @@ -60,7 +61,6 @@ fn main() { "LibStakingChangeLog", "LibGateway", "LibQuorum", - "ValidatorRewardFacet", ] { let module_name = camel_to_snake(contract_name); let input_path = diff --git a/contracts/binding/src/lib.rs b/contracts/binding/src/lib.rs index a617bead0e..bbc78042bd 100644 --- a/contracts/binding/src/lib.rs +++ b/contracts/binding/src/lib.rs @@ -30,6 +30,8 @@ pub mod ownership_facet; #[allow(clippy::all)] pub mod register_subnet_facet; #[allow(clippy::all)] +pub mod subnet_actor_activity_facet; +#[allow(clippy::all)] pub mod subnet_actor_checkpointing_facet; #[allow(clippy::all)] pub mod subnet_actor_diamond; @@ -48,8 +50,6 @@ pub mod subnet_registry_diamond; #[allow(clippy::all)] pub mod top_down_finality_facet; #[allow(clippy::all)] -pub mod validator_reward_facet; -#[allow(clippy::all)] pub mod xnet_messaging_facet; // The list of contracts need to convert FvmAddress to fvm_shared::Address diff --git a/contracts/contracts/SubnetActorDiamond.sol b/contracts/contracts/SubnetActorDiamond.sol index 7f3fb5087c..cf4ac475b9 100644 --- a/contracts/contracts/SubnetActorDiamond.sol +++ b/contracts/contracts/SubnetActorDiamond.sol @@ -15,7 +15,7 @@ import {SubnetIDHelper} from "./lib/SubnetIDHelper.sol"; import {LibStaking} from "./lib/LibStaking.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {AssetHelper} from "./lib/AssetHelper.sol"; -import {LibValidatorReward} from "./activities/ValidatorRewardFacet.sol"; +import {LibActivity} from "./lib/LibActivity.sol"; error FunctionNotFound(bytes4 _functionSelector); @@ -107,7 +107,7 @@ contract SubnetActorDiamond { } if (params.validatorRewarder != address(0)) { - LibValidatorReward.setRewarder(params.validatorRewarder); + LibActivity.setRewarder(params.validatorRewarder); } } diff --git a/contracts/contracts/SubnetRegistryDiamond.sol b/contracts/contracts/SubnetRegistryDiamond.sol index 250dfffb61..871d67a066 100644 --- a/contracts/contracts/SubnetRegistryDiamond.sol +++ b/contracts/contracts/SubnetRegistryDiamond.sol @@ -25,7 +25,7 @@ contract SubnetRegistryDiamond { address diamondCutFacet; address diamondLoupeFacet; address ownershipFacet; - address validatorRewardFacet; + address activityFacet; bytes4[] subnetActorGetterSelectors; bytes4[] subnetActorManagerSelectors; bytes4[] subnetActorRewarderSelectors; @@ -34,7 +34,7 @@ contract SubnetRegistryDiamond { bytes4[] subnetActorDiamondCutSelectors; bytes4[] subnetActorDiamondLoupeSelectors; bytes4[] subnetActorOwnershipSelectors; - bytes4[] validatorRewardSelectors; + bytes4[] subnetActorActivitySelectors; SubnetCreationPrivileges creationPrivileges; } @@ -66,7 +66,7 @@ contract SubnetRegistryDiamond { if (params.ownershipFacet == address(0)) { revert FacetCannotBeZero(); } - if (params.validatorRewardFacet == address(0)) { + if (params.activityFacet == address(0)) { revert FacetCannotBeZero(); } @@ -88,7 +88,7 @@ contract SubnetRegistryDiamond { s.SUBNET_ACTOR_DIAMOND_CUT_FACET = params.diamondCutFacet; s.SUBNET_ACTOR_LOUPE_FACET = params.diamondLoupeFacet; s.SUBNET_ACTOR_OWNERSHIP_FACET = params.ownershipFacet; - s.VALIDATOR_REWARD_FACET = params.validatorRewardFacet; + s.VALIDATOR_REWARD_FACET = params.activityFacet; s.subnetActorGetterSelectors = params.subnetActorGetterSelectors; s.subnetActorManagerSelectors = params.subnetActorManagerSelectors; @@ -98,7 +98,7 @@ contract SubnetRegistryDiamond { s.subnetActorDiamondCutSelectors = params.subnetActorDiamondCutSelectors; s.subnetActorDiamondLoupeSelectors = params.subnetActorDiamondLoupeSelectors; s.subnetActorOwnershipSelectors = params.subnetActorOwnershipSelectors; - s.validatorRewardSelectors = params.validatorRewardSelectors; + s.subnetActorActivitySelectors = params.subnetActorActivitySelectors; s.creationPrivileges = params.creationPrivileges; } diff --git a/contracts/contracts/activities/IValidatorRewarder.sol b/contracts/contracts/activities/IValidatorRewarder.sol deleted file mode 100644 index 052b233dea..0000000000 --- a/contracts/contracts/activities/IValidatorRewarder.sol +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.23; - -import {SubnetID} from "../structs/Subnet.sol"; -import {Consensus} from "./Activity.sol"; - -/// @title ValidatorRewarder interface. -/// -/// @dev Implement this interface and supply the address of the implementation contract at subnet creation to process -/// subnet summaries at this level, and disburse rewards to validators based on their block production activity. -/// -/// This interface will be called by the subnet actor when a relayer presents a -interface IValidatorRewarder { - /// @notice Called by the subnet manager contract to instruct the rewarder to process the subnet summary and - /// disburse any relevant rewards. - /// @dev This method should revert if the summary is invalid; this will cause the - function disburseRewards(SubnetID calldata id, Consensus.ValidatorData calldata detail) external; -} - -/// @title Validator reward setup interface -/// -/// @dev This is used to initialize a reward distribution -interface IValidatorRewardSetup { - function initDistribution( - SubnetID calldata subnetId, - uint64 checkpointHeight, - bytes32 commitment, - uint64 totalActiveValidators - ) external; -} diff --git a/contracts/contracts/activities/LibActivityMerkleVerifier.sol b/contracts/contracts/activities/LibActivityMerkleVerifier.sol deleted file mode 100644 index 42a737b346..0000000000 --- a/contracts/contracts/activities/LibActivityMerkleVerifier.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.23; - -import {SubnetID} from "../structs/Subnet.sol"; -import {InvalidActivityProof} from "../errors/IPCErrors.sol"; -import {Consensus} from "./Activity.sol"; -import {MerkleProof} from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; - -/// Verifies the proof to the commitment in subnet activity summary -library LibActivityMerkleVerifier { - function ensureValidProof( - bytes32 commitment, - Consensus.ValidatorData calldata detail, - Consensus.MerkleHash[] calldata proof - ) internal pure { - // Constructing leaf: https://github.com/OpenZeppelin/merkle-tree#leaf-hash - bytes32 leaf = keccak256(bytes.concat(keccak256(abi.encode(detail.validator, detail.blocksCommitted)))); - // converting proof to bytes32[] - bytes32[] memory proofBytes = new bytes32[](proof.length); - for (uint256 i = 0; i < proof.length; i++) { - proofBytes[i] = Consensus.MerkleHash.unwrap(proof[i]); - } - bool valid = MerkleProof.verify({proof: proofBytes, root: commitment, leaf: leaf}); - if (!valid) { - revert InvalidActivityProof(); - } - } -} diff --git a/contracts/contracts/activities/ValidatorRewardFacet.sol b/contracts/contracts/activities/ValidatorRewardFacet.sol deleted file mode 100644 index 1927a9f738..0000000000 --- a/contracts/contracts/activities/ValidatorRewardFacet.sol +++ /dev/null @@ -1,237 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.23; - -import {Consensus} from "./Activity.sol"; - -import {EnumerableMap} from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; -import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; -import {IValidatorRewarder, IValidatorRewardSetup} from "./IValidatorRewarder.sol"; -import {LibActivityMerkleVerifier} from "./LibActivityMerkleVerifier.sol"; -import {LibDiamond} from "../lib/LibDiamond.sol"; -import {NotAuthorized, SubnetNoTargetCommitment, CommitmentAlreadyInitialized, ValidatorAlreadyClaimed, NotGateway, NotOwner} from "../errors/IPCErrors.sol"; -import {Pausable} from "../lib/LibPausable.sol"; -import {ReentrancyGuard} from "../lib/LibReentrancyGuard.sol"; -import {SubnetIDHelper} from "../lib/SubnetIDHelper.sol"; -import {SubnetID} from "../structs/Subnet.sol"; - -/// The validator reward facet for the parent subnet, i.e. for validators in the child subnet -/// to claim their reward in the parent subnet, which should be the current subnet this facet -/// is deployed. -contract ValidatorRewardFacet is ReentrancyGuard, Pausable { - // Entrypoint for validators to batch claim rewards in the parent subnet, for a given subnet, - // against multiple checkpoints at once. Atomically succeeds or reverts. - function batchSubnetClaim( - SubnetID calldata subnet, - uint64[] calldata checkpointHeights, - Consensus.ValidatorClaim[] calldata claims - ) external nonReentrant whenNotPaused { - require(checkpointHeights.length == claims.length, "length mismatch"); - uint256 len = claims.length; - for (uint256 i = 0; i < len; ) { - _claim(subnet, checkpointHeights[i], claims[i].data, claims[i].proof); - unchecked { - i++; - } - } - } - - /// Entrypoint for validators to claim their reward for doing work in the child subnet. - function claim( - SubnetID calldata subnet, - uint64 checkpointHeight, - Consensus.ValidatorData calldata data, - Consensus.MerkleHash[] calldata proof - ) external nonReentrant whenNotPaused { - _claim(subnet, checkpointHeight, data, proof); - } - - // ======== Internal functions =========== - - function _claim( - SubnetID calldata subnetId, - uint64 checkpointHeight, - Consensus.ValidatorData calldata detail, - Consensus.MerkleHash[] calldata proof - ) internal { - ValidatorRewardStorage storage s = LibValidatorReward.facetStorage(); - - // Note: No need to check if the subnet is active. If the subnet is not active, the checkpointHeight - // will never exist. - if (msg.sender != detail.validator) { - revert NotAuthorized(msg.sender); - } - - LibValidatorReward.handleDistribution(subnetId, checkpointHeight, detail, proof); - } -} - -/// The activity summary commiment that is currently under reward distribution -struct RewardDistribution { - /// Total number of valdators to claim the distribution - uint64 totalValidators; - /// The list of validators that have claimed the reward - EnumerableSet.AddressSet claimed; -} - -/// Used by the SubnetActor to track the rewards for each validator -struct ValidatorRewardStorage { - /// @notice The contract address for the validator rewarder. - address validatorRewarder; - /// @notice Summaries look up pending to be processed. - /// If the validator rewarder is non-zero, these denote summaries presentable at this level. - /// If the validator rewarder is zero, these summaries must be relayed upwards in the next bottom-up checkpoint. - /// Partitioned by subnet ID (hash) then by checkpoint block height in the child subnet to the commitment - mapping(bytes32 => EnumerableMap.Bytes32ToBytes32Map) commitments; - /// @notice Index over presentable summaries back to the subnet ID, so we can locate them quickly when they're presented. - /// Only used if the validator rewarder is non-zero. - /// Partitioned by subnet ID (hash) then by checkpoint block height in the child subnet to the commitment - mapping(bytes32 => mapping(uint64 => RewardDistribution)) distributions; -} - -/// The payload for list commitments query -struct ListCommitmentDetail { - /// The child subnet checkpoint height - uint64 checkpointHeight; - /// The actual commiment of the activities - bytes32 commitment; -} - -library LibValidatorReward { - bytes32 private constant NAMESPACE = keccak256("validator.reward.parent"); - - using SubnetIDHelper for SubnetID; - using EnumerableMap for EnumerableMap.Bytes32ToBytes32Map; - using EnumerableSet for EnumerableSet.AddressSet; - - // =========== External library functions ============= - - function initNewDistribution( - SubnetID calldata subnetId, - uint64 checkpointHeight, - Consensus.MerkleHash commitment, - uint64 totalActiveValidators - ) internal { - ValidatorRewardStorage storage ds = facetStorage(); - - bytes32 subnetKey = subnetId.toHash(); - - if (ds.distributions[subnetKey][checkpointHeight].totalValidators != 0) { - revert CommitmentAlreadyInitialized(); - } - - ds.commitments[subnetKey].set(bytes32(uint256(checkpointHeight)), Consensus.MerkleHash.unwrap(commitment)); - ds.distributions[subnetKey][checkpointHeight].totalValidators = totalActiveValidators; - } - - function listCommitments( - SubnetID calldata subnetId - ) internal view returns (ListCommitmentDetail[] memory listDetails) { - ValidatorRewardStorage storage ds = facetStorage(); - - bytes32 subnetKey = subnetId.toHash(); - - uint256 size = ds.commitments[subnetKey].length(); - listDetails = new ListCommitmentDetail[](size); - - for (uint256 i = 0; i < size; ) { - (bytes32 heightBytes32, bytes32 commitment) = ds.commitments[subnetKey].at(i); - - listDetails[i] = ListCommitmentDetail({ - checkpointHeight: uint64(uint256(heightBytes32)), - commitment: commitment - }); - - unchecked { - i++; - } - } - - return listDetails; - } - - function setRewarder(address rewarder) internal { - ValidatorRewardStorage storage ds = facetStorage(); - ds.validatorRewarder = rewarder; - } - - // ============ Internal library functions ============ - - function facetStorage() internal pure returns (ValidatorRewardStorage storage ds) { - bytes32 position = NAMESPACE; - assembly { - ds.slot := position - } - return ds; - } - - function handleDistribution( - SubnetID calldata subnetId, - uint64 checkpointHeight, - Consensus.ValidatorData calldata detail, - Consensus.MerkleHash[] calldata proof - ) internal { - ValidatorRewardStorage storage s = LibValidatorReward.facetStorage(); - - bytes32 subnetKey = subnetId.toHash(); - - bytes32 commitment = ensureValidCommitment(s, subnetKey, checkpointHeight); - LibActivityMerkleVerifier.ensureValidProof(commitment, detail, proof); - - validatorTryClaim(s, subnetKey, checkpointHeight, detail.validator); - IValidatorRewarder(s.validatorRewarder).disburseRewards(subnetId, detail); - } - - function ensureValidCommitment( - ValidatorRewardStorage storage ds, - bytes32 subnetKey, - uint64 checkpointHeight - ) internal view returns (bytes32) { - (bool exists, bytes32 commitment) = ds.commitments[subnetKey].tryGet(bytes32(uint256(checkpointHeight))); - if (!exists) { - revert SubnetNoTargetCommitment(); - } - - // Note: ideally we should check the commitment actually exists, but we dont have to as - // Note: the code will ensure if commitments contains the commitment, - // Note: the commitment will have distribution - // if (ds.distributions[commitment].checkpointHeight == 0) { - // revert CommitmentNotFound(); - // } - - return commitment; - } - - /// Validator tries to claim the reward. The validator can only claim the reward if the validator - /// has not claimed before - function validatorTryClaim( - ValidatorRewardStorage storage ds, - bytes32 subnetKey, - uint64 checkpointHeight, - address validator - ) internal { - if (ds.distributions[subnetKey][checkpointHeight].claimed.contains(validator)) { - revert ValidatorAlreadyClaimed(); - } - - ds.distributions[subnetKey][checkpointHeight].claimed.add(validator); - } - - /// Try to remove the distribution in the target subnet when ALL VALIDATORS HAVE CLAIMED. - function tryPurgeDistribution( - ValidatorRewardStorage storage ds, - SubnetID calldata subnetId, - uint64 checkpointHeight - ) internal { - bytes32 subnetKey = subnetId.toHash(); - - uint256 total = uint256(ds.distributions[subnetKey][checkpointHeight].totalValidators); - uint256 claimed = ds.distributions[subnetKey][checkpointHeight].claimed.length(); - - if (claimed < total) { - return; - } - - delete ds.commitments[subnetKey]; - delete ds.distributions[subnetKey][checkpointHeight]; - } -} diff --git a/contracts/contracts/errors/IPCErrors.sol b/contracts/contracts/errors/IPCErrors.sol index 402eefdef7..7d73a8df48 100644 --- a/contracts/contracts/errors/IPCErrors.sol +++ b/contracts/contracts/errors/IPCErrors.sol @@ -80,8 +80,7 @@ error InvalidFederationPayload(); error DuplicatedGenesisValidator(); error NotEnoughGenesisValidators(); error ValidatorPowerChangeDenied(); -error CommitmentAlreadyInitialized(); -error SubnetNoTargetCommitment(); +error MissingActivityCommitment(); error ValidatorAlreadyClaimed(); error InvalidActivityProof(); error NotOwner(); diff --git a/contracts/contracts/examples/ValidatorRewarderMap.sol b/contracts/contracts/examples/ValidatorRewarderMap.sol index 8f0ffd7d8d..08022b698e 100644 --- a/contracts/contracts/examples/ValidatorRewarderMap.sol +++ b/contracts/contracts/examples/ValidatorRewarderMap.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.23; -import {IValidatorRewarder} from "../activities/IValidatorRewarder.sol"; -import {Consensus} from "../activities/Activity.sol"; +import {IValidatorRewarder} from "../interfaces/IValidatorRewarder.sol"; +import {Consensus} from "../structs/Activity.sol"; import {SubnetID} from "../structs/Subnet.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; @@ -20,7 +20,7 @@ contract ValidatorRewarderMap is IValidatorRewarder, Ownable { subnetId = id; } - function disburseRewards(SubnetID calldata id, Consensus.ValidatorData calldata detail) external { + function notifyValidClaim(SubnetID calldata id, Consensus.ValidatorData calldata detail) external { require(keccak256(abi.encode(id)) == keccak256(abi.encode(subnetId)), "not my subnet"); address actor = id.route[id.route.length - 1]; diff --git a/contracts/contracts/gateway/router/CheckpointingFacet.sol b/contracts/contracts/gateway/router/CheckpointingFacet.sol index fafbecc0ca..54e2b1e523 100644 --- a/contracts/contracts/gateway/router/CheckpointingFacet.sol +++ b/contracts/contracts/gateway/router/CheckpointingFacet.sol @@ -17,7 +17,7 @@ import {CrossMsgHelper} from "../../lib/CrossMsgHelper.sol"; import {IpcEnvelope, SubnetID} from "../../structs/CrossNet.sol"; import {SubnetIDHelper} from "../../lib/SubnetIDHelper.sol"; -import {ActivityRollupRecorded, FullActivityRollup} from "../../activities/Activity.sol"; +import {ActivityRollupRecorded, FullActivityRollup} from "../../structs/Activity.sol"; contract CheckpointingFacet is GatewayActorModifiers { using SubnetIDHelper for SubnetID; @@ -45,54 +45,21 @@ contract CheckpointingFacet is GatewayActorModifiers { execBottomUpMsgs(checkpoint.msgs, subnet); } - /// @notice creates a new bottom-up checkpoint with activity report - /// @param checkpoint - a bottom-up checkpoint - /// @param membershipRootHash - a root hash of the Merkle tree built from the validator public keys and their weight - /// @param membershipWeight - the total weight of the membership - /// @param fullSummary - the full validators' activities summary - function createBUChptWithActivities( - BottomUpCheckpoint calldata checkpoint, - bytes32 membershipRootHash, - uint256 membershipWeight, - FullActivityRollup calldata fullSummary - ) external systemActorOnly { - if (LibGateway.bottomUpCheckpointExists(checkpoint.blockHeight)) { - revert CheckpointAlreadyExists(); - } - - LibQuorum.createQuorumInfo({ - self: s.checkpointQuorumMap, - objHeight: checkpoint.blockHeight, - objHash: keccak256(abi.encode(checkpoint)), - membershipRootHash: membershipRootHash, - membershipWeight: membershipWeight, - majorityPercentage: s.majorityPercentage - }); - - LibGateway.storeBottomUpCheckpoint(checkpoint); - - emit ActivityRollupRecorded(uint64(checkpoint.blockHeight), fullSummary); - } - /// @notice creates a new bottom-up checkpoint /// @param checkpoint - a bottom-up checkpoint /// @param membershipRootHash - a root hash of the Merkle tree built from the validator public keys and their weight /// @param membershipWeight - the total weight of the membership + /// @param activity - the full activity rollup function createBottomUpCheckpoint( BottomUpCheckpoint calldata checkpoint, bytes32 membershipRootHash, - uint256 membershipWeight + uint256 membershipWeight, + FullActivityRollup calldata activity ) external systemActorOnly { if (LibGateway.bottomUpCheckpointExists(checkpoint.blockHeight)) { revert CheckpointAlreadyExists(); } - // TODO(rewarder): step 1. call fvm ActivityTrackerActor::get_summary to generate the summary - // TODO(rewarder): step 2. update checkpoint.activities with that in step 1 - // TODO: (if there is more time, should wrap param checkpoint with another data structure) - // TODO(rewarder): step 3. call fvm ActivityTrackerActor::purge_activities to purge the activities - // TODO(rewarder): step 4. emit validator details as event - LibQuorum.createQuorumInfo({ self: s.checkpointQuorumMap, objHeight: checkpoint.blockHeight, @@ -103,6 +70,8 @@ contract CheckpointingFacet is GatewayActorModifiers { }); LibGateway.storeBottomUpCheckpoint(checkpoint); + + emit ActivityRollupRecorded(uint64(checkpoint.blockHeight), activity); } /// @notice Set a new checkpoint retention height and garbage collect all checkpoints in range [`retentionHeight`, `newRetentionHeight`) diff --git a/contracts/contracts/interfaces/IGateway.sol b/contracts/contracts/interfaces/IGateway.sol index 9d820dff6a..1c807ea812 100644 --- a/contracts/contracts/interfaces/IGateway.sol +++ b/contracts/contracts/interfaces/IGateway.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.23; import {BottomUpCheckpoint, BottomUpMsgBatch, IpcEnvelope, ParentFinality} from "../structs/CrossNet.sol"; +import {FullActivityRollup} from "../structs/Activity.sol"; import {SubnetID} from "../structs/Subnet.sol"; import {FvmAddress} from "../structs/FvmAddress.sol"; @@ -71,6 +72,7 @@ interface IGateway { function createBottomUpCheckpoint( BottomUpCheckpoint calldata checkpoint, bytes32 membershipRootHash, - uint256 membershipWeight + uint256 membershipWeight, + FullActivityRollup calldata activity ) external; } diff --git a/contracts/contracts/interfaces/IValidatorRewarder.sol b/contracts/contracts/interfaces/IValidatorRewarder.sol new file mode 100644 index 0000000000..44a9e2cece --- /dev/null +++ b/contracts/contracts/interfaces/IValidatorRewarder.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity ^0.8.23; + +import {SubnetID} from "../structs/Subnet.sol"; +import {Consensus} from "../structs/Activity.sol"; + +/// @title ValidatorRewarder interface. +/// +/// @dev Implement this interface and supply the address of the implementation contract at subnet creation to process +/// consensus activity summaries at this level, and disburse rewards to validators based on their block production +/// activities inside the subnet. +/// +/// This interface will be called by the subnet actor when a validator presents a _valid_ proof of consensus activity, +/// via the SubnetActivityActivityFacet#claim method. +interface IValidatorRewarder { + /// @notice Called by the subnet manager contract to instruct the rewarder to process the subnet summary and + /// disburse any relevant rewards. + /// @dev This method should revert if the summary is invalid; this will cause the + function notifyValidClaim(SubnetID calldata id, Consensus.ValidatorData calldata validatedData) external; +} diff --git a/contracts/contracts/lib/LibActivity.sol b/contracts/contracts/lib/LibActivity.sol new file mode 100644 index 0000000000..4e72dd50c3 --- /dev/null +++ b/contracts/contracts/lib/LibActivity.sol @@ -0,0 +1,173 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity ^0.8.23; + +import {IValidatorRewarder} from "../interfaces/IValidatorRewarder.sol"; +import {Consensus, CompressedActivityRollup} from "../structs/Activity.sol"; +import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; +import {MerkleProof} from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; +import {SubnetID} from "../structs/Subnet.sol"; +import {SubnetIDHelper} from "../lib/SubnetIDHelper.sol"; +import {InvalidActivityProof, MissingActivityCommitment, ValidatorAlreadyClaimed} from "../errors/IPCErrors.sol"; + +/// Library to handle activity rollups. +library LibActivity { + bytes32 private constant CONSENSUS_NAMESPACE = keccak256("activity.consensus"); + + using SubnetIDHelper for SubnetID; + using EnumerableSet for EnumerableSet.AddressSet; + using EnumerableSet for EnumerableSet.Bytes32Set; + + // Newtype for extra safety. + type SubnetKey is bytes32; + + /// An object to track consensus-related activity submissions from subnets. + struct ConsensusTracker { + /// An enumeration of checkpoint heights that are pending. + EnumerableSet.Bytes32Set pendingHeights; + /// The pending summaries for each checkpoint height, including information about the validators that have already claimed rewards. + mapping(uint64 => ConsensusPendingAtHeight) pending; + } + + struct ConsensusPendingAtHeight { + /// The original compressed summary submitted for this height. + /// We store the summary in full, or we relay it upwards if there is no validator rewarder configured. + Consensus.CompressedSummary summary; + /// Tracks validators have already claimed rewards for this height. + EnumerableSet.AddressSet claimed; + } + + /// Used by the SubnetActor to track the rewards for each validator + struct ConsensusStorage { + /// @notice The contract address for the validator rewarder. + address validatorRewarder; + /// @notice Tracks pending summaries to be processed. + /// If the validator rewarder is non-zero, these denote summaries presentable at this level. + /// If the validator rewarder is zero, these summaries must be relayed upwards in the next bottom-up checkpoint. + /// Partitioned by subnet ID (hash) then by checkpoint block height in the child subnet to the commitment + mapping(SubnetKey => ConsensusTracker) tracker; + } + + /// Return type for the list commitments view method. + struct ListPendingReturnEntry { + uint64 height; + Consensus.CompressedSummary summary; + address[] claimed; + } + + function ensureValidProof( + Consensus.MerkleHash commitment, + Consensus.ValidatorData calldata detail, + Consensus.MerkleHash[] calldata proof + ) internal pure { + // Constructing leaf: https://github.com/OpenZeppelin/merkle-tree#leaf-hash + bytes32 leaf = keccak256(bytes.concat(keccak256(abi.encode(detail.validator, detail.blocksCommitted)))); + // converting proof to bytes32[] + bytes32[] memory proofBytes = new bytes32[](proof.length); + for (uint256 i = 0; i < proof.length; i++) { + proofBytes[i] = Consensus.MerkleHash.unwrap(proof[i]); + } + bool valid = MerkleProof.verify({proof: proofBytes, root: Consensus.MerkleHash.unwrap(commitment), leaf: leaf}); + if (!valid) { + revert InvalidActivityProof(); + } + } + + // =========== External library functions ============= + + function recordActivityRollup( + SubnetID calldata subnet, + uint64 checkpointHeight, + CompressedActivityRollup calldata activity + ) internal { + ConsensusStorage storage s = consensusStorage(); + + SubnetKey subnetKey = SubnetKey.wrap(subnet.toHash()); + + ConsensusTracker storage tracker = s.tracker[subnetKey]; + bool added = tracker.pendingHeights.add(bytes32(uint256(checkpointHeight))); + require(added, "duplicate checkpoint height"); + + ConsensusPendingAtHeight storage pending = tracker.pending[checkpointHeight]; + pending.summary = activity.consensus; + } + + /// A view accessor to query the pending consensus summaries for a given subnet. + function listPendingConsensus( + SubnetID calldata subnet + ) internal view returns (ListPendingReturnEntry[] memory result) { + ConsensusStorage storage s = consensusStorage(); + + SubnetKey subnetKey = SubnetKey.wrap(subnet.toHash()); + + uint256 size = s.tracker[subnetKey].pendingHeights.length(); + result = new ListPendingReturnEntry[](size); + + // Ok to not optimize with unchecked increments, since we expect this to be used off-chain only, for introspection. + for (uint256 i = 0; i < size; i++) { + ConsensusTracker storage tracker = s.tracker[subnetKey]; + bytes32[] memory heights = tracker.pendingHeights.values(); + + for (uint256 j = 0; j < heights.length; j++) { + uint64 height = uint64(uint256(heights[j]) << 192 >> 192); + ConsensusPendingAtHeight storage pending = tracker.pending[height]; + result[i] = ListPendingReturnEntry({ + height: height, + summary: pending.summary, + claimed: pending.claimed.values() + }); + } + } + + return result; + } + + function processConsensusClaim( + SubnetID calldata subnet, + uint64 checkpointHeight, + Consensus.ValidatorData calldata data, + Consensus.MerkleHash[] calldata proof + ) internal { + ConsensusStorage storage s = consensusStorage(); + + SubnetKey subnetKey = SubnetKey.wrap(subnet.toHash()); + + // Check the validity of the proof. + ConsensusPendingAtHeight storage pending = s.tracker[subnetKey].pending[checkpointHeight]; + Consensus.MerkleHash commitment = pending.summary.dataRootCommitment; + if (Consensus.MerkleHash.unwrap(commitment) == bytes32(0)) { + revert MissingActivityCommitment(); + } + ensureValidProof(commitment, data, proof); + + // Mark the validator as claimed. + bool added = pending.claimed.add(data.validator); + if (!added) { + revert ValidatorAlreadyClaimed(); + } + + // Notify the validator rewarder of a valid claim. + IValidatorRewarder(s.validatorRewarder).notifyValidClaim(subnet, data); + + // Prune state for this height if all validators have claimed. + if (pending.claimed.length() == pending.summary.stats.totalActiveValidators) { + ConsensusTracker storage tracker = s.tracker[subnetKey]; + tracker.pendingHeights.remove(bytes32(uint256(checkpointHeight))); + delete tracker.pending[checkpointHeight]; + } + } + + function setRewarder(address rewarder) internal { + ConsensusStorage storage ds = consensusStorage(); + ds.validatorRewarder = rewarder; + } + + // ============ Internal library functions ============ + + function consensusStorage() internal pure returns (ConsensusStorage storage ds) { + bytes32 position = CONSENSUS_NAMESPACE; + assembly { + ds.slot := position + } + return ds; + } +} diff --git a/contracts/contracts/lib/LibGateway.sol b/contracts/contracts/lib/LibGateway.sol index eb96ea800a..e48c0dcee7 100644 --- a/contracts/contracts/lib/LibGateway.sol +++ b/contracts/contracts/lib/LibGateway.sol @@ -82,7 +82,7 @@ library LibGateway { b.subnetID = checkpoint.subnetID; b.nextConfigurationNumber = checkpoint.nextConfigurationNumber; b.blockHeight = checkpoint.blockHeight; - b.activities = checkpoint.activities; + b.activity = checkpoint.activity; uint256 msgLength = checkpoint.msgs.length; for (uint256 i; i < msgLength; ) { diff --git a/contracts/contracts/lib/LibSubnetRegistryStorage.sol b/contracts/contracts/lib/LibSubnetRegistryStorage.sol index c403815137..665a144fba 100644 --- a/contracts/contracts/lib/LibSubnetRegistryStorage.sol +++ b/contracts/contracts/lib/LibSubnetRegistryStorage.sol @@ -44,7 +44,7 @@ struct SubnetRegistryActorStorage { /// The subnet actor ownership facet functions selectors bytes4[] subnetActorOwnershipSelectors; /// The validator reward facet functions selectors - bytes4[] validatorRewardSelectors; + bytes4[] subnetActorActivitySelectors; /// @notice Mapping that tracks the deployed subnet actors per user. /// Key is the hash of Subnet ID, values are addresses. /// mapping owner => nonce => subnet diff --git a/contracts/contracts/activities/Activity.sol b/contracts/contracts/structs/Activity.sol similarity index 100% rename from contracts/contracts/activities/Activity.sol rename to contracts/contracts/structs/Activity.sol diff --git a/contracts/contracts/structs/CrossNet.sol b/contracts/contracts/structs/CrossNet.sol index 5f5d8ae1ae..1f59623463 100644 --- a/contracts/contracts/structs/CrossNet.sol +++ b/contracts/contracts/structs/CrossNet.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.23; import {SubnetID, IPCAddress} from "./Subnet.sol"; import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; -import {CompressedActivityRollup} from "../activities/Activity.sol"; +import {CompressedActivityRollup} from "../structs/Activity.sol"; uint64 constant MAX_MSGS_PER_BATCH = 10; uint256 constant BATCH_PERIOD = 100; @@ -30,8 +30,8 @@ struct BottomUpCheckpoint { uint64 nextConfigurationNumber; /// @dev Batch of messages to execute. IpcEnvelope[] msgs; - /// @dev The activity summary from child subnet to parent subnet - CompressedActivityRollup activities; + /// @dev The activity rollup from child subnet to parent subnet. + CompressedActivityRollup activity; } /// @notice A batch of bottom-up messages for execution. diff --git a/contracts/contracts/subnet/SubnetActorActivityFacet.sol b/contracts/contracts/subnet/SubnetActorActivityFacet.sol new file mode 100644 index 0000000000..49cd64b71a --- /dev/null +++ b/contracts/contracts/subnet/SubnetActorActivityFacet.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity ^0.8.23; + +import {Consensus} from "../structs/Activity.sol"; +import {LibActivity} from "../lib/LibActivity.sol"; +import {LibDiamond} from "../lib/LibDiamond.sol"; +import {NotAuthorized} from "../errors/IPCErrors.sol"; +import {Pausable} from "../lib/LibPausable.sol"; +import {ReentrancyGuard} from "../lib/LibReentrancyGuard.sol"; +import {SubnetIDHelper} from "../lib/SubnetIDHelper.sol"; +import {SubnetID} from "../structs/Subnet.sol"; + +/// The validator reward facet for the parent subnet, i.e. for validators in the child subnet +/// to claim their reward in the parent subnet, which should be the current subnet this facet +/// is deployed. +contract SubnetActorActivityFacet is ReentrancyGuard, Pausable { + // Entrypoint for validators to batch claim rewards in the parent subnet, for a given subnet, + // against multiple checkpoints at once. Atomically succeeds or reverts. + function batchSubnetClaim( + SubnetID calldata subnet, + uint64[] calldata checkpointHeights, + Consensus.ValidatorClaim[] calldata claims + ) external nonReentrant whenNotPaused { + require(checkpointHeights.length == claims.length, "length mismatch"); + uint256 len = claims.length; + for (uint256 i = 0; i < len; ) { + _claim(subnet, checkpointHeights[i], claims[i].data, claims[i].proof); + unchecked { + i++; + } + } + } + + /// Entrypoint for validators to claim their reward for doing work in the child subnet. + function claim( + SubnetID calldata subnet, + uint64 checkpointHeight, + Consensus.ValidatorData calldata data, + Consensus.MerkleHash[] calldata proof + ) external nonReentrant whenNotPaused { + _claim(subnet, checkpointHeight, data, proof); + } + + // ======== Internal functions =========== + + function _claim( + SubnetID calldata subnetId, + uint64 checkpointHeight, + Consensus.ValidatorData calldata detail, + Consensus.MerkleHash[] calldata proof + ) internal { + // Note: No need to check if the subnet is active. If the subnet is not active, the checkpointHeight + // will never exist. + if (msg.sender != detail.validator) { + revert NotAuthorized(msg.sender); + } + + LibActivity.processConsensusClaim(subnetId, checkpointHeight, detail, proof); + } +} diff --git a/contracts/contracts/subnet/SubnetActorCheckpointingFacet.sol b/contracts/contracts/subnet/SubnetActorCheckpointingFacet.sol index ad540d61f5..fd72786f9c 100644 --- a/contracts/contracts/subnet/SubnetActorCheckpointingFacet.sol +++ b/contracts/contracts/subnet/SubnetActorCheckpointingFacet.sol @@ -13,7 +13,7 @@ import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet import {LibSubnetActor} from "../lib/LibSubnetActor.sol"; import {Pausable} from "../lib/LibPausable.sol"; import {LibGateway} from "../lib/LibGateway.sol"; -import {LibValidatorReward} from "../activities/ValidatorRewardFacet.sol"; +import {LibActivity} from "../lib/LibActivity.sol"; contract SubnetActorCheckpointingFacet is SubnetActorModifiers, ReentrancyGuard, Pausable { using EnumerableSet for EnumerableSet.AddressSet; @@ -50,12 +50,7 @@ contract SubnetActorCheckpointingFacet is SubnetActorModifiers, ReentrancyGuard, // Commit in gateway to distribute rewards IGateway(s.ipcGatewayAddr).commitCheckpoint(checkpoint); - LibValidatorReward.initNewDistribution( - checkpoint.subnetID, - uint64(checkpoint.blockHeight), - checkpoint.activities.consensus.dataRootCommitment, - checkpoint.activities.consensus.stats.totalActiveValidators - ); + LibActivity.recordActivityRollup(checkpoint.subnetID, uint64(checkpoint.blockHeight), checkpoint.activity); // confirming the changes in membership in the child LibStaking.confirmChange(checkpoint.nextConfigurationNumber); diff --git a/contracts/contracts/subnetregistry/RegisterSubnetFacet.sol b/contracts/contracts/subnetregistry/RegisterSubnetFacet.sol index dea2c5eb76..ed9cb4f25e 100644 --- a/contracts/contracts/subnetregistry/RegisterSubnetFacet.sol +++ b/contracts/contracts/subnetregistry/RegisterSubnetFacet.sol @@ -83,7 +83,7 @@ contract RegisterSubnetFacet is ReentrancyGuard { diamondCut[8] = IDiamond.FacetCut({ facetAddress: s.VALIDATOR_REWARD_FACET, action: IDiamond.FacetCutAction.Add, - functionSelectors: s.validatorRewardSelectors + functionSelectors: s.subnetActorActivitySelectors }); // slither-disable-next-line reentrancy-benign diff --git a/contracts/tasks/deploy-registry.ts b/contracts/tasks/deploy-registry.ts index 50c0491e4e..14a6ac1f7c 100644 --- a/contracts/tasks/deploy-registry.ts +++ b/contracts/tasks/deploy-registry.ts @@ -45,7 +45,7 @@ task('deploy-registry') { name: 'DiamondLoupeFacet' }, { name: 'OwnershipFacet' }, { - name: 'ValidatorRewardFacet', + name: 'SubnetActorActivityFacet', libraries: ['SubnetIDHelper'], }, ) @@ -92,7 +92,7 @@ task('deploy-registry') diamondCutFacet: subnetActorFacets.addresses['DiamondCutFacet'], diamondLoupeFacet: subnetActorFacets.addresses['DiamondLoupeFacet'], ownershipFacet: subnetActorFacets.addresses['OwnershipFacet'], - validatorRewardFacet: subnetActorFacets.addresses['ValidatorRewardFacet'], + activityFacet: subnetActorFacets.addresses['SubnetActorActivityFacet'], subnetActorGetterSelectors: selectors(subnetActorFacets.contracts['SubnetActorGetterFacet']), subnetActorManagerSelectors: selectors(subnetActorFacets.contracts['SubnetActorManagerFacet']), @@ -102,7 +102,7 @@ task('deploy-registry') subnetActorDiamondCutSelectors: selectors(subnetActorFacets.contracts['DiamondCutFacet']), subnetActorDiamondLoupeSelectors: selectors(subnetActorFacets.contracts['DiamondLoupeFacet']), subnetActorOwnershipSelectors: selectors(subnetActorFacets.contracts['OwnershipFacet']), - validatorRewardSelectors: selectors(subnetActorFacets.contracts['ValidatorRewardFacet']), + subnetActorActivitySelectors: selectors(subnetActorFacets.contracts['SubnetActorActivityFacet']), creationPrivileges: Number(mode), } diff --git a/contracts/tasks/gen-selector-library.ts b/contracts/tasks/gen-selector-library.ts index 512060afba..a55db8ddb7 100644 --- a/contracts/tasks/gen-selector-library.ts +++ b/contracts/tasks/gen-selector-library.ts @@ -6,14 +6,18 @@ import { selectors } from './lib' task('gen-selector-library', 'Generates a Solidity library with contract selectors for tests').setAction( async (_args, hre: HardhatRuntimeEnvironment) => { - await hre.run('compile') - // ridiculously, this appears to be the only way to get hardhat to compile a specific subtree // we are only updating the in-memory representation of the config, so it won't write this value out to disk // be careful if you compose this task with other tasks in larger scripts! + console.log('compiling mocks...') + const oldSources = hre.config.paths.sources hre.config.paths.sources = './test/mocks' await hre.run('compile') + hre.config.paths.sources = oldSources + console.log('compiling contracts...') + await hre.run('compile') + const contracts: string[] = [ 'OwnershipFacet', 'DiamondCutFacet', @@ -32,7 +36,7 @@ task('gen-selector-library', 'Generates a Solidity library with contract selecto 'RegisterSubnetFacet', 'SubnetGetterFacet', 'SubnetActorMock', - 'ValidatorRewardFacet', + 'SubnetActorActivityFacet', ] const resolveSelectors = async (contractName: string) => { diff --git a/contracts/test/IntegrationTestBase.sol b/contracts/test/IntegrationTestBase.sol index 066c2e72e3..19013b3d73 100644 --- a/contracts/test/IntegrationTestBase.sol +++ b/contracts/test/IntegrationTestBase.sol @@ -46,9 +46,9 @@ import {GatewayFacetsHelper} from "./helpers/GatewayFacetsHelper.sol"; import {SubnetActorFacetsHelper} from "./helpers/SubnetActorFacetsHelper.sol"; import {DiamondFacetsHelper} from "./helpers/DiamondFacetsHelper.sol"; -import {FullActivityRollup, CompressedActivityRollup, Consensus} from "../contracts/activities/Activity.sol"; +import {FullActivityRollup, CompressedActivityRollup, Consensus} from "../contracts/structs/Activity.sol"; import {ValidatorRewarderMap} from "../contracts/examples/ValidatorRewarderMap.sol"; -import {ValidatorRewardFacet} from "../contracts/activities/ValidatorRewardFacet.sol"; +import {SubnetActorActivityFacet} from "../contracts/subnet/SubnetActorActivityFacet.sol"; struct TestSubnetDefinition { GatewayDiamond gateway; @@ -167,7 +167,7 @@ contract TestSubnetActor is Test, TestParams { bytes4[] saCutterSelectors; bytes4[] saLouperSelectors; bytes4[] saOwnershipSelectors; - bytes4[] validatorRewardSelectors; + bytes4[] saActivitySelectors; SubnetActorDiamond saDiamond; SubnetActorMock saMock; @@ -182,7 +182,7 @@ contract TestSubnetActor is Test, TestParams { saCutterSelectors = SelectorLibrary.resolveSelectors("DiamondCutFacet"); saLouperSelectors = SelectorLibrary.resolveSelectors("DiamondLoupeFacet"); saOwnershipSelectors = SelectorLibrary.resolveSelectors("OwnershipFacet"); - validatorRewardSelectors = SelectorLibrary.resolveSelectors("ValidatorRewardFacet"); + saActivitySelectors = SelectorLibrary.resolveSelectors("SubnetActorActivityFacet"); } function defaultSubnetActorParamsWith( @@ -499,7 +499,7 @@ contract IntegrationTestBase is Test, TestParams, TestRegistry, TestSubnetActor, DiamondLoupeFacet louper = new DiamondLoupeFacet(); DiamondCutFacet cutter = new DiamondCutFacet(); OwnershipFacet ownership = new OwnershipFacet(); - ValidatorRewardFacet validatorReward = new ValidatorRewardFacet(); + SubnetActorActivityFacet activity = new SubnetActorActivityFacet(); IDiamond.FacetCut[] memory diamondCut = new IDiamond.FacetCut[](9); @@ -569,9 +569,9 @@ contract IntegrationTestBase is Test, TestParams, TestRegistry, TestSubnetActor, diamondCut[8] = ( IDiamond.FacetCut({ - facetAddress: address(validatorReward), + facetAddress: address(activity), action: IDiamond.FacetCutAction.Add, - functionSelectors: validatorRewardSelectors + functionSelectors: saActivitySelectors }) ); SubnetActorDiamond diamond = new SubnetActorDiamond(diamondCut, params, address(this)); @@ -934,7 +934,7 @@ contract IntegrationTestBase is Test, TestParams, TestRegistry, TestSubnetActor, blockHash: keccak256(abi.encode(h)), nextConfigurationNumber: nextConfigNum - 1, msgs: new IpcEnvelope[](0), - activities: CompressedActivityRollup({ + activity: CompressedActivityRollup({ consensus: Consensus.CompressedSummary({ stats: Consensus.AggregatedStats({ totalActiveValidators: uint64(validators.length), @@ -977,7 +977,7 @@ contract IntegrationTestBase is Test, TestParams, TestRegistry, TestSubnetActor, blockHash: keccak256(abi.encode(h)), nextConfigurationNumber: nextConfigNum - 1, msgs: new IpcEnvelope[](0), - activities: activities + activity: activities }); vm.deal(address(saDiamond), 100 ether); diff --git a/contracts/test/helpers/ActivityHelper.sol b/contracts/test/helpers/ActivityHelper.sol index 037db293f9..104fa5b15e 100644 --- a/contracts/test/helpers/ActivityHelper.sol +++ b/contracts/test/helpers/ActivityHelper.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.23; -import {Consensus, CompressedActivityRollup} from "../../contracts/activities/Activity.sol"; +import {Consensus, CompressedActivityRollup, FullActivityRollup} from "../../contracts/structs/Activity.sol"; library ActivityHelper { function newCompressedActivityRollup( @@ -45,4 +45,15 @@ library ActivityHelper { return wrapped; } + + function dummyActivityRollup() internal pure returns (FullActivityRollup memory rollup) { + Consensus.ValidatorData[] memory data = new Consensus.ValidatorData[](0); + rollup = FullActivityRollup({ + consensus: Consensus.FullSummary({ + stats: Consensus.AggregatedStats({totalActiveValidators: 0, totalNumBlocksCommitted: 0}), + data: data + }) + }); + return rollup; + } } diff --git a/contracts/test/helpers/MerkleTreeHelper.sol b/contracts/test/helpers/MerkleTreeHelper.sol index f3b911eafe..c2789fb62a 100644 --- a/contracts/test/helpers/MerkleTreeHelper.sol +++ b/contracts/test/helpers/MerkleTreeHelper.sol @@ -32,7 +32,7 @@ library MerkleTreeHelper { return (root, proofs); } - function createMerkleProofsForActivities( + function createMerkleProofsForConsensusActivity( address[] memory addrs, uint64[] memory blocksMined ) internal returns (bytes32, bytes32[][] memory) { diff --git a/contracts/test/helpers/SelectorLibrary.sol b/contracts/test/helpers/SelectorLibrary.sol index 9dfe76e4c3..ae80a44821 100644 --- a/contracts/test/helpers/SelectorLibrary.sol +++ b/contracts/test/helpers/SelectorLibrary.sol @@ -48,7 +48,7 @@ library SelectorLibrary { if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("CheckpointingFacet"))) { return abi.decode( - hex"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000553b4e7bf00000000000000000000000000000000000000000000000000000000a0316672000000000000000000000000000000000000000000000000000000002ea952910000000000000000000000000000000000000000000000000000000036bfdf6700000000000000000000000000000000000000000000000000000000ac81837900000000000000000000000000000000000000000000000000000000", + hex"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000453b4e7bf00000000000000000000000000000000000000000000000000000000a031667200000000000000000000000000000000000000000000000000000000d8b4602500000000000000000000000000000000000000000000000000000000ac81837900000000000000000000000000000000000000000000000000000000", (bytes4[]) ); } @@ -122,7 +122,7 @@ library SelectorLibrary { (bytes4[]) ); } - if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("ValidatorRewardFacet"))) { + if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("SubnetActorActivityFacet"))) { return abi.decode( hex"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000202eca6eb00000000000000000000000000000000000000000000000000000000f9d3434c00000000000000000000000000000000000000000000000000000000", diff --git a/contracts/test/helpers/SubnetActorFacetsHelper.sol b/contracts/test/helpers/SubnetActorFacetsHelper.sol index fcea95a4fc..595b0ba930 100644 --- a/contracts/test/helpers/SubnetActorFacetsHelper.sol +++ b/contracts/test/helpers/SubnetActorFacetsHelper.sol @@ -4,12 +4,12 @@ pragma solidity ^0.8.23; import {SubnetActorManagerFacet} from "../../contracts/subnet/SubnetActorManagerFacet.sol"; import {SubnetActorPauseFacet} from "../../contracts/subnet/SubnetActorPauseFacet.sol"; import {SubnetActorCheckpointingFacet} from "../../contracts/subnet/SubnetActorCheckpointingFacet.sol"; +import {SubnetActorActivityFacet} from "../../contracts/subnet/SubnetActorActivityFacet.sol"; import {SubnetActorRewardFacet} from "../../contracts/subnet/SubnetActorRewardFacet.sol"; import {SubnetActorGetterFacet} from "../../contracts/subnet/SubnetActorGetterFacet.sol"; import {SubnetActorDiamond} from "../../contracts/SubnetActorDiamond.sol"; import {DiamondLoupeFacet} from "../../contracts/diamond/DiamondLoupeFacet.sol"; import {DiamondCutFacet} from "../../contracts/diamond/DiamondCutFacet.sol"; -import {ValidatorRewardFacet} from "../../contracts/activities/ValidatorRewardFacet.sol"; library SubnetActorFacetsHelper { function manager(address sa) internal pure returns (SubnetActorManagerFacet) { @@ -47,10 +47,8 @@ library SubnetActorFacetsHelper { return facet; } - // - - function validatorReward(SubnetActorDiamond sa) internal pure returns (ValidatorRewardFacet) { - ValidatorRewardFacet facet = ValidatorRewardFacet(address(sa)); + function activity(SubnetActorDiamond sa) internal pure returns (SubnetActorActivityFacet) { + SubnetActorActivityFacet facet = SubnetActorActivityFacet(address(sa)); return facet; } diff --git a/contracts/test/integration/GatewayDiamond.t.sol b/contracts/test/integration/GatewayDiamond.t.sol index 69e53166a7..6a96a6c3b6 100644 --- a/contracts/test/integration/GatewayDiamond.t.sol +++ b/contracts/test/integration/GatewayDiamond.t.sol @@ -39,7 +39,7 @@ import {GatewayFacetsHelper} from "../helpers/GatewayFacetsHelper.sol"; import {SubnetActorDiamond} from "../../contracts/SubnetActorDiamond.sol"; import {SubnetActorFacetsHelper} from "../helpers/SubnetActorFacetsHelper.sol"; -import {FullActivityRollup, Consensus} from "../../contracts/activities/Activity.sol"; +import {FullActivityRollup, Consensus} from "../../contracts/structs/Activity.sol"; import {ActivityHelper} from "../helpers/ActivityHelper.sol"; contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeTokenMock { @@ -1071,7 +1071,7 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHash: keccak256("block1"), nextConfigurationNumber: 1, msgs: new IpcEnvelope[](0), - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); BottomUpCheckpoint memory checkpoint = BottomUpCheckpoint({ @@ -1080,13 +1080,18 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHash: keccak256("block1"), nextConfigurationNumber: 1, msgs: new IpcEnvelope[](0), - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); // failed to create a checkpoint with zero membership weight vm.startPrank(FilAddress.SYSTEM_ACTOR); vm.expectRevert(ZeroMembershipWeight.selector); - gatewayDiamond.checkpointer().createBottomUpCheckpoint(checkpoint, membershipRoot, 0); + gatewayDiamond.checkpointer().createBottomUpCheckpoint( + checkpoint, + membershipRoot, + 0, + ActivityHelper.dummyActivityRollup() + ); vm.stopPrank(); // failed create a processed checkpoint @@ -1095,7 +1100,8 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT gatewayDiamond.checkpointer().createBottomUpCheckpoint( old, membershipRoot, - weights[0] + weights[1] + weights[2] + weights[0] + weights[1] + weights[2], + ActivityHelper.dummyActivityRollup() ); vm.stopPrank(); @@ -1104,7 +1110,8 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT gatewayDiamond.checkpointer().createBottomUpCheckpoint( checkpoint, membershipRoot, - weights[0] + weights[1] + weights[2] + weights[0] + weights[1] + weights[2], + ActivityHelper.dummyActivityRollup() ); vm.stopPrank(); @@ -1122,7 +1129,7 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHash: keccak256("block"), nextConfigurationNumber: 2, msgs: new IpcEnvelope[](0), - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); vm.startPrank(FilAddress.SYSTEM_ACTOR); @@ -1130,7 +1137,8 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT gatewayDiamond.checkpointer().createBottomUpCheckpoint( checkpoint, membershipRoot, - weights[0] + weights[1] + weights[2] + weights[0] + weights[1] + weights[2], + ActivityHelper.dummyActivityRollup() ); vm.stopPrank(); @@ -1146,7 +1154,7 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHash: keccak256("block1"), nextConfigurationNumber: 1, msgs: new IpcEnvelope[](0), - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); vm.expectRevert(InvalidCheckpointSource.selector); @@ -1168,7 +1176,7 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHash: keccak256("block1"), nextConfigurationNumber: 1, msgs: new IpcEnvelope[](0), - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); vm.prank(caller); @@ -1215,7 +1223,7 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHash: keccak256("block1"), nextConfigurationNumber: 1, msgs: msgs, - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); vm.prank(caller); @@ -1236,7 +1244,7 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHash: keccak256("block1"), nextConfigurationNumber: 1, msgs: new IpcEnvelope[](0), - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); BottomUpCheckpoint memory checkpoint2 = BottomUpCheckpoint({ @@ -1245,7 +1253,7 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHash: keccak256("block2"), nextConfigurationNumber: 1, msgs: new IpcEnvelope[](0), - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); // create a checkpoint @@ -1253,12 +1261,14 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT gatewayDiamond.checkpointer().createBottomUpCheckpoint( checkpoint1, membershipRoot, - weights[0] + weights[1] + weights[2] + weights[0] + weights[1] + weights[2], + ActivityHelper.dummyActivityRollup() ); gatewayDiamond.checkpointer().createBottomUpCheckpoint( checkpoint2, membershipRoot, - weights[0] + weights[1] + weights[2] + weights[0] + weights[1] + weights[2], + ActivityHelper.dummyActivityRollup() ); vm.stopPrank(); @@ -1310,7 +1320,7 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHash: keccak256("block"), nextConfigurationNumber: 1, msgs: new IpcEnvelope[](0), - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); // create a checkpoint @@ -1318,7 +1328,8 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT gatewayDiamond.checkpointer().createBottomUpCheckpoint( checkpoint, membershipRoot, - weights[0] + weights[1] + weights[2] + weights[0] + weights[1] + weights[2], + ActivityHelper.dummyActivityRollup() ); vm.stopPrank(); @@ -1372,7 +1383,7 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHash: keccak256("block"), nextConfigurationNumber: 1, msgs: new IpcEnvelope[](0), - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); // create a checkpoint @@ -1380,7 +1391,8 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT gatewayDiamond.checkpointer().createBottomUpCheckpoint( checkpoint, membershipRoot, - weights[0] + weights[1] + weights[2] + weights[0] + weights[1] + weights[2], + ActivityHelper.dummyActivityRollup() ); vm.stopPrank(); @@ -1456,12 +1468,17 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHash: keccak256("block"), nextConfigurationNumber: 1, msgs: new IpcEnvelope[](0), - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); // create a checkpoint vm.startPrank(FilAddress.SYSTEM_ACTOR); - gatewayDiamond.checkpointer().createBottomUpCheckpoint(checkpoint, membershipRoot, 10); + gatewayDiamond.checkpointer().createBottomUpCheckpoint( + checkpoint, + membershipRoot, + 10, + ActivityHelper.dummyActivityRollup() + ); vm.stopPrank(); uint8 v; @@ -1491,12 +1508,17 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHash: keccak256("block"), nextConfigurationNumber: 1, msgs: new IpcEnvelope[](0), - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); // create a checkpoint vm.startPrank(FilAddress.SYSTEM_ACTOR); - gatewayDiamond.checkpointer().createBottomUpCheckpoint(checkpoint, membershipRoot, 10); + gatewayDiamond.checkpointer().createBottomUpCheckpoint( + checkpoint, + membershipRoot, + 10, + ActivityHelper.dummyActivityRollup() + ); vm.stopPrank(); uint8 v; @@ -1536,12 +1558,17 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHash: keccak256("block"), nextConfigurationNumber: 1, msgs: new IpcEnvelope[](0), - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); // create a checkpoint vm.startPrank(FilAddress.SYSTEM_ACTOR); - gatewayDiamond.checkpointer().createBottomUpCheckpoint(checkpoint, membershipRoot, 10); + gatewayDiamond.checkpointer().createBottomUpCheckpoint( + checkpoint, + membershipRoot, + 10, + ActivityHelper.dummyActivityRollup() + ); vm.stopPrank(); uint8 v; @@ -1585,10 +1612,15 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHash: keccak256("block"), nextConfigurationNumber: 1, msgs: new IpcEnvelope[](0), - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); - gatewayDiamond.checkpointer().createBottomUpCheckpoint(checkpoint, membershipRoot, 10); + gatewayDiamond.checkpointer().createBottomUpCheckpoint( + checkpoint, + membershipRoot, + 10, + ActivityHelper.dummyActivityRollup() + ); } vm.stopPrank(); @@ -1649,7 +1681,7 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeT blockHash: keccak256("block1"), nextConfigurationNumber: 1, msgs: msgs, - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); vm.prank(caller); diff --git a/contracts/test/integration/GatewayDiamondToken.t.sol b/contracts/test/integration/GatewayDiamondToken.t.sol index 3b239b5995..b1d01eb355 100644 --- a/contracts/test/integration/GatewayDiamondToken.t.sol +++ b/contracts/test/integration/GatewayDiamondToken.t.sol @@ -33,7 +33,7 @@ import {IERC20Errors} from "@openzeppelin/contracts/interfaces/draft-IERC6093.so import {GatewayFacetsHelper} from "../helpers/GatewayFacetsHelper.sol"; -import {FullActivityRollup, Consensus} from "../../contracts/activities/Activity.sol"; +import {FullActivityRollup, Consensus} from "../../contracts/structs/Activity.sol"; import {ActivityHelper} from "../helpers/ActivityHelper.sol"; contract GatewayDiamondTokenTest is Test, IntegrationTestBase { @@ -167,7 +167,7 @@ contract GatewayDiamondTokenTest is Test, IntegrationTestBase { blockHeight: gatewayDiamond.getter().bottomUpCheckPeriod(), nextConfigurationNumber: 0, msgs: msgs, - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); vm.prank(address(saDiamond)); @@ -226,7 +226,7 @@ contract GatewayDiamondTokenTest is Test, IntegrationTestBase { blockHeight: gatewayDiamond.getter().bottomUpCheckPeriod(), nextConfigurationNumber: 0, msgs: msgs, - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); // Verify that we received the call and that the recipient has the tokens. diff --git a/contracts/test/integration/MultiSubnet.t.sol b/contracts/test/integration/MultiSubnet.t.sol index 1bf25a3f0d..53654136dd 100644 --- a/contracts/test/integration/MultiSubnet.t.sol +++ b/contracts/test/integration/MultiSubnet.t.sol @@ -45,7 +45,7 @@ import {SubnetActorFacetsHelper} from "../helpers/SubnetActorFacetsHelper.sol"; import "forge-std/console.sol"; -import {FullActivityRollup, Consensus} from "../../contracts/activities/Activity.sol"; +import {FullActivityRollup, Consensus} from "../../contracts/structs/Activity.sol"; import {ActivityHelper} from "../helpers/ActivityHelper.sol"; contract MultiSubnetTest is Test, IntegrationTestBase { @@ -1352,11 +1352,16 @@ contract MultiSubnetTest is Test, IntegrationTestBase { blockHash: keccak256("block1"), nextConfigurationNumber: 0, msgs: batch.msgs, - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); vm.startPrank(FilAddress.SYSTEM_ACTOR); - checkpointer.createBottomUpCheckpoint(checkpoint, membershipRoot, weights[0] + weights[1] + weights[2]); + checkpointer.createBottomUpCheckpoint( + checkpoint, + membershipRoot, + weights[0] + weights[1] + weights[2], + ActivityHelper.dummyActivityRollup() + ); vm.stopPrank(); return checkpoint; @@ -1382,11 +1387,16 @@ contract MultiSubnetTest is Test, IntegrationTestBase { blockHash: keccak256("block1"), nextConfigurationNumber: 0, msgs: msgs, - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); vm.startPrank(FilAddress.SYSTEM_ACTOR); - checkpointer.createBottomUpCheckpoint(checkpoint, membershipRoot, weights[0] + weights[1] + weights[2]); + checkpointer.createBottomUpCheckpoint( + checkpoint, + membershipRoot, + weights[0] + weights[1] + weights[2], + ActivityHelper.dummyActivityRollup() + ); vm.stopPrank(); return checkpoint; diff --git a/contracts/test/integration/SubnetActorDiamond.t.sol b/contracts/test/integration/SubnetActorDiamond.t.sol index ecfd54c187..5ead392fbe 100644 --- a/contracts/test/integration/SubnetActorDiamond.t.sol +++ b/contracts/test/integration/SubnetActorDiamond.t.sol @@ -43,7 +43,7 @@ import {GatewayFacetsHelper} from "../helpers/GatewayFacetsHelper.sol"; import {ERC20PresetFixedSupply} from "../helpers/ERC20PresetFixedSupply.sol"; import {SubnetValidatorGater} from "../../contracts/examples/SubnetValidatorGater.sol"; -import {FullActivityRollup, Consensus} from "../../contracts/activities/Activity.sol"; +import {FullActivityRollup, Consensus} from "../../contracts/structs/Activity.sol"; import {ValidatorRewarderMap} from "../../contracts/examples/ValidatorRewarderMap.sol"; import {MerkleTreeHelper} from "../helpers/MerkleTreeHelper.sol"; import {ActivityHelper} from "../helpers/ActivityHelper.sol"; @@ -695,7 +695,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHash: keccak256("block1"), nextConfigurationNumber: 0, msgs: msgs, - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); BottomUpCheckpoint memory checkpointWithIncorrectHeight = BottomUpCheckpoint({ @@ -704,7 +704,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHash: keccak256("block1"), nextConfigurationNumber: 0, msgs: msgs, - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); vm.deal(address(saDiamond), 100 ether); @@ -805,7 +805,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHash: keccak256("block1"), nextConfigurationNumber: 0, msgs: msgs, - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); BottomUpCheckpoint memory checkpointWithIncorrectHeight = BottomUpCheckpoint({ @@ -814,7 +814,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHash: keccak256("block1"), nextConfigurationNumber: 0, msgs: new IpcEnvelope[](0), - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); vm.deal(address(saDiamond), 100 ether); @@ -843,7 +843,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { // submit another again checkpoint.blockHeight = 2; - checkpoint.activities = ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))); + checkpoint.activity = ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))); hash = keccak256(abi.encode(checkpoint)); for (uint256 i = 0; i < 3; i++) { @@ -900,7 +900,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHash: keccak256("block1"), nextConfigurationNumber: 0, msgs: msgs, - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); submitCheckpointInternal(checkpoint, validators, signatures, keys); require(saDiamond.getter().lastBottomUpCheckpointHeight() == 1, " checkpoint height incorrect"); @@ -913,7 +913,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHash: keccak256("block2"), nextConfigurationNumber: 0, msgs: msgs, - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); submitCheckpointInternal(checkpoint, validators, signatures, keys); require(saDiamond.getter().lastBottomUpCheckpointHeight() == 3, " checkpoint height incorrect"); @@ -925,7 +925,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHash: keccak256("block1"), nextConfigurationNumber: 0, msgs: msgs, - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); vm.expectRevert(BottomUpCheckpointAlreadySubmitted.selector); submitCheckpointInternal(checkpoint, validators, signatures, keys); @@ -937,7 +937,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHash: keccak256("block2"), nextConfigurationNumber: 0, msgs: msgs, - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); vm.expectRevert(CannotSubmitFutureCheckpoint.selector); submitCheckpointInternal(checkpoint, validators, signatures, keys); @@ -948,7 +948,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHash: keccak256("block2"), nextConfigurationNumber: 0, msgs: new IpcEnvelope[](0), - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); submitCheckpointInternal(checkpoint, validators, signatures, keys); require( @@ -962,7 +962,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHash: keccak256("block2"), nextConfigurationNumber: 0, msgs: msgs, - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); submitCheckpointInternal(checkpoint, validators, signatures, keys); require( @@ -976,7 +976,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHash: keccak256("block2"), nextConfigurationNumber: 0, msgs: msgs, - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); submitCheckpointInternal(checkpoint, validators, signatures, keys); require( @@ -990,7 +990,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHash: keccak256("block2"), nextConfigurationNumber: 0, msgs: new IpcEnvelope[](0), - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); vm.expectRevert(InvalidCheckpointEpoch.selector); submitCheckpointInternal(checkpoint, validators, signatures, keys); @@ -1001,7 +1001,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHash: keccak256("block2"), nextConfigurationNumber: 0, msgs: new IpcEnvelope[](0), - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); submitCheckpointInternal(checkpoint, validators, signatures, keys); require( @@ -1015,7 +1015,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHash: keccak256("block2"), nextConfigurationNumber: 0, msgs: new IpcEnvelope[](0), - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); submitCheckpointInternal(checkpoint, validators, signatures, keys); require( @@ -1057,7 +1057,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHash: keccak256("block1"), nextConfigurationNumber: 0, msgs: msgs, - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); vm.deal(address(saDiamond), 100 ether); @@ -1101,7 +1101,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blockHash: keccak256("block2"), nextConfigurationNumber: 0, msgs: msgs, - activities: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) + activity: ActivityHelper.newCompressedActivityRollup(1, 3, bytes32(uint256(0))) }); hash = keccak256(abi.encode(checkpoint)); @@ -2334,7 +2334,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { } // ============== Test Activities =============== - function testGatewayDiamond_ValidatorClaimMiningReward_Works() public { + function testSubnetActor_ValidatorClaimMiningReward_Works() public { gatewayAddress = address(gatewayDiamond); Asset memory source = Asset({kind: AssetKind.Native, tokenAddress: address(0)}); @@ -2370,45 +2370,52 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blocksMined[0] = 1; blocksMined[1] = 2; - (bytes32 activityRoot, bytes32[][] memory proofs) = MerkleTreeHelper.createMerkleProofsForActivities( + (bytes32 activityRoot, bytes32[][] memory proofs) = MerkleTreeHelper.createMerkleProofsForConsensusActivity( addrs, blocksMined ); confirmChange(addrs, privKeys, ActivityHelper.newCompressedActivityRollup(2, 3, activityRoot)); + uint64 bottomUpCheckPeriod = uint64(gatewayDiamond.getter().bottomUpCheckPeriod()); + vm.startPrank(addrs[0]); vm.deal(addrs[0], 1 ether); - saDiamond.validatorReward().claim( + saDiamond.activity().claim( subnetId, - uint64(gatewayDiamond.getter().bottomUpCheckPeriod()), + bottomUpCheckPeriod, Consensus.ValidatorData({validator: addrs[0], blocksCommitted: blocksMined[0]}), ActivityHelper.wrapBytes32Array(proofs[0]) ); vm.startPrank(addrs[1]); vm.deal(addrs[1], 1 ether); - saDiamond.validatorReward().claim( + saDiamond.activity().claim( subnetId, - uint64(gatewayDiamond.getter().bottomUpCheckPeriod()), + bottomUpCheckPeriod, Consensus.ValidatorData({validator: addrs[1], blocksCommitted: blocksMined[1]}), ActivityHelper.wrapBytes32Array(proofs[1]) ); + // These validators have no claims; they were inactive, so the pending activity should've been removed + // and as a result, the claim should fail. + vm.startPrank(addrs[2]); vm.deal(addrs[2], 1 ether); - saDiamond.validatorReward().claim( + vm.expectRevert(MissingActivityCommitment.selector); + saDiamond.activity().claim( subnetId, - uint64(gatewayDiamond.getter().bottomUpCheckPeriod()), + bottomUpCheckPeriod, Consensus.ValidatorData({validator: addrs[2], blocksCommitted: blocksMined[2]}), ActivityHelper.wrapBytes32Array(proofs[2]) ); vm.startPrank(addrs[3]); vm.deal(addrs[3], 1 ether); - saDiamond.validatorReward().claim( + vm.expectRevert(MissingActivityCommitment.selector); + saDiamond.activity().claim( subnetId, - uint64(gatewayDiamond.getter().bottomUpCheckPeriod()), + bottomUpCheckPeriod, Consensus.ValidatorData({validator: addrs[3], blocksCommitted: blocksMined[3]}), ActivityHelper.wrapBytes32Array(proofs[3]) ); @@ -2420,7 +2427,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { assert(m.blocksCommitted(addrs[3]) == 0); } - function testGatewayDiamond_ValidatorBatchClaimMiningReward_Works() public { + function testSubnetActor_ValidatorBatchClaimMiningReward_Works() public { ValidatorRewarderMap m = new ValidatorRewarderMap(); { gatewayAddress = address(gatewayDiamond); @@ -2460,12 +2467,12 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blocksMined[0] = 1; blocksMined[1] = 2; - (bytes32 activityRoot1, bytes32[][] memory proofs1) = MerkleTreeHelper.createMerkleProofsForActivities( + (bytes32 activityRoot1, bytes32[][] memory proofs1) = MerkleTreeHelper.createMerkleProofsForConsensusActivity( addrs, blocksMined ); - (bytes32 activityRoot2, bytes32[][] memory proofs2) = MerkleTreeHelper.createMerkleProofsForActivities( + (bytes32 activityRoot2, bytes32[][] memory proofs2) = MerkleTreeHelper.createMerkleProofsForConsensusActivity( addrs, blocksMined ); @@ -2491,13 +2498,13 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { proof: ActivityHelper.wrapBytes32Array(proofs2[0]) }); - saDiamond.validatorReward().batchSubnetClaim(subnetId, checkpointHeights, claimProofs); + saDiamond.activity().batchSubnetClaim(subnetId, checkpointHeights, claimProofs); // check assert(m.blocksCommitted(addrs[0]) == 2); } - function testGatewayDiamond_ValidatorBatchClaimMiningReward_NoDoubleClaim() public { + function testSubnetActor_ValidatorBatchClaimMiningReward_NoDoubleClaim() public { ValidatorRewarderMap m = new ValidatorRewarderMap(); { gatewayAddress = address(gatewayDiamond); @@ -2537,11 +2544,11 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { blocksMined[0] = 1; blocksMined[1] = 2; - (bytes32 activityRoot1, bytes32[][] memory proofs1) = MerkleTreeHelper.createMerkleProofsForActivities( + (bytes32 activityRoot1, bytes32[][] memory proofs1) = MerkleTreeHelper.createMerkleProofsForConsensusActivity( addrs, blocksMined ); - (bytes32 activityRoot2, bytes32[][] memory proofs2) = MerkleTreeHelper.createMerkleProofsForActivities( + (bytes32 activityRoot2, bytes32[][] memory proofs2) = MerkleTreeHelper.createMerkleProofsForConsensusActivity( addrs, blocksMined ); @@ -2568,7 +2575,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { }); vm.expectRevert(ValidatorAlreadyClaimed.selector); - saDiamond.validatorReward().batchSubnetClaim(subnetId, heights, claimProofs); + saDiamond.activity().batchSubnetClaim(subnetId, heights, claimProofs); } // ----------------------------------------------------------------------------------------------------------------- diff --git a/contracts/test/integration/SubnetRegistry.t.sol b/contracts/test/integration/SubnetRegistry.t.sol index 68e99f550c..3703c3fbed 100644 --- a/contracts/test/integration/SubnetRegistry.t.sol +++ b/contracts/test/integration/SubnetRegistry.t.sol @@ -18,6 +18,7 @@ import {SubnetActorPauseFacet} from "../../contracts/subnet/SubnetActorPauseFace import {SubnetActorCheckpointingFacet} from "../../contracts/subnet/SubnetActorCheckpointingFacet.sol"; import {SubnetActorRewardFacet} from "../../contracts/subnet/SubnetActorRewardFacet.sol"; import {SubnetActorDiamond} from "../../contracts/SubnetActorDiamond.sol"; +import {SubnetActorActivityFacet} from "../../contracts/subnet/SubnetActorActivityFacet.sol"; import {SubnetID, PermissionMode, SubnetCreationPrivileges} from "../../contracts/structs/Subnet.sol"; import {SubnetRegistryDiamond} from "../../contracts/SubnetRegistryDiamond.sol"; @@ -29,7 +30,6 @@ import {OwnershipFacet} from "../../contracts/OwnershipFacet.sol"; import {AssetHelper} from "../../contracts/lib/AssetHelper.sol"; import {RegistryFacetsHelper} from "../helpers/RegistryFacetsHelper.sol"; import {DiamondFacetsHelper} from "../helpers/DiamondFacetsHelper.sol"; -import {ValidatorRewardFacet} from "../../contracts/activities/ValidatorRewardFacet.sol"; import {ValidatorRewarderMap} from "../../contracts/examples/ValidatorRewarderMap.sol"; import {SelectorLibrary} from "../helpers/SelectorLibrary.sol"; @@ -68,7 +68,7 @@ contract SubnetRegistryTest is Test, TestRegistry, IntegrationTestBase { params.diamondCutFacet = address(new DiamondCutFacet()); params.diamondLoupeFacet = address(new DiamondLoupeFacet()); params.ownershipFacet = address(new OwnershipFacet()); - params.validatorRewardFacet = address(new ValidatorRewardFacet()); + params.activityFacet = address(new SubnetActorActivityFacet()); params.subnetActorGetterSelectors = mockedSelectors; params.subnetActorManagerSelectors = mockedSelectors2; @@ -78,7 +78,7 @@ contract SubnetRegistryTest is Test, TestRegistry, IntegrationTestBase { params.subnetActorDiamondCutSelectors = SelectorLibrary.resolveSelectors("DiamondCutFacet"); params.subnetActorDiamondLoupeSelectors = SelectorLibrary.resolveSelectors("DiamondLoupeFacet"); params.subnetActorOwnershipSelectors = SelectorLibrary.resolveSelectors("OwnershipFacet"); - params.validatorRewardSelectors = SelectorLibrary.resolveSelectors("ValidatorRewardFacet"); + params.subnetActorActivitySelectors = SelectorLibrary.resolveSelectors("SubnetActorActivityFacet"); params.creationPrivileges = SubnetCreationPrivileges.Unrestricted; @@ -174,7 +174,7 @@ contract SubnetRegistryTest is Test, TestRegistry, IntegrationTestBase { new SubnetRegistryDiamond(diamondCut, params); params.ownershipFacet = address(8); - params.validatorRewardFacet = address(9); + params.activityFacet = address(9); new SubnetRegistryDiamond(diamondCut, params); } diff --git a/contracts/test/invariants/SubnetRegistryInvariants.t.sol b/contracts/test/invariants/SubnetRegistryInvariants.t.sol index e26c32a2e6..b6858f1329 100644 --- a/contracts/test/invariants/SubnetRegistryInvariants.t.sol +++ b/contracts/test/invariants/SubnetRegistryInvariants.t.sol @@ -18,7 +18,7 @@ import {SubnetGetterFacet} from "../../contracts/subnetregistry/SubnetGetterFace import {DiamondLoupeFacet} from "../../contracts/diamond/DiamondLoupeFacet.sol"; import {DiamondCutFacet} from "../../contracts/diamond/DiamondCutFacet.sol"; import {OwnershipFacet} from "../../contracts/OwnershipFacet.sol"; -import {ValidatorRewardFacet} from "../../contracts/activities/ValidatorRewardFacet.sol"; +import {SubnetActorActivityFacet} from "../../contracts/subnet/SubnetActorActivityFacet.sol"; import {IntegrationTestBase, TestRegistry} from "../IntegrationTestBase.sol"; import {SelectorLibrary} from "../helpers/SelectorLibrary.sol"; @@ -52,7 +52,7 @@ contract SubnetRegistryInvariants is StdInvariant, Test, TestRegistry, Integrati params.diamondCutFacet = address(new DiamondCutFacet()); params.diamondLoupeFacet = address(new DiamondLoupeFacet()); params.ownershipFacet = address(new OwnershipFacet()); - params.validatorRewardFacet = address(new ValidatorRewardFacet()); + params.activityFacet = address(new SubnetActorActivityFacet()); params.subnetActorGetterSelectors = mockedSelectors; params.subnetActorManagerSelectors = mockedSelectors2; @@ -62,7 +62,7 @@ contract SubnetRegistryInvariants is StdInvariant, Test, TestRegistry, Integrati params.subnetActorDiamondCutSelectors = SelectorLibrary.resolveSelectors("DiamondCutFacet"); params.subnetActorDiamondLoupeSelectors = SelectorLibrary.resolveSelectors("DiamondLoupeFacet"); params.subnetActorOwnershipSelectors = SelectorLibrary.resolveSelectors("OwnershipFacet"); - params.validatorRewardSelectors = SelectorLibrary.resolveSelectors("ValidatorRewardFacet"); + params.subnetActorActivitySelectors = SelectorLibrary.resolveSelectors("SubnetActorActivityFacet"); registryDiamond = createSubnetRegistry(params); registryHandler = new SubnetRegistryHandler(registryDiamond); diff --git a/extras/linked-token/test/MultiSubnetTest.t.sol b/extras/linked-token/test/MultiSubnetTest.t.sol index 26d7d529b8..8b421d7e30 100644 --- a/extras/linked-token/test/MultiSubnetTest.t.sol +++ b/extras/linked-token/test/MultiSubnetTest.t.sol @@ -9,6 +9,7 @@ import {TestUtils} from "@ipc/test/helpers/TestUtils.sol"; import {MerkleTreeHelper} from "@ipc/test/helpers/MerkleTreeHelper.sol"; import {GatewayFacetsHelper} from "@ipc/test/helpers/GatewayFacetsHelper.sol"; import {SubnetActorFacetsHelper} from "@ipc/test/helpers/SubnetActorFacetsHelper.sol"; +import {ActivityHelper} from "@ipc/test/helpers/ActivityHelper.sol"; import {LinkedTokenController} from "../contracts/LinkedTokenController.sol"; import {LinkedTokenReplica} from "../contracts/LinkedTokenReplica.sol"; @@ -28,7 +29,7 @@ import {GatewayGetterFacet} from "@ipc/contracts/gateway/GatewayGetterFacet.sol" import {SubnetActorCheckpointingFacet} from "@ipc/contracts/subnet/SubnetActorCheckpointingFacet.sol"; import {CheckpointingFacet} from "@ipc/contracts/gateway/router/CheckpointingFacet.sol"; import {FvmAddressHelper} from "@ipc/contracts/lib/FvmAddressHelper.sol"; -import {Consensus, CompressedActivityRollup} from "@ipc/contracts/activities/Activity.sol"; +import {Consensus, CompressedActivityRollup} from "@ipc/contracts/structs/Activity.sol"; import {IpcEnvelope, BottomUpMsgBatch, BottomUpCheckpoint, ParentFinality, IpcMsgKind, ResultMsg, CallMsg} from "@ipc/contracts/structs/CrossNet.sol"; import {SubnetIDHelper} from "@ipc/contracts/lib/SubnetIDHelper.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; @@ -385,7 +386,7 @@ contract MultiSubnetTest is IntegrationTestBase { blockHash: keccak256("block1"), nextConfigurationNumber: 0, msgs: batch.msgs, - activities: CompressedActivityRollup({ + activity: CompressedActivityRollup({ consensus: Consensus.CompressedSummary({ stats: Consensus.AggregatedStats({ totalActiveValidators: 1, @@ -397,7 +398,7 @@ contract MultiSubnetTest is IntegrationTestBase { }); vm.startPrank(FilAddress.SYSTEM_ACTOR); - checkpointer.createBottomUpCheckpoint(checkpoint, membershipRoot, weights[0] + weights[1] + weights[2]); + checkpointer.createBottomUpCheckpoint(checkpoint, membershipRoot, weights[0] + weights[1] + weights[2], ActivityHelper.dummyActivityRollup()); vm.stopPrank(); return checkpoint; diff --git a/fendermint/testing/contract-test/tests/staking/machine.rs b/fendermint/testing/contract-test/tests/staking/machine.rs index 4926475f53..b950dd339c 100644 --- a/fendermint/testing/contract-test/tests/staking/machine.rs +++ b/fendermint/testing/contract-test/tests/staking/machine.rs @@ -286,7 +286,7 @@ impl StateMachine for StakingMachine { block_hash: *block_hash, next_configuration_number: *next_configuration_number, msgs: Vec::new(), - activities: Default::default(), + activity: Default::default(), }; let checkpoint_hash = checkpoint.clone().abi_hash(); diff --git a/fendermint/vm/actor_interface/src/ipc.rs b/fendermint/vm/actor_interface/src/ipc.rs index 572df6af76..d3f4c18d7c 100644 --- a/fendermint/vm/actor_interface/src/ipc.rs +++ b/fendermint/vm/actor_interface/src/ipc.rs @@ -119,8 +119,9 @@ lazy_static! { abi: ia::ownership_facet::OWNERSHIPFACET_ABI.to_owned(), }, EthFacet { - name: "ValidatorRewardFacet", - abi: ia::validator_reward_facet::VALIDATORREWARDFACET_ABI.to_owned(), + name: "SubnetActorActivityFacet", + abi: ia::subnet_actor_activity_facet::SUBNETACTORACTIVITYFACET_ABI + .to_owned(), }, // ========== IF YOU WANT TO ADD FACET FOR SUBNET, APPEND HERE ========== // The registry has its own facets: @@ -475,7 +476,7 @@ pub mod registry { pub diamond_cut_facet: Address, pub diamond_loupe_facet: Address, pub ownership_facet: Address, - pub validator_reward_facet: Address, + pub activity_facet: Address, pub subnet_getter_selectors: Vec, pub subnet_manager_selectors: Vec, pub subnet_rewarder_selectors: Vec, @@ -484,7 +485,7 @@ pub mod registry { pub subnet_actor_diamond_cut_selectors: Vec, pub subnet_actor_diamond_loupe_selectors: Vec, pub subnet_actor_ownership_selectors: Vec, - pub validator_reward_selectors: Vec, + pub subnet_actor_activity_selectors: Vec, pub creation_privileges: u8, // 0 = Unrestricted, 1 = Owner. } } @@ -541,7 +542,7 @@ pub mod subnet { ], next_configuration_number: 1, msgs: vec![], - activities: Default::default(), + activity: Default::default(), }; let param_type = BottomUpCheckpoint::param_type(); diff --git a/fendermint/vm/interpreter/src/fvm/checkpoint.rs b/fendermint/vm/interpreter/src/fvm/checkpoint.rs index 5aca2db831..6f077de653 100644 --- a/fendermint/vm/interpreter/src/fvm/checkpoint.rs +++ b/fendermint/vm/interpreter/src/fvm/checkpoint.rs @@ -94,7 +94,7 @@ where let num_msgs = msgs.len(); - let full_activity_rollup = state.activities_tracker().commit_activity()?; + let full_activity_rollup = state.activity_tracker().commit_activity()?; // Construct checkpoint. let checkpoint = BottomUpCheckpoint { @@ -103,7 +103,7 @@ where block_hash, next_configuration_number, msgs, - activities: full_activity_rollup.compressed()?, + activity: full_activity_rollup.compressed()?, }; // Save the checkpoint in the ledger. @@ -249,21 +249,21 @@ where block_hash: cp.block_hash, next_configuration_number: cp.next_configuration_number, msgs: convert_tokenizables(cp.msgs)?, - activities: checkpoint::CompressedActivityRollup { + activity: checkpoint::CompressedActivityRollup { consensus: checkpoint::CompressedSummary { stats: checkpoint::AggregatedStats { total_active_validators: cp - .activities + .activity .consensus .stats .total_active_validators, total_num_blocks_committed: cp - .activities + .activity .consensus .stats .total_num_blocks_committed, }, - data_root_commitment: cp.activities.consensus.data_root_commitment, + data_root_commitment: cp.activity.consensus.data_root_commitment, }, }, }; diff --git a/fendermint/vm/interpreter/src/fvm/exec.rs b/fendermint/vm/interpreter/src/fvm/exec.rs index 3006218a5e..803d54bc4a 100644 --- a/fendermint/vm/interpreter/src/fvm/exec.rs +++ b/fendermint/vm/interpreter/src/fvm/exec.rs @@ -204,7 +204,7 @@ where let mut block_end_events = BlockEndEvents::default(); if let Some(pubkey) = state.block_producer() { - state.activities_tracker().record_block_committed(pubkey)?; + state.activity_tracker().record_block_committed(pubkey)?; } let next_gas_market = state.finalize_gas_market()?; diff --git a/fendermint/vm/interpreter/src/fvm/state/exec.rs b/fendermint/vm/interpreter/src/fvm/state/exec.rs index 65b0a94386..bcd6570b8d 100644 --- a/fendermint/vm/interpreter/src/fvm/state/exec.rs +++ b/fendermint/vm/interpreter/src/fvm/state/exec.rs @@ -292,7 +292,7 @@ where self.executor.context().network.chain_id } - pub fn activities_tracker(&mut self) -> ActorActivityTracker { + pub fn activity_tracker(&mut self) -> ActorActivityTracker { ActorActivityTracker { executor: self } } diff --git a/fendermint/vm/interpreter/src/fvm/state/ipc.rs b/fendermint/vm/interpreter/src/fvm/state/ipc.rs index 2eb04c752c..484ef1d522 100644 --- a/fendermint/vm/interpreter/src/fvm/state/ipc.rs +++ b/fendermint/vm/interpreter/src/fvm/state/ipc.rs @@ -123,7 +123,7 @@ impl GatewayCaller { state: &mut FvmExecState, checkpoint: checkpointing_facet::BottomUpCheckpoint, power_table: &[Validator], - activities: checkpointing_facet::FullActivityRollup, + activity: checkpointing_facet::FullActivityRollup, ) -> anyhow::Result { // Construct a Merkle tree from the power table, which we can use to validate validator set membership // when the signatures are submitted in transactions for accumulation. @@ -137,11 +137,11 @@ impl GatewayCaller { Ok(self .checkpointing .call_with_return(state, |c| { - c.create_bu_chpt_with_activities( + c.create_bottom_up_checkpoint( checkpoint, tree.root_hash().0, total_power, - activities, + activity, ) })? .into_return()) diff --git a/fendermint/vm/interpreter/src/genesis.rs b/fendermint/vm/interpreter/src/genesis.rs index c7458de3f4..ce610e0bf0 100644 --- a/fendermint/vm/interpreter/src/genesis.rs +++ b/fendermint/vm/interpreter/src/genesis.rs @@ -594,7 +594,7 @@ fn deploy_contracts( let diamond_loupe_facet = facets.remove(0); let diamond_cut_facet = facets.remove(0); let ownership_facet = facets.remove(0); - let validator_reward_facet = facets.remove(0); + let activity_facet = facets.remove(0); debug_assert_eq!(facets.len(), 2, "SubnetRegistry has 2 facets of its own"); @@ -608,7 +608,7 @@ fn deploy_contracts( diamond_cut_facet: diamond_cut_facet.facet_address, diamond_loupe_facet: diamond_loupe_facet.facet_address, ownership_facet: ownership_facet.facet_address, - validator_reward_facet: validator_reward_facet.facet_address, + activity_facet: activity_facet.facet_address, subnet_getter_selectors: getter_facet.function_selectors, subnet_manager_selectors: manager_facet.function_selectors, subnet_rewarder_selectors: rewarder_facet.function_selectors, @@ -617,7 +617,7 @@ fn deploy_contracts( subnet_actor_diamond_cut_selectors: diamond_cut_facet.function_selectors, subnet_actor_diamond_loupe_selectors: diamond_loupe_facet.function_selectors, subnet_actor_ownership_selectors: ownership_facet.function_selectors, - validator_reward_selectors: validator_reward_facet.function_selectors, + subnet_actor_activity_selectors: activity_facet.function_selectors, creation_privileges: 0, }; diff --git a/ipc/api/src/evm.rs b/ipc/api/src/evm.rs index dd40829eaa..0e15ed8e5c 100644 --- a/ipc/api/src/evm.rs +++ b/ipc/api/src/evm.rs @@ -20,7 +20,7 @@ use fvm_shared::econ::TokenAmount; use ipc_actors_abis::{ checkpointing_facet, gateway_getter_facet, gateway_manager_facet, gateway_messenger_facet, lib_gateway, register_subnet_facet, subnet_actor_checkpointing_facet, subnet_actor_diamond, - subnet_actor_getter_facet, top_down_finality_facet, validator_reward_facet, + subnet_actor_getter_facet, top_down_finality_facet, subnet_actor_activity_facet, xnet_messaging_facet, }; @@ -191,7 +191,7 @@ macro_rules! bottom_up_checkpoint_conversion { .into_iter() .map($module::IpcEnvelope::try_from) .collect::, _>>()?, - activities: checkpoint.activity_rollup.try_into()?, + activity: checkpoint.activity_rollup.try_into()?, }) } } @@ -210,7 +210,7 @@ macro_rules! bottom_up_checkpoint_conversion { .into_iter() .map(IpcEnvelope::try_from) .collect::, _>>()?, - activity_rollup: value.activities.into(), + activity_rollup: value.activity.into(), }) } } @@ -284,7 +284,7 @@ base_type_conversion!(subnet_actor_checkpointing_facet); base_type_conversion!(gateway_getter_facet); base_type_conversion!(gateway_messenger_facet); base_type_conversion!(lib_gateway); -base_type_conversion!(validator_reward_facet); +base_type_conversion!(subnet_actor_activity_facet); base_type_conversion!(checkpointing_facet); cross_msg_types!(gateway_getter_facet); diff --git a/ipc/provider/src/manager/evm/manager.rs b/ipc/provider/src/manager/evm/manager.rs index 43d68971a5..b5f2342acc 100644 --- a/ipc/provider/src/manager/evm/manager.rs +++ b/ipc/provider/src/manager/evm/manager.rs @@ -11,7 +11,7 @@ use ipc_actors_abis::{ checkpointing_facet, gateway_getter_facet, gateway_manager_facet, gateway_messenger_facet, lib_gateway, lib_quorum, lib_staking_change_log, register_subnet_facet, subnet_actor_checkpointing_facet, subnet_actor_getter_facet, subnet_actor_manager_facet, - subnet_actor_reward_facet, validator_reward_facet, + subnet_actor_reward_facet, subnet_actor_activity_facet, }; use ipc_api::evm::{fil_to_eth_amount, payload_to_evm_address, subnet_id_to_evm_addresses}; use ipc_api::validator::from_contract_validators; @@ -43,7 +43,7 @@ use ethers::types::{BlockId, Eip1559TransactionRequest, ValueOrArray, H256, I256 use ethers::middleware::Middleware; use fvm_shared::clock::ChainEpoch; use fvm_shared::{address::Address, econ::TokenAmount}; -use ipc_actors_abis::validator_reward_facet::ValidatorClaim; +use ipc_actors_abis::subnet_actor_activity_facet::ValidatorClaim; use ipc_api::checkpoint::{ consensus::ValidatorData, BottomUpCheckpoint, BottomUpCheckpointBundle, QuorumReachedEvent, Signature, @@ -1342,7 +1342,7 @@ impl ValidatorRewarder for EthSubnetManager { let claim = ValidatorClaim { // Even though it's the same struct but still need to do a mapping due to // different crate from ethers-rs - data: validator_reward_facet::ValidatorData { + data: subnet_actor_activity_facet::ValidatorData { validator: data.validator, blocks_committed: data.blocks_committed, }, @@ -1410,7 +1410,7 @@ impl ValidatorRewarder for EthSubnetManager { claims: Vec<(u64, ValidatorClaim)>, ) -> Result<()> { let signer = Arc::new(self.get_signer(submitter)?); - let contract = validator_reward_facet::ValidatorRewardFacet::new( + let contract = subnet_actor_activity_facet::SubnetActorActivityFacet::new( contract_address_from_subnet(reward_claim_subnet)?, signer.clone(), ); diff --git a/ipc/provider/src/manager/subnet.rs b/ipc/provider/src/manager/subnet.rs index a520959492..6e31b4552c 100644 --- a/ipc/provider/src/manager/subnet.rs +++ b/ipc/provider/src/manager/subnet.rs @@ -7,7 +7,7 @@ use anyhow::Result; use async_trait::async_trait; use fvm_shared::clock::ChainEpoch; use fvm_shared::{address::Address, econ::TokenAmount}; -use ipc_actors_abis::validator_reward_facet::ValidatorClaim; +use ipc_actors_abis::subnet_actor_activity_facet::ValidatorClaim; use ipc_api::checkpoint::{ consensus::ValidatorData, BottomUpCheckpoint, BottomUpCheckpointBundle, QuorumReachedEvent, Signature,