snarkvm_console_program/request/
mod.rs1mod input_id;
17pub use input_id::InputID;
18
19mod bytes;
20mod serialize;
21mod sign;
22mod string;
23mod verify;
24
25use crate::{Identifier, Plaintext, ProgramID, Record, Value, ValueType, compute_function_id};
26use snarkvm_console_account::{Address, ComputeKey, GraphKey, PrivateKey, Signature, ViewKey};
27use snarkvm_console_network::Network;
28use snarkvm_console_types::prelude::*;
29
30#[derive(Clone, PartialEq, Eq)]
31pub struct Request<N: Network> {
32 signer: Address<N>,
34 network_id: U16<N>,
36 program_id: ProgramID<N>,
38 function_name: Identifier<N>,
40 input_ids: Vec<InputID<N>>,
42 inputs: Vec<Value<N>>,
44 signature: Signature<N>,
46 sk_tag: Field<N>,
48 tvk: Field<N>,
50 tcm: Field<N>,
52 scm: Field<N>,
54}
55
56impl<N: Network>
57 From<(
58 Address<N>,
59 U16<N>,
60 ProgramID<N>,
61 Identifier<N>,
62 Vec<InputID<N>>,
63 Vec<Value<N>>,
64 Signature<N>,
65 Field<N>,
66 Field<N>,
67 Field<N>,
68 Field<N>,
69 )> for Request<N>
70{
71 fn from(
73 (signer, network_id, program_id, function_name, input_ids, inputs, signature, sk_tag, tvk, tcm, scm): (
74 Address<N>,
75 U16<N>,
76 ProgramID<N>,
77 Identifier<N>,
78 Vec<InputID<N>>,
79 Vec<Value<N>>,
80 Signature<N>,
81 Field<N>,
82 Field<N>,
83 Field<N>,
84 Field<N>,
85 ),
86 ) -> Self {
87 if *network_id != N::ID {
89 N::halt(format!("Invalid network ID. Expected {}, found {}", N::ID, *network_id))
90 } else {
91 Self { signer, network_id, program_id, function_name, input_ids, inputs, signature, sk_tag, tvk, tcm, scm }
92 }
93 }
94}
95
96impl<N: Network> Request<N> {
97 pub const fn signer(&self) -> &Address<N> {
99 &self.signer
100 }
101
102 pub const fn network_id(&self) -> &U16<N> {
104 &self.network_id
105 }
106
107 pub const fn program_id(&self) -> &ProgramID<N> {
109 &self.program_id
110 }
111
112 pub const fn function_name(&self) -> &Identifier<N> {
114 &self.function_name
115 }
116
117 pub fn input_ids(&self) -> &[InputID<N>] {
119 &self.input_ids
120 }
121
122 pub fn inputs(&self) -> &[Value<N>] {
124 &self.inputs
125 }
126
127 pub const fn signature(&self) -> &Signature<N> {
129 &self.signature
130 }
131
132 pub const fn sk_tag(&self) -> &Field<N> {
134 &self.sk_tag
135 }
136
137 pub const fn tvk(&self) -> &Field<N> {
139 &self.tvk
140 }
141
142 pub fn to_tpk(&self) -> Group<N> {
144 let challenge = self.signature.challenge();
146 let response = self.signature.response();
148 let pk_sig = self.signature.compute_key().pk_sig();
150 (pk_sig * challenge) + N::g_scalar_multiply(&response)
152 }
153
154 pub const fn tcm(&self) -> &Field<N> {
156 &self.tcm
157 }
158
159 pub const fn scm(&self) -> &Field<N> {
161 &self.scm
162 }
163}
164
165#[cfg(test)]
166mod test_helpers {
167 use super::*;
168 use snarkvm_console_network::MainnetV0;
169
170 type CurrentNetwork = MainnetV0;
171
172 const ITERATIONS: u64 = 1000;
173
174 pub(super) fn sample_requests(rng: &mut TestRng) -> Vec<Request<CurrentNetwork>> {
175 (0..ITERATIONS)
176 .map(|i| {
177 let private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
179 let address = Address::try_from(&private_key).unwrap();
180
181 let program_id = ProgramID::from_str("token.aleo").unwrap();
183 let function_name = Identifier::from_str("transfer").unwrap();
184
185 let record_string =
187 format!("{{ owner: {address}.private, token_amount: {i}u64.private, _nonce: 2293253577170800572742339369209137467208538700597121244293392265726446806023group.public }}");
188
189 let input_constant = Value::from_str(&format!("{{ token_amount: {i}u128 }}")).unwrap();
191 let input_public = Value::from_str(&format!("{{ token_amount: {i}u128 }}")).unwrap();
192 let input_private = Value::from_str(&format!("{{ token_amount: {i}u128 }}")).unwrap();
193 let input_record = Value::from_str(&record_string).unwrap();
194 let input_external_record = Value::from_str(&record_string).unwrap();
195 let inputs = vec![input_constant, input_public, input_private, input_record, input_external_record];
196
197 let input_types = [
199 ValueType::from_str("amount.constant").unwrap(),
200 ValueType::from_str("amount.public").unwrap(),
201 ValueType::from_str("amount.private").unwrap(),
202 ValueType::from_str("token.record").unwrap(),
203 ValueType::from_str("token.aleo/token.record").unwrap(),
204 ];
205
206 let root_tvk = None;
208 let is_root = Uniform::rand(rng);
210 let program_checksum = match i % 2 == 0 {
212 true => Some(Field::rand(rng)),
213 false => None,
214 };
215
216 let request =
218 Request::sign(&private_key, program_id, function_name, inputs.into_iter(), &input_types, root_tvk, is_root, program_checksum, rng).unwrap();
219 assert!(request.verify(&input_types, is_root, program_checksum));
220 request
221 })
222 .collect()
223 }
224}