use dep::std; global state_depth = 9; global utxo_depth = 4; global batch_depth = 4; fn main( current_root: pub Field, deposit: pub Field, withdrawals: pub [Field; 16], commitment_out: pub [Field; 16], recipients: pub [Field; 16], oracle: pub Field, old_root_proof: [Field; 16], nullifier_hashes: pub [Field; 16], secrets: [Field; 16], utxo_in: [Field; 48], utxo_out: [Field; 48], indexes: [Field; 48], hash_path: [Field; 272], ) -> pub Field { let trees: Field = 4; let mut sum_in: Field = deposit; let mut sum_out: Field = withdrawals.reduce(|a, b| a + b); 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; utxo_depth] = [0; utxo_depth]; let mut hash_path_tx: [Field; batch_depth] = [0; batch_depth]; let mut hash_path_historic: [Field; state_depth] = [0; state_depth]; for j in 0..4 { hash_path_utxo[j] = hash_path[(state_depth + utxo_depth + batch_depth) * i + j]; hash_path_tx[j] = hash_path[(state_depth + utxo_depth + batch_depth) * i + utxo_depth + j]; } for l in 0..state_depth { hash_path_historic[l] = hash_path[(state_depth + utxo_depth + batch_depth) * i + utxo_depth + batch_depth + l]; } let index_utxo = indexes[trees * i + 0]; let index_tx = indexes[trees * i + 1]; let index_historic = indexes[trees * i + 2]; let utxo_root = std::merkle::compute_merkle_root( commitment_in, index_utxo, hash_path_utxo ); let tx_root = std::merkle::compute_merkle_root( utxo_root, index_tx, hash_path_tx ); let leaf_batch = std::hash::pedersen([tx_root, oracle])[0]; let leaf_historic = std::hash::pedersen([leaf_batch, old_root_proof[i]])[0]; let historic_root = std::merkle::compute_merkle_root( leaf_historic, index_historic, hash_path_historic ); assert(historic_root == current_root); 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); } } assert(sum_in == sum_out); let utxo_root_calc: Field = pedersen_tree_four(commitment_out); utxo_root_calc } 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] }