Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Test] This PR adds a test that shows record production/consumption behaviors in an external call. #2611

Open
wants to merge 2 commits into
base: staging
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
261 changes: 261 additions & 0 deletions ledger/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3143,3 +3143,264 @@ fn test_forged_block_subdags() {
assert!(ledger.check_next_block(&forged_block_2_from_both_subdags, &mut rand::thread_rng()).is_err());
}
}

#[test]
fn test_record_creation_and_consumption_in_call() {
let rng = &mut TestRng::default();

// Sample the test environment.
let crate::test_helpers::TestEnv { ledger, private_key, view_key, .. } = crate::test_helpers::sample_test_env(rng);

// A helper function to get the record counts.
let get_record_counts = || {
let slow_spent_filter = RecordsFilter::SlowSpent(private_key);
let slow_unspent_filter = RecordsFilter::SlowUnspent(private_key);
let spent_records = ledger.find_records(&view_key, RecordsFilter::Spent).unwrap().collect_vec().len();
let slow_spent_records = ledger.find_records(&view_key, slow_spent_filter).unwrap().collect_vec().len();
let unspent_records = ledger.find_records(&view_key, RecordsFilter::Unspent).unwrap().collect_vec().len();
let slow_unspent_records = ledger.find_records(&view_key, slow_unspent_filter).unwrap().collect_vec().len();
let records = ledger.records().collect_vec().len();
(spent_records, slow_spent_records, unspent_records, slow_unspent_records, records)
};

// Check the initial record counts.
let (
initial_spent_records,
initial_slow_spent_records,
initial_unspent_records,
initial_slow_unspent_records,
initial_records,
) = get_record_counts();
assert_eq!(0, initial_spent_records);
assert_eq!(0, initial_slow_spent_records);
assert_eq!(4, initial_unspent_records);
assert_eq!(4, initial_slow_unspent_records);
assert_eq!(4, initial_records);

// Initialize the two programs.
let program_0 = Program::from_str(
r"
program child.aleo;

record data:
owner as address.private;
val as u64.private;

function mint:
cast self.signer 0u64 into r0 as data.record;
output r0 as data.record;

function burn:
input r0 as data.record;
",
)
.unwrap();

let program_1 = Program::from_str(
r"
import child.aleo;

program parent.aleo;

function create_without_output:
call child.aleo/mint into r0;

function create:
call child.aleo/mint into r0;
output r0 as child.aleo/data.record;

function consume_without_call:
input r0 as child.aleo/data.record;

function consume:
input r0 as child.aleo/data.record;
call child.aleo/burn r0;

function create_and_consume:
call child.aleo/mint into r0;
call child.aleo/burn r0;
",
)
.unwrap();

// Deploy the programs.
let deployment_0 = ledger.vm().deploy(&private_key, &program_0, None, 0, None, rng).unwrap();
let block =
ledger.prepare_advance_to_next_beacon_block(&private_key, vec![], vec![], vec![deployment_0], rng).unwrap();
assert_eq!(block.transactions().num_accepted(), 1);
ledger.advance_to_next_block(&block).unwrap();

let deployment_1 = ledger.vm().deploy(&private_key, &program_1, None, 0, None, rng).unwrap();
let block =
ledger.prepare_advance_to_next_beacon_block(&private_key, vec![], vec![], vec![deployment_1], rng).unwrap();
assert_eq!(block.transactions().num_accepted(), 1);
ledger.advance_to_next_block(&block).unwrap();

// Call the `mint` function.
let transaction = ledger
.vm()
.execute(&private_key, ("child.aleo", "mint"), Vec::<Value<CurrentNetwork>>::new().iter(), None, 0, None, rng)
.unwrap();
let mint_record = transaction.records().last().unwrap().1.decrypt(&view_key).unwrap();
let block =
ledger.prepare_advance_to_next_beacon_block(&private_key, vec![], vec![], vec![transaction], rng).unwrap();
assert_eq!(block.transactions().num_accepted(), 1);
ledger.advance_to_next_block(&block).unwrap();

// Check the record counts.
let (num_spent_records, num_slow_spent_records, num_unspent_records, num_slow_unspent_records, num_records) =
get_record_counts();
assert_eq!(num_spent_records, initial_spent_records);
assert_eq!(num_slow_spent_records, initial_slow_spent_records);
assert_eq!(num_unspent_records, initial_unspent_records + 1);
assert_eq!(num_slow_unspent_records, initial_slow_unspent_records + 1);
assert_eq!(num_records, initial_records + 1);

// Call the `create_without_output` function.
let transaction = ledger
.vm()
.execute(
&private_key,
("parent.aleo", "create_without_output"),
Vec::<Value<CurrentNetwork>>::new().iter(),
None,
0,
None,
rng,
)
.unwrap();

let block =
ledger.prepare_advance_to_next_beacon_block(&private_key, vec![], vec![], vec![transaction], rng).unwrap();
assert_eq!(block.transactions().num_accepted(), 1);
ledger.advance_to_next_block(&block).unwrap();

// Check the record counts.
let (num_spent_records, num_slow_spent_records, num_unspent_records, num_slow_unspent_records, num_records) =
get_record_counts();
assert_eq!(num_spent_records, initial_spent_records);
assert_eq!(num_slow_spent_records, initial_slow_spent_records);
assert_eq!(num_unspent_records, initial_unspent_records + 2);
assert_eq!(num_slow_unspent_records, initial_slow_unspent_records + 2);
assert_eq!(num_records, initial_records + 2);

// Call the `burn` function on record created by `create_without_output`.
let record = block.records().collect_vec().last().unwrap().1.decrypt(&view_key).unwrap();
let transaction = ledger
.vm()
.execute(&private_key, ("child.aleo", "burn"), vec![Value::Record(record)].iter(), None, 0, None, rng)
.unwrap();
let block =
ledger.prepare_advance_to_next_beacon_block(&private_key, vec![], vec![], vec![transaction], rng).unwrap();
assert_eq!(block.transactions().num_accepted(), 1);
ledger.advance_to_next_block(&block).unwrap();

// Check the record counts.
let (num_spent_records, num_slow_spent_records, num_unspent_records, num_slow_unspent_records, num_records) =
get_record_counts();
assert_eq!(num_spent_records, initial_spent_records + 1);
assert_eq!(num_slow_spent_records, initial_slow_spent_records + 1);
assert_eq!(num_unspent_records, initial_unspent_records + 1);
assert_eq!(num_slow_unspent_records, initial_slow_unspent_records + 1);
assert_eq!(num_records, initial_records + 2);

// Call the `create` function.
let transaction = ledger
.vm()
.execute(
&private_key,
("parent.aleo", "create"),
Vec::<Value<CurrentNetwork>>::new().iter(),
None,
0,
None,
rng,
)
.unwrap();
let block =
ledger.prepare_advance_to_next_beacon_block(&private_key, vec![], vec![], vec![transaction], rng).unwrap();
assert_eq!(block.transactions().num_accepted(), 1);
ledger.advance_to_next_block(&block).unwrap();

// Ensure that a record was created and spent.
let (num_spent_records, num_slow_spent_records, num_unspent_records, num_slow_unspent_records, num_records) =
get_record_counts();
assert_eq!(num_spent_records, initial_spent_records + 1);
assert_eq!(num_slow_spent_records, initial_slow_spent_records + 1);
assert_eq!(num_unspent_records, initial_unspent_records + 2);
assert_eq!(num_slow_unspent_records, initial_slow_unspent_records + 2);
assert_eq!(num_records, initial_records + 3);

// Call the `consume_without_call` function.
let transaction = ledger
.vm()
.execute(
&private_key,
("parent.aleo", "consume_without_call"),
vec![Value::Record(mint_record.clone())].iter(),
None,
0,
None,
rng,
)
.unwrap();
let block =
ledger.prepare_advance_to_next_beacon_block(&private_key, vec![], vec![], vec![transaction], rng).unwrap();
assert_eq!(block.transactions().num_accepted(), 1);
ledger.advance_to_next_block(&block).unwrap();

// Ensure that no records were created or spent.
let (num_spent_records, num_slow_spent_records, num_unspent_records, num_slow_unspent_records, num_records) =
get_record_counts();
assert_eq!(num_spent_records, initial_spent_records + 1);
assert_eq!(num_slow_spent_records, initial_slow_spent_records + 1);
assert_eq!(num_unspent_records, initial_unspent_records + 2);
assert_eq!(num_slow_unspent_records, initial_slow_unspent_records + 2);
assert_eq!(num_records, initial_records + 3);

// Call the `consume` function.
let transaction = ledger
.vm()
.execute(&private_key, ("parent.aleo", "consume"), vec![Value::Record(mint_record)].iter(), None, 0, None, rng)
.unwrap();
let block =
ledger.prepare_advance_to_next_beacon_block(&private_key, vec![], vec![], vec![transaction], rng).unwrap();
assert_eq!(block.transactions().num_accepted(), 1);
ledger.advance_to_next_block(&block).unwrap();

// Ensure that the record was spent.
let (num_spent_records, num_slow_spent_records, num_unspent_records, num_slow_unspent_records, num_records) =
get_record_counts();
assert_eq!(num_spent_records, initial_spent_records + 2);
assert_eq!(num_slow_spent_records, initial_slow_spent_records + 2);
assert_eq!(num_unspent_records, initial_unspent_records + 1);
assert_eq!(num_slow_unspent_records, initial_slow_unspent_records + 1);
assert_eq!(num_records, initial_records + 3);

// Call the `create_and_consume` function.
let transaction = ledger
.vm()
.execute(
&private_key,
("parent.aleo", "create_and_consume"),
Vec::<Value<CurrentNetwork>>::new().iter(),
None,
0,
None,
rng,
)
.unwrap();
let block =
ledger.prepare_advance_to_next_beacon_block(&private_key, vec![], vec![], vec![transaction], rng).unwrap();
assert_eq!(block.transactions().num_accepted(), 1);
ledger.advance_to_next_block(&block).unwrap();

// Ensure that a record was created and spent.
let (num_spent_records, num_slow_spent_records, num_unspent_records, num_slow_unspent_records, num_records) =
get_record_counts();
assert_eq!(num_spent_records, initial_spent_records + 3);
assert_eq!(num_slow_spent_records, initial_slow_spent_records + 3);
assert_eq!(num_unspent_records, initial_unspent_records + 1);
assert_eq!(num_slow_unspent_records, initial_slow_unspent_records + 1);
assert_eq!(num_records, initial_records + 4);
}