mod input_id;
pub use input_id::InputID;
mod bytes;
mod serialize;
mod sign;
mod string;
mod verify;
use crate::{Identifier, Plaintext, ProgramID, Record, Value, ValueType, compute_function_id};
use snarkvm_console_account::{Address, ComputeKey, GraphKey, PrivateKey, Signature, ViewKey};
use snarkvm_console_network::Network;
use snarkvm_console_types::prelude::*;
#[derive(Clone, PartialEq, Eq)]
pub struct Request<N: Network> {
signer: Address<N>,
network_id: U16<N>,
program_id: ProgramID<N>,
function_name: Identifier<N>,
input_ids: Vec<InputID<N>>,
inputs: Vec<Value<N>>,
signature: Signature<N>,
sk_tag: Field<N>,
tvk: Field<N>,
tcm: Field<N>,
scm: Field<N>,
}
impl<N: Network>
From<(
Address<N>,
U16<N>,
ProgramID<N>,
Identifier<N>,
Vec<InputID<N>>,
Vec<Value<N>>,
Signature<N>,
Field<N>,
Field<N>,
Field<N>,
Field<N>,
)> for Request<N>
{
fn from(
(signer, network_id, program_id, function_name, input_ids, inputs, signature, sk_tag, tvk, tcm, scm): (
Address<N>,
U16<N>,
ProgramID<N>,
Identifier<N>,
Vec<InputID<N>>,
Vec<Value<N>>,
Signature<N>,
Field<N>,
Field<N>,
Field<N>,
Field<N>,
),
) -> Self {
if *network_id != N::ID {
N::halt(format!("Invalid network ID. Expected {}, found {}", N::ID, *network_id))
} else {
Self { signer, network_id, program_id, function_name, input_ids, inputs, signature, sk_tag, tvk, tcm, scm }
}
}
}
impl<N: Network> Request<N> {
pub const fn signer(&self) -> &Address<N> {
&self.signer
}
pub const fn network_id(&self) -> &U16<N> {
&self.network_id
}
pub const fn program_id(&self) -> &ProgramID<N> {
&self.program_id
}
pub const fn function_name(&self) -> &Identifier<N> {
&self.function_name
}
pub fn input_ids(&self) -> &[InputID<N>] {
&self.input_ids
}
pub fn inputs(&self) -> &[Value<N>] {
&self.inputs
}
pub const fn signature(&self) -> &Signature<N> {
&self.signature
}
pub const fn sk_tag(&self) -> &Field<N> {
&self.sk_tag
}
pub const fn tvk(&self) -> &Field<N> {
&self.tvk
}
pub fn to_tpk(&self) -> Group<N> {
let challenge = self.signature.challenge();
let response = self.signature.response();
let pk_sig = self.signature.compute_key().pk_sig();
(pk_sig * challenge) + N::g_scalar_multiply(&response)
}
pub const fn tcm(&self) -> &Field<N> {
&self.tcm
}
pub const fn scm(&self) -> &Field<N> {
&self.scm
}
}
#[cfg(test)]
mod test_helpers {
use super::*;
use snarkvm_console_network::MainnetV0;
type CurrentNetwork = MainnetV0;
const ITERATIONS: u64 = 1000;
pub(super) fn sample_requests(rng: &mut TestRng) -> Vec<Request<CurrentNetwork>> {
(0..ITERATIONS)
.map(|i| {
let private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
let address = Address::try_from(&private_key).unwrap();
let program_id = ProgramID::from_str("token.aleo").unwrap();
let function_name = Identifier::from_str("transfer").unwrap();
let record_string =
format!("{{ owner: {address}.private, token_amount: {i}u64.private, _nonce: 2293253577170800572742339369209137467208538700597121244293392265726446806023group.public }}");
let input_constant = Value::from_str(&format!("{{ token_amount: {i}u128 }}")).unwrap();
let input_public = Value::from_str(&format!("{{ token_amount: {i}u128 }}")).unwrap();
let input_private = Value::from_str(&format!("{{ token_amount: {i}u128 }}")).unwrap();
let input_record = Value::from_str(&record_string).unwrap();
let input_external_record = Value::from_str(&record_string).unwrap();
let inputs = vec![input_constant, input_public, input_private, input_record, input_external_record];
let is_root = false;
let input_types = [
ValueType::from_str("amount.constant").unwrap(),
ValueType::from_str("amount.public").unwrap(),
ValueType::from_str("amount.private").unwrap(),
ValueType::from_str("token.record").unwrap(),
ValueType::from_str("token.aleo/token.record").unwrap(),
];
let root_tvk = None;
let request =
Request::sign(&private_key, program_id, function_name, inputs.into_iter(), &input_types, root_tvk, is_root, rng).unwrap();
assert!(request.verify(&input_types, is_root));
request
})
.collect()
}
}