@crisp-e3/contracts 0.15.0 → 0.17.0
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.
- package/contracts/CRISPOnchainVerifier.sol +2493 -0
- package/contracts/CRISPProgram.sol +223 -67
- package/contracts/CRISPVerifier.sol +524 -468
- package/contracts/Mocks/MockInterfold.sol +32 -2
- package/contracts/Mocks/MockVotesToken.sol +48 -0
- package/contracts/interfaces/IERC6372Clock.sol +16 -0
- package/contracts/interfaces/IHonkVerifier.sol +19 -0
- package/contracts/interfaces/IVotesToken.sol +17 -0
- package/package.json +4 -4
|
@@ -12,6 +12,7 @@ import { IDecryptionVerifier } from "@interfold/contracts/contracts/interfaces/I
|
|
|
12
12
|
import { IPkVerifier } from "@interfold/contracts/contracts/interfaces/IPkVerifier.sol";
|
|
13
13
|
|
|
14
14
|
contract MockInterfold {
|
|
15
|
+
bytes32 public constant ENCRYPTION_SCHEME_ID = keccak256("fhe.rs:BFV");
|
|
15
16
|
bytes public plaintextOutput;
|
|
16
17
|
bytes32 public committeePublicKey;
|
|
17
18
|
|
|
@@ -29,13 +30,42 @@ contract MockInterfold {
|
|
|
29
30
|
_request(program, numOptions);
|
|
30
31
|
}
|
|
31
32
|
|
|
33
|
+
/// @notice Request an E3 with caller-supplied program params.
|
|
34
|
+
/// @dev `_request` hardcodes a TOKEN-census round. `CensusMode.ONCHAIN` needs a token, a credit
|
|
35
|
+
/// mode and a census mode that only the caller knows, and the snapshot is taken during
|
|
36
|
+
/// `validate`, so the params have to reach it here rather than being patched afterwards.
|
|
37
|
+
function requestWithParams(address program, uint256 numOptions, bytes memory params) external {
|
|
38
|
+
e3s[nextE3Id] = E3({
|
|
39
|
+
seed: 0,
|
|
40
|
+
committeeSize: IInterfold.CommitteeSize.Minimum,
|
|
41
|
+
requestBlock: 0,
|
|
42
|
+
inputWindow: [uint256(0), uint256(0)],
|
|
43
|
+
encryptionSchemeId: ENCRYPTION_SCHEME_ID,
|
|
44
|
+
e3Program: IE3Program(address(0)),
|
|
45
|
+
paramSet: 0, // Insecure512
|
|
46
|
+
customParams: params,
|
|
47
|
+
decryptionVerifier: IDecryptionVerifier(address(0)),
|
|
48
|
+
pkVerifier: IPkVerifier(address(0)),
|
|
49
|
+
committeePublicKey: committeePublicKey,
|
|
50
|
+
ciphertextOutput: bytes32(0),
|
|
51
|
+
plaintextOutput: plaintextOutput,
|
|
52
|
+
requester: address(0),
|
|
53
|
+
ciphertextCommitment: bytes32(0)
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
IE3Program(program).validate(nextE3Id, 0, bytes(""), bytes(""), params);
|
|
57
|
+
|
|
58
|
+
nextE3Id++;
|
|
59
|
+
numOptions; // silence unused-parameter warning; the count travels inside `params`
|
|
60
|
+
}
|
|
61
|
+
|
|
32
62
|
function _request(address program, uint256 numOptions) internal {
|
|
33
63
|
e3s[nextE3Id] = E3({
|
|
34
64
|
seed: 0,
|
|
35
65
|
committeeSize: IInterfold.CommitteeSize.Minimum,
|
|
36
66
|
requestBlock: 0,
|
|
37
67
|
inputWindow: [uint256(0), uint256(0)],
|
|
38
|
-
encryptionSchemeId:
|
|
68
|
+
encryptionSchemeId: ENCRYPTION_SCHEME_ID,
|
|
39
69
|
e3Program: IE3Program(address(0)),
|
|
40
70
|
paramSet: 0, // Insecure512
|
|
41
71
|
customParams: abi.encode(address(0), nextE3Id, numOptions, 0, 0, 0),
|
|
@@ -72,7 +102,7 @@ contract MockInterfold {
|
|
|
72
102
|
committeeSize: IInterfold.CommitteeSize.Minimum,
|
|
73
103
|
requestBlock: 0,
|
|
74
104
|
inputWindow: [uint256(0), block.timestamp + 100],
|
|
75
|
-
encryptionSchemeId:
|
|
105
|
+
encryptionSchemeId: ENCRYPTION_SCHEME_ID,
|
|
76
106
|
e3Program: IE3Program(address(0)),
|
|
77
107
|
paramSet: 0, // Insecure512
|
|
78
108
|
customParams: abi.encode(address(0), 0, 2, 0, 0, 0),
|
|
@@ -0,0 +1,48 @@
|
|
|
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 { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
|
9
|
+
import { ERC20Permit } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
|
|
10
|
+
import { ERC20Votes } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol";
|
|
11
|
+
import { Nonces } from "@openzeppelin/contracts/utils/Nonces.sol";
|
|
12
|
+
|
|
13
|
+
/// @title MockVotesToken
|
|
14
|
+
/// @notice An ERC20Votes token for exercising `CensusMode.ONCHAIN`.
|
|
15
|
+
/// @dev `MockVotingToken` is a plain ERC20 with no `getPastVotes`, which makes it the negative
|
|
16
|
+
/// case for the token probe in `CRISPProgram._initRound`. This one is the positive case.
|
|
17
|
+
///
|
|
18
|
+
/// Uses the timestamp clock, matching `InterfoldToken`. A round records its snapshot in whatever
|
|
19
|
+
/// units the token reports, so a mock on the default block-number clock would exercise a
|
|
20
|
+
/// different path from the token this mode is built for.
|
|
21
|
+
contract MockVotesToken is ERC20, ERC20Permit, ERC20Votes {
|
|
22
|
+
constructor() ERC20("Mock Votes Token", "MVOTE") ERC20Permit("Mock Votes Token") {
|
|
23
|
+
_mint(msg.sender, 1e24);
|
|
24
|
+
_delegate(msg.sender, msg.sender);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function mint(address to, uint256 amount) external {
|
|
28
|
+
_mint(to, amount);
|
|
29
|
+
if (delegates(to) == address(0)) _delegate(to, to);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function clock() public view override returns (uint48) {
|
|
33
|
+
return uint48(block.timestamp);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/// @dev Declared pure per ERC-6372, so it cannot read `clock()`.
|
|
37
|
+
function CLOCK_MODE() public pure override returns (string memory) {
|
|
38
|
+
return "mode=timestamp";
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function _update(address from, address to, uint256 value) internal override(ERC20, ERC20Votes) {
|
|
42
|
+
super._update(from, to, value);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function nonces(address owner) public view override(ERC20Permit, Nonces) returns (uint256) {
|
|
46
|
+
return super.nonces(owner);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
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
|
+
/// @notice The ERC-6372 clock of a token, used to record the snapshot of a round.
|
|
9
|
+
/// @dev Kept separate from `IVotesToken` because it is the optional half of the token surface.
|
|
10
|
+
/// A token that predates ERC-6372 still answers `getPastVotes`, so `CRISPProgram` falls back to
|
|
11
|
+
/// block numbers when this call reverts rather than refusing the round.
|
|
12
|
+
interface IERC6372Clock {
|
|
13
|
+
/// @notice The current timepoint, in the clock units of the token.
|
|
14
|
+
/// @return The timepoint.
|
|
15
|
+
function clock() external view returns (uint48);
|
|
16
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
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
|
+
/// @notice The subset of a generated Honk verifier that `CRISPProgram` calls.
|
|
9
|
+
/// @dev Declared as an interface so the census paths can hold verifiers generated from different
|
|
10
|
+
/// circuits. `CRISPVerifier.sol` and `CRISPOnchainVerifier.sol` both declare a contract named
|
|
11
|
+
/// `HonkVerifier`, so importing both concrete types would collide.
|
|
12
|
+
interface IHonkVerifier {
|
|
13
|
+
/// @notice Verify a folded ballot proof against its public inputs.
|
|
14
|
+
/// @dev Reverts rather than returning false when the public inputs do not match the proof.
|
|
15
|
+
/// @param proof The folded proof.
|
|
16
|
+
/// @param publicInputs The public inputs, in the order the fold circuit declares them.
|
|
17
|
+
/// @return True when the proof is valid.
|
|
18
|
+
function verify(bytes calldata proof, bytes32[] calldata publicInputs) external view returns (bool);
|
|
19
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
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
|
+
/// @notice The subset of an ERC20Votes token that `CensusMode.ONCHAIN` reads.
|
|
9
|
+
/// @dev Required, not optional. A round that names a token which cannot answer this is rejected
|
|
10
|
+
/// at request time, because every input would otherwise revert here after the fee is paid.
|
|
11
|
+
interface IVotesToken {
|
|
12
|
+
/// @notice The voting power of an account at a past timepoint.
|
|
13
|
+
/// @param account The account to read.
|
|
14
|
+
/// @param timepoint The timepoint, in the ERC-6372 clock units of the token.
|
|
15
|
+
/// @return The voting power at that timepoint.
|
|
16
|
+
function getPastVotes(address account, uint256 timepoint) external view returns (uint256);
|
|
17
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crisp-e3/contracts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"contracts",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"@zk-kit/lazy-imt.sol": "2.0.0-beta.12",
|
|
32
32
|
"poseidon-solidity": "^0.0.5",
|
|
33
33
|
"solady": "^0.1.13",
|
|
34
|
-
"@interfold/contracts": "0.
|
|
34
|
+
"@interfold/contracts": "0.6.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@nomicfoundation/hardhat-keystore": "3.0.3",
|
|
@@ -53,8 +53,8 @@
|
|
|
53
53
|
"typechain": "^8.3.0",
|
|
54
54
|
"typescript": "5.8.3",
|
|
55
55
|
"viem": "2.30.6",
|
|
56
|
-
"@crisp-e3/
|
|
57
|
-
"@crisp-e3/
|
|
56
|
+
"@crisp-e3/sdk": "^0.17.0",
|
|
57
|
+
"@crisp-e3/zk-inputs": "^0.17.0"
|
|
58
58
|
},
|
|
59
59
|
"scripts": {
|
|
60
60
|
"compile": "hardhat compile",
|