use console::{
account::{Address, PrivateKey},
prelude::*,
program::{Ciphertext, Literal, Plaintext, ProgramOwner, Record, Value},
types::Field,
};
use ledger_block::{
Block,
ConfirmedTransaction,
Deployment,
Execution,
Fee,
Header,
Input,
Output,
Ratifications,
Rejected,
Transaction,
Transactions,
Transition,
};
use ledger_query::Query;
use ledger_store::{BlockStore, helpers::memory::BlockMemory};
use synthesizer_process::Process;
use synthesizer_program::Program;
use once_cell::sync::OnceCell;
type CurrentNetwork = console::network::MainnetV0;
type CurrentAleo = circuit::network::AleoV0;
pub fn sample_transition(rng: &mut TestRng) -> Transition<CurrentNetwork> {
crate::sample_execution(rng).into_transitions().next().unwrap()
}
pub fn sample_inputs() -> Vec<(<CurrentNetwork as Network>::TransitionID, Input<CurrentNetwork>)> {
let rng = &mut TestRng::default();
let transaction = crate::sample_execution_transaction_with_fee(true, rng);
let transition = transaction.transitions().next().unwrap();
let transition_id = *transition.id();
let input = transition.inputs().iter().next().unwrap().clone();
let plaintext = Plaintext::Literal(Literal::Field(Uniform::rand(rng)), Default::default());
let plaintext_hash = CurrentNetwork::hash_bhp1024(&plaintext.to_bits_le()).unwrap();
let fields: Vec<_> = (0..10).map(|_| Uniform::rand(rng)).collect();
let ciphertext = Ciphertext::from_fields(&fields).unwrap();
let ciphertext_hash = CurrentNetwork::hash_bhp1024(&ciphertext.to_bits_le()).unwrap();
vec![
(transition_id, input),
(Uniform::rand(rng), Input::Constant(Uniform::rand(rng), None)),
(Uniform::rand(rng), Input::Constant(plaintext_hash, Some(plaintext.clone()))),
(Uniform::rand(rng), Input::Public(Uniform::rand(rng), None)),
(Uniform::rand(rng), Input::Public(plaintext_hash, Some(plaintext))),
(Uniform::rand(rng), Input::Private(Uniform::rand(rng), None)),
(Uniform::rand(rng), Input::Private(ciphertext_hash, Some(ciphertext))),
(Uniform::rand(rng), Input::Record(Uniform::rand(rng), Uniform::rand(rng))),
(Uniform::rand(rng), Input::ExternalRecord(Uniform::rand(rng))),
]
}
pub fn sample_outputs() -> Vec<(<CurrentNetwork as Network>::TransitionID, Output<CurrentNetwork>)> {
let rng = &mut TestRng::default();
let transaction = crate::sample_execution_transaction_with_fee(true, rng);
let transition = transaction.transitions().next().unwrap();
let transition_id = *transition.id();
let input = transition.outputs().iter().next().unwrap().clone();
let plaintext = Plaintext::Literal(Literal::Field(Uniform::rand(rng)), Default::default());
let plaintext_hash = CurrentNetwork::hash_bhp1024(&plaintext.to_bits_le()).unwrap();
let fields: Vec<_> = (0..10).map(|_| Uniform::rand(rng)).collect();
let ciphertext = Ciphertext::from_fields(&fields).unwrap();
let ciphertext_hash = CurrentNetwork::hash_bhp1024(&ciphertext.to_bits_le()).unwrap();
let randomizer = Uniform::rand(rng);
let nonce = CurrentNetwork::g_scalar_multiply(&randomizer);
let record = Record::<CurrentNetwork, Plaintext<CurrentNetwork>>::from_str(
&format!("{{ owner: aleo1d5hg2z3ma00382pngntdp68e74zv54jdxy249qhaujhks9c72yrs33ddah.private, token_amount: 100u64.private, _nonce: {nonce}.public }}"),
).unwrap();
let record_ciphertext = record.encrypt(randomizer).unwrap();
let record_checksum = CurrentNetwork::hash_bhp1024(&record_ciphertext.to_bits_le()).unwrap();
vec![
(transition_id, input),
(Uniform::rand(rng), Output::Constant(Uniform::rand(rng), None)),
(Uniform::rand(rng), Output::Constant(plaintext_hash, Some(plaintext.clone()))),
(Uniform::rand(rng), Output::Public(Uniform::rand(rng), None)),
(Uniform::rand(rng), Output::Public(plaintext_hash, Some(plaintext))),
(Uniform::rand(rng), Output::Private(Uniform::rand(rng), None)),
(Uniform::rand(rng), Output::Private(ciphertext_hash, Some(ciphertext))),
(Uniform::rand(rng), Output::Record(Uniform::rand(rng), Uniform::rand(rng), None)),
(Uniform::rand(rng), Output::Record(Uniform::rand(rng), record_checksum, Some(record_ciphertext))),
(Uniform::rand(rng), Output::ExternalRecord(Uniform::rand(rng))),
]
}
pub fn sample_deployment(rng: &mut TestRng) -> Deployment<CurrentNetwork> {
static INSTANCE: OnceCell<Deployment<CurrentNetwork>> = OnceCell::new();
INSTANCE
.get_or_init(|| {
let (string, program) = Program::<CurrentNetwork>::parse(
r"
program testing.aleo;
mapping store:
key as u32.public;
value as u32.public;
function compute:
input r0 as u32.private;
add r0 r0 into r1;
output r1 as u32.public;",
)
.unwrap();
assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'");
let process = Process::load().unwrap();
let deployment = process.deploy::<CurrentAleo, _>(&program, rng).unwrap();
Deployment::from_str(&deployment.to_string()).unwrap()
})
.clone()
}
pub fn sample_rejected_deployment(is_fee_private: bool, rng: &mut TestRng) -> Rejected<CurrentNetwork> {
let deployment = match crate::sample_deployment_transaction(is_fee_private, rng) {
Transaction::Deploy(_, _, deployment, _) => (*deployment).clone(),
_ => unreachable!(),
};
let private_key = PrivateKey::new(rng).unwrap();
let deployment_id = deployment.to_deployment_id().unwrap();
let program_owner = ProgramOwner::new(&private_key, deployment_id, rng).unwrap();
Rejected::new_deployment(program_owner, deployment)
}
pub fn sample_execution(rng: &mut TestRng) -> Execution<CurrentNetwork> {
let block = crate::sample_genesis_block(rng);
let transaction = block.transactions().iter().next().unwrap().deref().clone();
if let Transaction::Execute(_, execution, _) = transaction { execution } else { unreachable!() }
}
pub fn sample_rejected_execution(is_fee_private: bool, rng: &mut TestRng) -> Rejected<CurrentNetwork> {
let execution = match crate::sample_execution_transaction_with_fee(is_fee_private, rng) {
Transaction::Execute(_, execution, _) => execution,
_ => unreachable!(),
};
Rejected::new_execution(execution)
}
pub fn sample_fee_private_hardcoded(rng: &mut TestRng) -> Fee<CurrentNetwork> {
static INSTANCE: OnceCell<Fee<CurrentNetwork>> = OnceCell::new();
INSTANCE
.get_or_init(|| {
let deployment_or_execution_id = Field::rand(rng);
sample_fee_private(deployment_or_execution_id, rng)
})
.clone()
}
pub fn sample_fee_private(deployment_or_execution_id: Field<CurrentNetwork>, rng: &mut TestRng) -> Fee<CurrentNetwork> {
let (block, transaction, private_key) = crate::sample_genesis_block_and_components(rng);
let credits = transaction.records().next().unwrap().1.clone();
let credits = credits.decrypt(&private_key.try_into().unwrap()).unwrap();
let base_fee_in_microcredits = 10_000_000;
let priority_fee_in_microcredits = 1_000;
let process = Process::load().unwrap();
let authorization = process
.authorize_fee_private::<CurrentAleo, _>(
&private_key,
credits,
base_fee_in_microcredits,
priority_fee_in_microcredits,
deployment_or_execution_id,
rng,
)
.unwrap();
let (_, mut trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap();
let block_store = BlockStore::<CurrentNetwork, BlockMemory<_>>::open(None).unwrap();
block_store.insert(&FromStr::from_str(&block.to_string()).unwrap()).unwrap();
trace.prepare(Query::from(block_store)).unwrap();
let fee = trace.prove_fee::<CurrentAleo, _>(rng).unwrap();
Fee::from_str(&fee.to_string()).unwrap()
}
pub fn sample_fee_public_hardcoded(rng: &mut TestRng) -> Fee<CurrentNetwork> {
static INSTANCE: OnceCell<Fee<CurrentNetwork>> = OnceCell::new();
INSTANCE
.get_or_init(|| {
let deployment_or_execution_id = Field::rand(rng);
sample_fee_public(deployment_or_execution_id, rng)
})
.clone()
}
pub fn sample_fee_public(deployment_or_execution_id: Field<CurrentNetwork>, rng: &mut TestRng) -> Fee<CurrentNetwork> {
let (block, _, private_key) = crate::sample_genesis_block_and_components(rng);
let base_fee_in_microcredits = 10_000_000;
let priority_fee_in_microcredits = 1_000;
let process = Process::load().unwrap();
let authorization = process
.authorize_fee_public::<CurrentAleo, _>(
&private_key,
base_fee_in_microcredits,
priority_fee_in_microcredits,
deployment_or_execution_id,
rng,
)
.unwrap();
let (_, mut trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap();
let block_store = BlockStore::<CurrentNetwork, BlockMemory<_>>::open(None).unwrap();
block_store.insert(&FromStr::from_str(&block.to_string()).unwrap()).unwrap();
trace.prepare(Query::from(block_store)).unwrap();
let fee = trace.prove_fee::<CurrentAleo, _>(rng).unwrap();
Fee::from_str(&fee.to_string()).unwrap()
}
pub fn small_transaction_program() -> Program<CurrentNetwork> {
Program::from_str(
r"
program testing_small.aleo;
function small_transaction:
cast 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field into r0 as [field; 32u32];
cast r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 into r1 as [[field; 32u32]; 32u32];
cast r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 into r2 as [[field; 32u32]; 32u32];
cast r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 into r3 as [[field; 32u32]; 32u32];
output r1 as [[field; 32u32]; 32u32].public;
output r2 as [[field; 32u32]; 32u32].public;
output r3 as [[field; 32u32]; 32u32].public;").unwrap()
}
pub fn large_transaction_program() -> Program<CurrentNetwork> {
Program::from_str(
r"
program testing_large.aleo;
function large_transaction:
cast 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field into r0 as [field; 32u32];
cast r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 into r1 as [[field; 32u32]; 27u32];
cast r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 into r2 as [[field; 32u32]; 27u32];
cast r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 into r3 as [[field; 32u32]; 27u32];
cast r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 into r4 as [[field; 32u32]; 27u32];
output r1 as [[field; 32u32]; 27u32].public;
output r2 as [[field; 32u32]; 27u32].public;
output r3 as [[field; 32u32]; 27u32].public;
output r4 as [[field; 32u32]; 27u32].public;").unwrap()
}
pub fn sample_deployment_transaction(is_fee_private: bool, rng: &mut TestRng) -> Transaction<CurrentNetwork> {
let private_key = PrivateKey::new(rng).unwrap();
let deployment = crate::sample_deployment(rng);
let deployment_id = deployment.to_deployment_id().unwrap();
let owner = ProgramOwner::new(&private_key, deployment_id, rng).unwrap();
let fee = match is_fee_private {
true => crate::sample_fee_private(deployment_id, rng),
false => crate::sample_fee_public(deployment_id, rng),
};
Transaction::from_deployment(owner, deployment, fee).unwrap()
}
pub fn sample_execution_transaction_with_fee(is_fee_private: bool, rng: &mut TestRng) -> Transaction<CurrentNetwork> {
let execution = crate::sample_execution(rng);
let execution_id = execution.to_execution_id().unwrap();
let fee = match is_fee_private {
true => crate::sample_fee_private(execution_id, rng),
false => crate::sample_fee_public(execution_id, rng),
};
Transaction::from_execution(execution, Some(fee)).unwrap()
}
pub fn sample_large_execution_transaction(rng: &mut TestRng) -> Transaction<CurrentNetwork> {
static INSTANCE: once_cell::sync::OnceCell<Execution<CurrentNetwork>> = once_cell::sync::OnceCell::new();
let execution = INSTANCE
.get_or_init(|| {
let program = large_transaction_program();
let mut process = synthesizer_process::Process::load().unwrap();
process.add_program(&program).unwrap();
let private_key = PrivateKey::new(rng).unwrap();
let authorization = process
.authorize::<CurrentAleo, _>(
&private_key,
"testing_large.aleo",
"large_transaction",
Vec::<Value<CurrentNetwork>>::new().iter(),
rng,
)
.unwrap();
let (_, mut trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap();
let block_store =
ledger_store::BlockStore::<CurrentNetwork, ledger_store::helpers::memory::BlockMemory<_>>::open(None)
.unwrap();
trace.prepare(ledger_query::Query::from(block_store)).unwrap();
let execution = trace.prove_execution::<CurrentAleo, _>("testing.aleo", rng).unwrap();
Execution::from_bytes_le(&execution.to_bytes_le().unwrap()).unwrap()
})
.clone();
let execution_id = execution.to_execution_id().unwrap();
let fee = crate::sample_fee_public(execution_id, rng);
Transaction::from_execution(execution, Some(fee)).unwrap()
}
pub fn sample_fee_private_transaction(rng: &mut TestRng) -> Transaction<CurrentNetwork> {
let fee = crate::sample_fee_private_hardcoded(rng);
Transaction::from_fee(fee).unwrap()
}
pub fn sample_fee_public_transaction(rng: &mut TestRng) -> Transaction<CurrentNetwork> {
let fee = crate::sample_fee_public_hardcoded(rng);
Transaction::from_fee(fee).unwrap()
}
pub fn sample_block_transactions(rng: &mut TestRng) -> Transactions<CurrentNetwork> {
crate::sample_genesis_block(rng).transactions().clone()
}
pub fn sample_genesis_block(rng: &mut TestRng) -> Block<CurrentNetwork> {
let (block, _, _) = crate::sample_genesis_block_and_components(rng);
block
}
pub fn sample_genesis_block_and_transaction(rng: &mut TestRng) -> (Block<CurrentNetwork>, Transaction<CurrentNetwork>) {
let (block, transaction, _) = crate::sample_genesis_block_and_components(rng);
(block, transaction)
}
pub fn sample_genesis_block_and_components(
rng: &mut TestRng,
) -> (Block<CurrentNetwork>, Transaction<CurrentNetwork>, PrivateKey<CurrentNetwork>) {
static INSTANCE: OnceCell<(Block<CurrentNetwork>, Transaction<CurrentNetwork>, PrivateKey<CurrentNetwork>)> =
OnceCell::new();
INSTANCE.get_or_init(|| crate::sample_genesis_block_and_components_raw(rng)).clone()
}
fn sample_genesis_block_and_components_raw(
rng: &mut TestRng,
) -> (Block<CurrentNetwork>, Transaction<CurrentNetwork>, PrivateKey<CurrentNetwork>) {
let private_key = PrivateKey::new(rng).unwrap();
let address = Address::<CurrentNetwork>::try_from(private_key).unwrap();
let locator = ("credits.aleo", "transfer_public_to_private");
let amount = 100_000_000u64;
let inputs = [address.to_string(), format!("{amount}_u64")];
let process = Process::load().unwrap();
let authorization =
process.authorize::<CurrentAleo, _>(&private_key, locator.0, locator.1, inputs.iter(), rng).unwrap();
let (_, mut trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap();
let block_store = BlockStore::<CurrentNetwork, BlockMemory<_>>::open(None).unwrap();
trace.prepare(Query::from(block_store)).unwrap();
let execution = trace.prove_execution::<CurrentAleo, _>(locator.0, rng).unwrap();
let execution = Execution::from_str(&execution.to_string()).unwrap();
let transaction = Transaction::from_execution(execution, None).unwrap();
let confirmed = ConfirmedTransaction::accepted_execute(0, transaction.clone(), vec![]).unwrap();
let transactions = Transactions::from_iter([confirmed]);
let ratifications = Ratifications::try_from(vec![]).unwrap();
let header = Header::genesis(&ratifications, &transactions, vec![]).unwrap();
let previous_hash = <CurrentNetwork as Network>::BlockHash::default();
let block = Block::new_beacon(
&private_key,
previous_hash,
header,
ratifications,
None.into(),
vec![],
transactions,
vec![],
rng,
)
.unwrap();
assert!(block.header().is_genesis(), "Failed to initialize a genesis block");
(block, transaction, private_key)
}