charms_spell_checker/
lib.rs1pub mod app;
2pub mod bin;
3
4use crate::app::AppContractVK;
5use charms_client::NormalizedSpell;
6use charms_data::App;
7
8pub(crate) fn is_correct(
10 spell: &NormalizedSpell,
11 prev_txs: &Vec<bitcoin::Transaction>,
12 app_contract_vks: &Vec<(App, AppContractVK)>,
13 spell_vk: &String,
14) -> bool {
15 let prev_spells = charms_client::prev_spells(prev_txs, spell_vk);
16 if !charms_client::well_formed(spell, &prev_spells) {
17 eprintln!("not well formed");
18 return false;
19 }
20 let Some(prev_txids) = spell.tx.prev_txids() else {
21 unreachable!("the spell is well formed: tx.ins MUST be Some");
22 };
23 if prev_txids != prev_spells.keys().collect() {
24 eprintln!("spell.tx.prev_txids() != prev_spells.keys()");
25 return false;
26 }
27
28 let apps = charms_client::apps(spell);
29 if apps.len() != app_contract_vks.len() {
30 eprintln!("apps.len() != app_contract_proofs.len()");
31 return false;
32 }
33 if !apps
34 .iter()
35 .zip(app_contract_vks)
36 .all(|(app0, (app, proof))| {
37 app == app0
38 && proof.verify(
39 app,
40 &charms_client::to_tx(spell, &prev_spells),
41 &spell.app_public_inputs[app],
42 )
43 })
44 {
45 eprintln!("app_contract_proofs verification failed");
46 return false;
47 }
48
49 true
50}
51
52#[cfg(test)]
53mod test {
54 #[test]
55 fn dummy() {}
56}