-
Notifications
You must be signed in to change notification settings - Fork 16
/
hydra-s1.circom
135 lines (119 loc) · 6.18 KB
/
hydra-s1.circom
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
pragma circom 2.1.2;
include "../node_modules/circomlib/circuits/compconstant.circom";
include "../node_modules/circomlib/circuits/comparators.circom";
include "../node_modules/circomlib/circuits/poseidon.circom";
include "../node_modules/circomlib/circuits/bitify.circom";
include "../node_modules/circomlib/circuits/mux1.circom";
include "../node_modules/circomlib/circuits/babyjub.circom";
include "./common/verify-merkle-path.circom";
include "./common/verify-hydra-commitment.circom";
// This is the circuit for the Hydra S1 Proving Scheme
// please read this doc to understand the underlying concepts
// https://hydra-s1.docs.sismo.io
template hydraS1(registryTreeHeight, accountsTreeHeight) {
// Private inputs
signal input sourceIdentifier;
signal input sourceSecret;
signal input sourceCommitmentReceipt[3];
signal input destinationSecret;
signal input destinationCommitmentReceipt[3];
signal input accountMerklePathElements[accountsTreeHeight];
signal input accountMerklePathIndices[accountsTreeHeight];
signal input accountsTreeRoot;
signal input registryMerklePathElements[registryTreeHeight];
signal input registryMerklePathIndices[registryTreeHeight];
signal input sourceValue;
// Public inputs
signal input destinationIdentifier;
signal input chainId;
signal input commitmentMapperPubKey[2];
signal input registryTreeRoot;
signal input externalNullifier;
signal input nullifier;
signal input claimedValue;
signal input accountsTreeValue;
signal input isStrict;
// Verify the source account went through the Hydra Delegated Proof of Ownership
// That means the user own the source address
component sourceCommitmentVerification = VerifyHydraCommitment();
sourceCommitmentVerification.address <== sourceIdentifier;
sourceCommitmentVerification.secret <== sourceSecret;
sourceCommitmentVerification.commitmentMapperPubKey[0] <== commitmentMapperPubKey[0];
sourceCommitmentVerification.commitmentMapperPubKey[1] <== commitmentMapperPubKey[1];
sourceCommitmentVerification.commitmentReceipt[0] <== sourceCommitmentReceipt[0];
sourceCommitmentVerification.commitmentReceipt[1] <== sourceCommitmentReceipt[1];
sourceCommitmentVerification.commitmentReceipt[2] <== sourceCommitmentReceipt[2];
// Verify the destination account went through the Hydra Delegated Proof of Ownership
// That means the user own the destination address
component destinationCommitmentVerification = VerifyHydraCommitment();
destinationCommitmentVerification.address <== destinationIdentifier;
destinationCommitmentVerification.secret <== destinationSecret;
destinationCommitmentVerification.commitmentMapperPubKey[0] <== commitmentMapperPubKey[0];
destinationCommitmentVerification.commitmentMapperPubKey[1] <== commitmentMapperPubKey[1];
destinationCommitmentVerification.commitmentReceipt[0] <== destinationCommitmentReceipt[0];
destinationCommitmentVerification.commitmentReceipt[1] <== destinationCommitmentReceipt[1];
destinationCommitmentVerification.commitmentReceipt[2] <== destinationCommitmentReceipt[2];
// Verification that the source account is part of an accounts tree
// Recreating the leaf which is the hash of an account identifier and an account value
component accountLeafConstructor = Poseidon(2);
accountLeafConstructor.inputs[0] <== sourceIdentifier;
accountLeafConstructor.inputs[1] <== sourceValue;
// This tree is an Accounts Merkle Tree which is constituted by accounts
// https://accounts-registry-tree.docs.sismo.io
// leaf = Hash(accountIdentifier, accountValue)
// verify the merkle path
component accountsTreesPathVerifier = VerifyMerklePath(accountsTreeHeight);
accountsTreesPathVerifier.leaf <== accountLeafConstructor.out;
accountsTreesPathVerifier.root <== accountsTreeRoot;
for (var i = 0; i < accountsTreeHeight; i++) {
accountsTreesPathVerifier.pathElements[i] <== accountMerklePathElements[i];
accountsTreesPathVerifier.pathIndices[i] <== accountMerklePathIndices[i];
}
// Verification that the accounts tree is part of a registry tree
// Recreating the leaf
component registryLeafConstructor = Poseidon(2);
registryLeafConstructor.inputs[0] <== accountsTreeRoot;
registryLeafConstructor.inputs[1] <== accountsTreeValue;
// https://accounts-registry-tree.docs.sismo.io
// leaf = Hash(accountsTreeRoot, accountsTreeValue)
// verify the merkle path
component registryTreePathVerifier = VerifyMerklePath(registryTreeHeight);
registryTreePathVerifier.leaf <== registryLeafConstructor.out;
registryTreePathVerifier.root <== registryTreeRoot;
for (var i = 0; i < registryTreeHeight; i++) {
registryTreePathVerifier.pathElements[i] <== registryMerklePathElements[i];
registryTreePathVerifier.pathIndices[i] <== registryMerklePathIndices[i];
}
// Verify claimed value validity
// Prevent overflow of comparator range
component sourceInRange = Num2Bits(252);
sourceInRange.in <== sourceValue;
component claimedInRange = Num2Bits(252);
claimedInRange.in <== claimedValue;
// 0 <= claimedValue <= sourceValue
component leq = LessEqThan(252);
leq.in[0] <== claimedValue;
leq.in[1] <== sourceValue;
leq.out === 1;
// If isStrict == 1 then claimedValue == sourceValue
0 === (isStrict-1)*isStrict;
sourceValue === sourceValue+((claimedValue-sourceValue)*isStrict);
// Verify the nullifier is valid
// compute the sourceSecretHash using the hash of the sourceSecret
signal sourceSecretHash;
component sourceSecretHasher = Poseidon(2);
sourceSecretHasher.inputs[0] <== sourceSecret;
sourceSecretHasher.inputs[1] <== 1;
sourceSecretHash <== sourceSecretHasher.out;
// Verify the nullifier is valid
// by hashing the sourceSecretHash and externalNullifier
// and verifying the result is equals
component nullifierHasher = Poseidon(2);
nullifierHasher.inputs[0] <== sourceSecretHash;
nullifierHasher.inputs[1] <== externalNullifier;
nullifierHasher.out === nullifier;
// Square serve to avoid removing by the compilator optimizer
signal chainIdSquare;
chainIdSquare <== chainId * chainId;
}
component main {public [commitmentMapperPubKey, registryTreeRoot, externalNullifier, nullifier, destinationIdentifier, claimedValue, chainId, accountsTreeValue, isStrict]} = hydraS1(20,20);