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}