11// SPDX-License-Identifier: BSD-3-Clause-Clear
22pragma solidity ^ 0.8.24 ;
33import { gatewayConfigAddress } from "../addresses/GatewayConfigAddress.sol " ;
4+ import { coprocessorContextsAddress } from "../addresses/CoprocessorContextsAddress.sol " ;
45import { kmsManagementAddress } from "../addresses/KmsManagementAddress.sol " ;
56import { Ownable2StepUpgradeable } from "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol " ;
67import { Strings } from "@openzeppelin/contracts/utils/Strings.sol " ;
78import "./interfaces/ICiphertextCommits.sol " ;
89import "./interfaces/IGatewayConfig.sol " ;
10+ import { ICoprocessorContexts } from "./interfaces/ICoprocessorContexts.sol " ;
911import "./interfaces/IKmsManagement.sol " ;
1012import "./shared/UUPSUpgradeableEmptyProxy.sol " ;
1113import "./shared/GatewayConfigChecks.sol " ;
1214import "./shared/Pausable.sol " ;
1315import "./libraries/HandleOps.sol " ;
14-
16+ import { CoprocessorContexts } from "./CoprocessorContexts.sol " ;
17+ import { ContextChecks } from "./shared/ContextChecks.sol " ;
1518/**
1619 * @title CiphertextCommits smart contract
1720 * @dev See {ICiphertextCommits}.
@@ -21,11 +24,15 @@ contract CiphertextCommits is
2124 Ownable2StepUpgradeable ,
2225 UUPSUpgradeableEmptyProxy ,
2326 GatewayConfigChecks ,
24- Pausable
27+ Pausable ,
28+ ContextChecks
2529{
26- /// @notice The address of the GatewayConfig contract, used for fetching information about coprocessors .
30+ /// @notice The address of the GatewayConfig contract, used for fetching information about host chains .
2731 IGatewayConfig private constant GATEWAY_CONFIG = IGatewayConfig (gatewayConfigAddress);
2832
33+ /// @notice The address of the CoprocessorContexts contract, used for fetching information about coprocessors.
34+ ICoprocessorContexts private constant COPROCESSOR_CONTEXTS = ICoprocessorContexts (coprocessorContextsAddress);
35+
2936 /// @notice The address of the KmsManagement contract, used for fetching information about the current key.
3037 IKmsManagement private constant KMS_MANAGEMENT = IKmsManagement (kmsManagementAddress);
3138
@@ -59,6 +66,8 @@ contract CiphertextCommits is
5966 _alreadyAddedCoprocessorTxSenders;
6067 /// @notice The mapping of the coprocessor transaction senders that have added the ciphertext.
6168 mapping (bytes32 ctHandle = > address [] coprocessorTxSenderAddresses ) _coprocessorTxSenderAddresses;
69+ /// @notice The coprocessor context ID associated to the add ciphertext
70+ mapping (bytes32 addCiphertextHash = > uint256 contextId ) inputVerificationContextId;
6271 }
6372
6473 /// @dev Storage location has been computed using the following command:
@@ -77,27 +86,55 @@ contract CiphertextCommits is
7786 * @dev This function needs to be public in order to be called by the UUPS proxy.
7887 */
7988 /// @custom:oz-upgrades-validate-as-initializer
80- function initializeFromEmptyProxy () public virtual onlyFromEmptyProxy reinitializer (2 ) {
89+ function initializeFromEmptyProxy () public virtual onlyFromEmptyProxy reinitializer (3 ) {
8190 __Ownable_init (owner ());
8291 __Pausable_init ();
8392 }
8493
94+ /// @notice Reinitializes the contract.
95+ function reinitializeV2 () external reinitializer (3 ) {}
96+
8597 /// @notice See {ICiphertextCommits-addCiphertextMaterial}.
86- /// @dev This function calls the GatewayConfig contract to check that the sender address is a Coprocessor.
8798 function addCiphertextMaterial (
8899 bytes32 ctHandle ,
89100 uint256 keyId ,
90101 bytes32 ciphertextDigest ,
91102 bytes32 snsCiphertextDigest
92- ) external virtual onlyCoprocessorTxSender whenNotPaused {
103+ ) external virtual whenNotPaused refreshCoprocessorContextStatuses {
93104 /// @dev Extract the chainId from the ciphertext handle
94105 uint256 chainId = HandleOps.extractChainId (ctHandle);
95106
96107 /// @dev Check that the associated host chain is registered
97108 GATEWAY_CONFIG.checkHostChainIsRegistered (chainId);
98109
110+ // Compute the hash of the ciphertext material to differentiate different ciphertext
111+ // material additions
112+ bytes32 addCiphertextHash = keccak256 (
113+ abi.encode (ctHandle, chainId, keyId, ciphertextDigest, snsCiphertextDigest)
114+ );
115+
99116 CiphertextCommitsStorage storage $ = _getCiphertextCommitsStorage ();
100117
118+ // Get the context ID from the input verification context ID mapping
119+ uint256 contextId = $.inputVerificationContextId[addCiphertextHash];
120+
121+ // If the context ID is not set, get the active coprocessor context's ID and associate it to
122+ // this ciphertext material addition
123+ if (contextId == 0 ) {
124+ contextId = COPROCESSOR_CONTEXTS.getActiveCoprocessorContextId ();
125+ $.inputVerificationContextId[addCiphertextHash] = contextId;
126+
127+ // Else, that means a coprocessor already started to add the ciphertext material
128+ // and we need to check that the context is active or suspended
129+ // If it is not, that means the context is no longer valid for this operation and we revert
130+ } else if (! COPROCESSOR_CONTEXTS.isCoprocessorContextActiveOrSuspended (contextId)) {
131+ ContextStatus contextStatus = COPROCESSOR_CONTEXTS.getCoprocessorContextStatus (contextId);
132+ revert InvalidCoprocessorContextAddCiphertext (ctHandle, contextId, contextStatus);
133+ }
134+
135+ // Only accept coprocessor transaction senders from the same context
136+ COPROCESSOR_CONTEXTS.checkIsCoprocessorTxSenderFromContext (contextId, msg .sender );
137+
101138 /**
102139 * @dev Check if the coprocessor transaction sender has already added the ciphertext handle.
103140 * Note that a coprocessor transaction sender cannot add the same ciphertext material on
@@ -118,20 +155,17 @@ contract CiphertextCommits is
118155 * Coprocessors can only have a consensus on a ciphertext material with the same information.
119156 * This hash is used to track the addition consensus on the received ciphertext material.
120157 */
121- bytes32 addCiphertextHash = keccak256 (
122- abi.encode (ctHandle, chainId, keyId, ciphertextDigest, snsCiphertextDigest)
123- );
124158 $._addCiphertextHashCounters[addCiphertextHash]++ ;
125159
126160 $._alreadyAddedCoprocessorTxSenders[ctHandle][msg .sender ] = true ;
127161 $._coprocessorTxSenderAddresses[ctHandle].push (msg .sender );
128162
129- /// @dev Only send the event if consensus has not been reached in a previous call
130- /// @dev and the consensus is reached in the current call.
131- /// @dev This means a "late" addition will not be reverted, just ignored
163+ // Only send the event if consensus has not been reached in a previous call and the consensus
164+ // is reached in the current call. This means a "late" addition will not be reverted, just ignored
165+ // Besides, consensus only considers the coprocessors of the same context
132166 if (
133167 ! $._isCiphertextMaterialAdded[ctHandle] &&
134- _isConsensusReached ($._addCiphertextHashCounters[addCiphertextHash])
168+ _isConsensusReached (contextId, $._addCiphertextHashCounters[addCiphertextHash])
135169 ) {
136170 $._ciphertextDigests[ctHandle] = ciphertextDigest;
137171 $._snsCiphertextDigests[ctHandle] = snsCiphertextDigest;
@@ -141,6 +175,7 @@ contract CiphertextCommits is
141175
142176 emit AddCiphertextMaterial (
143177 ctHandle,
178+ contextId,
144179 ciphertextDigest,
145180 snsCiphertextDigest,
146181 $._coprocessorTxSenderAddresses[ctHandle]
@@ -220,11 +255,14 @@ contract CiphertextCommits is
220255 // solhint-disable-next-line no-empty-blocks
221256 function _authorizeUpgrade (address _newImplementation ) internal virtual override onlyOwner {}
222257
223- /// @notice Checks if the consensus is reached among the Coprocessors.
224- /// @param coprocessorCounter The number of coprocessors that agreed
225- /// @return Whether the consensus is reached
226- function _isConsensusReached (uint256 coprocessorCounter ) internal view virtual returns (bool ) {
227- uint256 consensusThreshold = GATEWAY_CONFIG.getCoprocessorMajorityThreshold ();
258+ /**
259+ * @notice Checks if the consensus is reached among the coprocessors from the same context.
260+ * @param contextId The coprocessor context ID
261+ * @param coprocessorCounter The number of coprocessors that agreed
262+ * @return Whether the consensus is reached
263+ */
264+ function _isConsensusReached (uint256 contextId , uint256 coprocessorCounter ) internal view virtual returns (bool ) {
265+ uint256 consensusThreshold = COPROCESSOR_CONTEXTS.getCoprocessorMajorityThresholdFromContext (contextId);
228266 return coprocessorCounter >= consensusThreshold;
229267 }
230268
0 commit comments