@crisp-e3/contracts 0.0.1-test → 0.0.2-test

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,6 +10,7 @@ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
10
10
  import {IE3Program} from "@enclave-e3/contracts/contracts/interfaces/IE3Program.sol";
11
11
  import {IInputValidator} from "@enclave-e3/contracts/contracts/interfaces/IInputValidator.sol";
12
12
  import {IEnclave} from "@enclave-e3/contracts/contracts/interfaces/IEnclave.sol";
13
+ import {E3} from "@enclave-e3/contracts/contracts/interfaces/IE3.sol";
13
14
  import {CRISPInputValidatorFactory} from "./CRISPInputValidatorFactory.sol";
14
15
  import {HonkVerifier} from "./CRISPVerifier.sol";
15
16
 
@@ -24,6 +25,10 @@ contract CRISPProgram is IE3Program, Ownable {
24
25
  HonkVerifier private immutable HONK_VERIFIER;
25
26
  bytes32 public imageId;
26
27
 
28
+ /// @notice Half of the largest minimum degree used to fit votes
29
+ /// inside the plaintext polynomial
30
+ uint256 public constant HALF_LARGEST_MINIMUM_DEGREE = 28;
31
+
27
32
  // Mappings
28
33
  mapping(address => bool) public authorizedContracts;
29
34
  mapping(uint256 e3Id => bytes32 paramsHash) public paramsHashes;
@@ -55,10 +60,7 @@ contract CRISPProgram is IE3Program, Ownable {
55
60
  ) Ownable(msg.sender) {
56
61
  require(address(_enclave) != address(0), EnclaveAddressZero());
57
62
  require(address(_verifier) != address(0), VerifierAddressZero());
58
- require(
59
- address(_inputValidatorFactory) != address(0),
60
- InvalidInputValidatorFactory()
61
- );
63
+ require(address(_inputValidatorFactory) != address(0), InvalidInputValidatorFactory());
62
64
  require(address(_honkVerifier) != address(0), InvalidHonkVerifier());
63
65
 
64
66
  enclave = _enclave;
@@ -91,36 +93,68 @@ contract CRISPProgram is IE3Program, Ownable {
91
93
  /// @notice Validate the E3 program parameters
92
94
  /// @param e3Id The E3 program ID
93
95
  /// @param e3ProgramParams The E3 program parameters
94
- function validate(
95
- uint256 e3Id,
96
- uint256,
97
- bytes calldata e3ProgramParams,
98
- bytes calldata
99
- ) external returns (bytes32, IInputValidator inputValidator) {
100
- require(
101
- authorizedContracts[msg.sender] || msg.sender == owner(),
102
- CallerNotAuthorized()
103
- );
96
+ function validate(uint256 e3Id, uint256, bytes calldata e3ProgramParams, bytes calldata)
97
+ external
98
+ returns (bytes32, IInputValidator inputValidator)
99
+ {
100
+ require(authorizedContracts[msg.sender] || msg.sender == owner(), CallerNotAuthorized());
104
101
  require(paramsHashes[e3Id] == bytes32(0), E3AlreadyInitialized());
105
102
  paramsHashes[e3Id] = keccak256(e3ProgramParams);
106
103
 
107
104
  // Deploy a new input validator
108
- inputValidator = IInputValidator(
109
- INPUT_VALIDATOR_FACTORY.deploy(address(HONK_VERIFIER), owner())
110
- );
105
+ inputValidator = IInputValidator(INPUT_VALIDATOR_FACTORY.deploy(address(HONK_VERIFIER), owner()));
111
106
 
112
107
  return (ENCRYPTION_SCHEME_ID, inputValidator);
113
108
  }
114
109
 
110
+ /// @notice Decode the tally from the plaintext output
111
+ /// @param e3Id The E3 program ID
112
+ /// @return yes The number of yes votes
113
+ /// @return no The number of no votes
114
+ function decodeTally(uint256 e3Id) public view returns (uint256 yes, uint256 no) {
115
+ // fetch from enclave
116
+ E3 memory e3 = enclave.getE3(e3Id);
117
+
118
+ // abi decode it into an array of uint256
119
+ uint256[] memory tally = abi.decode(e3.plaintextOutput, (uint256[]));
120
+
121
+ /// @notice We want to completely ignore anything outside of the coefficients
122
+ /// we agreed to store out votes on.
123
+ uint256 halfD = tally.length / 2;
124
+ uint256 START_INDEX_Y = halfD - HALF_LARGEST_MINIMUM_DEGREE;
125
+ uint256 START_INDEX_N = tally.length - HALF_LARGEST_MINIMUM_DEGREE;
126
+
127
+ // first weight (we are converting back from bits to integer)
128
+ uint256 weight = 2 ** (HALF_LARGEST_MINIMUM_DEGREE - 1);
129
+
130
+ // Convert yes votes
131
+ for (uint256 i = START_INDEX_Y; i < halfD; i++) {
132
+ yes += tally[i] * weight;
133
+ weight /= 2; // Right shift equivalent
134
+ }
135
+
136
+ // Reset weight for no votes
137
+ weight = 2 ** (HALF_LARGEST_MINIMUM_DEGREE - 1);
138
+
139
+ // Convert no votes
140
+ for (uint256 i = START_INDEX_N; i < tally.length; i++) {
141
+ no += tally[i] * weight;
142
+ weight /= 2;
143
+ }
144
+
145
+ return (yes, no);
146
+ }
147
+
115
148
  /// @notice Verify the proof
116
149
  /// @param e3Id The E3 program ID
117
150
  /// @param ciphertextOutputHash The hash of the ciphertext output
118
151
  /// @param proof The proof to verify
119
- function verify(
120
- uint256 e3Id,
121
- bytes32 ciphertextOutputHash,
122
- bytes memory proof
123
- ) external view override returns (bool) {
152
+ function verify(uint256 e3Id, bytes32 ciphertextOutputHash, bytes memory proof)
153
+ external
154
+ view
155
+ override
156
+ returns (bool)
157
+ {
124
158
  require(paramsHashes[e3Id] != bytes32(0), E3DoesNotExist());
125
159
  bytes32 inputRoot = bytes32(enclave.getInputRoot(e3Id));
126
160
  bytes memory journal = new bytes(396); // (32 + 1) * 4 * 3
@@ -137,11 +171,7 @@ contract CRISPProgram is IE3Program, Ownable {
137
171
  /// @param journal The journal to encode into
138
172
  /// @param startIndex The start index in the journal
139
173
  /// @param hashVal The hash value to encode
140
- function encodeLengthPrefixAndHash(
141
- bytes memory journal,
142
- uint256 startIndex,
143
- bytes32 hashVal
144
- ) internal pure {
174
+ function encodeLengthPrefixAndHash(bytes memory journal, uint256 startIndex, bytes32 hashVal) internal pure {
145
175
  journal[startIndex] = 0x20;
146
176
  startIndex += 4;
147
177
  for (uint256 i = 0; i < 32; i++) {
@@ -0,0 +1,39 @@
1
+ // SPDX-License-Identifier: LGPL-3.0-only
2
+ //
3
+ // This file is provided WITHOUT ANY WARRANTY;
4
+ // without even the implied warranty of MERCHANTABILITY
5
+ // or FITNESS FOR A PARTICULAR PURPOSE.
6
+ pragma solidity >=0.8.27;
7
+
8
+ import {E3} from "@enclave-e3/contracts/contracts/interfaces/IE3.sol";
9
+ import {IE3Program} from "@enclave-e3/contracts/contracts/interfaces/IE3Program.sol";
10
+ import {IInputValidator} from "@enclave-e3/contracts/contracts/interfaces/IInputValidator.sol";
11
+ import {IDecryptionVerifier} from "@enclave-e3/contracts/contracts/interfaces/IDecryptionVerifier.sol";
12
+
13
+ contract MockEnclave {
14
+ bytes public plaintextOutput;
15
+
16
+ function setPlaintextOutput(uint256[] memory plaintext) external {
17
+ plaintextOutput = abi.encode(plaintext);
18
+ }
19
+
20
+ function getE3(uint256 e3Id) external view returns (E3 memory) {
21
+ return E3({
22
+ seed: 0,
23
+ threshold: [uint32(1), uint32(2)],
24
+ requestBlock: 0,
25
+ startWindow: [uint256(0), uint256(0)],
26
+ duration: 0,
27
+ expiration: 0,
28
+ encryptionSchemeId: bytes32(0),
29
+ e3Program: IE3Program(address(0)),
30
+ e3ProgramParams: bytes(""),
31
+ customParams: bytes(""),
32
+ inputValidator: IInputValidator(address(0)),
33
+ decryptionVerifier: IDecryptionVerifier(address(0)),
34
+ committeePublicKey: bytes32(0),
35
+ ciphertextOutput: bytes32(0),
36
+ plaintextOutput: plaintextOutput
37
+ });
38
+ }
39
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crisp-e3/contracts",
3
- "version": "0.0.1-test",
3
+ "version": "0.0.2-test",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "contracts",
@@ -47,6 +47,7 @@
47
47
  "@types/chai": "^4.2.0",
48
48
  "@types/mocha": ">=9.1.0",
49
49
  "@types/node": "^22.18.0",
50
+ "chai": "^6.2.0",
50
51
  "dotenv": "^16.4.5",
51
52
  "ethers": "^6.15.0",
52
53
  "forge-std": "github:foundry-rs/forge-std#v1.9.4",
@@ -57,7 +58,9 @@
57
58
  "ts-node": "^10.9.2",
58
59
  "typechain": "^8.3.0",
59
60
  "typescript": "5.8.3",
60
- "viem": "2.30.6"
61
+ "viem": "2.30.6",
62
+ "@crisp-e3/sdk": "^0.0.2-test",
63
+ "@crisp-e3/zk-inputs": "^0.0.2-test"
61
64
  },
62
65
  "scripts": {
63
66
  "compile": "hardhat compile",
@@ -66,7 +69,7 @@
66
69
  "deploy:contracts": "hardhat run deploy/deploy.ts",
67
70
  "deploy:contracts:full": "export DEPLOY_ENCLAVE=true && pnpm deploy:contracts",
68
71
  "deploy:contracts:full:mock": "export DEPLOY_ENCLAVE=true && export USE_MOCK_VERIFIER=true && export USE_MOCK_INPUT_VALIDATOR=true && pnpm deploy:contracts",
69
- "test": "hardhat test tests/crisp.contracts.test.ts --network localhost",
72
+ "test": "hardhat test mocha",
70
73
  "verify": "hardhat run deploy/verify.ts"
71
74
  }
72
75
  }