@crisp-e3/contracts 0.16.0 → 0.18.0-insecure.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/CRISPProgram.sol +485 -78
- package/contracts/Mocks/MockInterfold.sol +37 -3
- package/contracts/Mocks/MockVotesToken.sol +48 -0
- package/contracts/interfaces/IERC6372Clock.sol +16 -0
- package/contracts/interfaces/IHonkVerifier.sol +21 -0
- package/contracts/interfaces/IVotesToken.sol +23 -0
- package/contracts/verifiers/CRISPOnchainVerifier.sol +2493 -0
- package/contracts/{CRISPVerifier.sol → verifiers/CRISPVerifier.sol} +45 -45
- package/package.json +9 -4
|
@@ -19,6 +19,11 @@ contract MockInterfold {
|
|
|
19
19
|
uint256 public nextE3Id;
|
|
20
20
|
|
|
21
21
|
mapping(uint256 => E3) public e3s;
|
|
22
|
+
mapping(IE3Program => bool) public e3Programs;
|
|
23
|
+
|
|
24
|
+
function registerE3Program(IE3Program program) external {
|
|
25
|
+
e3Programs[program] = true;
|
|
26
|
+
}
|
|
22
27
|
|
|
23
28
|
function request(address program) external {
|
|
24
29
|
_request(program, 2);
|
|
@@ -30,6 +35,35 @@ contract MockInterfold {
|
|
|
30
35
|
_request(program, numOptions);
|
|
31
36
|
}
|
|
32
37
|
|
|
38
|
+
/// @notice Request an E3 with caller-supplied program params.
|
|
39
|
+
/// @dev `_request` hardcodes a TOKEN-census round. `CensusMode.ONCHAIN` needs a token, a credit
|
|
40
|
+
/// mode and a census mode that only the caller knows, and the snapshot is taken during
|
|
41
|
+
/// `validate`, so the params have to reach it here rather than being patched afterwards.
|
|
42
|
+
function requestWithParams(address program, uint256 numOptions, bytes memory params) external {
|
|
43
|
+
e3s[nextE3Id] = E3({
|
|
44
|
+
seed: 0,
|
|
45
|
+
committeeSize: IInterfold.CommitteeSize.Minimum,
|
|
46
|
+
requestBlock: 0,
|
|
47
|
+
inputWindow: [uint256(0), uint256(0)],
|
|
48
|
+
encryptionSchemeId: ENCRYPTION_SCHEME_ID,
|
|
49
|
+
e3Program: IE3Program(address(0)),
|
|
50
|
+
paramSet: 0, // Insecure512
|
|
51
|
+
customParams: params,
|
|
52
|
+
decryptionVerifier: IDecryptionVerifier(address(0)),
|
|
53
|
+
pkVerifier: IPkVerifier(address(0)),
|
|
54
|
+
committeePublicKey: committeePublicKey,
|
|
55
|
+
ciphertextOutput: bytes32(0),
|
|
56
|
+
plaintextOutput: plaintextOutput,
|
|
57
|
+
requester: address(0),
|
|
58
|
+
ciphertextCommitment: bytes32(0)
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
IE3Program(program).validate(nextE3Id, 0, bytes(""), bytes(""), params);
|
|
62
|
+
|
|
63
|
+
nextE3Id++;
|
|
64
|
+
numOptions; // silence unused-parameter warning; the count travels inside `params`
|
|
65
|
+
}
|
|
66
|
+
|
|
33
67
|
function _request(address program, uint256 numOptions) internal {
|
|
34
68
|
e3s[nextE3Id] = E3({
|
|
35
69
|
seed: 0,
|
|
@@ -39,7 +73,7 @@ contract MockInterfold {
|
|
|
39
73
|
encryptionSchemeId: ENCRYPTION_SCHEME_ID,
|
|
40
74
|
e3Program: IE3Program(address(0)),
|
|
41
75
|
paramSet: 0, // Insecure512
|
|
42
|
-
customParams: abi.encode(address(0), nextE3Id, numOptions, 0, 0, 0),
|
|
76
|
+
customParams: abi.encode(address(0), nextE3Id, numOptions, 0, 0, 0, 0),
|
|
43
77
|
decryptionVerifier: IDecryptionVerifier(address(0)),
|
|
44
78
|
pkVerifier: IPkVerifier(address(0)),
|
|
45
79
|
committeePublicKey: committeePublicKey,
|
|
@@ -49,7 +83,7 @@ contract MockInterfold {
|
|
|
49
83
|
ciphertextCommitment: bytes32(0)
|
|
50
84
|
});
|
|
51
85
|
|
|
52
|
-
IE3Program(program).validate(nextE3Id, 0, bytes(""), bytes(""), abi.encode(address(0), nextE3Id, numOptions, 0, 0, 0));
|
|
86
|
+
IE3Program(program).validate(nextE3Id, 0, bytes(""), bytes(""), abi.encode(address(0), nextE3Id, numOptions, 0, 0, 0, 0));
|
|
53
87
|
|
|
54
88
|
nextE3Id++;
|
|
55
89
|
}
|
|
@@ -76,7 +110,7 @@ contract MockInterfold {
|
|
|
76
110
|
encryptionSchemeId: ENCRYPTION_SCHEME_ID,
|
|
77
111
|
e3Program: IE3Program(address(0)),
|
|
78
112
|
paramSet: 0, // Insecure512
|
|
79
|
-
customParams: abi.encode(address(0), 0, 2, 0, 0, 0),
|
|
113
|
+
customParams: abi.encode(address(0), 0, 2, 0, 0, 0, 0),
|
|
80
114
|
decryptionVerifier: IDecryptionVerifier(address(0)),
|
|
81
115
|
pkVerifier: IPkVerifier(address(0)),
|
|
82
116
|
committeePublicKey: committeePublicKey,
|
|
@@ -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,21 @@
|
|
|
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. Every generated verifier declares a contract named `HonkVerifier`, and there is one
|
|
11
|
+
/// per census mode per BFV preset under `contracts/verifiers/<preset>/`, so importing the concrete
|
|
12
|
+
/// types would collide. Deployment resolves the right one by fully qualified name; see
|
|
13
|
+
/// `scripts/verifiers.ts`.
|
|
14
|
+
interface IHonkVerifier {
|
|
15
|
+
/// @notice Verify a folded ballot proof against its public inputs.
|
|
16
|
+
/// @dev Reverts rather than returning false when the public inputs do not match the proof.
|
|
17
|
+
/// @param proof The folded proof.
|
|
18
|
+
/// @param publicInputs The public inputs, in the order the fold circuit declares them.
|
|
19
|
+
/// @return True when the proof is valid.
|
|
20
|
+
function verify(bytes calldata proof, bytes32[] calldata publicInputs) external view returns (bool);
|
|
21
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
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
|
+
|
|
18
|
+
/// @notice The token's decimals, used to derive the default voting-power divisor.
|
|
19
|
+
/// @dev Optional: a token without it falls back to a divisor of 1, so the probe must not be
|
|
20
|
+
/// treated as a requirement the way `getPastVotes` is.
|
|
21
|
+
/// @return The number of decimals.
|
|
22
|
+
function decimals() external view returns (uint8);
|
|
23
|
+
}
|