Skip to content
Draft
27 changes: 27 additions & 0 deletions contracts/script/GenerateAlloc.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { IIPTokenStaking } from "../src/interfaces/IIPTokenStaking.sol";
import { IPTokenStaking } from "../src/protocol/IPTokenStaking.sol";
import { UpgradeEntrypoint } from "../src/protocol/UpgradeEntrypoint.sol";
import { UBIPool } from "../src/protocol/UBIPool.sol";
import { DKG } from "../src/protocol/DKG.sol";

import { ChainIds } from "./utils/ChainIds.sol";
import { EIP1967Helper } from "./utils/EIP1967Helper.sol";
Expand Down Expand Up @@ -183,6 +184,7 @@ contract GenerateAlloc is Script {
setStaking();
setUpgrade();
setUBIPool();
setDKG();
}

/// @dev Populates the upgradeable predeploys namespace with proxies, to reserve the addresses
Expand Down Expand Up @@ -336,6 +338,31 @@ contract GenerateAlloc is Script {
console2.log("UBIPool owner:", UBIPool(Predeploys.UBIPool).owner());
}

function setDKG() internal {
address impl = Predeploys.getImplAddress(Predeploys.DKG);
address tmp = address(new DKG());
vm.etch(impl, tmp.code);

InitializableHelper.disableInitializers(impl);

uint256 minReqRegisteredParticipants = 3;
uint256 minReqFinalizedParticipants = 3;
uint256 operationalThreshold = 670; // 67%
uint256 fee = 1 ether; // 1 IP
DKG(Predeploys.DKG).initialize(
timelock,
minReqRegisteredParticipants,
minReqFinalizedParticipants,
operationalThreshold,
fee
);

// reset tmp
vm.etch(tmp, "");
vm.store(tmp, 0, "0x");
vm.resetNonce(tmp);
}

