mod stack;
pub use stack::*;
mod additional_fee;
mod authorize;
mod deploy;
mod evaluate;
mod execute;
use crate::{
ledger::{ProgramStorage, ProgramStore},
AdditionalFee,
Instruction,
Operand,
Program,
ProvingKey,
UniversalSRS,
VerifyingKey,
};
use console::{
account::PrivateKey,
network::prelude::*,
program::{Identifier, Plaintext, ProgramID, Record, Request, Response, Value},
types::{I64, U64},
};
use indexmap::IndexMap;
use parking_lot::RwLock;
use std::sync::Arc;
#[cfg(feature = "aleo-cli")]
use colored::Colorize;
#[derive(Clone)]
pub struct Process<N: Network> {
universal_srs: Arc<UniversalSRS<N>>,
stacks: IndexMap<ProgramID<N>, Stack<N>>,
}
impl<N: Network> Process<N> {
#[inline]
pub fn setup<A: circuit::Aleo<Network = N>, R: Rng + CryptoRng>(rng: &mut R) -> Result<Self> {
let mut process = Self { universal_srs: Arc::new(UniversalSRS::load()?), stacks: IndexMap::new() };
let program = Program::credits()?;
let stack = Stack::new(&process, &program)?;
for function_name in program.functions().keys() {
stack.synthesize_key::<A, _>(function_name, rng)?;
}
process.stacks.insert(*program.id(), stack);
Ok(process)
}
#[inline]
pub fn add_program(&mut self, program: &Program<N>) -> Result<()> {
let stack = Stack::new(self, program)?;
self.stacks.insert(*program.id(), stack);
Ok(())
}
}
impl<N: Network> Process<N> {
#[inline]
pub fn load() -> Result<Self> {
let mut process = Self { universal_srs: Arc::new(UniversalSRS::load()?), stacks: IndexMap::new() };
let program = Program::credits()?;
let stack = Stack::new(&process, &program)?;
for function_name in program.functions().keys() {
let (proving_key, verifying_key) = snarkvm_parameters::testnet3::TESTNET3_CREDITS_PROGRAM
.get(&function_name.to_string())
.ok_or_else(|| anyhow!("Circuit keys for credits.aleo/{function_name}' not found"))?;
stack.insert_proving_key(function_name, ProvingKey::from_bytes_le(proving_key)?)?;
stack.insert_verifying_key(function_name, VerifyingKey::from_bytes_le(verifying_key)?)?;
}
process.stacks.insert(*program.id(), stack);
Ok(process)
}
#[inline]
pub const fn universal_srs(&self) -> &Arc<UniversalSRS<N>> {
&self.universal_srs
}
#[inline]
pub fn contains_program(&self, program_id: &ProgramID<N>) -> bool {
self.stacks.contains_key(program_id)
}
#[inline]
pub fn get_stack(&self, program_id: &ProgramID<N>) -> Result<&Stack<N>> {
let stack = self.stacks.get(program_id).ok_or_else(|| anyhow!("Program '{program_id}' does not exist"))?;
ensure!(stack.program_id() == program_id, "Expected program '{}', found '{program_id}'", stack.program_id());
Ok(stack)
}
#[inline]
pub fn get_program(&self, program_id: &ProgramID<N>) -> Result<&Program<N>> {
self.get_stack(program_id).map(Stack::program)
}
#[inline]
pub fn get_proving_key(&self, program_id: &ProgramID<N>, function_name: &Identifier<N>) -> Result<ProvingKey<N>> {
self.get_stack(program_id)?.get_proving_key(function_name)
}
#[inline]
pub fn get_verifying_key(
&self,
program_id: &ProgramID<N>,
function_name: &Identifier<N>,
) -> Result<VerifyingKey<N>> {
self.get_stack(program_id)?.get_verifying_key(function_name)
}
#[inline]
pub fn insert_proving_key(
&self,
program_id: &ProgramID<N>,
function_name: &Identifier<N>,
proving_key: ProvingKey<N>,
) -> Result<()> {
self.get_stack(program_id)?.insert_proving_key(function_name, proving_key)
}
#[inline]
pub fn insert_verifying_key(
&self,
program_id: &ProgramID<N>,
function_name: &Identifier<N>,
verifying_key: VerifyingKey<N>,
) -> Result<()> {
self.get_stack(program_id)?.insert_verifying_key(function_name, verifying_key)
}
#[inline]
pub fn synthesize_key<A: circuit::Aleo<Network = N>, R: Rng + CryptoRng>(
&self,
program_id: &ProgramID<N>,
function_name: &Identifier<N>,
rng: &mut R,
) -> Result<()> {
self.get_stack(program_id)?.synthesize_key::<A, R>(function_name, rng)
}
}
#[cfg(test)]
pub(crate) mod test_helpers {
use super::*;
use crate::{Process, Program, Transition};
use console::{
account::PrivateKey,
network::Testnet3,
program::{Identifier, Value},
};
use once_cell::sync::OnceCell;
type CurrentNetwork = Testnet3;
type CurrentAleo = circuit::network::AleoV0;
pub(crate) fn sample_key() -> (Identifier<CurrentNetwork>, ProvingKey<CurrentNetwork>, VerifyingKey<CurrentNetwork>)
{
static INSTANCE: OnceCell<(
Identifier<CurrentNetwork>,
ProvingKey<CurrentNetwork>,
VerifyingKey<CurrentNetwork>,
)> = OnceCell::new();
INSTANCE
.get_or_init(|| {
let (string, program) = Program::<CurrentNetwork>::parse(
r"
program testing.aleo;
function compute:
input r0 as u32.private;
input r1 as u32.public;
add r0 r1 into r2;
output r2 as u32.public;",
)
.unwrap();
assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'");
let function_name = Identifier::from_str("compute").unwrap();
let rng = &mut test_crypto_rng();
let process = sample_process(&program);
process.synthesize_key::<CurrentAleo, _>(program.id(), &function_name, rng).unwrap();
let proving_key = process.get_proving_key(program.id(), &function_name).unwrap();
let verifying_key = process.get_verifying_key(program.id(), &function_name).unwrap();
(function_name, proving_key, verifying_key)
})
.clone()
}
pub(crate) fn sample_execution() -> Execution<CurrentNetwork> {
static INSTANCE: OnceCell<Execution<CurrentNetwork>> = OnceCell::new();
INSTANCE
.get_or_init(|| {
let (string, program) = Program::<CurrentNetwork>::parse(
r"
program testing.aleo;
function compute:
input r0 as u32.private;
input r1 as u32.public;
add r0 r1 into r2;
output r2 as u32.public;",
)
.unwrap();
assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'");
let function_name = Identifier::from_str("compute").unwrap();
let rng = &mut test_crypto_rng();
let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
let process = sample_process(&program);
let authorization = process
.authorize::<CurrentAleo, _>(
&caller_private_key,
program.id(),
function_name,
&[
Value::<CurrentNetwork>::from_str("5u32").unwrap(),
Value::<CurrentNetwork>::from_str("10u32").unwrap(),
],
rng,
)
.unwrap();
assert_eq!(authorization.len(), 1);
let (_response, execution) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap();
assert_eq!(execution.len(), 1);
execution
})
.clone()
}
pub(crate) fn sample_transition() -> Transition<CurrentNetwork> {
let mut execution = sample_execution();
assert!(!execution.is_empty());
execution.pop().unwrap()
}
pub(crate) fn sample_process(program: &Program<CurrentNetwork>) -> Process<CurrentNetwork> {
let mut process = Process::load().unwrap();
process.add_program(program).unwrap();
process
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ProgramMemory;
use circuit::network::AleoV0;
use console::{
account::{Address, PrivateKey, ViewKey},
network::Testnet3,
program::{Identifier, Literal, Value},
types::Field,
};
type CurrentNetwork = Testnet3;
type CurrentAleo = AleoV0;
#[test]
fn test_process_execute_genesis() {
let program = Program::<CurrentNetwork>::credits().unwrap();
let rng = &mut test_crypto_rng();
let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
let _caller_view_key = ViewKey::try_from(&caller_private_key).unwrap();
let caller = Address::try_from(&caller_private_key).unwrap();
let r0 = Value::<CurrentNetwork>::from_str(&format!("{caller}")).unwrap();
let r1 = Value::<CurrentNetwork>::from_str("1_100_000_000_000_000_u64").unwrap();
let mut process = Process::load().unwrap();
let authorization = process
.authorize::<CurrentAleo, _>(
&caller_private_key,
program.id(),
Identifier::from_str("genesis").unwrap(),
&[r0.clone(), r1.clone()],
rng,
)
.unwrap();
assert_eq!(authorization.len(), 1);
let request = authorization.peek_next().unwrap();
let randomizer = CurrentNetwork::hash_to_scalar_psd2(&[*request.tvk(), Field::from_u64(2)]).unwrap();
let nonce = CurrentNetwork::g_scalar_multiply(&randomizer);
let r2 = Value::from_str(&format!(
"{{ owner: {caller}.private, gates: 1_100_000_000_000_000_u64.private, _nonce: {nonce}.public }}"
))
.unwrap();
assert_eq!(authorization.len(), 1);
let response = process.evaluate::<CurrentAleo>(authorization.replicate()).unwrap();
let candidate = response.outputs();
assert_eq!(1, candidate.len());
assert_eq!(r2, candidate[0]);
assert_eq!(authorization.len(), 1);
let (response, execution) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap();
let candidate = response.outputs();
assert_eq!(1, candidate.len());
assert_eq!(r2, candidate[0]);
assert!(process.verify_execution(&execution).is_ok());
let program = Program::<CurrentNetwork>::from_str(
r"program token.aleo;
record token:
owner as address.private;
gates as u64.private;
function genesis:
input r0 as address.private;
input r1 as u64.private;
cast r0 r1 into r2 as token.record;
output r2 as token.record;",
)
.unwrap();
process.add_program(&program).unwrap();
let authorization = process
.authorize::<CurrentAleo, _>(
&caller_private_key,
program.id(),
Identifier::from_str("genesis").unwrap(),
&[r0, r1],
rng,
)
.unwrap();
let result = process.execute::<CurrentAleo, _>(authorization, rng);
assert!(result.is_err());
assert_eq!(
result.err().unwrap().to_string(),
format!("'token.aleo/genesis' is not satisfied on the given inputs (26479 constraints).")
);
}
#[test]
fn test_process_circuit_key() {
let program = Program::<CurrentNetwork>::from_str(
r#"program testing.aleo;
function hello_world:
input r0 as u32.public;
input r1 as u32.private;
add r0 r1 into r2;
output r2 as u32.private;
"#,
)
.unwrap();
let function_name = Identifier::from_str("hello_world").unwrap();
let process = super::test_helpers::sample_process(&program);
process.synthesize_key::<CurrentAleo, _>(program.id(), &function_name, &mut test_crypto_rng()).unwrap();
}
#[test]
fn test_process_multirecords() {
let program = Program::<CurrentNetwork>::from_str(
r"program multirecord.aleo;
record record_a:
owner as address.private;
gates as u64.private;
record record_b:
owner as address.private;
gates as u64.private;
function initialize:
input r0 as record_a.record;
input r1 as record_b.record;
cast r0.owner r0.gates into r2 as record_a.record;
cast r1.owner r1.gates into r3 as record_b.record;
output r2 as record_a.record;
output r3 as record_b.record;",
)
.unwrap();
let function_name = Identifier::from_str("initialize").unwrap();
let rng = &mut test_crypto_rng();
let process = super::test_helpers::sample_process(&program);
let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
let _caller_view_key = ViewKey::try_from(&caller_private_key).unwrap();
let caller = Address::try_from(&caller_private_key).unwrap();
let input_a =
Value::from_str(&format!("{{ owner: {caller}.private, gates: 1234u64.private, _nonce: 0group.public }}"))
.unwrap();
let input_b =
Value::from_str(&format!("{{ owner: {caller}.private, gates: 4321u64.private, _nonce: 0group.public }}"))
.unwrap();
let authorization = process
.authorize::<CurrentAleo, _>(&caller_private_key, program.id(), function_name, &[input_a, input_b], rng)
.unwrap();
assert_eq!(authorization.len(), 1);
let request = authorization.peek_next().unwrap();
let randomizer_a = CurrentNetwork::hash_to_scalar_psd2(&[*request.tvk(), Field::from_u64(2)]).unwrap();
let nonce_a = CurrentNetwork::g_scalar_multiply(&randomizer_a);
let randomizer_b = CurrentNetwork::hash_to_scalar_psd2(&[*request.tvk(), Field::from_u64(3)]).unwrap();
let nonce_b = CurrentNetwork::g_scalar_multiply(&randomizer_b);
let output_a = Value::from_str(&format!(
"{{ owner: {caller}.private, gates: 1234u64.private, _nonce: {nonce_a}.public }}"
))
.unwrap();
let output_b = Value::from_str(&format!(
"{{ owner: {caller}.private, gates: 4321u64.private, _nonce: {nonce_b}.public }}"
))
.unwrap();
assert_eq!(authorization.len(), 1);
let response = process.evaluate::<CurrentAleo>(authorization.replicate()).unwrap();
let candidate = response.outputs();
assert_eq!(2, candidate.len());
assert_eq!(output_a, candidate[0]);
assert_eq!(output_b, candidate[1]);
assert_eq!(authorization.len(), 1);
let (response, execution) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap();
let candidate = response.outputs();
assert_eq!(2, candidate.len());
assert_eq!(output_a, candidate[0]);
assert_eq!(output_b, candidate[1]);
assert!(process.verify_execution(&execution).is_ok());
}
#[test]
fn test_process_self_caller() {
let program = Program::<CurrentNetwork>::from_str(
r"program caller.aleo;
record data:
owner as address.private;
gates as u64.private;
function initialize:
input r0 as data.record;
cast self.caller r0.gates into r1 as data.record;
output r1 as data.record;",
)
.unwrap();
let function_name = Identifier::from_str("initialize").unwrap();
let rng = &mut test_crypto_rng();
let process = super::test_helpers::sample_process(&program);
let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
let _caller_view_key = ViewKey::try_from(&caller_private_key).unwrap();
let caller = Address::try_from(&caller_private_key).unwrap();
let input =
Value::from_str(&format!("{{ owner: {caller}.private, gates: 1234u64.private, _nonce: 0group.public }}"))
.unwrap();
let authorization = process
.authorize::<CurrentAleo, _>(&caller_private_key, program.id(), function_name, &[input], rng)
.unwrap();
assert_eq!(authorization.len(), 1);
let request = authorization.peek_next().unwrap();
let randomizer = CurrentNetwork::hash_to_scalar_psd2(&[*request.tvk(), Field::from_u64(1)]).unwrap();
let nonce = CurrentNetwork::g_scalar_multiply(&randomizer);
let output =
Value::from_str(&format!("{{ owner: {caller}.private, gates: 1234u64.private, _nonce: {nonce}.public }}"))
.unwrap();
assert_eq!(authorization.len(), 1);
let response = process.evaluate::<CurrentAleo>(authorization.replicate()).unwrap();
let candidate = response.outputs();
assert_eq!(1, candidate.len());
assert_eq!(output, candidate[0]);
assert_eq!(authorization.len(), 1);
let (response, execution) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap();
let candidate = response.outputs();
assert_eq!(1, candidate.len());
assert_eq!(output, candidate[0]);
assert!(process.verify_execution(&execution).is_ok());
}
#[test]
fn test_process_program_id() {
let program = Program::<CurrentNetwork>::from_str(
r"program id.aleo;
interface data:
owner as address;
function initialize:
cast id.aleo into r0 as data;
output r0 as data.private;",
)
.unwrap();
let program_id = ProgramID::from_str("id.aleo").unwrap();
assert_eq!(*program.id(), program_id);
let function_name = Identifier::from_str("initialize").unwrap();
let rng = &mut test_crypto_rng();
let process = super::test_helpers::sample_process(&program);
let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
let authorization =
process.authorize::<CurrentAleo, _>(&caller_private_key, program.id(), function_name, &[], rng).unwrap();
assert_eq!(authorization.len(), 1);
let output = Value::from_str(&format!("{{ owner: {} }}", program_id.to_address().unwrap())).unwrap();
assert_eq!(authorization.len(), 1);
let response = process.evaluate::<CurrentAleo>(authorization.replicate()).unwrap();
let candidate = response.outputs();
assert_eq!(1, candidate.len());
assert_eq!(output, candidate[0]);
assert_eq!(authorization.len(), 1);
let (response, execution) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap();
let candidate = response.outputs();
assert_eq!(1, candidate.len());
assert_eq!(output, candidate[0]);
assert!(process.verify_execution(&execution).is_ok());
}
#[test]
fn test_process_execute_call_closure() {
let (string, program) = Program::<CurrentNetwork>::parse(
r"
program token.aleo;
record token:
owner as address.private;
gates as u64.private;
token_amount as u64.private;
// (a + (a + b)) + (a + b) == (3a + 2b)
closure execute:
input r0 as field;
input r1 as field;
add r0 r1 into r2;
add r0 r2 into r3;
add r2 r3 into r4;
output r4 as field;
output r3 as field;
output r2 as field;
function compute:
input r0 as field.private;
input r1 as field.public;
input r2 as token.record;
cast r2.owner r2.gates r2.token_amount into r3 as token.record;
call execute r0 r1 into r4 r5 r6;
output r3 as token.record;
output r4 as field.private;
output r5 as field.private;
output r6 as field.private;",
)
.unwrap();
assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'");
let function_name = Identifier::from_str("compute").unwrap();
let rng = &mut test_crypto_rng();
let process = super::test_helpers::sample_process(&program);
process.synthesize_key::<CurrentAleo, _>(program.id(), &function_name, rng).unwrap();
let process = super::test_helpers::sample_process(&program);
let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
let _caller_view_key = ViewKey::try_from(&caller_private_key).unwrap();
let caller = Address::try_from(&caller_private_key).unwrap();
let record_string = format!(
"{{ owner: {caller}.private, gates: 5u64.private, token_amount: 100u64.private, _nonce: 0group.public }}"
);
let r0 = Value::<CurrentNetwork>::from_str("3field").unwrap();
let r1 = Value::<CurrentNetwork>::from_str("5field").unwrap();
let r2 = Value::<CurrentNetwork>::from_str(&record_string).unwrap();
let authorization = process
.authorize::<CurrentAleo, _>(&caller_private_key, program.id(), function_name, &[r0, r1, r2], rng)
.unwrap();
assert_eq!(authorization.len(), 1);
let request = authorization.peek_next().unwrap();
let randomizer = CurrentNetwork::hash_to_scalar_psd2(&[*request.tvk(), Field::from_u64(3)]).unwrap();
let nonce = CurrentNetwork::g_scalar_multiply(&randomizer);
let r3 = Value::<CurrentNetwork>::from_str(&format!(
"{{ owner: {caller}.private, gates: 5u64.private, token_amount: 100u64.private, _nonce: {nonce}.public }}"
))
.unwrap();
let r4 = Value::from_str("19field").unwrap();
let r5 = Value::from_str("11field").unwrap();
let r6 = Value::from_str("8field").unwrap();
assert_eq!(authorization.len(), 1);
let response = process.evaluate::<CurrentAleo>(authorization.replicate()).unwrap();
let candidate = response.outputs();
assert_eq!(4, candidate.len());
assert_eq!(r3, candidate[0]);
assert_eq!(r4, candidate[1]);
assert_eq!(r5, candidate[2]);
assert_eq!(r6, candidate[3]);
assert_eq!(authorization.len(), 1);
let (response, execution) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap();
let candidate = response.outputs();
assert_eq!(4, candidate.len());
assert_eq!(r3, candidate[0]);
assert_eq!(r4, candidate[1]);
assert_eq!(r5, candidate[2]);
assert_eq!(r6, candidate[3]);
assert!(process.verify_execution(&execution).is_ok());
}
#[test]
fn test_process_execute_call_external_function() {
let (string, program0) = Program::<CurrentNetwork>::parse(
r"
program token.aleo;
record token:
owner as address.private;
gates as u64.private;
amount as u64.private;
function mint:
input r0 as address.private;
input r1 as u64.private;
cast r0 0u64 r1 into r2 as token.record;
output r2 as token.record;
function transfer:
input r0 as token.record;
input r1 as address.private;
input r2 as u64.private;
sub r0.amount r2 into r3;
cast r1 0u64 r2 into r4 as token.record;
cast r0.owner r0.gates r3 into r5 as token.record;
output r4 as token.record;
output r5 as token.record;",
)
.unwrap();
assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'");
let mut process = super::test_helpers::sample_process(&program0);
let (string, program1) = Program::<CurrentNetwork>::parse(
r"
import token.aleo;
program wallet.aleo;
function transfer:
input r0 as token.aleo/token.record;
input r1 as address.private;
input r2 as u64.private;
call token.aleo/transfer r0 r1 r2 into r3 r4;
output r3 as token.aleo/token.record;
output r4 as token.aleo/token.record;",
)
.unwrap();
assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'");
process.add_program(&program1).unwrap();
let rng = &mut test_crypto_rng();
let caller0_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
let caller0 = Address::try_from(&caller0_private_key).unwrap();
let caller1_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
let caller1 = Address::try_from(&caller1_private_key).unwrap();
let function_name = Identifier::from_str("transfer").unwrap();
let r0 = Value::<CurrentNetwork>::from_str(&format!(
"{{ owner: {caller0}.private, gates: 0u64.private, amount: 100u64.private, _nonce: 0group.public }}"
))
.unwrap();
let r1 = Value::<CurrentNetwork>::from_str(&caller1.to_string()).unwrap();
let r2 = Value::<CurrentNetwork>::from_str("99u64").unwrap();
let authorization = process
.authorize::<CurrentAleo, _>(&caller0_private_key, program1.id(), function_name, &[r0, r1, r2], rng)
.unwrap();
assert_eq!(authorization.len(), 2);
println!("\nAuthorize\n{:#?}\n\n", authorization.to_vec_deque());
let (output_a, output_b) = {
let request = authorization.to_vec_deque().pop_back().unwrap();
let randomizer_a = CurrentNetwork::hash_to_scalar_psd2(&[*request.tvk(), Field::from_u64(4)]).unwrap();
let nonce_a = CurrentNetwork::g_scalar_multiply(&randomizer_a);
let randomizer_b = CurrentNetwork::hash_to_scalar_psd2(&[*request.tvk(), Field::from_u64(5)]).unwrap();
let nonce_b = CurrentNetwork::g_scalar_multiply(&randomizer_b);
let output_a = Value::from_str(&format!(
"{{ owner: {caller1}.private, gates: 0u64.private, amount: 99u64.private, _nonce: {nonce_a}.public }}"
))
.unwrap();
let output_b = Value::from_str(&format!(
"{{ owner: {caller0}.private, gates: 0u64.private, amount: 1u64.private, _nonce: {nonce_b}.public }}"
))
.unwrap();
(output_a, output_b)
};
assert_eq!(authorization.len(), 2);
let response = process.evaluate::<CurrentAleo>(authorization.replicate()).unwrap();
let candidate = response.outputs();
assert_eq!(2, candidate.len());
assert_eq!(output_a, candidate[0]);
assert_eq!(output_b, candidate[1]);
assert_eq!(authorization.len(), 2);
let (response, execution) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap();
let candidate = response.outputs();
assert_eq!(2, candidate.len());
assert_eq!(output_a, candidate[0]);
assert_eq!(output_b, candidate[1]);
assert!(process.verify_execution(&execution).is_ok());
}
#[test]
fn test_process_execute_and_finalize_increment() {
let (string, program) = Program::<CurrentNetwork>::parse(
r"
program testing.aleo;
mapping account:
key owner as address.public;
value amount as u64.public;
function compute:
input r0 as address.public;
input r1 as u64.public;
input r2 as u64.public;
add r1 r2 into r3;
finalize r0 r3;
finalize compute:
input r0 as address.public;
input r1 as u64.public;
increment account[r0] by r1;
",
)
.unwrap();
assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'");
let program_id = program.id();
let mapping_name = Identifier::from_str("account").unwrap();
let function_name = Identifier::from_str("compute").unwrap();
let rng = &mut test_crypto_rng();
let process = super::test_helpers::sample_process(&program);
process.synthesize_key::<CurrentAleo, _>(program.id(), &function_name, rng).unwrap();
let mut process = Process::load().unwrap();
let store = ProgramStore::<_, ProgramMemory<_>>::open().unwrap();
let deployment = process.deploy::<CurrentAleo, _>(&program, rng).unwrap();
process.verify_deployment::<CurrentAleo, _>(&deployment, rng).unwrap();
process.finalize_deployment(&store, &deployment).unwrap();
let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
let _caller_view_key = ViewKey::try_from(&caller_private_key).unwrap();
let caller = Address::try_from(&caller_private_key).unwrap();
let r0 = Value::<CurrentNetwork>::from_str(&caller.to_string()).unwrap();
let r1 = Value::<CurrentNetwork>::from_str("3u64").unwrap();
let r2 = Value::<CurrentNetwork>::from_str("5u64").unwrap();
let authorization = process
.authorize::<CurrentAleo, _>(&caller_private_key, program.id(), function_name, &[r0, r1, r2], rng)
.unwrap();
assert_eq!(authorization.len(), 1);
let response = process.evaluate::<CurrentAleo>(authorization.replicate()).unwrap();
let candidate = response.outputs();
assert_eq!(0, candidate.len());
assert_eq!(authorization.len(), 1);
let (response, execution) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap();
let candidate = response.outputs();
assert_eq!(0, candidate.len());
assert!(process.verify_execution(&execution).is_ok());
process.finalize_execution(&store, &execution).unwrap();
let candidate =
store.get_value(program_id, &mapping_name, &Plaintext::from(Literal::Address(caller))).unwrap().unwrap();
assert_eq!(candidate, Value::from_str("8u64").unwrap());
}
#[test]
fn test_process_execute_and_finalize_increment_decrement() {
let (string, program) = Program::<CurrentNetwork>::parse(
r"
program testing.aleo;
mapping account:
key owner as address.public;
value amount as u64.public;
function compute:
input r0 as address.public;
input r1 as u64.public;
input r2 as u64.public;
add r1 r2 into r3;
finalize r0 r3;
finalize compute:
input r0 as address.public;
input r1 as u64.public;
increment account[r0] by r1;
decrement account[r0] by r1;
",
)
.unwrap();
assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'");
let program_id = program.id();
let mapping_name = Identifier::from_str("account").unwrap();
let function_name = Identifier::from_str("compute").unwrap();
let rng = &mut test_crypto_rng();
let process = super::test_helpers::sample_process(&program);
process.synthesize_key::<CurrentAleo, _>(program.id(), &function_name, rng).unwrap();
let mut process = Process::load().unwrap();
let store = ProgramStore::<_, ProgramMemory<_>>::open().unwrap();
let deployment = process.deploy::<CurrentAleo, _>(&program, rng).unwrap();
process.verify_deployment::<CurrentAleo, _>(&deployment, rng).unwrap();
process.finalize_deployment(&store, &deployment).unwrap();
let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
let _caller_view_key = ViewKey::try_from(&caller_private_key).unwrap();
let caller = Address::try_from(&caller_private_key).unwrap();
let r0 = Value::<CurrentNetwork>::from_str(&caller.to_string()).unwrap();
let r1 = Value::<CurrentNetwork>::from_str("3u64").unwrap();
let r2 = Value::<CurrentNetwork>::from_str("5u64").unwrap();
let authorization = process
.authorize::<CurrentAleo, _>(&caller_private_key, program.id(), function_name, &[r0, r1, r2], rng)
.unwrap();
assert_eq!(authorization.len(), 1);
let response = process.evaluate::<CurrentAleo>(authorization.replicate()).unwrap();
let candidate = response.outputs();
assert_eq!(0, candidate.len());
assert_eq!(authorization.len(), 1);
let (response, execution) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap();
let candidate = response.outputs();
assert_eq!(0, candidate.len());
assert!(process.verify_execution(&execution).is_ok());
process.finalize_execution(&store, &execution).unwrap();
let candidate =
store.get_value(program_id, &mapping_name, &Plaintext::from(Literal::Address(caller))).unwrap().unwrap();
assert_eq!(candidate, Value::from_str("0u64").unwrap());
}
#[test]
fn test_process_execute_mint_public() {
let (string, program) = Program::<CurrentNetwork>::parse(
r"
program token.aleo;
// On-chain storage of an `account` map, with `owner` as the key,
// and `amount` as the value.
mapping account:
// The token owner.
key owner as address.public;
// The token amount.
value amount as u64.public;
// The function `mint_public` issues the specified token amount
// for the token receiver publicly on the network.
function mint_public:
// Input the token receiver.
input r0 as address.public;
// Input the token amount.
input r1 as u64.public;
// Mint the tokens publicly.
finalize r0 r1;
// The finalize scope of `mint_public` increments the
// `account` of the token receiver by the specified amount.
finalize mint_public:
// Input the token receiver.
input r0 as address.public;
// Input the token amount.
input r1 as u64.public;
// Increments `account[r0]` by `r1`.
// If `account[r0]` does not exist, it will be created.
// If `account[r0] + r1` overflows, `mint_public` is reverted.
increment account[r0] by r1;
",
)
.unwrap();
assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'");
let program_id = program.id();
let mapping_name = Identifier::from_str("account").unwrap();
let function_name = Identifier::from_str("mint_public").unwrap();
let rng = &mut test_crypto_rng();
let process = super::test_helpers::sample_process(&program);
process.synthesize_key::<CurrentAleo, _>(program.id(), &function_name, rng).unwrap();
let mut process = Process::load().unwrap();
let store = ProgramStore::<_, ProgramMemory<_>>::open().unwrap();
let deployment = process.deploy::<CurrentAleo, _>(&program, rng).unwrap();
process.verify_deployment::<CurrentAleo, _>(&deployment, rng).unwrap();
process.finalize_deployment(&store, &deployment).unwrap();
process.synthesize_key::<CurrentAleo, _>(program.id(), &function_name, rng).unwrap();
let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
let _caller_view_key = ViewKey::try_from(&caller_private_key).unwrap();
let caller = Address::try_from(&caller_private_key).unwrap();
let r0 = Value::<CurrentNetwork>::from_str(&caller.to_string()).unwrap();
let r1 = Value::<CurrentNetwork>::from_str("3u64").unwrap();
let authorization = process
.authorize::<CurrentAleo, _>(&caller_private_key, program.id(), function_name, &[r0, r1], rng)
.unwrap();
assert_eq!(authorization.len(), 1);
let response = process.evaluate::<CurrentAleo>(authorization.replicate()).unwrap();
let candidate = response.outputs();
assert_eq!(0, candidate.len());
assert_eq!(authorization.len(), 1);
let (response, execution) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap();
let candidate = response.outputs();
assert_eq!(0, candidate.len());
assert!(process.verify_execution(&execution).is_ok());
process.finalize_execution(&store, &execution).unwrap();
let candidate =
store.get_value(program_id, &mapping_name, &Plaintext::from(Literal::Address(caller))).unwrap().unwrap();
assert_eq!(candidate, Value::from_str("3u64").unwrap());
}
}