-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathnym_ownership.circom
82 lines (69 loc) · 2.74 KB
/
nym_ownership.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
pragma circom 2.1.2;
include "../spartan_ecdsa/eff_ecdsa.circom";
include "../spartan_ecdsa/tree.circom";
include "../poseidon/poseidon.circom";
/**
* NymOwnership (pubkey)
* ================
*
* Implements the scheme defined here: https://ethresear.ch/t/a-simple-persistent-pseudonym-scheme/14930
*
* Pubkey membership in merkle root (not address) + nym ownership + content data commitment
*/
template NymOwnership(treeLevels) {
// public nym signature efficient-ecdsa artifacts
// note that U encodes msghash (= r^(-1)m * G ), thus relationship b/w nymSigU{x,y} and nym is publicly verifiable
// same holds for contentSig inputs below
signal input nymSigTx;
signal input nymSigTy;
signal input nymSigUx;
signal input nymSigUy;
// private nym signature efficient-ecdsa artifact
signal input nymSigS;
// nymHash = poseidon('s' part of ECDSASig(nym))
signal input nymHash;
// same relationship with `content` as `nymSig` inputs have with `nym` above
signal input contentSigTx;
signal input contentSigTy;
signal input contentSigUx;
signal input contentSigUy;
// private content signature efficient-ecdsa artifact
signal input contentSigS;
// merkle proof for membership check
signal input root;
signal input pathIndices[treeLevels];
signal input siblings[treeLevels];
// nym sig check
component nymSigVerify = EfficientECDSA();
nymSigVerify.Tx <== nymSigTx;
nymSigVerify.Ty <== nymSigTy;
nymSigVerify.Ux <== nymSigUx;
nymSigVerify.Uy <== nymSigUy;
nymSigVerify.s <== nymSigS;
// content data sig check
component contentSigVerify = EfficientECDSA();
contentSigVerify.Tx <== contentSigTx;
contentSigVerify.Ty <== contentSigTy;
contentSigVerify.Ux <== contentSigUx;
contentSigVerify.Uy <== contentSigUy;
contentSigVerify.s <== contentSigS;
// check that nym sig and content data sig are signed by the same key
nymSigVerify.pubKeyX === contentSigVerify.pubKeyX;
nymSigVerify.pubKeyY === contentSigVerify.pubKeyY;
// nym hash check (double input poseidon, so uses signedNymName as both inputs)
component nymHashCheck = Poseidon();
nymHashCheck.inputs[0] <== nymSigS;
nymHashCheck.inputs[1] <== nymSigS;
nymHashCheck.out === nymHash;
// merkle root check
component pubKeyHash = Poseidon();
pubKeyHash.inputs[0] <== nymSigVerify.pubKeyX;
pubKeyHash.inputs[1] <== nymSigVerify.pubKeyY;
component merkleProof = MerkleTreeInclusionProof(treeLevels);
merkleProof.leaf <== pubKeyHash.out;
for (var i = 0; i < treeLevels; i++) {
merkleProof.pathIndices[i] <== pathIndices[i];
merkleProof.siblings[i] <== siblings[i];
}
root === merkleProof.root;
}