use console::{
account::{Address, PrivateKey},
prelude::*,
program::{Ciphertext, Literal, Plaintext, ProgramOwner, Record},
types::Field,
};
use ledger_block::{
Block,
ConfirmedTransaction,
Deployment,
Execution,
Fee,
Header,
Input,
Output,
Ratifications,
Transaction,
Transactions,
Transition,
};
use ledger_query::Query;
use ledger_store::{helpers::memory::BlockMemory, BlockStore};
use synthesizer_process::Process;
use synthesizer_program::Program;
use once_cell::sync::OnceCell;
type CurrentNetwork = console::network::Testnet3;
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_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_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 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_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, transactions, vec![], rng).unwrap();
assert!(block.header().is_genesis(), "Failed to initialize a genesis block");
(block, transaction, private_key)
}