/// @notice Sets the bytecode for Create3 factory as a predeploy
/// @dev Create3 factory address https://github.com/ZeframLou/create3-factory
function setCreate3() internal {
Expand Down
20 changes: 20 additions & 0 deletions contracts/src/interfaces/IAttestationReportValidator.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.23;

interface IAttestationReportValidator {
// validateReport accepts a remote attestation report (e.g. rawQuote for SGX) and validates a remote attestation report following these steps
// 1. validate the report
// 1.1 checks the report size and format
// 1.2 checks the signature included in the report
// 1.3 checks if the signature is from an authorized authority (e.g. valid certificate etc)
// 2. extracts the code commitment from the report (e.g. MRENCLAVE in SGX) and compares it with the expected value
// this ensures the code and init data for loading the enclave was correct and untamperred
// 3. extracts the data commitment from the report (e.g. first 32 bytes of the REPORT_DATA) and compares it with the expected value
// this ensures the data part is correct, this is instance specific for example this is hash of node info values.
function validateReport(
bytes32 expectedCodeCommitment,
bytes32 expectedDataCommitment,
bytes calldata enclaveReport,
bytes calldata validationContext
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is validation context? is it params needed for passing to automata?

Copy link
Contributor Author

@Spablob Spablob Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's arbitrary data depending on each enclave type - for SGX is the tbcEvalNumber. When not needed can pass empty

) external returns (bool);
}
190 changes: 190 additions & 0 deletions contracts/src/interfaces/IDKG.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.23;

interface IDKG {
/// @notice Struct for the enclave type data unique to each enclave type
/// @param codeCommitment The code commitment
/// @param validationHookAddr The address of the validation hook
struct EnclaveTypeData {
bytes32 codeCommitment;
address validationHookAddr;
}

/// @notice Struct for the enclave instance data unique to each instance
/// @param round The round
/// @param validatorAddr The address of the validator
/// @param enclaveType The type of the enclave
/// @param enclaveCommKey The communication key of the enclave
/// @param dkgPubKey The DKG public key
struct EnclaveInstanceData {
uint32 round;
address validatorAddr;
bytes32 enclaveType;
bytes enclaveCommKey;
bytes dkgPubKey;
}

/// @notice Emitted when the minimum required registered participants is set
/// @param newMinReqRegisteredParticipants The new minimum required registered participants
event MinReqRegisteredParticipantsSet(uint256 newMinReqRegisteredParticipants);

/// @notice Emitted when the minimum required finalized participants is set
/// @param newMinReqFinalizedParticipants The new minimum required finalized participants
event MinReqFinalizedParticipantsSet(uint256 newMinReqFinalizedParticipants);

/// @notice Emitted when the operational threshold is set
/// @param newOperationalThreshold The new operational threshold
event OperationalThresholdSet(uint256 newOperationalThreshold);

/// @notice Emitted when the fee is set
/// @param newFee The new fee
event FeeSet(uint256 newFee);

/// @notice Emitted when an enclave type is whitelisted
/// @param enclaveType The type of the enclave
/// @param codeCommitment The code commitment
/// @param validationHookAddr The address of the validation hook
/// @param isWhitelisted Whether the enclave type is whitelisted
event EnclaveTypeWhitelisted(
bytes32 enclaveType,
bytes32 codeCommitment,
address validationHookAddr,
bool isWhitelisted
);

/// @notice Emitted when an enclave instance is registered
/// @param enclaveReport The enclave report
/// @param round The round
/// @param validatorAddr The address of the validator
/// @param enclaveType The type of the enclave
/// @param enclaveCommKey The communication key of the enclave
/// @param dkgPubKey The DKG public key
/// @param codeCommitment The code commitment
/// @param startBlockHeight The start block height
/// @param startBlockHash The start block hash
/// @param validationContext The validation context
event Registered(
bytes enclaveReport,
uint32 round,
address indexed validatorAddr,
bytes32 enclaveType,
bytes enclaveCommKey,
bytes dkgPubKey,
bytes32 codeCommitment,
uint256 startBlockHeight,
bytes32 startBlockHash,
bytes validationContext
);

/// @notice Emitted when an enclave instance is finalized
/// @param round The round
/// @param validatorAddr The address of the validator
/// @param enclaveType The type of the enclave
/// @param codeCommitment The code commitment
/// @param participantsRoot The participants root
/// @param globalPubKey The global public key
/// @param publicCoeffs The public coefficients
/// @param signature The signature
event Finalized(
uint32 round,
address indexed validatorAddr,
bytes32 enclaveType,
bytes32 codeCommitment,
bytes32 participantsRoot,
bytes globalPubKey,
bytes[] publicCoeffs,
bytes signature
);

/// @notice Sets the minimum number of participants needed to be registered for each round
/// @param newMinReqRegisteredParticipants The minimum number of participants needed to be registered for each round
function setMinReqRegisteredParticipants(uint256 newMinReqRegisteredParticipants) external;

/// @notice Sets the minimum number of participants needed to finish dkg for each round
/// @param newMinReqFinalizedParticipants The minimum number of participants needed to finish dkg for each round
function setMinReqFinalizedParticipants(uint256 newMinReqFinalizedParticipants) external;

/// @notice Sets the operational threshold
/// @param newOperationalThreshold The operational threshold
function setOperationalThreshold(uint256 newOperationalThreshold) external;

/// @notice Sets the fee paid to request DKG registration (register and finalize)
/// @param newFee The fee paid to request DKG registration (register and finalize)
function setFee(uint256 newFee) external;

/// @notice Whitelists an enclave type
/// @param enclaveType The type of the enclave
/// @param enclaveTypeData The data of the enclave type
/// @param isWhitelisted Whether the enclave type is whitelisted
function whitelistEnclaveType(
bytes32 enclaveType,
EnclaveTypeData memory enclaveTypeData,
bool isWhitelisted
) external;

/// @notice Authenticates an enclave report
/// @param enclaveReport The enclave report
/// @param enclaveInstanceData The data of the enclave instance
/// @param validationContext The validation context
function authenticateEnclaveReport(
bytes calldata enclaveReport,
EnclaveInstanceData calldata enclaveInstanceData,
bytes calldata validationContext
) external payable;

/// @notice Registers an enclave instance
/// @param enclaveReport The enclave report
/// @param enclaveInstanceData The data of the enclave instance
/// @param startBlockHeight The start block height
/// @param startBlockHash The start block hash
/// @param validationContext The validation context
function register(
bytes calldata enclaveReport,
EnclaveInstanceData calldata enclaveInstanceData,
uint256 startBlockHeight,
bytes32 startBlockHash,
bytes calldata validationContext
) external payable;

/// @notice Finalizes an enclave instance
/// @param round The round
/// @param validatorAddr The address of the validator
/// @param enclaveType The type of the enclave
/// @param participantsRoot The participants root
/// @param globalPubKey The global public key
/// @param publicCoeffs The public coefficients
/// @param signature The signature
function finalize(
uint32 round,
address validatorAddr,
bytes32 enclaveType,
bytes32 participantsRoot,
bytes calldata globalPubKey,
bytes[] calldata publicCoeffs,
bytes calldata signature
) external payable;

/// @notice Gets the minimum number of participants needed to be registered for each round
/// @return The minimum number of participants needed to be registered for each round
function minReqRegisteredParticipants() external view returns (uint256);

/// @notice Gets the minimum number of participants needed to finish dkg for each round
/// @return The minimum number of participants needed to finish dkg for each round
function minReqFinalizedParticipants() external view returns (uint256);

/// @notice Gets the operational threshold
/// @return The operational threshold
function operationalThreshold() external view returns (uint256);

/// @notice Gets the fee paid to request DKG registration (register and finalize)
/// @return The fee paid to request DKG registration (register and finalize)
function fee() external view returns (uint256);

/// @notice Gets the enclave type data
/// @param enclaveType The type of the enclave
function enclaveTypeData(bytes32 enclaveType) external view returns (EnclaveTypeData memory);

/// @notice Gets the is enclave type whitelisted
/// @param enclaveType The type of the enclave
function isEnclaveTypeWhitelisted(bytes32 enclaveType) external view returns (bool);
}
22 changes: 22 additions & 0 deletions contracts/src/interfaces/ISGXValidationHook.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.23;

import { IAttestationReportValidator } from "./IAttestationReportValidator.sol";

interface ISGXValidationHook is IAttestationReportValidator {
/// @notice Sets the address of the automata validation contract
/// @param newAutomataValidationAddr The address of the automata validation contract
function setAutomataValidationAddr(address newAutomataValidationAddr) external;

/// @notice Sets the TCB evaluation data number
/// @param newTcbEvaluationDataNumber The TCB evaluation data number
function setTcbEvaluationDataNumber(uint32 newTcbEvaluationDataNumber) external;

/// @notice Gets the address of the automata validation contract
/// @return The address of the automata validation contract
function automataValidationAddr() external view returns (address);

/// @notice Gets the TCB evaluation data number
/// @return The TCB evaluation data number
function tcbEvaluationDataNumber() external view returns (uint32);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.23;

interface IAutomataDcapAttestationFee {
function verifyAndAttestOnChain(
bytes calldata rawQuote,
uint32 tcbEvaluationDataNumber
) external payable returns (bool success, bytes memory output);
}
50 changes: 50 additions & 0 deletions contracts/src/libraries/BytesUtils.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.23;

library BytesUtils {
/// @dev Copies a substring into a new byte string
/// @param self The byte string to copy from
/// @param offset The offset to start copying at
/// @param len The number of bytes to copy
/// @return The new byte string
function substring(bytes memory self, uint256 offset, uint256 len) internal pure returns (bytes memory) {
require(offset + len <= self.length);

bytes memory ret = new bytes(len);
uint256 dest;
uint256 src;

assembly {
dest := add(ret, 32)
src := add(add(self, 32), offset)
}
memcpy(dest, src, len);

return ret;
}

function memcpy(uint256 dest, uint256 src, uint256 len) private pure {
// Copy word-length chunks while possible
for (; len >= 32; len -= 32) {
assembly {
mstore(dest, mload(src))
}
dest += 32;
src += 32;
}

// Copy remaining bytes
uint256 mask;
if (len == 0) {
mask = type(uint256).max; // Set to maximum value of uint256
} else {
mask = 256 ** (32 - len) - 1;
}

assembly {
let srcpart := and(mload(src), not(mask))
let destpart := and(mload(dest), mask)
mstore(dest, or(destpart, srcpart))
}
}
}
2 changes: 2 additions & 0 deletions contracts/src/libraries/Predeploys.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ library Predeploys {
address internal constant UBIPool = 0xCccCCC0000000000000000000000000000000002;
/// @dev UpgradeEntryPoint proxy address
address internal constant Upgrades = 0xccCCcc0000000000000000000000000000000003;
/// @dev DKG proxy address
address internal constant DKG = 0xCcCcCC0000000000000000000000000000000004;

/// @notice Create3 factory address https://github.com/ZeframLou/create3-factory
/// @dev Since Create3 is deployed using Create2, which is deterministic but depends on the deployer's wallet,
Expand Down
Loading
Loading