essential-debugger 0.2.0

An experimental constraint debugger for the Essential constraint checking engine
Documentation
use essential_constraint_vm as constraint_vm;
use essential_debugger::Source;
use essential_sign::secp256k1::{PublicKey, Secp256k1, SecretKey};
use essential_state_read_vm as state_read_vm;
use essential_types::{
    predicate::{Directive, Predicate},
    solution::{Mutation, Solution, SolutionData},
    PredicateAddress,
};

#[tokio::test]
#[ignore = "can't run in ci"]
async fn test_debugger() {
    let predicate = Predicate {
        // State read program to read state slot 0.
        state_read: vec![state_read_vm::asm::to_bytes([
            state_read_vm::asm::Stack::Push(1).into(),
            state_read_vm::asm::StateSlots::AllocSlots.into(),
            state_read_vm::asm::Stack::Push(0).into(),
            state_read_vm::asm::Stack::Push(0).into(),
            state_read_vm::asm::Stack::Push(0).into(),
            state_read_vm::asm::Stack::Push(0).into(),
            state_read_vm::asm::Stack::Push(4).into(),
            state_read_vm::asm::Stack::Push(1).into(),
            state_read_vm::asm::Stack::Push(0).into(),
            state_read_vm::asm::StateRead::KeyRange,
            state_read_vm::asm::TotalControlFlow::Halt.into(),
        ])
        .collect()],
        // Program to check pre-mutation value is None and
        // post-mutation value is 42 at slot 0.
        constraints: vec![constraint_vm::asm::to_bytes([
            constraint_vm::asm::Stack::Push(0).into(),
            constraint_vm::asm::Stack::Push(1).into(),
            constraint_vm::asm::Stack::Push(2).into(),
            constraint_vm::asm::Stack::Push(3).into(),
            constraint_vm::asm::Stack::Pop.into(),
            constraint_vm::asm::Stack::Pop.into(),
            constraint_vm::asm::Stack::Pop.into(),
            constraint_vm::asm::Stack::Pop.into(),
            constraint_vm::asm::Stack::Push(0).into(), // slot
            constraint_vm::asm::Stack::Push(0).into(), // pre
            constraint_vm::asm::Access::StateLen.into(),
            constraint_vm::asm::Stack::Push(0).into(),
            constraint_vm::asm::Pred::Eq.into(),
            constraint_vm::asm::Stack::Push(0).into(), // slot
            constraint_vm::asm::Stack::Push(1).into(), // post
            constraint_vm::asm::Access::State.into(),
            constraint_vm::asm::Stack::Push(42).into(),
            constraint_vm::asm::Pred::Eq.into(),
            constraint_vm::asm::Pred::And.into(),
        ])
        .collect()],
        directive: Directive::Satisfy,
    };

    let (sk, _pk) = random_keypair([0; 32]);
    let contract = essential_sign::contract::sign(vec![predicate.clone()].into(), &sk);
    let predicate_addr = PredicateAddress {
        contract: essential_hash::contract_addr::from_contract(&contract.contract),
        predicate: essential_hash::content_addr(&contract.contract.predicates[0]),
    };

    // Construct the solution decision variables.
    // The first is an inline variable 42.
    let decision_variables = vec![vec![42]];

    // Create the solution.
    let solution = Solution {
        data: vec![SolutionData {
            predicate_to_solve: predicate_addr,
            decision_variables,
            state_mutations: vec![Mutation {
                key: vec![0, 0, 0, 0],
                value: vec![42],
            }],
            transient_data: vec![],
        }],
    };

    let other_source = r#"
const ::foo::FOO: int = 1;
    "#;
    let predicate_source = r#"
predicate ::Foo {
    storage {
        bar: ( b256 => int ),
    }
    pub var ::baz: int;
    constraint (::baz == 42);
    constraint (::baz == 1);
}
    "#;

    let source = Source::default()
        .with_other_code(other_source)
        .with_predicate_find_line(predicate_source, 1);

    essential_debugger::run_with_source(solution, 0, predicate, 0, Default::default(), source)
        .await
        .unwrap();
}

pub fn random_keypair(seed: [u8; 32]) -> (SecretKey, PublicKey) {
    use rand::SeedableRng;
    let mut rng = rand::rngs::SmallRng::from_seed(seed);
    let secp = Secp256k1::new();
    secp.generate_keypair(&mut rng)
}