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 | k = 11;
field = "pallas";
constant "Fee_V1" {
EcFixedPointShort VALUE_COMMIT_VALUE,
EcFixedPoint VALUE_COMMIT_RANDOM,
EcFixedPointBase NULLIFIER_K,
}
witness "Fee_V1" {
# Secret key used to derive input's nullifier
Base input_secret,
# Input coin's leaf position in the Merkle tree of coins
Uint32 input_leaf_pos,
# Merkle path to the coin
MerklePath input_path,
# Secret key used to derive public key for the tx signature
Base signature_secret,
# Value of the input coin
Base input_value,
# Random blinding factor for the input value commitment
Scalar input_value_blind,
# Input coin's spend hook
Base input_spend_hook,
# Data passed from the input to the invoked contract
Base input_user_data,
# Unique coin blind corresponding to the input coin
Base input_coin_blind,
# Blinding factor for the encrypted user_data
Base input_user_data_blind,
# Value of the output coin
Base output_value,
# Output coin's spend hook
Base output_spend_hook,
# Data passed from the output coin to the invoked contract
Base output_user_data,
# Random blinding factor for the output value commitment
Scalar output_value_blind,
# Unique coin blind corresponding to the output coin
Base output_coin_blind,
# Token ID
Base token,
# Random blinding factor for the token ID
Base token_blind,
}
circuit "Fee_V1" {
# Derive the input coin
pub = ec_mul_base(input_secret, NULLIFIER_K);
pub_x = ec_get_x(pub);
pub_y = ec_get_y(pub);
input_coin = poseidon_hash(
pub_x,
pub_y,
input_value,
token,
input_spend_hook,
input_user_data,
input_coin_blind,
);
nullifier = poseidon_hash(input_secret, input_coin);
constrain_instance(nullifier);
# Pedersen commitment for the input coin value
input_vcv = ec_mul_short(input_value, VALUE_COMMIT_VALUE);
input_vcr = ec_mul(input_value_blind, VALUE_COMMIT_RANDOM);
input_value_commit = ec_add(input_vcv, input_vcr);
constrain_instance(ec_get_x(input_value_commit));
constrain_instance(ec_get_y(input_value_commit));
# Commitment for the token ID
token_commit = poseidon_hash(token, token_blind);
constrain_instance(token_commit);
# Merkle root
root = merkle_root(input_leaf_pos, input_path, input_coin);
constrain_instance(root);
# Export user_data
user_data_enc = poseidon_hash(input_user_data, input_user_data_blind);
constrain_instance(user_data_enc);
# Reveal spend_hook
ZERO = witness_base(0);
constrain_equal_base(input_spend_hook, ZERO);
# Derive a public key for the signature and
# constrain its coordinates
signature_public = ec_mul_base(signature_secret, NULLIFIER_K);
constrain_instance(ec_get_x(signature_public));
constrain_instance(ec_get_y(signature_public));
# Derive output coin
output_coin = poseidon_hash(
pub_x,
pub_y,
output_value,
token,
output_spend_hook,
output_user_data,
output_coin_blind,
);
constrain_instance(output_coin);
# Pedersen commitment for the output coin value
output_vcv = ec_mul_short(output_value, VALUE_COMMIT_VALUE);
output_vcr = ec_mul(output_value_blind, VALUE_COMMIT_RANDOM);
output_value_commit = ec_add(output_vcv, output_vcr);
constrain_instance(ec_get_x(output_value_commit));
constrain_instance(ec_get_y(output_value_commit));
}
|