1use alloc::sync::Arc;
2
3use processor::{
4 AdviceProvider, AdviceSource, DefaultHost, ErrorContext, MastForest, ProcessState,
5};
6use prover::{ExecutionError, Host, MemAdviceProvider};
7use stdlib::{EVENT_FALCON_SIG_TO_STACK, falcon_sign};
8use vm_core::mast::MastNodeExt;
9
10pub struct TestHost(DefaultHost<MemAdviceProvider>);
11
12impl TestHost {
13 pub fn new(advice_provider: MemAdviceProvider) -> Self {
14 Self(DefaultHost::new(advice_provider))
15 }
16
17 pub fn load_mast_forest(&mut self, mast_forest: Arc<MastForest>) -> Result<(), ExecutionError> {
18 self.0.load_mast_forest(mast_forest)
19 }
20
21 pub fn advice_provider(&self) -> &MemAdviceProvider {
22 self.0.advice_provider()
23 }
24
25 pub fn advice_provider_mut(&mut self) -> &mut MemAdviceProvider {
26 self.0.advice_provider_mut()
27 }
28
29 pub fn into_inner(self) -> MemAdviceProvider {
30 self.0.into_inner()
31 }
32}
33
34impl Host for TestHost {
35 type AdviceProvider = MemAdviceProvider;
36
37 fn advice_provider(&self) -> &Self::AdviceProvider {
38 self.0.advice_provider()
39 }
40
41 fn advice_provider_mut(&mut self) -> &mut Self::AdviceProvider {
42 self.0.advice_provider_mut()
43 }
44
45 fn get_mast_forest(&self, node_digest: &prover::Digest) -> Option<Arc<processor::MastForest>> {
46 self.0.get_mast_forest(node_digest)
47 }
48
49 fn on_event(
50 &mut self,
51 process: ProcessState,
52 event_id: u32,
53 err_ctx: &ErrorContext<'_, impl MastNodeExt>,
54 ) -> Result<(), ExecutionError> {
55 if event_id == EVENT_FALCON_SIG_TO_STACK {
56 let advice_provider = self.advice_provider_mut();
57 push_falcon_signature(advice_provider, process, err_ctx)
58 } else {
59 Ok(())
60 }
61 }
62}
63
64pub fn push_falcon_signature(
82 advice_provider: &mut impl AdviceProvider,
83 process: ProcessState,
84 err_ctx: &ErrorContext<'_, impl MastNodeExt>,
85) -> Result<(), ExecutionError> {
86 let pub_key = process.get_stack_word(0);
87 let msg = process.get_stack_word(1);
88
89 let pk_sk = advice_provider
90 .get_mapped_values(&pub_key.into())
91 .ok_or(ExecutionError::advice_map_key_not_found(pub_key, err_ctx))?;
92
93 let result = falcon_sign(pk_sk, msg)
94 .ok_or_else(|| ExecutionError::malformed_signature_key("RPO Falcon512", err_ctx))?;
95
96 for r in result {
97 advice_provider.push_stack(AdviceSource::Value(r), err_ctx)?;
98 }
99 Ok(())
100}