Skip to content

Commit

Permalink
Merge pull request #2406 from AleoHQ/is-open-to-new-stakers
Browse files Browse the repository at this point in the history
Update `is_open` flag to check for new stakers
  • Loading branch information
howardwu committed Mar 23, 2024
2 parents b924170 + bb9bf60 commit 0029b6a
Show file tree
Hide file tree
Showing 7 changed files with 448 additions and 78 deletions.
8 changes: 4 additions & 4 deletions ledger/block/src/transition/mod.rs
Expand Up @@ -311,17 +311,17 @@ impl<N: Network> Transition<N> {
/// Returns `true` if this is a `bond_public` transition.
#[inline]
pub fn is_bond_public(&self) -> bool {
self.inputs.len() == 2
&& self.outputs.is_empty()
self.inputs.len() == 3
&& self.outputs.len() == 1
&& self.program_id.to_string() == "credits.aleo"
&& self.function_name.to_string() == "bond_public"
}

/// Returns `true` if this is an `unbond_public` transition.
#[inline]
pub fn is_unbond_public(&self) -> bool {
self.inputs.len() == 2
&& self.outputs.is_empty()
self.inputs.len() == 1
&& self.outputs.len() == 1
&& self.program_id.to_string() == "credits.aleo"
&& self.function_name.to_string() == "unbond_public"
}
Expand Down
3 changes: 3 additions & 0 deletions ledger/src/tests.rs
Expand Up @@ -1589,6 +1589,9 @@ fn test_max_committee_limit_with_bonds() {
)
.unwrap();

// Ensure that the `bond_second_transaction` is rejected.
assert_eq!(block.transactions().num_rejected(), 1);

// Check that the next block is valid.
ledger.check_next_block(&block, rng).unwrap();

Expand Down
264 changes: 247 additions & 17 deletions synthesizer/process/src/tests/test_credits.rs
Expand Up @@ -941,6 +941,126 @@ fn test_bond_delegator_multiple_bonds() {
.unwrap();
}

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

// Construct the process.
let process = Process::<CurrentNetwork>::load().unwrap();

// Initialize a new finalize store.
let finalize_store = FinalizeStore::<CurrentNetwork, FinalizeMemory<_>>::open(None).unwrap();

// Initialize the validators and delegators.
let (validators, delegators) = initialize_stakers(&finalize_store, 1, 1, rng).unwrap();
let (validator_private_key, (validator_address, _)) = validators.first().unwrap();
let (delegator_private_key, (delegator_address, _)) = delegators.first().unwrap();

// Retrieve the account balances.
let validator_public_balance = account_balance(&finalize_store, validator_address).unwrap();
let delegator_public_balance = account_balance(&finalize_store, delegator_address).unwrap();

// Prepare the validator amount.
let validator_amount = MIN_VALIDATOR_STAKE;
// Perform the bond.
bond_public(
&process,
&finalize_store,
validator_private_key,
validator_address,
validator_address,
validator_amount,
rng,
)
.unwrap();

// Check that the committee, bond, unbond, and withdraw states are correct.
assert_eq!(committee_state(&finalize_store, validator_address).unwrap(), Some((validator_amount, true)));
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(*validator_address));
assert_eq!(
account_balance(&finalize_store, validator_address).unwrap(),
validator_public_balance - validator_amount
);

// Bond the delegator to the validator.
let delegator_amount = MIN_DELEGATOR_STAKE;
bond_public(
&process,
&finalize_store,
delegator_private_key,
validator_address,
delegator_address,
delegator_amount,
rng,
)
.unwrap();

// Check that the committee, bond, unbond, and withdraw states are correct.
let combined_amount = validator_amount + delegator_amount;
assert_eq!(committee_state(&finalize_store, validator_address).unwrap(), Some((combined_amount, true)));
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 the validator again.
bond_public(
&process,
&finalize_store,
validator_private_key,
validator_address,
validator_address,
validator_amount,
rng,
)
.unwrap();

// Check that the committee, bond, unbond, and withdraw states are correct.
let combined_amount = 2 * validator_amount + delegator_amount;
assert_eq!(committee_state(&finalize_store, validator_address).unwrap(), Some((combined_amount, true)));
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(*validator_address));
assert_eq!(
account_balance(&finalize_store, validator_address).unwrap(),
validator_public_balance - (2 * validator_amount)
);

