TritonVM / tasm-lang

Writing tasm with Rust syntax
15 stars 2 forks source link

Compile `RemovalRecordsIntegrity` program from `neptune-core` #36

Open Sword-Smith opened 11 months ago

Sword-Smith commented 11 months ago

We compiled this by hand but we should be able to handle it through this compiler as well

This is how the Rust shadowing was defined. The program should be derivable from it. Note, though, that the program below uses an old interface for Triton-VM, and that the secret input now can be provided in three ways: as individual BFieldElements (machine words), as Digest, and through initial RAM values.

fn rust_shadow(
        public_input: &[BFieldElement],
        secret_input: &[BFieldElement],
    ) -> anyhow::Result<Vec<BFieldElement>> {
        let hash_of_kernel = *Digest::decode(
            &public_input
                .iter()
                .copied()
                .take(DIGEST_LENGTH)
                .rev()
                .collect_vec(),
        )
        .expect("Could not decode public input in Removal Records Integrity :: verify_raw");

        // 1. read and process witness data
        let witness = *RemovalRecordsIntegrityWitness::decode(
            &secret_input.iter().skip(1).copied().collect_vec(),
        )
        .unwrap();

        println!("first element of witness: {}", witness.encode()[0]);
        println!("first element of kernel: {}", witness.kernel.encode()[0]);

        // 2. assert that the kernel from the witness matches the hash in the public input
        // now we can trust all data in kernel
        assert_eq!(
            hash_of_kernel,
            witness.kernel.mast_hash(),
            "hash of kernel ({})\nwitness kernel ({})",
            hash_of_kernel,
            witness.kernel.mast_hash()
        );

        // 3. assert that the mutator set's MMRs in the witness match the kernel
        // now we can trust all data in these MMRs as well
        let mutator_set_hash = Hash::hash_pair(
            &Hash::hash_pair(&witness.aocl.bag_peaks(), &witness.swbfi.bag_peaks()),
            &Hash::hash_pair(&witness.swbfa_hash, &Digest::default()),
        );
        assert_eq!(witness.kernel.mutator_set_hash, mutator_set_hash);

        // 4. derive index sets from inputs and match them against those listed in the kernel
        // How do we trust input UTXOs?
        // Because they generate removal records, and we can match
        // those against the removal records that are listed in the
        // kernel.
        let items = witness.input_utxos.iter().map(Hash::hash).collect_vec();

        // test that removal records listed in kernel match those derived from input utxos
        let digests_of_derived_index_lists = items
            .iter()
            .zip(witness.membership_proofs.iter())
            .map(|(item, msmp)| {
                AbsoluteIndexSet::new(&get_swbf_indices::<Hash>(
                    item,
                    &msmp.sender_randomness,
                    &msmp.receiver_preimage,
                    msmp.auth_path_aocl.leaf_index,
                ))
                .encode()
            })
            .map(|x| Hash::hash_varlen(&x))
            .collect::<HashSet<_>>();
        let digests_of_claimed_index_lists = witness
            .kernel
            .inputs
            .iter()
            .map(|input| input.absolute_indices.encode())
            .map(|x| Hash::hash_varlen(&x))
            .collect::<HashSet<_>>();
        assert_eq!(
            digests_of_derived_index_lists,
            digests_of_claimed_index_lists
        );

        // 5. verify that all input utxos (mutator set items) live in the AOCL
        assert!(items
            .iter()
            .zip(witness.membership_proofs.iter())
            .map(|(item, msmp)| {
                (
                    commit::<Hash>(
                        item,
                        &msmp.sender_randomness,
                        &msmp.receiver_preimage.hash::<Hash>(),
                    ),
                    &msmp.auth_path_aocl,
                )
            })
            .all(|(cc, mp)| {
                mp.verify(
                    &witness.aocl.get_peaks(),
                    &cc.canonical_commitment,
                    witness.aocl.count_leaves(),
                )
                .0
            }));

        Ok(vec![])
    }