-
Notifications
You must be signed in to change notification settings - Fork 1
/
create-coin-commitment-multiflag.zk
133 lines (98 loc) · 4.78 KB
/
create-coin-commitment-multiflag.zk
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
open Extended_lib;
//mh0 is a Merkel tree root - only public input
let main = fun ( mh0 : field, nf : field, cm_new : field, ()) => {
// (1: validity & 2: ownership)
// I (1) know a route through the merkel tree {M0, M1, M2, M3} leading to a commitment we call t
// ie, hashed with its Merkel sibling M3, then all hashed with Merkel parent M2, then all hashed with Merkel grandparent M1
// gives Merkel root mh0
// Further I (2) know a secret r, a value v and flag which concatenated and hashed give t.
// I know r, flag s.t. HS of {r,v,flag} = some t, s.t.
// t= HM (M0,(M1,(M2,(M3, t))))
// (3: non-inflation)
// TODO: My output value vo is (lt)equal to the value v of the original coin
// v=1
// (4: Flag-carrying)
// TODO: My output commitment does not add extra 'bits' to the flag
// TODO: ie, flag*discarded_flags = flag
// My output commitment has the same flag to the flag of the previous commitment
// (5: nullifiability)
// The nullifier n refers to that commitment t and is signed.
// ie n = hash (r,t)
//NB: In variable names, xxx_bool is generally used to refer to the list(boolean) version of a value. _Not_ bool/ list(bool) !
let params = load_pedersen_params("./constants/bn128-params");
let hash_bits = fun (pre_image : list(boolean)) => {
Pedersen.digest_bits(params, pre_image);
};
let hash_field = fun (pre_image : field) => {
Pedersen.digest_bits(params, Field.to_bits(pre_image));
};
let order_nodes = fun (a: field, b_tuple: (field, boolean)) => {
let (b, lr_bit_b) = b_tuple;
select(lr_bit_b, ~then_=(a,b), ~else_=(b,a));
// result
// .append (dir*a, not dir*b, not dir * a, dir * b)
// .filter (nonzero)
// .map (field -> list(bool))
// result[0]::result[1];
};
let hash_merkle_nodes = fun (ordered_nodes_tuple : (field, field)) => {
let node1_bool = Field.to_bits( fst(ordered_nodes_tuple) );
let node2_bool = Field.to_bits( snd(ordered_nodes_tuple) );
hash_bits ( node1_bool @ node2_bool ) ;
};
let hash_commitment = fun (secret : field, val1 : field, val2 : field) => {
let secret_bool = Field.to_bits(secret);
let val1_bool = Field.to_bits(val1);
let val2_bool = Field.to_bits(val2);
let hashable = secret_bool@val1_bool@val2_bool ;
let hashable = secret_bool ;
//TODO: check bit length of 3way concat (defaults are OK? )
hash_bits(hashable);
};
let hash_nullifier_commitment = fun (secret : field, n : field) => {
let secret_bool = Field.to_bits(secret);
let n_bool = Field.to_bits(n);
let hashable = secret_bool@n_bool ;
hash_bits (secret_bool@n_bool);
};
// TODO: pass private inputs to Prover
let (r, v, flag, tree_threeple, r', flag', v', discarded_flags) =
Prover {
let [r, v, flag, l1_sib_string, l2_sib_string, l3_sib_string, r', v', flag' ] = read_lines ("transfer_secrets") ;
//let [r, v, flag, l1_sib_string, l2_sib_string, l3_sib_string, r', v', flag' ] = [998, 1, 0, "4567,0", "7385,1", "2372,0", 999, 1, 0];
let sep = String.get (",",0i);
let [l1_hash, l1_dir] = String.split_on_char(sep, l1_sib_string);
let l1_sibling = (Field.of_string(l1_hash), Stdlib.bool_of_string(l1_dir)) ;
let [l2_hash, l2_dir] = String.split_on_char(sep, l2_sib_string);
let l2_sibling = (Field.of_string(l2_hash), Stdlib.bool_of_string(l2_dir)) ;
let [l3_hash, l3_dir] = String.split_on_char(sep, l3_sib_string);
let l3_sibling = (Field.of_string(l3_hash), Stdlib.bool_of_string(l3_dir)) ;
let r = Field.of_string(r);
let v = Field.of_string(v);
let flag = Field.of_string(flag);
let r' = Field.of_string(r');
let v' = Field.of_string(v');
let flag' = Field.of_string(flag');
// Get the following:
// v : field, flag : field, l1_sibling : (field, boolean), l2_sibling : (field, boolean), l3_sibling : (field, boolean)
// r,flag,r',flag', v ,v'
// let level2_parent = hash_merkle_nodes (order_nodes (fst(l3_sibling), fst(l3_sibling)));
// Field.print (level2_parent);
(r, v, flag, (l1_sibling, l2_sibling, l3_sibling), r', flag', v') ;
};
let t = hash_commitment (r, v, flag);
let t' = hash_commitment (r',v',flag');
let (l1_sibling, l2_sibling, l3_sibling) = tree_threeple;
let t = hash_commitment (r, v, flag);
let level2_parent = hash_merkle_nodes(order_nodes(t, l3_sibling));
let level1_parent = hash_merkle_nodes(order_nodes(level2_parent, l2_sibling));
let calculated_root = hash_merkle_nodes(order_nodes(level1_parent, l1_sibling));
// nullifier will require commitment to be hashed with secret a second time in order to sign that it refers to this commitment
// and not another maliciously signed with the same secret but different values
let n = hash_nullifier_commitment (r, t);
assert_r1(calculated_root, 1, mh0);
assert_r1(v, 1, v');
assert_r1(flag', discarded_flags, flag);
assert_r1(n, 1, nf);
assert_r1(t',1,cm_new);
};