@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
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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.
|
|
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
|
|
72
|
+
"test": "hardhat test mocha",
|
|
70
73
|
"verify": "hardhat run deploy/verify.ts"
|
|
71
74
|
}
|
|
72
75
|
}
|