main.nr 4.31 KB
Newer Older
John Doe's avatar
John Doe committed
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
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] 
}