sp1_lib/
unconstrained.rs

1/// Executes a block of code unconstrained by the VM. This macro is useful for running code that
2/// helps provide information to the program but does not need to be constrained by the VM. For
3/// example, running `ecrecover` is expensive in the VM but verifying a signature when you know the
4/// public key is not. `unconstrained` can be used to provide the public key without spending VM CPU
5/// cycles.
6///
7/// Any changes to the VM state will be reset at the end of the block. To provide data to the VM,
8/// use `io::hint` or `io::hint_slice`, and read it using `io::read` or `io::read_vec`.
9#[macro_export]
10macro_rules! unconstrained {
11    (  $($block:tt)* ) => {
12        use $crate::{syscall_enter_unconstrained, syscall_exit_unconstrained};
13
14        let continue_unconstrained: bool;
15        unsafe {
16            continue_unconstrained = syscall_enter_unconstrained();
17        }
18
19        // If continue_unconstrained is true (only possible in the runtime), execute
20        // the inner code. Otherwise, nothing happens.
21        if continue_unconstrained {
22            // Declare an immutable closure to ensure at compile time that no memory is changed
23            let _unconstrained_closure = || -> () {
24                $($block)*
25            };
26
27            _unconstrained_closure();
28
29            unsafe {
30                syscall_exit_unconstrained();
31            }
32        }
33
34    };
35}