Skip to main content

charms_spell_checker/
lib.rs

1pub mod app;
2pub mod bin;
3
4use crate::app::AppContractVK;
5use charms_client::NormalizedSpell;
6use charms_data::App;
7
8/// Check if the spell is correct.
9pub(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}