use crate::Process;
use algorithms::snark::varuna::VarunaVersion;
use circuit::network::AleoV0;
use console::{
account::{Address, PrivateKey},
network::{MainnetV0, prelude::*},
program::{Identifier, Literal, Plaintext, ProgramID, Value},
types::U64,
};
use ledger_committee::{MIN_DELEGATOR_STAKE, MIN_VALIDATOR_SELF_STAKE, MIN_VALIDATOR_STAKE};
use ledger_query::Query;
use ledger_store::{
BlockStore,
FinalizeMode,
FinalizeStorage,
FinalizeStore,
atomic_finalize,
helpers::memory::{BlockMemory, FinalizeMemory},
};
use synthesizer_program::{FinalizeGlobalState, FinalizeStoreTrait, Program};
use aleo_std::StorageMode;
use indexmap::IndexMap;
type CurrentNetwork = MainnetV0;
type CurrentAleo = AleoV0;
const NUM_BLOCKS_TO_UNLOCK: u32 = 360;
const TEST_COMMISSION: u8 = 5;
macro_rules! sample_finalize_store {
() => {{
#[cfg(feature = "rocks")]
let store = FinalizeStore::<CurrentNetwork, ledger_store::helpers::rocksdb::FinalizeDB<_>>::open(
std::sync::Arc::new(tempfile::tempdir().expect("Failed to open temporary directory")),
)
.unwrap();
#[cfg(not(feature = "rocks"))]
let store =
FinalizeStore::<CurrentNetwork, FinalizeMemory<_>>::open(aleo_std::StorageMode::new_test(None)).unwrap();
store
}};
}
macro_rules! test_atomic_finalize {
($store:ident, $mode:expr, $test:block) => {{
let mut run = || -> Result<()> { atomic_finalize!($store, $mode, $test) };
run()
}};
}
fn sample_finalize_state(block_height: u32) -> FinalizeGlobalState {
FinalizeGlobalState::from(block_height as u64, block_height, [0u8; 32])
}
fn get_mapping_value<N: Network, F: FinalizeStorage<N>>(
store: &FinalizeStore<N, F>,
program_id: &str,
mapping: &str,
key: Literal<N>,
) -> Result<Option<Value<N>>> {
let program_id = ProgramID::from_str(program_id)?;
let mapping = Identifier::from_str(mapping)?;
let key = Plaintext::from(key);
match store.get_value_speculative(program_id, mapping, &key) {
Ok(result) => Ok(result),
Err(err) => bail!("Error getting value for program_id: {program_id}, mapping: {mapping}, key: {key}: {err}"),
}
}
fn account_balance<N: Network, F: FinalizeStorage<N>>(
store: &FinalizeStore<N, F>,
address: &Address<N>,
) -> Result<u64> {
match get_mapping_value(store, "credits.aleo", "account", Literal::Address(*address))? {
Some(Value::Plaintext(Plaintext::Literal(Literal::U64(balance), _))) => Ok(*balance),
_ => bail!("Missing or malformed account balance for {address}"),
}
}
fn committee_state<N: Network, F: FinalizeStorage<N>>(
store: &FinalizeStore<N, F>,
address: &Address<N>,
) -> Result<Option<(u64, bool, u8)>> {
let committee_state = match get_mapping_value(store, "credits.aleo", "committee", Literal::Address(*address))? {
Some(Value::Plaintext(Plaintext::Struct(state, _))) => state,
None => return Ok(None),
_ => bail!("Malformed committee state for {address}"),
};
let staked_microcredits = match get_mapping_value(store, "credits.aleo", "delegated", Literal::Address(*address))? {
Some(Value::Plaintext(Plaintext::Literal(Literal::U64(microcredits), _))) => microcredits,
None => return Ok(None),
_ => bail!("Malformed delegate state for {address}"),
};
let commission = match committee_state.get(&Identifier::from_str("commission")?) {
Some(Plaintext::Literal(Literal::U8(commission), _)) => **commission,
_ => bail!("`commission` not found for: {address}"),
};
let is_open = match committee_state.get(&Identifier::from_str("is_open")?) {
Some(Plaintext::Literal(Literal::Boolean(is_open), _)) => **is_open,
_ => bail!("`is_open` not found for: {address}"),
};
Ok(Some((*staked_microcredits, is_open, commission)))
}
fn delegated_state<N: Network, F: FinalizeStorage<N>>(
store: &FinalizeStore<N, F>,
address: &Address<N>,
) -> Result<Option<u64>> {
let state = match get_mapping_value(store, "credits.aleo", "delegated", Literal::Address(*address))? {
Some(Value::Plaintext(Plaintext::Literal(Literal::U64(microcredits), _))) => microcredits,
None => return Ok(None),
_ => bail!("Malformed delegate state for {address}"),
};
Ok(Some(*state))
}
fn bond_state<N: Network, F: FinalizeStorage<N>>(
store: &FinalizeStore<N, F>,
address: &Address<N>,
) -> Result<Option<(Address<N>, u64)>> {
let state = match get_mapping_value(store, "credits.aleo", "bonded", Literal::Address(*address))? {
Some(Value::Plaintext(Plaintext::Struct(state, _))) => state,
None => return Ok(None),
_ => bail!("Malformed bond state for {address}"),
};
let validator = match state.get(&Identifier::from_str("validator")?) {
Some(Plaintext::Literal(Literal::Address(address), _)) => *address,
_ => bail!("`validator` not found for: {address}"),
};
let microcredits = match state.get(&Identifier::from_str("microcredits")?) {
Some(Plaintext::Literal(Literal::U64(microcredits), _)) => **microcredits,
_ => bail!("`microcredits` not found for: {address}"),
};
Ok(Some((validator, microcredits)))
}
fn unbond_state<N: Network, F: FinalizeStorage<N>>(
store: &FinalizeStore<N, F>,
address: &Address<N>,
) -> Result<Option<(u64, u32)>> {
let state = match get_mapping_value(store, "credits.aleo", "unbonding", Literal::Address(*address))? {
Some(Value::Plaintext(Plaintext::Struct(state, _))) => state,
None => return Ok(None),
_ => bail!("Malformed unbond state for {address}"),
};
let microcredits = match state.get(&Identifier::from_str("microcredits")?) {
Some(Plaintext::Literal(Literal::U64(microcredits), _)) => **microcredits,
_ => bail!("`microcredits` not found for: {address}"),
};
let height = match state.get(&Identifier::from_str("height")?) {
Some(Plaintext::Literal(Literal::U32(height), _)) => **height,
_ => bail!("`height` not found for: {address}"),
};
Ok(Some((microcredits, height)))
}
fn withdraw_state<N: Network, F: FinalizeStorage<N>>(
store: &FinalizeStore<N, F>,
address: &Address<N>,
) -> Result<Option<Address<N>>> {
let withdrawal_address = match get_mapping_value(store, "credits.aleo", "withdraw", Literal::Address(*address))? {
Some(Value::Plaintext(Plaintext::Literal(Literal::Address(withdrawal_address), _))) => withdrawal_address,
None => return Ok(None),
_ => bail!("Malformed withdraw state for {address}"),
};
Ok(Some(withdrawal_address))
}
fn initialize_account<N: Network, F: FinalizeStorage<N>>(
finalize_store: &FinalizeStore<N, F>,
address: &Address<N>,
balance: u64,
) -> Result<()> {
let program = Program::<N>::credits()?;
for mapping in program.mappings().values() {
if !finalize_store.contains_mapping_confirmed(program.id(), mapping.name())? {
finalize_store.initialize_mapping(*program.id(), *mapping.name())?;
}
}
let key = Plaintext::from(Literal::Address(*address));
let value = Value::from(Literal::U64(U64::new(balance)));
finalize_store.insert_key_value(
ProgramID::from_str("credits.aleo")?,
Identifier::from_str("account")?,
key,
value,
)?;
assert_eq!(balance, account_balance(finalize_store, address).unwrap());
Ok(())
}
fn initialize_stakers<N: Network, F: FinalizeStorage<N>>(
finalize_store: &FinalizeStore<N, F>,
num_validators: u32,
num_delegators: u32,
rng: &mut TestRng,
) -> Result<(
IndexMap<PrivateKey<N>, (Address<N>, u64, PrivateKey<N>, Address<N>)>,
IndexMap<PrivateKey<N>, (Address<N>, u64)>,
)> {
let program = Program::<N>::credits()?;
for mapping in program.mappings().values() {
if !finalize_store.contains_mapping_confirmed(program.id(), mapping.name())? {
finalize_store.initialize_mapping(*program.id(), *mapping.name())?;
}
}
let mapping = Identifier::from_str("account")?;
let mut validators: IndexMap<_, _> = Default::default();
let mut delegators: IndexMap<_, _> = Default::default();
for i in 0..(num_validators + num_delegators) {
let private_key = PrivateKey::<N>::new(rng)?;
let address = Address::try_from(&private_key)?;
let balance = 100_000_000_000_000u64;
let key = Plaintext::from(Literal::Address(address));
let value = Value::from(Literal::U64(U64::new(balance)));
finalize_store.insert_key_value(*program.id(), mapping, key, value)?;
assert_eq!(balance, account_balance(finalize_store, &address).unwrap());
if i < num_validators {
let withdrawal_private_key = PrivateKey::<N>::new(rng)?;
let withdrawal_address = Address::try_from(&withdrawal_private_key)?;
validators.insert(private_key, (address, balance, withdrawal_private_key, withdrawal_address));
} else {
delegators.insert(private_key, (address, balance));
}
}
Ok((validators, delegators))
}
fn execute_function<F: FinalizeStorage<CurrentNetwork>>(
process: &Process<CurrentNetwork>,
finalize_store: &FinalizeStore<CurrentNetwork, F>,
caller_private_key: &PrivateKey<CurrentNetwork>,
function: &str,
inputs: &[String],
block_height: Option<u32>,
rng: &mut TestRng,
) -> Result<()> {
let authorization =
process.authorize::<CurrentAleo, _>(caller_private_key, "credits.aleo", function, inputs.iter(), rng)?;
let (_, mut trace) = process.execute::<CurrentAleo, _>(authorization, rng)?;
let block_store = BlockStore::<CurrentNetwork, BlockMemory<_>>::open(StorageMode::new_test(None))?;
trace.prepare(Query::from(&block_store))?;
let execution = trace.prove_execution::<CurrentAleo, _>(function, VarunaVersion::V1, rng)?;
let block_height = block_height.unwrap_or(1);
process.finalize_execution(sample_finalize_state(block_height), finalize_store, &execution, None)?;
Ok(())
}
fn bond_validator<F: FinalizeStorage<CurrentNetwork>>(
process: &Process<CurrentNetwork>,
finalize_store: &FinalizeStore<CurrentNetwork, F>,
caller_private_key: &PrivateKey<CurrentNetwork>,
withdrawal_address: &Address<CurrentNetwork>,
amount: u64,
commission: u8,
rng: &mut TestRng,
) -> Result<()> {
execute_function(
process,
finalize_store,
caller_private_key,
"bond_validator",
&[withdrawal_address.to_string(), format!("{amount}_u64"), format!("{commission}_u8")],
None,
rng,
)
}
fn bond_public<F: FinalizeStorage<CurrentNetwork>>(
process: &Process<CurrentNetwork>,
finalize_store: &FinalizeStore<CurrentNetwork, F>,
caller_private_key: &PrivateKey<CurrentNetwork>,
validator_address: &Address<CurrentNetwork>,
withdrawal_address: &Address<CurrentNetwork>,
amount: u64,
rng: &mut TestRng,
) -> Result<()> {
execute_function(
process,
finalize_store,
caller_private_key,
"bond_public",
&[validator_address.to_string(), withdrawal_address.to_string(), format!("{amount}_u64")],
None,
rng,
)
}
fn unbond_public<F: FinalizeStorage<CurrentNetwork>>(
process: &Process<CurrentNetwork>,
finalize_store: &FinalizeStore<CurrentNetwork, F>,
caller_private_key: &PrivateKey<CurrentNetwork>,
address: &Address<CurrentNetwork>,
amount: u64,
block_height: u32,
rng: &mut TestRng,
) -> Result<()> {
execute_function(
process,
finalize_store,
caller_private_key,
"unbond_public",
&[address.to_string(), format!("{amount}_u64")],
Some(block_height),
rng,
)
}
fn set_validator_state<F: FinalizeStorage<CurrentNetwork>>(
process: &Process<CurrentNetwork>,
finalize_store: &FinalizeStore<CurrentNetwork, F>,
caller_private_key: &PrivateKey<CurrentNetwork>,
is_open: bool,
rng: &mut TestRng,
) -> Result<()> {
execute_function(
process,
finalize_store,
caller_private_key,
"set_validator_state",
&[format!("{is_open}")],
None,
rng,
)
}
fn claim_unbond_public<F: FinalizeStorage<CurrentNetwork>>(
process: &Process<CurrentNetwork>,
finalize_store: &FinalizeStore<CurrentNetwork, F>,
caller_private_key: &PrivateKey<CurrentNetwork>,
address: &Address<CurrentNetwork>,
block_height: u32,
rng: &mut TestRng,
) -> Result<()> {
execute_function(
process,
finalize_store,
caller_private_key,
"claim_unbond_public",
&[address.to_string()],
Some(block_height),
rng,
)
}
#[test]
fn test_credits_program_id_simple() {
let program = Program::<CurrentNetwork>::credits().unwrap();
assert_eq!(program.id().to_string(), "credits.aleo");
}
#[test]
fn test_bond_validator_simple() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let store = sample_finalize_store!();
let (validators, _) = initialize_stakers(&store, 1, 0, rng).unwrap();
let (validator_private_key, (validator_address, _, _, withdrawal_address)) = validators.first().unwrap();
let public_balance = account_balance(&store, validator_address).unwrap();
let amount = MIN_VALIDATOR_STAKE;
assert_eq!(committee_state(&store, validator_address).unwrap(), None);
assert_eq!(delegated_state(&store, validator_address).unwrap(), None);
assert_eq!(bond_state(&store, validator_address).unwrap(), None);
assert_eq!(unbond_state(&store, validator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, validator_address).unwrap(), None);
assert_eq!(account_balance(&store, validator_address).unwrap(), public_balance);
test_atomic_finalize!(store, FinalizeMode::RealRun, {
bond_validator(&process, &store, validator_private_key, withdrawal_address, amount, TEST_COMMISSION, rng)
.unwrap();
assert_eq!(committee_state(&store, validator_address).unwrap(), Some((amount, true, TEST_COMMISSION)));
assert_eq!(delegated_state(&store, validator_address).unwrap(), Some(amount));
assert_eq!(bond_state(&store, validator_address).unwrap(), Some((*validator_address, amount)));
assert_eq!(unbond_state(&store, validator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
assert_eq!(account_balance(&store, validator_address).unwrap(), public_balance - amount);
Ok(())
})
.unwrap();
assert_eq!(committee_state(&store, validator_address).unwrap(), Some((amount, true, TEST_COMMISSION)));
assert_eq!(delegated_state(&store, validator_address).unwrap(), Some(amount));
assert_eq!(bond_state(&store, validator_address).unwrap(), Some((*validator_address, amount)));
assert_eq!(unbond_state(&store, validator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
assert_eq!(account_balance(&store, validator_address).unwrap(), public_balance - amount);
}
#[test]
fn test_bond_public_with_minimum_bond() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let store = sample_finalize_store!();
let validator_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
let validator_address = Address::try_from(&validator_private_key).unwrap();
let withdrawal_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
let withdrawal_address = Address::try_from(&withdrawal_private_key).unwrap();
let delegator_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
let delegator_address = Address::try_from(&delegator_private_key).unwrap();
let validator_balance = 1_000_000_000u64; let delegator_balance = 100_000_000_000_000u64;
initialize_account(&store, &validator_address, validator_balance).unwrap();
initialize_account(&store, &delegator_address, delegator_balance).unwrap();
let delegator_amount = MIN_VALIDATOR_STAKE - MIN_VALIDATOR_SELF_STAKE;
let validator_amount = MIN_VALIDATOR_SELF_STAKE;
assert_eq!(committee_state(&store, &validator_address).unwrap(), None);
assert_eq!(delegated_state(&store, &validator_address).unwrap(), None);
assert_eq!(bond_state(&store, &validator_address).unwrap(), None);
assert_eq!(unbond_state(&store, &validator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, &validator_address).unwrap(), None);
assert_eq!(account_balance(&store, &validator_address).unwrap(), validator_balance);
assert_eq!(account_balance(&store, &delegator_address).unwrap(), delegator_balance);
test_atomic_finalize!(store, FinalizeMode::RealRun, {
bond_public(
&process,
&store,
&delegator_private_key,
&validator_address,
&delegator_address,
delegator_amount,
rng,
)
.unwrap();
assert_eq!(committee_state(&store, &validator_address).unwrap(), None);
assert_eq!(delegated_state(&store, &validator_address).unwrap(), Some(delegator_amount));
assert_eq!(bond_state(&store, &delegator_address).unwrap(), Some((validator_address, delegator_amount)));
assert_eq!(unbond_state(&store, &validator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, &delegator_address).unwrap(), Some(delegator_address));
assert_eq!(account_balance(&store, &delegator_address).unwrap(), delegator_balance - delegator_amount);
bond_validator(
&process,
&store,
&validator_private_key,
&withdrawal_address,
validator_amount,
TEST_COMMISSION,
rng,
)
.unwrap();
assert_eq!(
committee_state(&store, &validator_address).unwrap(),
Some((validator_amount + delegator_amount, true, TEST_COMMISSION))
);
assert_eq!(delegated_state(&store, &validator_address).unwrap(), Some(validator_amount + delegator_amount));
assert_eq!(bond_state(&store, &delegator_address).unwrap(), Some((validator_address, delegator_amount)));
assert_eq!(unbond_state(&store, &validator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, &validator_address).unwrap(), Some(withdrawal_address));
assert_eq!(withdraw_state(&store, &delegator_address).unwrap(), Some(delegator_address));
assert_eq!(account_balance(&store, &delegator_address).unwrap(), delegator_balance - delegator_amount);
assert_eq!(account_balance(&store, &validator_address).unwrap(), validator_balance - validator_amount);
Ok(())
})
.unwrap();
}
#[test]
fn test_bond_validator_below_min_stake_fails() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let store = sample_finalize_store!();
let (validators, _) = initialize_stakers(&store, 1, 0, rng).unwrap();
let (validator_private_key, (validator_address, _, _, withdrawal_address)) = validators.first().unwrap();
let public_balance = account_balance(&store, validator_address).unwrap();
test_atomic_finalize!(store, FinalizeMode::RealRun, {
let amount = rng.gen_range(1_000_000..MIN_VALIDATOR_STAKE);
let result =
bond_validator(&process, &store, validator_private_key, withdrawal_address, amount, TEST_COMMISSION, rng);
assert!(result.is_err());
assert_eq!(committee_state(&store, validator_address).unwrap(), None);
assert_eq!(bond_state(&store, validator_address).unwrap(), None);
assert_eq!(unbond_state(&store, validator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, validator_address).unwrap(), None);
assert_eq!(account_balance(&store, validator_address).unwrap(), public_balance);
Ok(())
})
.unwrap();
}
#[test]
fn test_bond_validator_same_withdrawal_address_fails() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let store = sample_finalize_store!();
let (validators, _) = initialize_stakers(&store, 1, 0, rng).unwrap();
let (validator_private_key, (validator_address, _, _, _)) = validators.first().unwrap();
let public_balance = account_balance(&store, validator_address).unwrap();
test_atomic_finalize!(store, FinalizeMode::RealRun, {
let amount = MIN_VALIDATOR_STAKE;
let result =
bond_validator(&process, &store, validator_private_key, validator_address, amount, TEST_COMMISSION, rng);
assert!(result.is_err());
assert_eq!(committee_state(&store, validator_address).unwrap(), None);
assert_eq!(bond_state(&store, validator_address).unwrap(), None);
assert_eq!(unbond_state(&store, validator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, validator_address).unwrap(), None);
assert_eq!(account_balance(&store, validator_address).unwrap(), public_balance);
Ok(())
})
.unwrap();
}
#[test]
fn test_bond_validator_with_insufficient_funds_fails() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let store = sample_finalize_store!();
let (validators, _) = initialize_stakers(&store, 1, 0, rng).unwrap();
let (validator_private_key, (validator_address, _, _, withdrawal_address)) = validators.first().unwrap();
let public_balance = account_balance(&store, validator_address).unwrap();
test_atomic_finalize!(store, FinalizeMode::RealRun, {
let amount = public_balance + 1;
let result =
bond_validator(&process, &store, validator_private_key, withdrawal_address, amount, TEST_COMMISSION, rng);
assert!(result.is_err());
assert_eq!(committee_state(&store, validator_address).unwrap(), None);
assert_eq!(delegated_state(&store, validator_address).unwrap(), None);
assert_eq!(bond_state(&store, validator_address).unwrap(), None);
assert_eq!(unbond_state(&store, validator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, validator_address).unwrap(), None);
assert_eq!(account_balance(&store, validator_address).unwrap(), public_balance);
Ok(())
})
.unwrap();
}
#[test]
fn test_bond_validator_different_commission_fails() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let store = sample_finalize_store!();
let (validators, _) = initialize_stakers(&store, 1, 0, rng).unwrap();
let (validator_private_key, (validator_address, _, _, withdrawal_address)) = validators.first().unwrap();
let public_balance = account_balance(&store, validator_address).unwrap();
test_atomic_finalize!(store, FinalizeMode::RealRun, {
let amount = MIN_VALIDATOR_STAKE;
assert!(amount < public_balance);
bond_validator(&process, &store, validator_private_key, withdrawal_address, amount, TEST_COMMISSION, rng)
.unwrap();
assert_eq!(committee_state(&store, validator_address).unwrap(), Some((amount, true, TEST_COMMISSION)));
assert_eq!(delegated_state(&store, validator_address).unwrap(), Some(amount));
assert_eq!(bond_state(&store, validator_address).unwrap(), Some((*validator_address, amount)));
assert_eq!(unbond_state(&store, validator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
let public_balance_1 = account_balance(&store, validator_address).unwrap();
assert_eq!(public_balance_1, public_balance - amount);
let amount = MIN_VALIDATOR_STAKE;
assert!(amount < public_balance);
let result = bond_validator(
&process,
&store,
validator_private_key,
withdrawal_address,
amount,
TEST_COMMISSION + 1,
rng,
);
assert!(result.is_err());
assert_eq!(committee_state(&store, validator_address).unwrap(), Some((amount, true, TEST_COMMISSION)));
assert_eq!(delegated_state(&store, validator_address).unwrap(), Some(amount));
assert_eq!(bond_state(&store, validator_address).unwrap(), Some((*validator_address, amount)));
assert_eq!(unbond_state(&store, validator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
let public_balance_2 = account_balance(&store, validator_address).unwrap();
assert_eq!(public_balance_2, public_balance - amount);
Ok(())
})
.unwrap();
}
#[test]
fn test_bond_validator_multiple_bonds() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let store = sample_finalize_store!();
let (validators, _) = initialize_stakers(&store, 1, 0, rng).unwrap();
let (validator_private_key, (validator_address, _, _, withdrawal_address)) = validators.first().unwrap();
let public_balance = account_balance(&store, validator_address).unwrap();
test_atomic_finalize!(store, FinalizeMode::RealRun, {
let amount = MIN_VALIDATOR_STAKE;
assert!(amount < public_balance);
bond_validator(&process, &store, validator_private_key, withdrawal_address, amount, TEST_COMMISSION, rng)
.unwrap();
assert_eq!(committee_state(&store, validator_address).unwrap(), Some((amount, true, TEST_COMMISSION)));
assert_eq!(delegated_state(&store, validator_address).unwrap(), Some(amount));
assert_eq!(bond_state(&store, validator_address).unwrap(), Some((*validator_address, amount)));
assert_eq!(unbond_state(&store, validator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
let public_balance_1 = account_balance(&store, validator_address).unwrap();
assert_eq!(public_balance_1, public_balance - amount);
let amount = MIN_VALIDATOR_STAKE;
assert!(amount < public_balance_1);
bond_validator(&process, &store, validator_private_key, withdrawal_address, amount, TEST_COMMISSION, rng)
.unwrap();
assert_eq!(committee_state(&store, validator_address).unwrap(), Some((amount * 2, true, TEST_COMMISSION)));
assert_eq!(delegated_state(&store, validator_address).unwrap(), Some(amount * 2));
assert_eq!(bond_state(&store, validator_address).unwrap(), Some((*validator_address, amount * 2)));
assert_eq!(unbond_state(&store, validator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
let public_balance_2 = account_balance(&store, validator_address).unwrap();
assert_eq!(public_balance_2, public_balance_1 - amount);
Ok(())
})
.unwrap();
}
#[test]
fn test_bond_validator_to_other_validator_fails() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let store = sample_finalize_store!();
let (validators, _) = initialize_stakers(&store, 2, 0, rng).unwrap();
let mut validators = validators.into_iter();
let (validator_private_key_1, (validator_address_1, _, _, withdrawal_address_1)) = validators.next().unwrap();
let (validator_private_key_2, (validator_address_2, _, _, withdrawal_address_2)) = validators.next().unwrap();
test_atomic_finalize!(store, FinalizeMode::RealRun, {
let public_balance_1 = account_balance(&store, &validator_address_1).unwrap();
let public_balance_2 = account_balance(&store, &validator_address_2).unwrap();
let amount = MIN_VALIDATOR_STAKE;
bond_validator(&process, &store, &validator_private_key_1, &withdrawal_address_1, amount, TEST_COMMISSION, rng)
.unwrap();
assert_eq!(committee_state(&store, &validator_address_1).unwrap(), Some((amount, true, TEST_COMMISSION)));
assert_eq!(committee_state(&store, &validator_address_2).unwrap(), None);
assert_eq!(delegated_state(&store, &validator_address_1).unwrap(), Some(amount));
assert_eq!(delegated_state(&store, &validator_address_2).unwrap(), None);
assert_eq!(bond_state(&store, &validator_address_1).unwrap(), Some((validator_address_1, amount)));
assert_eq!(bond_state(&store, &validator_address_2).unwrap(), None);
assert_eq!(unbond_state(&store, &validator_address_1).unwrap(), None);
assert_eq!(unbond_state(&store, &validator_address_2).unwrap(), None);
assert_eq!(withdraw_state(&store, &validator_address_1).unwrap(), Some(withdrawal_address_1));
assert_eq!(withdraw_state(&store, &validator_address_2).unwrap(), None);
assert_eq!(account_balance(&store, &validator_address_1).unwrap(), public_balance_1 - amount);
assert_eq!(account_balance(&store, &validator_address_2).unwrap(), public_balance_2);
let amount = MIN_VALIDATOR_STAKE;
bond_validator(&process, &store, &validator_private_key_2, &withdrawal_address_2, amount, TEST_COMMISSION, rng)
.unwrap();
assert_eq!(committee_state(&store, &validator_address_1).unwrap(), Some((amount, true, TEST_COMMISSION)));
assert_eq!(committee_state(&store, &validator_address_2).unwrap(), Some((amount, true, TEST_COMMISSION)));
assert_eq!(delegated_state(&store, &validator_address_1).unwrap(), Some(amount));
assert_eq!(delegated_state(&store, &validator_address_2).unwrap(), Some(amount));
assert_eq!(bond_state(&store, &validator_address_1).unwrap(), Some((validator_address_1, amount)));
assert_eq!(bond_state(&store, &validator_address_2).unwrap(), Some((validator_address_2, amount)));
assert_eq!(unbond_state(&store, &validator_address_1).unwrap(), None);
assert_eq!(unbond_state(&store, &validator_address_2).unwrap(), None);
assert_eq!(withdraw_state(&store, &validator_address_1).unwrap(), Some(withdrawal_address_1));
assert_eq!(withdraw_state(&store, &validator_address_2).unwrap(), Some(withdrawal_address_2));
assert_eq!(account_balance(&store, &validator_address_1).unwrap(), public_balance_1 - amount);
assert_eq!(account_balance(&store, &validator_address_2).unwrap(), public_balance_2 - amount);
assert!(public_balance_1 > 2 * amount, "There is not enough balance to bond to another validator.");
let result = bond_public(
&process,
&store,
&validator_private_key_1,
&validator_address_2,
&validator_address_1,
amount,
rng,
);
assert!(result.is_err());
Ok(())
})
.unwrap();
}
#[test]
fn test_bond_delegator_simple() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let store = sample_finalize_store!();
let (validators, delegators) = initialize_stakers(&store, 1, 1, rng).unwrap();
let (validator_private_key, (validator_address, _, _, withdrawal_address)) = validators.first().unwrap();
let (delegator_private_key, (delegator_address, _)) = delegators.first().unwrap();
let validator_balance = account_balance(&store, validator_address).unwrap();
let delegator_balance = account_balance(&store, delegator_address).unwrap();
let validator_amount = MIN_VALIDATOR_STAKE;
bond_validator(&process, &store, validator_private_key, withdrawal_address, validator_amount, TEST_COMMISSION, rng)
.unwrap();
let delegator_amount = MIN_DELEGATOR_STAKE;
test_atomic_finalize!(store, FinalizeMode::RealRun, {
bond_public(
&process,
&store,
delegator_private_key,
validator_address,
delegator_address,
delegator_amount,
rng,
)
.unwrap();
let combined_amount = validator_amount + delegator_amount;
assert_eq!(committee_state(&store, validator_address).unwrap(), Some((combined_amount, true, TEST_COMMISSION)));
assert_eq!(committee_state(&store, delegator_address).unwrap(), None);
assert_eq!(bond_state(&store, validator_address).unwrap(), Some((*validator_address, validator_amount)));
assert_eq!(bond_state(&store, delegator_address).unwrap(), Some((*validator_address, delegator_amount)));
assert_eq!(unbond_state(&store, validator_address).unwrap(), None);
assert_eq!(unbond_state(&store, delegator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
assert_eq!(withdraw_state(&store, delegator_address).unwrap(), Some(*delegator_address));
assert_eq!(account_balance(&store, validator_address).unwrap(), validator_balance - validator_amount);
assert_eq!(account_balance(&store, delegator_address).unwrap(), delegator_balance - delegator_amount);
Ok(())
})
.unwrap();
assert_eq!(account_balance(&store, delegator_address).unwrap(), delegator_balance - delegator_amount);
}
#[test]
fn test_bond_delegator_below_min_stake_fails() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let store = sample_finalize_store!();
let (validators, delegators) = initialize_stakers(&store, 1, 1, rng).unwrap();
let (validator_private_key, (validator_address, _, _, withdrawal_address)) = validators.first().unwrap();
let (delegator_private_key, (delegator_address, _)) = delegators.first().unwrap();
let validator_balance = account_balance(&store, validator_address).unwrap();
let delegator_balance = account_balance(&store, delegator_address).unwrap();
test_atomic_finalize!(store, FinalizeMode::RealRun, {
let validator_amount = MIN_VALIDATOR_STAKE;
bond_validator(
&process,
&store,
validator_private_key,
withdrawal_address,
validator_amount,
TEST_COMMISSION,
rng,
)
.unwrap();
let delegator_amount = rng.gen_range(1_000_000..MIN_DELEGATOR_STAKE);
let result = bond_public(
&process,
&store,
delegator_private_key,
validator_address,
delegator_address,
delegator_amount,
rng,
);
assert!(result.is_err());
assert_eq!(
committee_state(&store, validator_address).unwrap(),
Some((validator_amount, true, TEST_COMMISSION))
);
assert_eq!(committee_state(&store, delegator_address).unwrap(), None);
assert_eq!(bond_state(&store, validator_address).unwrap(), Some((*validator_address, validator_amount)));
assert_eq!(bond_state(&store, delegator_address).unwrap(), None);
assert_eq!(unbond_state(&store, validator_address).unwrap(), None);
assert_eq!(unbond_state(&store, delegator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
assert_eq!(withdraw_state(&store, delegator_address).unwrap(), None);
assert_eq!(account_balance(&store, validator_address).unwrap(), validator_balance - validator_amount);
assert_eq!(account_balance(&store, delegator_address).unwrap(), delegator_balance);
Ok(())
})
.unwrap();
}
#[test]
fn test_bond_delegator_with_insufficient_funds_fails() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let store = sample_finalize_store!();
let (validators, delegators) = initialize_stakers(&store, 1, 1, rng).unwrap();
let (validator_private_key, (validator_address, _, _, withdrawal_address)) = validators.first().unwrap();
let (delegator_private_key, (delegator_address, _)) = delegators.first().unwrap();
let validator_balance = account_balance(&store, validator_address).unwrap();
let delegator_balance = account_balance(&store, delegator_address).unwrap();
test_atomic_finalize!(store, FinalizeMode::RealRun, {
let validator_amount = MIN_VALIDATOR_STAKE;
bond_validator(
&process,
&store,
validator_private_key,
withdrawal_address,
validator_amount,
TEST_COMMISSION,
rng,
)
.unwrap();
let delegator_amount = delegator_balance + 1;
let result = bond_public(
&process,
&store,
delegator_private_key,
withdrawal_address,
delegator_address,
delegator_amount,
rng,
);
assert!(result.is_err());
assert_eq!(
committee_state(&store, validator_address).unwrap(),
Some((validator_amount, true, TEST_COMMISSION))
);
assert_eq!(committee_state(&store, delegator_address).unwrap(), None);
assert_eq!(bond_state(&store, validator_address).unwrap(), Some((*validator_address, validator_amount)));
assert_eq!(bond_state(&store, delegator_address).unwrap(), None);
assert_eq!(unbond_state(&store, validator_address).unwrap(), None);
assert_eq!(unbond_state(&store, delegator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
assert_eq!(withdraw_state(&store, delegator_address).unwrap(), None);
assert_eq!(account_balance(&store, validator_address).unwrap(), validator_balance - validator_amount);
assert_eq!(account_balance(&store, delegator_address).unwrap(), delegator_balance);
Ok(())
})
.unwrap();
}
#[test]
fn test_bond_delegator_multiple_bonds() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let store = sample_finalize_store!();
let (validators, delegators) = initialize_stakers(&store, 1, 1, rng).unwrap();
let (validator_private_key, (validator_address, _, _, withdrawal_address)) = validators.first().unwrap();
let (delegator_private_key, (delegator_address, _)) = delegators.first().unwrap();
let validator_balance = account_balance(&store, validator_address).unwrap();
let delegator_balance = account_balance(&store, delegator_address).unwrap();
let validator_amount = MIN_VALIDATOR_STAKE;
bond_validator(&process, &store, validator_private_key, withdrawal_address, validator_amount, TEST_COMMISSION, rng)
.unwrap();
test_atomic_finalize!(store, FinalizeMode::RealRun, {
let delegator_amount = MIN_DELEGATOR_STAKE;
assert!(delegator_amount < delegator_balance);
bond_public(
&process,
&store,
delegator_private_key,
validator_address,
delegator_address,
delegator_amount,
rng,
)
.unwrap();
let combined_amount = validator_amount + delegator_amount;
assert_eq!(committee_state(&store, validator_address).unwrap(), Some((combined_amount, true, TEST_COMMISSION)));
assert_eq!(committee_state(&store, delegator_address).unwrap(), None);
assert_eq!(bond_state(&store, validator_address).unwrap(), Some((*validator_address, validator_amount)));
assert_eq!(bond_state(&store, delegator_address).unwrap(), Some((*validator_address, delegator_amount)));
assert_eq!(unbond_state(&store, validator_address).unwrap(), None);
assert_eq!(unbond_state(&store, delegator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
assert_eq!(withdraw_state(&store, delegator_address).unwrap(), Some(*delegator_address));
let validator_balance_1 = account_balance(&store, validator_address).unwrap();
let delegator_balance_1 = account_balance(&store, delegator_address).unwrap();
assert_eq!(validator_balance_1, validator_balance - validator_amount);
assert_eq!(delegator_balance_1, delegator_balance - delegator_amount);
let delegator_amount = MIN_DELEGATOR_STAKE;
assert!(delegator_amount < delegator_balance_1);
bond_public(
&process,
&store,
delegator_private_key,
validator_address,
delegator_address,
delegator_amount,
rng,
)
.unwrap();
let combined_amount = validator_amount + delegator_amount + delegator_amount;
assert_eq!(committee_state(&store, validator_address).unwrap(), Some((combined_amount, true, TEST_COMMISSION)));
assert_eq!(committee_state(&store, delegator_address).unwrap(), None);
assert_eq!(bond_state(&store, validator_address).unwrap(), Some((*validator_address, validator_amount)));
assert_eq!(bond_state(&store, delegator_address).unwrap(), Some((*validator_address, 2 * delegator_amount)));
assert_eq!(unbond_state(&store, validator_address).unwrap(), None);
assert_eq!(unbond_state(&store, delegator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
assert_eq!(withdraw_state(&store, delegator_address).unwrap(), Some(*delegator_address));
let validator_balance_2 = account_balance(&store, validator_address).unwrap();
let delegator_balance_2 = account_balance(&store, delegator_address).unwrap();
assert_eq!(validator_balance_2, validator_balance_1);
assert_eq!(delegator_balance_2, delegator_balance_1 - delegator_amount);
Ok(())
})
.unwrap();
}
#[test]
fn test_bond_validator_and_delegator_multiple_times() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let finalize_store = FinalizeStore::<CurrentNetwork, FinalizeMemory<_>>::open(StorageMode::new_test(None)).unwrap();
let (validators, delegators) = initialize_stakers(&finalize_store, 1, 1, rng).unwrap();
let (validator_private_key, (validator_address, _, _, withdrawal_address)) = validators.first().unwrap();
let (delegator_private_key, (delegator_address, _)) = delegators.first().unwrap();
let validator_public_balance = account_balance(&finalize_store, validator_address).unwrap();
let delegator_public_balance = account_balance(&finalize_store, delegator_address).unwrap();
let validator_amount = MIN_VALIDATOR_STAKE;
bond_validator(
&process,
&finalize_store,
validator_private_key,
withdrawal_address,
validator_amount,
TEST_COMMISSION,
rng,
)
.unwrap();
assert_eq!(
committee_state(&finalize_store, validator_address).unwrap(),
Some((validator_amount, true, TEST_COMMISSION))
);
assert_eq!(bond_state(&finalize_store, validator_address).unwrap(), Some((*validator_address, validator_amount)));
assert_eq!(unbond_state(&finalize_store, validator_address).unwrap(), None);
assert_eq!(withdraw_state(&finalize_store, validator_address).unwrap(), Some(*withdrawal_address));
assert_eq!(
account_balance(&finalize_store, validator_address).unwrap(),
validator_public_balance - validator_amount
);
let delegator_amount = MIN_DELEGATOR_STAKE;
bond_public(
&process,
&finalize_store,
delegator_private_key,
validator_address,
delegator_address,
delegator_amount,
rng,
)
.unwrap();
let combined_amount = validator_amount + delegator_amount;
assert_eq!(
committee_state(&finalize_store, validator_address).unwrap(),
Some((combined_amount, true, TEST_COMMISSION))
);
assert_eq!(bond_state(&finalize_store, delegator_address).unwrap(), Some((*validator_address, delegator_amount)));
assert_eq!(unbond_state(&finalize_store, delegator_address).unwrap(), None);
assert_eq!(withdraw_state(&finalize_store, delegator_address).unwrap(), Some(*delegator_address));
assert_eq!(
account_balance(&finalize_store, delegator_address).unwrap(),
delegator_public_balance - delegator_amount
);
bond_validator(
&process,
&finalize_store,
validator_private_key,
withdrawal_address,
validator_amount,
TEST_COMMISSION,
rng,
)
.unwrap();
let combined_amount = 2 * validator_amount + delegator_amount;
assert_eq!(
committee_state(&finalize_store, validator_address).unwrap(),
Some((combined_amount, true, TEST_COMMISSION))
);
assert_eq!(
bond_state(&finalize_store, validator_address).unwrap(),
Some((*validator_address, 2 * validator_amount))
);
assert_eq!(unbond_state(&finalize_store, validator_address).unwrap(), None);
assert_eq!(withdraw_state(&finalize_store, validator_address).unwrap(), Some(*withdrawal_address));
assert_eq!(
account_balance(&finalize_store, validator_address).unwrap(),
validator_public_balance - (2 * validator_amount)
);
bond_public(
&process,
&finalize_store,
delegator_private_key,
validator_address,
delegator_address,
delegator_amount,
rng,
)
.unwrap();
let combined_amount = 2 * (validator_amount + delegator_amount);
assert_eq!(
committee_state(&finalize_store, validator_address).unwrap(),
Some((combined_amount, true, TEST_COMMISSION))
);
assert_eq!(
bond_state(&finalize_store, delegator_address).unwrap(),
Some((*validator_address, 2 * delegator_amount))
);
assert_eq!(unbond_state(&finalize_store, delegator_address).unwrap(), None);
assert_eq!(withdraw_state(&finalize_store, delegator_address).unwrap(), Some(*delegator_address));
assert_eq!(
account_balance(&finalize_store, delegator_address).unwrap(),
delegator_public_balance - (2 * delegator_amount)
);
}
#[test]
fn test_bond_delegator_to_multiple_validators_fails() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let store = sample_finalize_store!();
let (validators, delegators) = initialize_stakers(&store, 2, 1, rng).unwrap();
let mut validators = validators.into_iter();
let (validator_private_key_1, (validator_address_1, _, _, withdrawal_address_1)) = validators.next().unwrap();
let (validator_private_key_2, (validator_address_2, _, _, withdrawal_address_2)) = validators.next().unwrap();
let (delegator_private_key, (delegator_address, _)) = delegators.first().unwrap();
let validator_1_balance = account_balance(&store, &validator_address_1).unwrap();
let validator_2_balance = account_balance(&store, &validator_address_2).unwrap();
let delegator_balance = account_balance(&store, delegator_address).unwrap();
let validator_1_amount = MIN_VALIDATOR_STAKE;
bond_validator(
&process,
&store,
&validator_private_key_1,
&withdrawal_address_1,
validator_1_amount,
TEST_COMMISSION,
rng,
)
.unwrap();
let validator_2_amount = MIN_VALIDATOR_STAKE;
bond_validator(
&process,
&store,
&validator_private_key_2,
&withdrawal_address_2,
validator_2_amount,
TEST_COMMISSION,
rng,
)
.unwrap();
test_atomic_finalize!(store, FinalizeMode::RealRun, {
let delegator_amount = MIN_DELEGATOR_STAKE;
assert!(delegator_amount < delegator_balance);
bond_public(
&process,
&store,
delegator_private_key,
&validator_address_1,
delegator_address,
delegator_amount,
rng,
)
.unwrap();
let combined_amount = validator_1_amount + delegator_amount;
assert_eq!(
committee_state(&store, &validator_address_1).unwrap(),
Some((combined_amount, true, TEST_COMMISSION))
);
assert_eq!(
committee_state(&store, &validator_address_2).unwrap(),
Some((validator_2_amount, true, TEST_COMMISSION))
);
assert_eq!(committee_state(&store, delegator_address).unwrap(), None);
assert_eq!(bond_state(&store, &validator_address_1).unwrap(), Some((validator_address_1, validator_1_amount)));
assert_eq!(bond_state(&store, &validator_address_2).unwrap(), Some((validator_address_2, validator_2_amount)));
assert_eq!(bond_state(&store, delegator_address).unwrap(), Some((validator_address_1, delegator_amount)));
assert_eq!(unbond_state(&store, &validator_address_1).unwrap(), None);
assert_eq!(unbond_state(&store, &validator_address_2).unwrap(), None);
assert_eq!(unbond_state(&store, delegator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, &validator_address_1).unwrap(), Some(withdrawal_address_1));
assert_eq!(withdraw_state(&store, &validator_address_2).unwrap(), Some(withdrawal_address_2));
assert_eq!(withdraw_state(&store, delegator_address).unwrap(), Some(*delegator_address));
let validator_1_balance_1 = account_balance(&store, &validator_address_1).unwrap();
let validator_2_balance_1 = account_balance(&store, &validator_address_2).unwrap();
let delegator_balance_1 = account_balance(&store, delegator_address).unwrap();
assert_eq!(validator_1_balance_1, validator_1_balance - validator_1_amount);
assert_eq!(validator_2_balance_1, validator_2_balance - validator_2_amount);
assert_eq!(delegator_balance_1, delegator_balance - delegator_amount);
let delegator_amount = MIN_DELEGATOR_STAKE;
assert!(delegator_amount < delegator_balance_1);
let result = bond_public(
&process,
&store,
delegator_private_key,
&validator_address_2,
delegator_address,
delegator_amount,
rng,
);
assert!(result.is_err());
let combined_amount = validator_1_amount + delegator_amount;
assert_eq!(
committee_state(&store, &validator_address_1).unwrap(),
Some((combined_amount, true, TEST_COMMISSION))
);
assert_eq!(
committee_state(&store, &validator_address_2).unwrap(),
Some((validator_2_amount, true, TEST_COMMISSION))
);
assert_eq!(committee_state(&store, delegator_address).unwrap(), None);
assert_eq!(bond_state(&store, &validator_address_1).unwrap(), Some((validator_address_1, validator_1_amount)));
assert_eq!(bond_state(&store, &validator_address_2).unwrap(), Some((validator_address_2, validator_2_amount)));
assert_eq!(bond_state(&store, delegator_address).unwrap(), Some((validator_address_1, delegator_amount)));
assert_eq!(unbond_state(&store, &validator_address_1).unwrap(), None);
assert_eq!(unbond_state(&store, &validator_address_2).unwrap(), None);
assert_eq!(unbond_state(&store, delegator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, &validator_address_1).unwrap(), Some(withdrawal_address_1));
assert_eq!(withdraw_state(&store, &validator_address_2).unwrap(), Some(withdrawal_address_2));
assert_eq!(withdraw_state(&store, delegator_address).unwrap(), Some(*delegator_address));
let validator_1_balance_2 = account_balance(&store, &validator_address_1).unwrap();
let validator_2_balance_2 = account_balance(&store, &validator_address_2).unwrap();
let delegator_balance_1 = account_balance(&store, delegator_address).unwrap();
assert_eq!(validator_1_balance_2, validator_1_balance_1);
assert_eq!(validator_2_balance_2, validator_2_balance_1);
assert_eq!(delegator_balance_1, delegator_balance_1);
Ok(())
})
.unwrap();
}
#[test]
fn test_unbond_validator() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let store = sample_finalize_store!();
let (validators, _) = initialize_stakers(&store, 1, 0, rng).unwrap();
let (validator_private_key, (validator_address, _, withdrawal_private_key, withdrawal_address)) =
validators.first().unwrap();
let validator_balance = account_balance(&store, validator_address).unwrap();
let validator_amount = 3 * MIN_VALIDATOR_STAKE;
bond_validator(&process, &store, validator_private_key, withdrawal_address, validator_amount, TEST_COMMISSION, rng)
.unwrap();
test_atomic_finalize!(store, FinalizeMode::RealRun, {
let unbond_amount_1 = MIN_VALIDATOR_STAKE;
let block_height_1 = rng.gen_range(1..100);
unbond_public(
&process,
&store,
withdrawal_private_key,
validator_address,
unbond_amount_1,
block_height_1,
rng,
)
.unwrap();
let decremented_amount = validator_amount - unbond_amount_1;
let unlock_height = block_height_1 + NUM_BLOCKS_TO_UNLOCK;
assert_eq!(
committee_state(&store, validator_address).unwrap(),
Some((decremented_amount, true, TEST_COMMISSION))
);
assert_eq!(bond_state(&store, validator_address).unwrap(), Some((*validator_address, decremented_amount)));
assert_eq!(unbond_state(&store, validator_address).unwrap(), Some((unbond_amount_1, unlock_height)));
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
let validator_balance_1 = account_balance(&store, validator_address).unwrap();
assert_eq!(validator_balance_1, validator_balance - validator_amount);
let unbond_amount_2 = MIN_VALIDATOR_STAKE;
let block_height_2 = rng.gen_range(block_height_1..1000);
unbond_public(
&process,
&store,
withdrawal_private_key,
validator_address,
unbond_amount_2,
block_height_2,
rng,
)
.unwrap();
let decremented_amount = validator_amount - unbond_amount_1 - unbond_amount_2;
let unbond_combined_amount = unbond_amount_1 + unbond_amount_2;
let unlock_height = block_height_2 + NUM_BLOCKS_TO_UNLOCK;
assert_eq!(
committee_state(&store, validator_address).unwrap(),
Some((decremented_amount, true, TEST_COMMISSION))
);
assert_eq!(bond_state(&store, validator_address).unwrap(), Some((*validator_address, decremented_amount)));
assert_eq!(unbond_state(&store, validator_address).unwrap(), Some((unbond_combined_amount, unlock_height)));
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
let validator_balance_2 = account_balance(&store, validator_address).unwrap();
assert_eq!(validator_balance_2, validator_balance_1);
let unbond_amount_3 = 1; let block_height_3 = rng.gen_range(block_height_2..10000);
unbond_public(
&process,
&store,
withdrawal_private_key,
validator_address,
unbond_amount_3,
block_height_3,
rng,
)
.unwrap();
let unlock_height = block_height_3 + NUM_BLOCKS_TO_UNLOCK;
assert_eq!(committee_state(&store, validator_address).unwrap(), None);
assert_eq!(bond_state(&store, validator_address).unwrap(), None);
assert_eq!(unbond_state(&store, validator_address).unwrap(), Some((validator_amount, unlock_height)));
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
let validator_balance_3 = account_balance(&store, validator_address).unwrap();
assert_eq!(validator_balance_3, validator_balance_2);
let unbond_amount_4 = 1;
let block_height_4 = rng.gen_range(block_height_3..100000);
let result = unbond_public(
&process,
&store,
withdrawal_private_key,
validator_address,
unbond_amount_4,
block_height_4,
rng,
);
assert!(result.is_err());
assert_eq!(committee_state(&store, validator_address).unwrap(), None);
assert_eq!(bond_state(&store, validator_address).unwrap(), None);
assert_eq!(unbond_state(&store, validator_address).unwrap(), Some((validator_amount, unlock_height)));
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
let validator_balance_4 = account_balance(&store, validator_address).unwrap();
assert_eq!(validator_balance_4, validator_balance_3);
Ok(())
})
.unwrap();
}
#[test]
fn test_bond_validator_fails_if_unbonding_state() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let store = sample_finalize_store!();
let (validators, _) = initialize_stakers(&store, 1, 0, rng).unwrap();
let (validator_private_key, (validator_address, _, withdrawal_private_key, withdrawal_address)) =
validators.first().unwrap();
let validator_amount = MIN_VALIDATOR_STAKE;
bond_validator(&process, &store, validator_private_key, withdrawal_address, validator_amount, TEST_COMMISSION, rng)
.unwrap();
test_atomic_finalize!(store, FinalizeMode::RealRun, {
assert_eq!(
committee_state(&store, validator_address).unwrap(),
Some((validator_amount, true, TEST_COMMISSION))
);
assert_eq!(bond_state(&store, validator_address).unwrap(), Some((*validator_address, validator_amount)));
assert_eq!(unbond_state(&store, validator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
let block_height = rng.gen_range(1..100);
unbond_public(&process, &store, withdrawal_private_key, validator_address, validator_amount, block_height, rng)
.unwrap();
let unlock_height = block_height + NUM_BLOCKS_TO_UNLOCK;
assert_eq!(committee_state(&store, validator_address).unwrap(), None);
assert_eq!(bond_state(&store, validator_address).unwrap(), None);
assert_eq!(unbond_state(&store, validator_address).unwrap(), Some((validator_amount, unlock_height)));
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
let rebonding_result = bond_validator(
&process,
&store,
validator_private_key,
withdrawal_address,
validator_amount,
TEST_COMMISSION,
rng,
);
assert!(rebonding_result.is_err());
let validator_balance = account_balance(&store, validator_address).unwrap();
assert!(validator_balance > MIN_VALIDATOR_STAKE);
assert_eq!(committee_state(&store, validator_address).unwrap(), None);
claim_unbond_public(&process, &store, validator_private_key, validator_address, unlock_height, rng).unwrap();
let new_commission = TEST_COMMISSION + 1;
bond_validator(
&process,
&store,
validator_private_key,
withdrawal_address,
validator_amount,
new_commission,
rng,
)
.unwrap();
assert_eq!(committee_state(&store, validator_address).unwrap(), Some((validator_amount, true, new_commission)));
assert_eq!(bond_state(&store, validator_address).unwrap(), Some((*validator_address, validator_amount)));
assert_eq!(unbond_state(&store, validator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
Ok(())
})
.unwrap();
}
#[test]
fn test_unbond_validator_fails_if_unbonding_beyond_their_stake() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let store = sample_finalize_store!();
let (validators, delegators) = initialize_stakers(&store, 1, 1, rng).unwrap();
let (validator_private_key, (validator_address, _, withdrawal_private_key, withdrawal_address)) =
validators.first().unwrap();
let (delegator_private_key, (delegator_address, _)) = delegators.first().unwrap();
let validator_balance = account_balance(&store, validator_address).unwrap();
let delegator_balance = account_balance(&store, delegator_address).unwrap();
let validator_amount = 2 * MIN_VALIDATOR_STAKE;
bond_validator(&process, &store, validator_private_key, withdrawal_address, validator_amount, TEST_COMMISSION, rng)
.unwrap();
test_atomic_finalize!(store, FinalizeMode::RealRun, {
let unbond_amount = validator_amount + 1;
let block_height = rng.gen_range(1..100);
let result = unbond_public(
&process,
&store,
withdrawal_private_key,
validator_address,
unbond_amount,
block_height,
rng,
);
assert!(result.is_err());
assert_eq!(
committee_state(&store, validator_address).unwrap(),
Some((validator_amount, true, TEST_COMMISSION))
);
assert_eq!(bond_state(&store, validator_address).unwrap(), Some((*validator_address, validator_amount)));
assert_eq!(unbond_state(&store, validator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
let validator_balance_1 = account_balance(&store, validator_address).unwrap();
assert_eq!(validator_balance_1, validator_balance - validator_amount);
Ok(())
})
.unwrap();
let delegator_amount = MIN_DELEGATOR_STAKE;
bond_public(&process, &store, delegator_private_key, validator_address, delegator_address, delegator_amount, rng)
.unwrap();
test_atomic_finalize!(store, FinalizeMode::RealRun, {
let unbond_amount = validator_amount + 1;
let block_height = rng.gen_range(1..100);
let result = unbond_public(
&process,
&store,
withdrawal_private_key,
validator_address,
unbond_amount,
block_height,
rng,
);
assert!(result.is_err());
let combined_amount = validator_amount + delegator_amount;
assert_eq!(committee_state(&store, validator_address).unwrap(), Some((combined_amount, true, TEST_COMMISSION)));
assert_eq!(committee_state(&store, delegator_address).unwrap(), None);
assert_eq!(bond_state(&store, validator_address).unwrap(), Some((*validator_address, validator_amount)));
assert_eq!(bond_state(&store, delegator_address).unwrap(), Some((*validator_address, delegator_amount)));
assert_eq!(unbond_state(&store, validator_address).unwrap(), None);
assert_eq!(unbond_state(&store, delegator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
assert_eq!(withdraw_state(&store, delegator_address).unwrap(), Some(*delegator_address));
let validator_balance_1 = account_balance(&store, validator_address).unwrap();
let delegator_balance_1 = account_balance(&store, delegator_address).unwrap();
assert_eq!(validator_balance_1, validator_balance - validator_amount);
assert_eq!(delegator_balance_1, delegator_balance - delegator_amount);
Ok(())
})
.unwrap();
}
#[test]
fn test_unbond_validator_continues_if_there_is_a_delegator() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let store = sample_finalize_store!();
let (validators, delegators) = initialize_stakers(&store, 1, 1, rng).unwrap();
let (validator_private_key, (validator_address, _, withdrawal_private_key, withdrawal_address)) =
validators.first().unwrap();
let (delegator_private_key, (delegator_address, _)) = delegators.first().unwrap();
let validator_balance = account_balance(&store, validator_address).unwrap();
let delegator_balance = account_balance(&store, delegator_address).unwrap();
let validator_amount = 2 * MIN_VALIDATOR_STAKE;
bond_validator(&process, &store, validator_private_key, withdrawal_address, validator_amount, TEST_COMMISSION, rng)
.unwrap();
let delegator_amount = MIN_DELEGATOR_STAKE;
bond_public(&process, &store, delegator_private_key, validator_address, delegator_address, delegator_amount, rng)
.unwrap();
test_atomic_finalize!(store, FinalizeMode::RealRun, {
let unbond_amount_1 = MIN_VALIDATOR_STAKE;
let block_height_1 = rng.gen_range(1..100);
unbond_public(
&process,
&store,
withdrawal_private_key,
validator_address,
unbond_amount_1,
block_height_1,
rng,
)
.unwrap();
let unbond_amount_2 = MIN_DELEGATOR_STAKE + 2;
let block_height_2 = rng.gen_range(block_height_1..1000);
let result = unbond_public(
&process,
&store,
withdrawal_private_key,
validator_address,
unbond_amount_2,
block_height_2,
rng,
);
assert!(result.is_ok());
let unlock_height = block_height_2 + NUM_BLOCKS_TO_UNLOCK;
assert_eq!(committee_state(&store, validator_address).unwrap(), None);
assert_eq!(delegated_state(&store, validator_address).unwrap(), Some(delegator_amount));
assert_eq!(committee_state(&store, delegator_address).unwrap(), None);
assert_eq!(bond_state(&store, validator_address).unwrap(), None);
assert_eq!(bond_state(&store, delegator_address).unwrap(), Some((*validator_address, delegator_amount)));
assert_eq!(unbond_state(&store, validator_address).unwrap(), Some((validator_amount, unlock_height)));
assert_eq!(unbond_state(&store, delegator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
assert_eq!(withdraw_state(&store, delegator_address).unwrap(), Some(*delegator_address));
let validator_balance_1 = account_balance(&store, validator_address).unwrap();
let delegator_balance_1 = account_balance(&store, delegator_address).unwrap();
assert_eq!(validator_balance_1, validator_balance - validator_amount);
assert_eq!(delegator_balance_1, delegator_balance - delegator_amount);
Ok(())
})
.unwrap();
}
#[test]
fn test_unbond_delegator() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let store = sample_finalize_store!();
let (validators, delegators) = initialize_stakers(&store, 1, 1, rng).unwrap();
let (validator_private_key, (validator_address, _, _, withdrawal_address)) = validators.first().unwrap();
let (delegator_private_key, (delegator_address, _)) = delegators.first().unwrap();
let validator_balance = account_balance(&store, validator_address).unwrap();
let delegator_balance = account_balance(&store, delegator_address).unwrap();
let validator_amount = MIN_VALIDATOR_STAKE;
bond_validator(&process, &store, validator_private_key, withdrawal_address, validator_amount, TEST_COMMISSION, rng)
.unwrap();
let delegator_amount = 3 * MIN_DELEGATOR_STAKE;
bond_public(&process, &store, delegator_private_key, validator_address, delegator_address, delegator_amount, rng)
.unwrap();
test_atomic_finalize!(store, FinalizeMode::RealRun, {
let unbond_amount_1 = MIN_DELEGATOR_STAKE;
let block_height_1 = rng.gen_range(1..100);
unbond_public(&process, &store, delegator_private_key, delegator_address, unbond_amount_1, block_height_1, rng)
.unwrap();
let decremented_amount = validator_amount + delegator_amount - unbond_amount_1;
let decremented_delegator = delegator_amount - unbond_amount_1;
let unlock_height = block_height_1 + NUM_BLOCKS_TO_UNLOCK;
assert_eq!(
committee_state(&store, validator_address).unwrap(),
Some((decremented_amount, true, TEST_COMMISSION))
);
assert_eq!(committee_state(&store, delegator_address).unwrap(), None);
assert_eq!(bond_state(&store, validator_address).unwrap(), Some((*validator_address, validator_amount)));
assert_eq!(bond_state(&store, delegator_address).unwrap(), Some((*validator_address, decremented_delegator)));
assert_eq!(unbond_state(&store, validator_address).unwrap(), None);
assert_eq!(unbond_state(&store, delegator_address).unwrap(), Some((unbond_amount_1, unlock_height)));
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
assert_eq!(withdraw_state(&store, delegator_address).unwrap(), Some(*delegator_address));
let validator_balance_1 = account_balance(&store, validator_address).unwrap();
let delegator_balance_1 = account_balance(&store, delegator_address).unwrap();
assert_eq!(validator_balance_1, validator_balance - validator_amount);
assert_eq!(delegator_balance_1, delegator_balance - delegator_amount);
let unbond_amount_2 = MIN_DELEGATOR_STAKE;
let block_height_2 = rng.gen_range(block_height_1..1000);
unbond_public(&process, &store, delegator_private_key, delegator_address, unbond_amount_2, block_height_2, rng)
.unwrap();
let decremented_amount = decremented_amount - unbond_amount_2;
let decremented_delegator = decremented_delegator - unbond_amount_2;
let unbond_combined_amount = unbond_amount_1 + unbond_amount_2;
let unlock_height = block_height_2 + NUM_BLOCKS_TO_UNLOCK;
assert_eq!(
committee_state(&store, validator_address).unwrap(),
Some((decremented_amount, true, TEST_COMMISSION))
);
assert_eq!(committee_state(&store, delegator_address).unwrap(), None);
assert_eq!(bond_state(&store, validator_address).unwrap(), Some((*validator_address, validator_amount)));
assert_eq!(bond_state(&store, delegator_address).unwrap(), Some((*validator_address, decremented_delegator)));
assert_eq!(unbond_state(&store, validator_address).unwrap(), None);
assert_eq!(unbond_state(&store, delegator_address).unwrap(), Some((unbond_combined_amount, unlock_height)));
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
assert_eq!(withdraw_state(&store, delegator_address).unwrap(), Some(*delegator_address));
let validator_balance_2 = account_balance(&store, validator_address).unwrap();
let delegator_balance_2 = account_balance(&store, delegator_address).unwrap();
assert_eq!(validator_balance_2, validator_balance_1);
assert_eq!(delegator_balance_2, delegator_balance_1);
let unbond_amount_3 = 1; let block_height_3 = rng.gen_range(block_height_2..10000);
unbond_public(&process, &store, delegator_private_key, delegator_address, unbond_amount_3, block_height_3, rng)
.unwrap();
let unlock_height = block_height_3 + NUM_BLOCKS_TO_UNLOCK;
assert_eq!(
committee_state(&store, validator_address).unwrap(),
Some((validator_amount, true, TEST_COMMISSION))
);
assert_eq!(committee_state(&store, delegator_address).unwrap(), None);
assert_eq!(bond_state(&store, validator_address).unwrap(), Some((*validator_address, validator_amount)));
assert_eq!(bond_state(&store, delegator_address).unwrap(), None);
assert_eq!(unbond_state(&store, validator_address).unwrap(), None);
assert_eq!(unbond_state(&store, delegator_address).unwrap(), Some((delegator_amount, unlock_height)));
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
assert_eq!(withdraw_state(&store, delegator_address).unwrap(), Some(*delegator_address));
let validator_balance_3 = account_balance(&store, validator_address).unwrap();
let delegator_balance_3 = account_balance(&store, delegator_address).unwrap();
assert_eq!(validator_balance_3, validator_balance_2);
assert_eq!(delegator_balance_3, delegator_balance_2);
let unbond_amount_4 = 1;
let block_height_4 = rng.gen_range(block_height_3..100000);
let result = unbond_public(
&process,
&store,
delegator_private_key,
delegator_address,
unbond_amount_4,
block_height_4,
rng,
);
assert!(result.is_err());
assert_eq!(
committee_state(&store, validator_address).unwrap(),
Some((validator_amount, true, TEST_COMMISSION))
);
assert_eq!(committee_state(&store, delegator_address).unwrap(), None);
assert_eq!(bond_state(&store, validator_address).unwrap(), Some((*validator_address, validator_amount)));
assert_eq!(bond_state(&store, delegator_address).unwrap(), None);
assert_eq!(unbond_state(&store, validator_address).unwrap(), None);
assert_eq!(unbond_state(&store, delegator_address).unwrap(), Some((delegator_amount, unlock_height)));
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
assert_eq!(withdraw_state(&store, delegator_address).unwrap(), Some(*delegator_address));
let validator_balance_4 = account_balance(&store, validator_address).unwrap();
let delegator_balance_4 = account_balance(&store, delegator_address).unwrap();
assert_eq!(validator_balance_4, validator_balance_3);
assert_eq!(delegator_balance_4, delegator_balance_3);
Ok(())
})
.unwrap();
}
#[test]
fn test_unbond_delegator_without_validator() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let store = sample_finalize_store!();
let (validators, delegators) = initialize_stakers(&store, 1, 1, rng).unwrap();
let (_, (validator_address, _, _, _)) = validators.first().unwrap();
let (delegator_private_key, (delegator_address, _)) = delegators.first().unwrap();
let delegator_amount = MIN_DELEGATOR_STAKE;
bond_public(&process, &store, delegator_private_key, validator_address, delegator_address, delegator_amount, rng)
.unwrap();
test_atomic_finalize!(store, FinalizeMode::RealRun, {
let block_height = rng.gen_range(1..100);
unbond_public(&process, &store, delegator_private_key, delegator_address, delegator_amount, block_height, rng)
.unwrap();
assert_eq!(committee_state(&store, validator_address).unwrap(), None);
assert_eq!(committee_state(&store, delegator_address).unwrap(), None);
assert_eq!(bond_state(&store, validator_address).unwrap(), None);
assert_eq!(bond_state(&store, delegator_address).unwrap(), None);
assert_eq!(unbond_state(&store, validator_address).unwrap(), None);
assert_eq!(
unbond_state(&store, delegator_address).unwrap(),
Some((delegator_amount, block_height + NUM_BLOCKS_TO_UNLOCK))
);
assert_eq!(withdraw_state(&store, validator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, delegator_address).unwrap(), Some(*delegator_address));
Ok(())
})
.unwrap();
}
#[test]
fn test_unbond_delegator_removes_validator_with_insufficient_stake() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let store = sample_finalize_store!();
let (validators, delegators) = initialize_stakers(&store, 1, 1, rng).unwrap();
let (validator_private_key, (validator_address, _, _, withdrawal_address)) = validators.first().unwrap();
let (delegator_private_key, (delegator_address, _)) = delegators.first().unwrap();
let delegator_amount = MIN_VALIDATOR_STAKE - MIN_VALIDATOR_SELF_STAKE;
bond_public(&process, &store, delegator_private_key, validator_address, delegator_address, delegator_amount, rng)
.unwrap();
bond_validator(
&process,
&store,
validator_private_key,
withdrawal_address,
MIN_VALIDATOR_SELF_STAKE,
TEST_COMMISSION,
rng,
)
.unwrap();
test_atomic_finalize!(store, FinalizeMode::RealRun, {
assert_eq!(
committee_state(&store, validator_address).unwrap(),
Some((MIN_VALIDATOR_STAKE, true, TEST_COMMISSION))
);
assert_eq!(committee_state(&store, delegator_address).unwrap(), None);
assert_eq!(
bond_state(&store, validator_address).unwrap(),
Some((*validator_address, MIN_VALIDATOR_SELF_STAKE))
);
assert_eq!(bond_state(&store, delegator_address).unwrap(), Some((*validator_address, delegator_amount)));
assert_eq!(unbond_state(&store, validator_address).unwrap(), None);
assert_eq!(unbond_state(&store, delegator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
assert_eq!(withdraw_state(&store, delegator_address).unwrap(), Some(*delegator_address));
let block_height = rng.gen_range(1..100);
unbond_public(&process, &store, delegator_private_key, delegator_address, delegator_amount, block_height, rng)
.unwrap();
assert_eq!(committee_state(&store, validator_address).unwrap(), None);
assert_eq!(committee_state(&store, delegator_address).unwrap(), None);
assert_eq!(bond_state(&store, validator_address).unwrap(), None);
assert_eq!(bond_state(&store, delegator_address).unwrap(), None);
assert_eq!(
unbond_state(&store, validator_address).unwrap(),
Some((MIN_VALIDATOR_SELF_STAKE, block_height + NUM_BLOCKS_TO_UNLOCK))
);
assert_eq!(
unbond_state(&store, delegator_address).unwrap(),
Some((delegator_amount, block_height + NUM_BLOCKS_TO_UNLOCK))
);
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
assert_eq!(withdraw_state(&store, delegator_address).unwrap(), Some(*delegator_address));
Ok(())
})
.unwrap();
}
#[test]
fn test_unbond_delegator_as_validator() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let finalize_store = FinalizeStore::<CurrentNetwork, FinalizeMemory<_>>::open(StorageMode::new_test(None)).unwrap();
let (validators, delegators) = initialize_stakers(&finalize_store, 2, 1, rng).unwrap();
let mut validators = validators.into_iter();
let (validator_private_key_1, (validator_address_1, _, withdrawal_private_key_1, withdrawal_address_1)) =
validators.next().unwrap();
let (validator_private_key_2, (_, _, withdrawal_private_key_2, withdrawal_address_2)) = validators.next().unwrap();
let (delegator_private_key, (delegator_address, _)) = delegators.first().unwrap();
let validator_amount = MIN_VALIDATOR_STAKE;
bond_validator(
&process,
&finalize_store,
&validator_private_key_1,
&withdrawal_address_1,
validator_amount,
TEST_COMMISSION,
rng,
)
.unwrap();
bond_validator(
&process,
&finalize_store,
&validator_private_key_2,
&withdrawal_address_2,
validator_amount,
TEST_COMMISSION,
rng,
)
.unwrap();
let delegator_amount = MIN_DELEGATOR_STAKE;
bond_public(
&process,
&finalize_store,
delegator_private_key,
&validator_address_1,
delegator_address,
delegator_amount,
rng,
)
.unwrap();
set_validator_state(&process, &finalize_store, &validator_private_key_1, false, rng).unwrap();
let block_height = rng.gen_range(1..100);
assert!(
unbond_public(&process, &finalize_store, &withdrawal_private_key_2, delegator_address, 0u64, block_height, rng)
.is_err()
);
unbond_public(&process, &finalize_store, &withdrawal_private_key_1, delegator_address, 0u64, block_height, rng)
.unwrap();
assert_eq!(
committee_state(&finalize_store, &validator_address_1).unwrap(),
Some((validator_amount, false, TEST_COMMISSION))
);
assert_eq!(bond_state(&finalize_store, delegator_address).unwrap(), None);
assert_eq!(unbond_state(&finalize_store, delegator_address).unwrap().unwrap().0, delegator_amount);
assert_eq!(withdraw_state(&finalize_store, delegator_address).unwrap(), Some(*delegator_address));
}
#[test]
fn test_claim_unbond() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let finalize_store = FinalizeStore::<CurrentNetwork, FinalizeMemory<_>>::open(StorageMode::new_test(None)).unwrap();
let (validators, _) = initialize_stakers(&finalize_store, 1, 0, rng).unwrap();
let (validator_private_key, (validator_address, _, withdrawal_private_key, withdrawal_address)) =
validators.first().unwrap();
let validator_amount = MIN_VALIDATOR_STAKE;
bond_validator(
&process,
&finalize_store,
validator_private_key,
withdrawal_address,
validator_amount,
TEST_COMMISSION,
rng,
)
.unwrap();
assert!(claim_unbond_public(&process, &finalize_store, validator_private_key, validator_address, 1, rng).is_err());
unbond_public(&process, &finalize_store, withdrawal_private_key, validator_address, validator_amount, 1, rng)
.unwrap();
let unbond_height = unbond_state(&finalize_store, validator_address).unwrap().unwrap().1;
assert!(
claim_unbond_public(
&process,
&finalize_store,
validator_private_key,
validator_address,
unbond_height - 1,
rng
)
.is_err()
);
let random_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
claim_unbond_public(&process, &finalize_store, &random_private_key, validator_address, unbond_height, rng).unwrap();
assert_eq!(account_balance(&finalize_store, withdrawal_address).unwrap(), validator_amount);
}
#[test]
fn test_set_validator_state() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let finalize_store = FinalizeStore::<CurrentNetwork, FinalizeMemory<_>>::open(StorageMode::new_test(None)).unwrap();
let (validators, _) = initialize_stakers(&finalize_store, 1, 0, rng).unwrap();
let (validator_private_key, (validator_address, _, _, withdrawal_address)) = validators.first().unwrap();
let amount = MIN_VALIDATOR_STAKE;
bond_validator(&process, &finalize_store, validator_private_key, withdrawal_address, amount, TEST_COMMISSION, rng)
.unwrap();
assert_eq!(committee_state(&finalize_store, validator_address).unwrap(), Some((amount, true, TEST_COMMISSION)));
set_validator_state(&process, &finalize_store, validator_private_key, false, rng).unwrap();
assert_eq!(committee_state(&finalize_store, validator_address).unwrap(), Some((amount, false, TEST_COMMISSION)));
set_validator_state(&process, &finalize_store, validator_private_key, false, rng).unwrap();
assert_eq!(committee_state(&finalize_store, validator_address).unwrap(), Some((amount, false, TEST_COMMISSION)));
set_validator_state(&process, &finalize_store, validator_private_key, true, rng).unwrap();
assert_eq!(committee_state(&finalize_store, validator_address).unwrap(), Some((amount, true, TEST_COMMISSION)));
}
#[test]
fn test_set_validator_state_for_non_validator_fails() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let finalize_store = FinalizeStore::<CurrentNetwork, FinalizeMemory<_>>::open(StorageMode::new_test(None)).unwrap();
let private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
assert!(set_validator_state(&process, &finalize_store, &private_key, false, rng).is_err());
}
#[test]
fn test_bonding_existing_stakers_to_closed_validator() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let finalize_store = FinalizeStore::<CurrentNetwork, FinalizeMemory<_>>::open(StorageMode::new_test(None)).unwrap();
let (validators, delegators) = initialize_stakers(&finalize_store, 1, 1, rng).unwrap();
let (validator_private_key, (validator_address, _, _, withdrawal_address)) = validators.first().unwrap();
let (delegator_private_key, (delegator_address, _)) = delegators.first().unwrap();
let validator_public_balance = account_balance(&finalize_store, validator_address).unwrap();
let delegator_public_balance = account_balance(&finalize_store, delegator_address).unwrap();
let validator_amount = MIN_VALIDATOR_STAKE;
bond_validator(
&process,
&finalize_store,
validator_private_key,
withdrawal_address,
validator_amount,
TEST_COMMISSION,
rng,
)
.unwrap();
assert_eq!(
committee_state(&finalize_store, validator_address).unwrap(),
Some((validator_amount, true, TEST_COMMISSION))
);
assert_eq!(bond_state(&finalize_store, validator_address).unwrap(), Some((*validator_address, validator_amount)));
assert_eq!(unbond_state(&finalize_store, validator_address).unwrap(), None);
assert_eq!(withdraw_state(&finalize_store, validator_address).unwrap(), Some(*withdrawal_address));
assert_eq!(
account_balance(&finalize_store, validator_address).unwrap(),
validator_public_balance - validator_amount
);
let delegator_amount = MIN_DELEGATOR_STAKE;
bond_public(
&process,
&finalize_store,
delegator_private_key,
validator_address,
delegator_address,
delegator_amount,
rng,
)
.unwrap();
let combined_amount = validator_amount + delegator_amount;
assert_eq!(
committee_state(&finalize_store, validator_address).unwrap(),
Some((combined_amount, true, TEST_COMMISSION))
);
assert_eq!(bond_state(&finalize_store, delegator_address).unwrap(), Some((*validator_address, delegator_amount)));
assert_eq!(unbond_state(&finalize_store, delegator_address).unwrap(), None);
assert_eq!(withdraw_state(&finalize_store, delegator_address).unwrap(), Some(*delegator_address));
assert_eq!(
account_balance(&finalize_store, delegator_address).unwrap(),
delegator_public_balance - delegator_amount
);
set_validator_state(&process, &finalize_store, validator_private_key, false, rng).unwrap();
bond_validator(
&process,
&finalize_store,
validator_private_key,
withdrawal_address,
validator_amount,
TEST_COMMISSION,
rng,
)
.unwrap();
let combined_amount = 2 * validator_amount + delegator_amount;
assert_eq!(
committee_state(&finalize_store, validator_address).unwrap(),
Some((combined_amount, false, TEST_COMMISSION))
);
assert_eq!(
bond_state(&finalize_store, validator_address).unwrap(),
Some((*validator_address, 2 * validator_amount))
);
assert_eq!(unbond_state(&finalize_store, validator_address).unwrap(), None);
assert_eq!(withdraw_state(&finalize_store, validator_address).unwrap(), Some(*withdrawal_address));
assert_eq!(
account_balance(&finalize_store, validator_address).unwrap(),
validator_public_balance - (2 * validator_amount)
);
bond_public(
&process,
&finalize_store,
delegator_private_key,
validator_address,
delegator_address,
delegator_amount,
rng,
)
.unwrap();
let combined_amount = 2 * (validator_amount + delegator_amount);
assert_eq!(
committee_state(&finalize_store, validator_address).unwrap(),
Some((combined_amount, false, TEST_COMMISSION))
);
assert_eq!(
bond_state(&finalize_store, delegator_address).unwrap(),
Some((*validator_address, 2 * delegator_amount))
);
assert_eq!(unbond_state(&finalize_store, delegator_address).unwrap(), None);
assert_eq!(withdraw_state(&finalize_store, delegator_address).unwrap(), Some(*delegator_address));
assert_eq!(
account_balance(&finalize_store, delegator_address).unwrap(),
delegator_public_balance - (2 * delegator_amount)
);
}
#[test]
fn test_bonding_new_staker_to_closed_validator_fails() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let finalize_store = FinalizeStore::<CurrentNetwork, FinalizeMemory<_>>::open(StorageMode::new_test(None)).unwrap();
let (validators, delegators) = initialize_stakers(&finalize_store, 1, 1, rng).unwrap();
let (validator_private_key, (validator_address, _, _, withdrawal_address)) = validators.first().unwrap();
let (delegator_private_key, (delegator_address, _)) = delegators.first().unwrap();
let amount = MIN_VALIDATOR_STAKE;
bond_validator(&process, &finalize_store, validator_private_key, withdrawal_address, amount, TEST_COMMISSION, rng)
.unwrap();
set_validator_state(&process, &finalize_store, validator_private_key, false, rng).unwrap();
let delegator_amount = MIN_DELEGATOR_STAKE;
assert!(
bond_public(
&process,
&finalize_store,
delegator_private_key,
validator_address,
delegator_address,
delegator_amount,
rng
)
.is_err()
);
}
#[test]
fn test_claim_unbond_public_to_withdrawal_address() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let store = sample_finalize_store!();
let (validators, delegators) = initialize_stakers(&store, 1, 1, rng).unwrap();
let (validator_private_key, (validator_address, _, withdrawal_private_key, withdrawal_address)) =
validators.first().unwrap();
let (delegator_private_key, (delegator_address, _)) = delegators.first().unwrap();
let validator_balance = account_balance(&store, validator_address).unwrap();
let delegator_balance = account_balance(&store, delegator_address).unwrap();
let delegator_withdraw_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
let delegator_withdrawal_address = Address::try_from(&delegator_withdraw_private_key).unwrap();
let validator_amount = MIN_VALIDATOR_STAKE;
bond_validator(&process, &store, validator_private_key, withdrawal_address, validator_amount, TEST_COMMISSION, rng)
.unwrap();
let delegator_amount = MIN_DELEGATOR_STAKE;
bond_public(
&process,
&store,
delegator_private_key,
validator_address,
&delegator_withdrawal_address,
delegator_amount,
rng,
)
.unwrap();
unbond_public(&process, &store, &delegator_withdraw_private_key, delegator_address, delegator_amount, 1, rng)
.unwrap();
let unbond_height = unbond_state(&store, delegator_address).unwrap().unwrap().1;
assert_eq!(account_balance(&store, delegator_address).unwrap(), delegator_balance - delegator_amount);
assert!(account_balance(&store, &delegator_withdrawal_address).is_err());
assert_eq!(bond_state(&store, delegator_address).unwrap(), None);
assert_eq!(unbond_state(&store, delegator_address).unwrap().unwrap().0, delegator_amount);
assert_eq!(withdraw_state(&store, delegator_address).unwrap(), Some(delegator_withdrawal_address));
claim_unbond_public(&process, &store, delegator_private_key, delegator_address, unbond_height, rng).unwrap();
assert_eq!(account_balance(&store, delegator_address).unwrap(), delegator_balance - delegator_amount);
assert_eq!(account_balance(&store, &delegator_withdrawal_address).unwrap(), delegator_amount);
assert_eq!(bond_state(&store, delegator_address).unwrap(), None);
assert_eq!(unbond_state(&store, delegator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, delegator_address).unwrap(), None);
unbond_public(&process, &store, withdrawal_private_key, validator_address, validator_amount, unbond_height, rng)
.unwrap();
let unbond_height = unbond_state(&store, validator_address).unwrap().unwrap().1;
assert_eq!(account_balance(&store, validator_address).unwrap(), validator_balance - validator_amount);
assert!(account_balance(&store, withdrawal_address).is_err());
assert_eq!(bond_state(&store, validator_address).unwrap(), None);
assert_eq!(unbond_state(&store, validator_address).unwrap().unwrap().0, validator_amount);
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
claim_unbond_public(&process, &store, validator_private_key, validator_address, unbond_height, rng).unwrap();
assert_eq!(account_balance(&store, validator_address).unwrap(), validator_balance - validator_amount);
assert_eq!(account_balance(&store, withdrawal_address).unwrap(), validator_amount);
assert_eq!(bond_state(&store, validator_address).unwrap(), None);
assert_eq!(unbond_state(&store, validator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, validator_address).unwrap(), None);
}
#[test]
fn test_bonding_multiple_stakers_to_same_withdrawal_address() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let store = sample_finalize_store!();
let (validators, delegators) = initialize_stakers(&store, 1, 1, rng).unwrap();
let (validator_private_key, (validator_address, _, _, withdrawal_address)) = validators.first().unwrap();
let (delegator_private_key, (delegator_address, _)) = delegators.first().unwrap();
let validator_amount = MIN_VALIDATOR_STAKE;
bond_validator(&process, &store, validator_private_key, withdrawal_address, validator_amount, TEST_COMMISSION, rng)
.unwrap();
let delegator_amount = MIN_DELEGATOR_STAKE;
bond_public(&process, &store, delegator_private_key, validator_address, withdrawal_address, delegator_amount, rng)
.unwrap();
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
assert_eq!(withdraw_state(&store, delegator_address).unwrap(), Some(*withdrawal_address));
}
#[test]
fn test_claim_unbond_public_removes_withdraw_mapping() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let store = sample_finalize_store!();
let (validators, _) = initialize_stakers(&store, 1, 0, rng).unwrap();
let (validator_private_key, (validator_address, _, withdrawal_private_key, withdrawal_address)) =
validators.first().unwrap();
let validator_balance = account_balance(&store, validator_address).unwrap();
let validator_amount = MIN_VALIDATOR_STAKE * 2;
bond_validator(&process, &store, validator_private_key, withdrawal_address, validator_amount, TEST_COMMISSION, rng)
.unwrap();
let unbond_amount = validator_amount / 2;
unbond_public(&process, &store, withdrawal_private_key, validator_address, unbond_amount, 1, rng).unwrap();
let unbond_height = unbond_state(&store, validator_address).unwrap().unwrap().1;
claim_unbond_public(&process, &store, validator_private_key, validator_address, unbond_height, rng).unwrap();
assert_eq!(account_balance(&store, validator_address).unwrap(), validator_balance - validator_amount);
assert_eq!(account_balance(&store, withdrawal_address).unwrap(), unbond_amount);
assert_eq!(
bond_state(&store, validator_address).unwrap(),
Some((*validator_address, validator_amount - unbond_amount))
);
assert_eq!(unbond_state(&store, validator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, validator_address).unwrap(), Some(*withdrawal_address));
unbond_public(&process, &store, withdrawal_private_key, validator_address, unbond_amount, unbond_height, rng)
.unwrap();
let unbond_height = unbond_state(&store, validator_address).unwrap().unwrap().1;
claim_unbond_public(&process, &store, validator_private_key, validator_address, unbond_height, rng).unwrap();
assert_eq!(account_balance(&store, validator_address).unwrap(), validator_balance - validator_amount);
assert_eq!(account_balance(&store, withdrawal_address).unwrap(), validator_amount);
assert_eq!(bond_state(&store, validator_address).unwrap(), None);
assert_eq!(unbond_state(&store, validator_address).unwrap(), None);
assert_eq!(withdraw_state(&store, validator_address).unwrap(), None);
}
#[test]
fn test_bond_validator_to_different_withdraw_address_fails() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let store = sample_finalize_store!();
let (validators, _) = initialize_stakers(&store, 1, 0, rng).unwrap();
let (validator_private_key, (_, _, _, withdrawal_address)) = validators.first().unwrap();
let validator_amount = MIN_VALIDATOR_STAKE;
bond_validator(&process, &store, validator_private_key, withdrawal_address, validator_amount, TEST_COMMISSION, rng)
.unwrap();
let new_withdraw_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
let new_withdraw_private_key = Address::try_from(&new_withdraw_private_key).unwrap();
assert!(
bond_validator(
&process,
&store,
validator_private_key,
&new_withdraw_private_key,
validator_amount,
TEST_COMMISSION,
rng
)
.is_err()
);
}
#[test]
fn test_bond_validator_with_different_commission_fails() {
let rng = &mut TestRng::default();
let process = Process::<CurrentNetwork>::load().unwrap();
let store = sample_finalize_store!();
let (validators, _) = initialize_stakers(&store, 1, 0, rng).unwrap();
let (validator_private_key, (_, _, _, withdrawal_address)) = validators.first().unwrap();
let validator_amount = MIN_VALIDATOR_STAKE;
bond_validator(&process, &store, validator_private_key, withdrawal_address, validator_amount, TEST_COMMISSION, rng)
.unwrap();
assert!(
bond_validator(
&process,
&store,
validator_private_key,
withdrawal_address,
validator_amount,
TEST_COMMISSION + 1,
rng
)
.is_err()
);
}
mod sanity_checks {
use super::*;
use crate::{Assignments, CallStack, Stack, StackExecute};
use circuit::Assignment;
use console::{program::Request, types::Field};
use synthesizer_program::StackProgram;
fn get_assignment<N: Network, A: circuit::Aleo<Network = N>>(
stack: &Stack<N>,
private_key: &PrivateKey<N>,
function_name: Identifier<N>,
inputs: &[Value<N>],
rng: &mut TestRng,
) -> Assignment<<N as Environment>::Field> {
let program = stack.program();
let program_id = *program.id();
let input_types = program.get_function(&function_name).unwrap().input_types();
let root_tvk = None;
let is_root = true;
let request =
Request::sign(private_key, program_id, function_name, inputs.iter(), &input_types, root_tvk, is_root, rng)
.unwrap();
let assignments = Assignments::<N>::default();
let call_stack = CallStack::CheckDeployment(vec![request], *private_key, assignments.clone(), None, None);
let _response = stack.execute_function::<A, _>(call_stack, None, None, rng).unwrap();
let assignment = assignments.read().last().unwrap().0.clone();
assignment
}
#[test]
fn test_sanity_check_transfer_private() {
let rng = &mut TestRng::default();
let private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
let caller = Address::try_from(&private_key).unwrap();
let process = Process::load().unwrap();
let stack = process.get_stack(ProgramID::from_str("credits.aleo").unwrap()).unwrap();
let function_name = Identifier::from_str("transfer_private").unwrap();
let r0 = Value::from_str(&format!(
"{{ owner: {caller}.private, microcredits: 1_500_000_000_000_000_u64.private, _nonce: {}.public }}",
console::types::Group::<CurrentNetwork>::zero()
))
.unwrap();
let r1 = Value::<CurrentNetwork>::from_str(&format!("{caller}")).unwrap();
let r2 = Value::<CurrentNetwork>::from_str("1_500_000_000_000_000_u64").unwrap();
let assignment = get_assignment::<_, CurrentAleo>(&stack, &private_key, function_name, &[r0, r1, r2], rng);
assert_eq!(16, assignment.num_public());
assert_eq!(50956, assignment.num_private());
assert_eq!(51002, assignment.num_constraints());
assert_eq!((99540, 111472, 77613), assignment.num_nonzeros());
}
#[test]
fn test_sanity_check_transfer_public() {
let rng = &mut TestRng::default();
let private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
let caller = Address::try_from(&private_key).unwrap();
let process = Process::load().unwrap();
let stack = process.get_stack(ProgramID::from_str("credits.aleo").unwrap()).unwrap();
let function_name = Identifier::from_str("transfer_public").unwrap();
let r0 = Value::<CurrentNetwork>::from_str(&format!("{caller}")).unwrap();
let r1 = Value::<CurrentNetwork>::from_str("1_500_000_000_000_000_u64").unwrap();
let assignment = get_assignment::<_, CurrentAleo>(&stack, &private_key, function_name, &[r0, r1], rng);
assert_eq!(11, assignment.num_public());
assert_eq!(12318, assignment.num_private());
assert_eq!(12325, assignment.num_constraints());
assert_eq!((28243, 38006, 16679), assignment.num_nonzeros());
}
#[test]
fn test_sanity_check_transfer_public_as_signer() {
let rng = &mut TestRng::default();
let private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
let signer = Address::try_from(&private_key).unwrap();
let process = Process::load().unwrap();
let stack = process.get_stack(ProgramID::from_str("credits.aleo").unwrap()).unwrap();
let function_name = Identifier::from_str("transfer_public_as_signer").unwrap();
let r0 = Value::<CurrentNetwork>::from_str(&format!("{signer}")).unwrap();
let r1 = Value::<CurrentNetwork>::from_str("1_500_000_000_000_000_u64").unwrap();
let assignment = get_assignment::<_, CurrentAleo>(&stack, &private_key, function_name, &[r0, r1], rng);
assert_eq!(11, assignment.num_public());
assert_eq!(12323, assignment.num_private());
assert_eq!(12330, assignment.num_constraints());
assert_eq!((28257, 38029, 16684), assignment.num_nonzeros());
}
#[test]
fn test_sanity_check_fee_private() {
let rng = &mut TestRng::default();
let private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
let caller = Address::try_from(&private_key).unwrap();
let process = Process::load().unwrap();
let stack = process.get_stack(ProgramID::from_str("credits.aleo").unwrap()).unwrap();
let function_name = Identifier::from_str("fee_private").unwrap();
let r0 = Value::from_str(&format!(
"{{ owner: {caller}.private, microcredits: 1_500_000_000_000_000_u64.private, _nonce: {}.public }}",
console::types::Group::<CurrentNetwork>::zero()
))
.unwrap();
let r1 = Value::<CurrentNetwork>::from_str("1_000_000_000_000_000_u64").unwrap();
let r2 = Value::<CurrentNetwork>::from_str("500_000_000_000_000_u64").unwrap();
let r3 = Value::<CurrentNetwork>::from_str(&Field::<CurrentNetwork>::rand(rng).to_string()).unwrap();
let assignment = get_assignment::<_, CurrentAleo>(&stack, &private_key, function_name, &[r0, r1, r2, r3], rng);
assert_eq!(15, assignment.num_public());
assert_eq!(38115, assignment.num_private());
assert_eq!(38151, assignment.num_constraints());
assert_eq!((73156, 82291, 56895), assignment.num_nonzeros());
}
#[test]
fn test_sanity_check_fee_public() {
let rng = &mut TestRng::default();
let private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
let process = Process::load().unwrap();
let stack = process.get_stack(ProgramID::from_str("credits.aleo").unwrap()).unwrap();
let function_name = Identifier::from_str("fee_public").unwrap();
let r0 = Value::<CurrentNetwork>::from_str("1_000_000_000_000_000_u64").unwrap();
let r1 = Value::<CurrentNetwork>::from_str("500_000_000_000_000_u64").unwrap();
let r2 = Value::<CurrentNetwork>::from_str(&Field::<CurrentNetwork>::rand(rng).to_string()).unwrap();
let assignment = get_assignment::<_, CurrentAleo>(&stack, &private_key, function_name, &[r0, r1, r2], rng);
assert_eq!(12, assignment.num_public());
assert_eq!(12920, assignment.num_private());
assert_eq!(12930, assignment.num_constraints());
assert_eq!((30587, 41288, 17213), assignment.num_nonzeros());
}
}