Skip to content

Commit

Permalink
Merge pull request #243 from gnosisguild/ry/260-excubiae-advanced
Browse files Browse the repository at this point in the history
BasePolicy -> AdvancedPolicy
  • Loading branch information
ryardley authored Feb 4, 2025
2 parents ee04ede + e764557 commit 25d7d9a
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 47 deletions.
12 changes: 8 additions & 4 deletions packages/evm/contracts/Enclave.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ pragma solidity >=0.8.27;

import { IEnclave, E3, IE3Program } from "./interfaces/IEnclave.sol";
import { ICiphernodeRegistry } from "./interfaces/ICiphernodeRegistry.sol";
import { IBasePolicy } from "./excubiae/core/interfaces/IBasePolicy.sol";
import {
IAdvancedPolicy
} from "./excubiae/core/interfaces/IAdvancedPolicy.sol";
import { Check } from "./excubiae/core/interfaces/IAdvancedChecker.sol";
import { IDecryptionVerifier } from "./interfaces/IDecryptionVerifier.sol";
import {
OwnableUpgradeable
Expand Down Expand Up @@ -62,7 +65,7 @@ contract Enclave is IEnclave, OwnableUpgradeable {
error InvalidEncryptionScheme(bytes32 encryptionSchemeId);
error InputDeadlinePassed(uint256 e3Id, uint256 expiration);
error InputDeadlineNotPassed(uint256 e3Id, uint256 expiration);
error InvalidComputationRequest(IBasePolicy inputValidator);
error InvalidComputationRequest(IAdvancedPolicy inputValidator);
error InvalidCiphernodeRegistry(ICiphernodeRegistry ciphernodeRegistry);
error InvalidDuration(uint256 duration);
error InvalidOutput(bytes output);
Expand All @@ -80,6 +83,7 @@ contract Enclave is IEnclave, OwnableUpgradeable {
error TargetOnly();
error TargetAlreadySet();
error AlreadyEnforced();
error MainCheckAlreadyEnforced();

////////////////////////////////////////////////////////////
// //
Expand Down Expand Up @@ -149,7 +153,7 @@ contract Enclave is IEnclave, OwnableUpgradeable {
nexte3Id++;
uint256 seed = uint256(keccak256(abi.encode(block.prevrandao, e3Id)));

(bytes32 encryptionSchemeId, IBasePolicy inputValidator) = e3Program
(bytes32 encryptionSchemeId, IAdvancedPolicy inputValidator) = e3Program
.validate(e3Id, seed, e3ProgramParams, computeProviderParams);
IDecryptionVerifier decryptionVerifier = decryptionVerifiers[
encryptionSchemeId
Expand Down Expand Up @@ -231,7 +235,7 @@ contract Enclave is IEnclave, OwnableUpgradeable {
bytes[] memory payload = new bytes[](1);
payload[0] = data;

e3.inputValidator.enforce(msg.sender, payload);
e3.inputValidator.enforce(msg.sender, payload, Check.MAIN);
uint256 inputHash = PoseidonT3.hash(
[uint256(keccak256(data)), inputCounts[e3Id]]
);
Expand Down
14 changes: 8 additions & 6 deletions packages/evm/contracts/excubiae/InputValidatorPolicy.sol
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.27;

import { BasePolicy } from "./core/BasePolicy.sol";
import { BaseChecker } from "./core/BaseChecker.sol";
import { AdvancedPolicy } from "./core/AdvancedPolicy.sol";
import { AdvancedChecker } from "./core/AdvancedChecker.sol";

/// @title BaseERC721Policy.
/// @notice Policy enforcer for Enclave Input validation.
/// @dev Extends BasePolicy with Enclave specific checks.
contract InputValidatorPolicy is BasePolicy {
contract InputValidatorPolicy is AdvancedPolicy {
/// @notice Checker contract reference.
BaseChecker public immutable CHECKER;
AdvancedChecker public immutable CHECKER;

/// @notice Initializes with checker contract.
/// @param _checker Checker contract address.
constructor(BaseChecker _checker) BasePolicy(_checker) {
CHECKER = BaseChecker(_checker);
constructor(
AdvancedChecker _checker
) AdvancedPolicy(_checker, true, true, true) {
CHECKER = AdvancedChecker(_checker);
}

/// @notice Returns policy identifier.
Expand Down
27 changes: 21 additions & 6 deletions packages/evm/contracts/excubiae/core/AdvancedPolicy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
// Auto-generated from https://github.com/privacy-scaling-explorations/excubiae.git@96a3312455417dc1b2e0d87066661fdf8f490fac
pragma solidity >=0.8.27;

import {Policy} from "./Policy.sol";
import {IAdvancedPolicy, Check} from "./interfaces/IAdvancedPolicy.sol";
import {AdvancedChecker, CheckStatus} from "./AdvancedChecker.sol";
import { Policy } from "./Policy.sol";
import { IAdvancedPolicy, Check } from "./interfaces/IAdvancedPolicy.sol";
import { AdvancedChecker, CheckStatus } from "./AdvancedChecker.sol";
import "hardhat/console.sol";

/// @title AdvancedPolicy.
/// @notice Implements advanced policy checks with pre, main, and post validation stages.
Expand Down Expand Up @@ -33,7 +34,12 @@ abstract contract AdvancedPolicy is IAdvancedPolicy, Policy {
/// @param _skipPre Skip pre-condition validation.
/// @param _skipPost Skip post-condition validation.
/// @param _allowMultipleMain Allow multiple main validations.
constructor(AdvancedChecker _advancedChecker, bool _skipPre, bool _skipPost, bool _allowMultipleMain) {
constructor(
AdvancedChecker _advancedChecker,
bool _skipPre,
bool _skipPost,
bool _allowMultipleMain
) {
ADVANCED_CHECKER = _advancedChecker;
SKIP_PRE = _skipPre;
SKIP_POST = _skipPost;
Expand All @@ -45,7 +51,11 @@ abstract contract AdvancedPolicy is IAdvancedPolicy, Policy {
/// @param subject Address to validate.
/// @param evidence Validation data.
/// @param checkType Type of check (PRE, MAIN, POST).
function enforce(address subject, bytes[] calldata evidence, Check checkType) external override onlyTarget {
function enforce(
address subject,
bytes[] calldata evidence,
Check checkType
) external override onlyTarget {
_enforce(subject, evidence, checkType);
}

Expand All @@ -61,8 +71,13 @@ abstract contract AdvancedPolicy is IAdvancedPolicy, Policy {
/// @custom:throws PreCheckNotEnforced If PRE check is required but not done.
/// @custom:throws MainCheckNotEnforced If MAIN check is required but not done.
/// @custom:throws MainCheckAlreadyEnforced If multiple MAIN checks not allowed.
function _enforce(address subject, bytes[] calldata evidence, Check checkType) internal {
function _enforce(
address subject,
bytes[] calldata evidence,
Check checkType
) internal {
if (!ADVANCED_CHECKER.check(subject, evidence, checkType)) {
console.log("_enforce()");
revert UnsuccessfulCheck();
}

Expand Down
6 changes: 4 additions & 2 deletions packages/evm/contracts/interfaces/IE3.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.27;

import { IBasePolicy } from "../excubiae/core/interfaces/IBasePolicy.sol";
import {
IAdvancedPolicy
} from "../excubiae/core/interfaces/IAdvancedPolicy.sol";
import { IE3Program } from "./IE3Program.sol";
import { IDecryptionVerifier } from "./IDecryptionVerifier.sol";

Expand Down Expand Up @@ -29,7 +31,7 @@ struct E3 {
bytes32 encryptionSchemeId;
IE3Program e3Program;
bytes e3ProgramParams;
IBasePolicy inputValidator;
IAdvancedPolicy inputValidator;
IDecryptionVerifier decryptionVerifier;
bytes32 committeePublicKey;
bytes32 ciphertextOutput;
Expand Down
8 changes: 6 additions & 2 deletions packages/evm/contracts/interfaces/IE3Program.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.27;

import { IBasePolicy } from "../excubiae/core/interfaces/IBasePolicy.sol";
import {
IAdvancedPolicy
} from "../excubiae/core/interfaces/IAdvancedPolicy.sol";

interface IE3Program {
/// @notice This function should be called by the Enclave contract to validate the computation parameters.
Expand All @@ -16,7 +18,9 @@ interface IE3Program {
uint256 seed,
bytes calldata e3ProgramParams,
bytes calldata computeProviderParams
) external returns (bytes32 encryptionSchemeId, IBasePolicy inputValidator);
)
external
returns (bytes32 encryptionSchemeId, IAdvancedPolicy inputValidator);

/// @notice This function should be called by the Enclave contract to verify the decrypted output of an E3.
/// @param e3Id ID of the E3.
Expand Down
10 changes: 5 additions & 5 deletions packages/evm/contracts/test/MockE3Program.sol
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.27;

import { IE3Program, IBasePolicy } from "../interfaces/IE3Program.sol";
import { IE3Program, IAdvancedPolicy } from "../interfaces/IE3Program.sol";

contract MockE3Program is IE3Program {
error invalidParams(bytes e3ProgramParams, bytes computeProviderParams);

bytes32 public constant ENCRYPTION_SCHEME_ID = keccak256("fhe.rs:BFV");

IBasePolicy private storageInputValidator;
IAdvancedPolicy private storageInputValidator;

constructor(IBasePolicy _inputValidator) {
constructor(IAdvancedPolicy _inputValidator) {
storageInputValidator = _inputValidator;
}

function setInputValidator(IBasePolicy _inputValidator) external {
function setInputValidator(IAdvancedPolicy _inputValidator) external {
storageInputValidator = _inputValidator;
}

Expand All @@ -26,7 +26,7 @@ contract MockE3Program is IE3Program {
)
external
view
returns (bytes32 encryptionSchemeId, IBasePolicy inputValidator)
returns (bytes32 encryptionSchemeId, IAdvancedPolicy inputValidator)
{
require(
computeProviderParams.length == 32,
Expand Down
11 changes: 6 additions & 5 deletions packages/evm/contracts/test/MockInputValidatorChecker.sol
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.27;

import { BaseChecker } from "../excubiae/core/BaseChecker.sol";
import { AdvancedChecker } from "../excubiae/core/AdvancedChecker.sol";
import { Check } from "../excubiae/core/interfaces/IAdvancedChecker.sol";

/// @title MockInputValidatorChecker.
/// @notice Enclave Input Validator
/// @dev Extends BaseChecker for input verification.
contract MockInputValidatorChecker is BaseChecker {
contract MockInputValidatorChecker is AdvancedChecker {
/// @param _verifiers Array of addresses for existing verification contracts.
constructor(address[] memory _verifiers) BaseChecker(_verifiers) {}
constructor(address[] memory _verifiers) AdvancedChecker(_verifiers) {}

/// @notice Validates input
/// @param subject Address to check.
/// @param evidence mock proof
/// @return True if proof is valid
function _check(
function _checkMain(
address subject,
bytes[] calldata evidence
) internal view override returns (bool) {
super._check(subject, evidence);
super._checkMain(subject, evidence);
bool success;

if (evidence[0].length == 3) {
Expand Down
19 changes: 2 additions & 17 deletions packages/evm/test/Enclave.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -958,8 +958,7 @@ describe("Enclave", function () {
);
});

// XXX: Skipping for now as fixing this would mean implementing an AdvancedPolicy in excubiae
it.skip("adds inputHash to merkle tree", async function () {
it("adds inputHash to merkle tree", async function () {
const { enclave, request } = await loadFixture(setup);
const inputData = abiCoder.encode(["bytes"], ["0xaabbccddeeff"]);

Expand Down Expand Up @@ -1332,20 +1331,6 @@ describe("Enclave", function () {
});

describe("InputValidatorPolicy", function () {
it("should validate inputs using the input validator", async function () {
const [owner, notTheOwner] = await ethers.getSigners();
const { inputValidatorPolicy } = await loadFixture(
deployInputValidatorContracts,
);
await inputValidatorPolicy.connect(owner).setTarget(owner);
const shouldPass = "0x1234"; // length 2 = pass
const contract = inputValidatorPolicy.connect(owner);
await contract.connect(owner).enforce(notTheOwner, [shouldPass]);
await expect(
contract.connect(owner).enforce(notTheOwner, [shouldPass]),
).to.be.revertedWithCustomError(inputValidatorPolicy, "AlreadyEnforced");
});

it("should fail with error if the checker fails", async function () {
const [owner, notTheOwner] = await ethers.getSigners();

Expand All @@ -1356,7 +1341,7 @@ describe("InputValidatorPolicy", function () {
const shouldFail = "0x123456"; // length 3 = fail
const contract = inputValidatorPolicy.connect(owner);
await expect(
contract.enforce(notTheOwner, [shouldFail]),
contract.enforce(notTheOwner, [shouldFail], 1),
).to.be.revertedWithCustomError(contract, "UnsuccessfulCheck");
});
});

0 comments on commit 25d7d9a

Please sign in to comment.