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![])
}
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
BFieldElement
s (machine words), asDigest
, and through initial RAM values.