// Bond the delegator to the validator again.
bond_public(
&process,
&finalize_store,
delegator_private_key,
validator_address,
delegator_address,
delegator_amount,
rng,
)
.unwrap();

// Check that the committee, bond, unbond, and withdraw states are correct.
let combined_amount = 2 * (validator_amount + delegator_amount);
assert_eq!(committee_state(&finalize_store, validator_address).unwrap(), Some((combined_amount, true)));
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_nonexistent_validator_fails() {
let rng = &mut TestRng::default();
Expand Down Expand Up @@ -1682,7 +1802,132 @@ fn test_set_validator_state_for_non_validator_fails() {
}

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

// Construct the process.
let process = Process::<CurrentNetwork>::load().unwrap();

// Initialize a new finalize store.
let finalize_store = FinalizeStore::<CurrentNetwork, FinalizeMemory<_>>::open(None).unwrap();

// Initialize the validators and delegators.
let (validators, delegators) = initialize_stakers(&finalize_store, 1, 1, rng).unwrap();
let (validator_private_key, (validator_address, _)) = validators.first().unwrap();
let (delegator_private_key, (delegator_address, _)) = delegators.first().unwrap();

// Retrieve the account balances.
let validator_public_balance = account_balance(&finalize_store, validator_address).unwrap();
let delegator_public_balance = account_balance(&finalize_store, delegator_address).unwrap();

// Prepare the validator amount.
let validator_amount = MIN_VALIDATOR_STAKE;
// Perform the bond.
bond_public(
&process,
&finalize_store,
validator_private_key,
validator_address,
validator_address,
validator_amount,
rng,
)
.unwrap();

// Check that the committee, bond, unbond, and withdraw states are correct.
assert_eq!(committee_state(&finalize_store, validator_address).unwrap(), Some((validator_amount, true)));
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(*validator_address));
assert_eq!(
account_balance(&finalize_store, validator_address).unwrap(),
validator_public_balance - validator_amount
);

// Bond the delegator to the validator.
let delegator_amount = MIN_DELEGATOR_STAKE;
bond_public(
&process,
&finalize_store,
delegator_private_key,
validator_address,
delegator_address,
delegator_amount,
rng,
)
.unwrap();

// Check that the committee, bond, unbond, and withdraw states are correct.
let combined_amount = validator_amount + delegator_amount;
assert_eq!(committee_state(&finalize_store, validator_address).unwrap(), Some((combined_amount, true)));
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 the validator `is_open` state to `false`.
set_validator_state(&process, &finalize_store, validator_private_key, false, rng).unwrap();

/* Ensure bonding to a closed validator succeeds for the existing stakers. */

// Bond the validator again.
bond_public(
&process,
&finalize_store,
validator_private_key,
validator_address,
validator_address,
validator_amount,
rng,
)
.unwrap();

// Check that the committee, bond, unbond, and withdraw states are correct.
let combined_amount = 2 * validator_amount + delegator_amount;
assert_eq!(committee_state(&finalize_store, validator_address).unwrap(), Some((combined_amount, false)));
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(*validator_address));
assert_eq!(
account_balance(&finalize_store, validator_address).unwrap(),
validator_public_balance - (2 * validator_amount)
);

// Bond the delegator to the validator again.
bond_public(
&process,
&finalize_store,
delegator_private_key,
validator_address,
delegator_address,
delegator_amount,
rng,
)
.unwrap();

// Check that the committee, bond, unbond, and withdraw states are correct.
let combined_amount = 2 * (validator_amount + delegator_amount);
assert_eq!(committee_state(&finalize_store, validator_address).unwrap(), Some((combined_amount, false)));
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();

// Construct the process.
Expand All @@ -1706,22 +1951,7 @@ fn test_bonding_to_closed_fails() {
// Set the validator `is_open` state to `false`.
set_validator_state(&process, &finalize_store, validator_private_key, false, rng).unwrap();

// Ensure that the validator can't bond additional stake.
let validator_amount = MIN_VALIDATOR_STAKE;
assert!(
bond_public(
&process,
&finalize_store,
validator_private_key,
validator_address,
validator_address,
validator_amount,
rng
)
.is_err()
);

// Ensure that delegators can't bond to the validator.
// Ensure that new delegators can't bond to the validator.
let delegator_amount = MIN_DELEGATOR_STAKE;
assert!(
bond_public(
Expand Down

0 comments on commit 0029b6a

Please sign in to comment.