use dep::std; fn main( tx_in: pub [Field; 16], amount_public_in: pub Field, amount_public_out: pub Field, commitment_out: pub [Field; 16], recipient: pub Field, oracle: pub Field, old_root: pub Field, new_root: pub Field, nullifier_hashes: pub [Field; 16], secrets: [Field; 16], utxo_in: [Field; 48], utxo_out: [Field; 48], roots: [Field; 64], leaves: [Field; 64], indexes: [Field; 64], hash_path: [Field; 288], ) { let trees: Field = 4; let mut sum_in: Field = amount_public_in; let mut sum_out: Field = amount_public_out; for i in 0..16 { if (utxo_in[i*3 + 1] != 0) { let owner = std::hash::pedersen([secrets[i]]); assert(owner[0] == utxo_in[i*3 + 0]); assert(nullifier_hashes[i] == std::hash::pedersen([secrets[i], secrets[i]])[0]); let commitment_in = std::hash::pedersen([utxo_in[i*3 + 0], utxo_in[i*3 + 1], utxo_in[i*3 + 2]])[0]; let mut hash_path_utxo: [Field; 4] = [0; 4]; let mut hash_path_tx: [Field; 4] = [0; 4]; let mut hash_path_batch: [Field; 5] = [0; 5]; let mut hash_path_historic: [Field; 5] = [0; 5]; for j in 0..4 { hash_path_utxo[j] = hash_path[18*i + 0 + j]; hash_path_tx[j] = hash_path[18*i + 4 + j]; } for l in 0..5 { hash_path_batch[l] = hash_path[18*i + 8 + l]; hash_path_historic[l] = hash_path[18*i + 13 + l]; } let leaf_tx = leaves[trees * i + 1]; let leaf_batch = leaves[trees * i + 2]; let leaf_historic = leaves[trees * i + 3]; let index_utxo = indexes[trees * i + 0]; let index_tx = indexes[trees * i + 1]; let index_batch = indexes[trees * i + 2]; let index_historic = indexes[trees * i + 3]; let root_tx = roots[trees * i + 1]; let root_batch = roots[trees * i + 2]; let root_historic = roots[trees * i + 3]; let utxo_root = std::merkle::compute_merkle_root( commitment_in, index_utxo, hash_path_utxo ); assert(utxo_root == leaf_tx); let tx_root = std::merkle::compute_merkle_root( leaf_tx, index_tx, hash_path_tx ); assert(tx_root == root_tx); let batch_root = std::merkle::compute_merkle_root( leaf_batch, index_batch, hash_path_batch ); assert(batch_root == root_batch); let historic_root = std::merkle::compute_merkle_root( leaf_historic, index_historic, hash_path_historic ); assert(historic_root == root_historic); sum_in += utxo_in[i*3 + 1]; } } for k in 0..16 { if (utxo_out[k*3 + 1] != 0) { let commitment_out_calc = std::hash::pedersen([utxo_out[k*3 + 0], utxo_out[k*3 + 1], utxo_out[k*3 + 2]]); assert(commitment_out_calc[0] == commitment_out[k]); sum_out += utxo_out[k*3 + 1]; } else { let zero_hash = 0xf35fcb490b7ea67c3ac26ed530fa5d8dfe8be344e7177ebb63fe02723fb6f725 as Field; assert(commitment_out[k] == zero_hash); } } let utxo_root_calc: Field = pedersen_tree_four(commitment_out); assert(tx_in[0] == utxo_root_calc); let tx_root_calc: Field = pedersen_tree_four(tx_in); assert(oracle == std::hash::pedersen([0])[0]); let batch_root_calc: Field = std::hash::pedersen([tx_root_calc, oracle])[0]; let new_root_calc: Field = std::hash::pedersen([batch_root_calc, old_root])[0]; assert(new_root == new_root_calc); assert(sum_in == sum_out); assert(recipient == recipient); } fn pedersen_tree_four(leaves: [Field; 16]) -> Field { let mut tx_tree: [Field; 16] = leaves; for l in 0..8 { tx_tree[l] = std::hash::pedersen([tx_tree[2*l], tx_tree[2*l + 1]])[0]; } for l in 0..4 { tx_tree[l] = std::hash::pedersen([tx_tree[2*l], tx_tree[2*l + 1]])[0]; } for l in 0..2 { tx_tree[l] = std::hash::pedersen([tx_tree[2*l], tx_tree[2*l + 1]])[0]; } std::hash::pedersen([tx_tree[0], tx_tree[1]])[0] }