1use anoma_rm_risc0::{
6 action::Action,
7 action_tree::MerkleTree,
8 compliance::{ComplianceWitness, INITIAL_ROOT},
9 compliance_unit::ComplianceUnit,
10 delta_proof::DeltaWitness,
11 logic_proof::LogicProver,
12 merkle_path::MerklePath,
13 nullifier_key::NullifierKey,
14 proving_system::ProofType,
15 resource::Resource,
16 transaction::{Delta, Transaction},
17 Digest,
18};
19use anoma_rm_risc0_test_witness::TestLogicWitness;
20use hex::FromHex;
21use k256::Scalar;
22use lazy_static::lazy_static;
23use serde::{Deserialize, Serialize};
24
25pub const TEST_LOGIC_PK: &[u8] = include_bytes!("../elf/logic-test-guest.bin");
27
28lazy_static! {
29 pub static ref TEST_LOGIC_VK: Digest =
31 Digest::from_hex("73167841dd698323eb04209f89e6c19c5559e83841277621ab538feb8a715dfe")
32 .unwrap();
33}
34
35#[derive(Clone, Default, Deserialize, Serialize)]
36pub struct TestLogic {
37 witness: TestLogicWitness,
38}
39
40impl TestLogic {
41 pub fn new(
42 resource: Resource,
43 receive_existence_path: MerklePath,
44 nf_key: NullifierKey,
45 is_consumed: bool,
46 ) -> Self {
47 let witness = TestLogicWitness {
48 resource,
49 receive_existence_path,
50 is_consumed,
51 nf_key,
52 };
53 TestLogic { witness }
54 }
55}
56
57impl LogicProver for TestLogic {
58 type Witness = TestLogicWitness;
59
60 fn proving_key() -> &'static [u8] {
61 TEST_LOGIC_PK
62 }
63
64 fn verifying_key() -> Digest {
65 *TEST_LOGIC_VK
66 }
67
68 fn witness(&self) -> &Self::Witness {
69 &self.witness
70 }
71}
72
73pub fn create_an_action_with_multiple_compliances(
74 compliance_num: usize,
75 nonce: u8,
76 proof_type: ProofType,
77) -> (Action, DeltaWitness) {
78 let nf_key = NullifierKey::default();
79 let nf_key_cm = nf_key.commit();
80
81 let (consumed_resources, created_resources): (Vec<_>, Vec<_>) = (0..compliance_num)
83 .map(|i| {
84 let mut consumed_resource = Resource {
85 logic_ref: TestLogic::verifying_key(),
86 nk_commitment: nf_key_cm,
87 quantity: 1,
88 ..Default::default()
89 };
90 consumed_resource.nonce = [[nonce; 16], [i as u8; 16]].concat().try_into().unwrap();
91 let consumed_resource_nf = consumed_resource.nullifier(&nf_key).unwrap();
92
93 let mut created_resource = consumed_resource;
94 created_resource.set_nonce(consumed_resource_nf);
95 (consumed_resource, created_resource)
96 })
97 .unzip();
98
99 let mut compliance_units = Vec::new();
100 let mut rcvs = Vec::new();
101 let mut action_tree = MerkleTree::new(vec![]);
102 for i in 0..compliance_num {
103 let compliance_witness = ComplianceWitness {
104 consumed_resource: consumed_resources[i],
105 merkle_path: MerklePath::default(), ephemeral_root: *INITIAL_ROOT,
107 nf_key: nf_key.clone(),
108 created_resource: created_resources[i],
109 rcv: Scalar::ONE.to_bytes().to_vec(), };
111
112 let compliance_receipt = ComplianceUnit::create(&compliance_witness, proof_type).unwrap();
113
114 let consumed_resource_nf = consumed_resources[i].nullifier(&nf_key).unwrap();
115 let created_resource_cm = created_resources[i].commitment();
116 action_tree.insert(consumed_resource_nf);
117 action_tree.insert(created_resource_cm);
118
119 compliance_units.push(compliance_receipt);
120 rcvs.push(compliance_witness.rcv);
121 }
122
123 let logic_verifier_inputs = (0..compliance_num)
124 .flat_map(|i| {
125 let consumed_resource_nf = consumed_resources[i].nullifier(&nf_key).unwrap();
126 let created_resource_cm = created_resources[i].commitment();
127 let consumed_resource_path = action_tree.generate_path(&consumed_resource_nf).unwrap();
128 let created_resource_path = action_tree.generate_path(&created_resource_cm).unwrap();
129
130 let consumed_logic = TestLogic::new(
131 consumed_resources[i],
132 consumed_resource_path,
133 nf_key.clone(),
134 true,
135 );
136 let consumed_logic_proof = consumed_logic.prove(proof_type).unwrap();
137
138 let created_logic = TestLogic::new(
139 created_resources[i],
140 created_resource_path,
141 nf_key.clone(),
142 false,
143 );
144 let created_logic_proof = created_logic.prove(proof_type).unwrap();
145
146 vec![consumed_logic_proof, created_logic_proof]
147 })
148 .collect();
149
150 let action = Action::new(compliance_units, logic_verifier_inputs).unwrap();
151 action.clone().verify().unwrap();
152
153 let delta_witness = DeltaWitness::from_bytes_vec(&rcvs).unwrap();
154 (action, delta_witness)
155}
156
157pub fn create_multiple_actions(
158 action_num: usize,
159 compliance_num: usize,
160 proof_type: ProofType,
161) -> (Vec<Action>, DeltaWitness) {
162 let mut actions = Vec::new();
163 let mut delta_witnesses = Vec::new();
164 for i in 0..action_num {
165 let (action, delta_witness) =
166 create_an_action_with_multiple_compliances(compliance_num, i as u8, proof_type);
167 actions.push(action);
168 delta_witnesses.push(delta_witness);
169 }
170 (actions, DeltaWitness::compress(&delta_witnesses))
171}
172
173pub fn generate_test_transaction(
175 n_actions: usize,
176 compliance_num: usize,
177 proof_type: ProofType,
178) -> Transaction {
179 let (actions, delta_witness) = create_multiple_actions(n_actions, compliance_num, proof_type);
180 let tx = Transaction::create(actions, Delta::Witness(delta_witness));
181 let balanced_tx = tx.generate_delta_proof().unwrap();
182 balanced_tx.clone().verify().unwrap();
183 balanced_tx
184}
185
186#[test]
187fn test_logic_prover() {
188 let proof_type = ProofType::Succinct;
189 let test_logic = TestLogic::default();
190 let proof = test_logic.prove(proof_type).unwrap();
191 proof.verify().unwrap();
192}
193
194#[test]
195fn test_action() {
196 let _ = create_an_action_with_multiple_compliances(2, 1, ProofType::Succinct);
197}
198
199#[test]
200fn test_unmatched_logic_verifier_inputs_in_action() {
201 let (actions, _) = create_multiple_actions(2, 1, ProofType::Succinct);
202 let mut action0 = actions[0].clone();
204 action0.logic_verifier_inputs = actions[1].logic_verifier_inputs.clone();
205 assert!(action0.verify().is_err());
206
207 let mut action1 = actions[1].clone();
209 action1.logic_verifier_inputs = vec![];
210 assert!(action1.verify().is_err());
211}
212
213#[test]
214fn test_nullifier_duplication_check() {
215 let mut tx = generate_test_transaction(2, 1, ProofType::Succinct);
216 assert!(tx.nf_duplication_check().is_ok());
217
218 tx.actions[1] = tx.actions[0].clone();
220
221 assert!(tx.nf_duplication_check().is_err());
222}
223
224#[test]
225fn test_transaction() {
226 let _ = generate_test_transaction(2, 2, ProofType::Succinct);
227}
228
229#[test]
230#[ignore]
231fn test_transaction_groth16() {
232 let _ = generate_test_transaction(2, 2, ProofType::Groth16);
233}
234
235#[test]
236fn test_aggregation_works() {
237 let tx = generate_test_transaction(2, 2, ProofType::Succinct);
238 let mut tx_str = tx.clone();
239 assert!(tx_str.aggregate(ProofType::Succinct).is_ok());
240 assert!(tx_str.aggregation_proof.is_some());
241 assert!(tx_str.verify_aggregation().is_ok());
242}
243
244#[test]
245#[ignore]
246fn test_aggregation_works_groth16() {
247 let tx = generate_test_transaction(2, 2, ProofType::Succinct);
248 let mut tx_str = tx.clone();
249 assert!(tx_str.aggregate(ProofType::Groth16).is_ok());
250 assert!(tx_str.aggregation_proof.is_some());
251 assert!(tx_str.verify_aggregation().is_ok());
252}
253
254#[test]
255fn test_verify_aggregation_fails_for_incorrect_instances() {
256 let tx = generate_test_transaction(2, 2, ProofType::Succinct);
257 let mut tx_str = tx.clone();
258 assert!(tx_str.aggregate(ProofType::Succinct).is_ok());
259
260 tx_str.actions[0].logic_verifier_inputs.pop();
261
262 assert!(tx_str.verify_aggregation().is_err());
263}
264
265#[test]
266fn test_cannot_aggregate_invalid_proofs() {
267 use anoma_rm_risc0::logic_proof::LogicVerifierInputs;
268
269 let tx = generate_test_transaction(2, 2, ProofType::Succinct);
270
271 let bad_lproof = LogicVerifierInputs {
273 proof: tx.actions[0].logic_verifier_inputs[0].clone().proof,
274 verifying_key: Digest::from_bytes([66u8; 32]), tag: tx.actions[0].logic_verifier_inputs[0].tag,
276 app_data: tx.actions[0].logic_verifier_inputs[0].app_data.clone(),
277 };
278
279 let bad_action = Action {
280 compliance_units: tx.actions[0].clone().compliance_units,
281 logic_verifier_inputs: vec![bad_lproof],
282 };
283 let bad_tx = Transaction::create(vec![bad_action, tx.actions[1].clone()], tx.delta_proof);
284
285 let mut bad_tx_str = bad_tx.clone();
286 assert!(bad_tx_str.aggregate(ProofType::Succinct).is_err());
287 assert!(bad_tx_str.aggregation_proof.is_none());
288}