snarkos_aot/auth/
query.rs1use std::collections::{HashMap, VecDeque};
2
3use anyhow::{anyhow, Result};
4use snarkvm::{
5 prelude::ProgramID,
6 synthesizer::{Authorization, Process, Program, Stack},
7};
8
9use crate::Network;
10
11pub fn fetch_program<N: Network>(id: ProgramID<N>, query: &str) -> Result<Program<N>> {
13 Ok(reqwest::blocking::get(format!("{query}/{}/program/{id}", N::str_id()))?.json()?)
14}
15
16pub fn load_program<N: Network>(
18 process: &mut Process<N>,
19 program_id: ProgramID<N>,
20 query: &str,
21) -> Result<()> {
22 let program = fetch_program(program_id, query)?;
23
24 if process.contains_program(&program_id) {
25 return Ok(());
26 }
27
28 for import_id in program.imports().keys() {
29 if !process.contains_program(import_id) {
30 load_program(process, program_id, query)?;
31 }
32 }
33
34 if !process.contains_program(program.id()) {
35 process.add_program(&program)?;
36 }
37
38 Ok(())
39}
40
41pub fn get_imports<N: Network>(
43 process: &Process<N>,
44 program: &Program<N>,
45 query: &str,
46) -> Result<HashMap<ProgramID<N>, Program<N>>> {
47 let mut imported = HashMap::new();
48 let mut queue = VecDeque::new();
49 queue.push_back(program.clone());
50
51 while let Some(program) = queue.pop_front() {
52 for import in program.imports().keys() {
53 if process.contains_program(import)
58 || imported.contains_key(import)
59 || *import == N::credits()
60 {
61 continue;
62 }
63
64 let import_program = fetch_program(*import, query)
65 .map_err(|e| anyhow!("failed to fetch imported program {import}: {e:?}"))?;
66
67 imported.insert(*import, import_program.clone());
68 queue.push_back(import_program);
69 }
70 }
71
72 Ok(imported)
73}
74
75pub fn get_process_imports<N: Network>(
76 process: &mut Process<N>,
77 program: &Program<N>,
78 query: Option<&str>,
79) -> Result<()> {
80 let imports = query
81 .map(|query| get_imports(process, program, query))
82 .transpose()?
83 .unwrap_or_default();
84
85 for (_, import) in imports {
86 process.add_stack(Stack::new(process, &import)?);
87 }
88
89 Ok(())
90}
91
92pub fn add_program_to_process<N: Network>(
93 process: &mut Process<N>,
94 program_id: ProgramID<N>,
95 query: &str,
96) -> Result<()> {
97 if process.contains_program(&program_id) {
99 return Ok(());
100 }
101
102 let program = fetch_program(program_id, query)
103 .map_err(|e| anyhow!("failed to fetch program {program_id}: {e:?}"))?;
104
105 get_process_imports(process, &program, Some(query))?;
106 process.add_program(&program)?;
107
108 Ok(())
109}
110
111pub fn add_many_programs_to_process<N: Network>(
112 process: &mut Process<N>,
113 programs: Vec<ProgramID<N>>,
114 query: &str,
115) -> Result<()> {
116 for program in programs {
117 add_program_to_process(process, program, query)?;
118 }
119
120 Ok(())
121}
122
123pub fn get_programs_from_auth<N: Network>(auth: &Authorization<N>) -> Vec<ProgramID<N>> {
124 auth.transitions()
125 .values()
126 .filter_map(|req| {
127 let id = *req.program_id();
128 (id != N::credits()).then_some(id)
129 })
130 .collect()
131}