Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion program/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ solana-program-error = "3.0.1"
solana-pubkey = "4.2.0"
solana-rent = "3.0.0"
solana-security-txt = "1.1.2"
solana-stake-interface = { version = "2", features = ["bincode", "borsh", "sysvar"] }
solana-stake-interface = { path = "../interface", version = "3.1.0", features = ["bincode", "borsh", "sysvar"] }
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iirc there was a reason we stopped using path in favor of version but i can never remember what it was... maybe @joncinque does? or it could have been febo, i dont think it was me

Copy link
Copy Markdown
Member Author

@grod220 grod220 Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh wait a sec: #79 (comment)

I suppose we want to keep it detached to update the interface & program independently? Why is that desirable though?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The chain of dependencies goes: program -> agave -> interface

This means we can't update agave until the interface is updated, and we can't update the program until agave is updated.

The whole point of separating out the interface was to remove the circular dependency between the program and agave.

As for the dep here, it's probably better to use the local one to help catch issues right away. But it does mean we can also accidentally publish the program crate without the interface and cause issues.

But I don't feel too strongly either way.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the worst case, I think someone attempts a stake-program publish when the used stake-interface version isn't published. That seems worthwhile as it requires interface changes to be handled in the program crate as they are changed versus lagging program-sync PRs.

That said, it's easy enough to drop the path = "../interface" if we run into issues later.

solana-sysvar = "3.0.0"
solana-sysvar-id = "3.1.0"
solana-vote-interface = { version = "5.0.0", features = ["bincode"] }
Expand All @@ -45,6 +45,9 @@ solana-pubkey = { version = "4.2.0", features = ["rand"] }
solana-sdk-ids = "3.1.0"
solana-signature = "3.4.0"
solana-signer = "3.0.0"
# TODO: Remove after agave/mollusk/stake-program depend on aligned StakeHistory version
# Either solana-stake-interface v3 or new solana-stake-history crate
solana-stake-interface-v2 = { package = "solana-stake-interface", version = "2.0.1" }
Comment on lines +48 to +50
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Points raised anza-xyz/mollusk#228 (review)

StakeHistory sysvar is creating a dependency chain between

stake interface -> agave -> mollusk -> stake program

Can be resolved by:

  1. Agave libraries shipping with updated solana-stake-inteface dependency
  2. Or even better, moving solana-stake-history to its own crate.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could potentially move stake history to its own crate, since it likely won't change as often.

Note that it wouldn't really help right now since it still depends on solana-sysvar, which depends on solana-account / solana-rent, which is at the root of all this annoyance.

Two versions of a crate is totally fine if there's no other way

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SysvarSerialize removed from stake & mollusk. Now just agave to go.

solana-svm-log-collector = "3.0.0"
solana-system-interface = { version = "2.0.0", features = ["bincode"] }
solana-transaction = "3.0.2"
Expand Down
14 changes: 10 additions & 4 deletions program/src/helpers/merge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,13 +307,15 @@ mod tests {
);

let mismatched_rent_exempt_reserve_ok = Meta {
#[allow(deprecated)]
rent_exempt_reserve: 42,
..Meta::default()
};
assert_ne!(
mismatched_rent_exempt_reserve_ok.rent_exempt_reserve,
Meta::default().rent_exempt_reserve,
);
#[allow(deprecated)]
let mismatched_rent_exempt_reserve = mismatched_rent_exempt_reserve_ok.rent_exempt_reserve;
#[allow(deprecated)]
let default_rent_exempt_reserve = Meta::default().rent_exempt_reserve;
assert_ne!(mismatched_rent_exempt_reserve, default_rent_exempt_reserve,);
assert!(MergeKind::metas_can_merge(
&Meta::default(),
&mismatched_rent_exempt_reserve_ok,
Expand Down Expand Up @@ -428,6 +430,7 @@ mod tests {
let new_rate_activation_epoch = Some(0);

let meta = Meta {
#[allow(deprecated)]
rent_exempt_reserve,
..Meta::auto(&authority_pubkey)
};
Expand Down Expand Up @@ -658,6 +661,7 @@ mod tests {
let activating_stake = 4242;
let inactive_total_lamports = 424242;
let meta = Meta {
#[allow(deprecated)]
rent_exempt_reserve,
..Meta::default()
};
Expand Down Expand Up @@ -742,6 +746,7 @@ mod tests {
let credits_a = 124_521_000u64;
let rent_exempt_reserve = 227_000_000u64;
let meta = Meta {
#[allow(deprecated)]
rent_exempt_reserve,
..Meta::default()
};
Expand Down Expand Up @@ -858,6 +863,7 @@ mod tests {
let credits_b = 100_000_000u64;
let rent_exempt_reserve = 227_000_000u64;
let meta = Meta {
#[allow(deprecated)]
rent_exempt_reserve,
..Meta::default()
};
Expand Down
15 changes: 11 additions & 4 deletions program/src/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ fn do_initialize(
let stake_state = StakeStateV2::Initialized(Meta {
authorized,
lockup,
#[allow(deprecated)]
rent_exempt_reserve: PSEUDO_RENT_EXEMPT_RESERVE,
});

Expand Down Expand Up @@ -544,8 +545,11 @@ impl Processor {
let is_active_or_activating =
source_status.effective > 0 || source_status.activating > 0;

let mut dest_meta = source_meta;
dest_meta.rent_exempt_reserve = PSEUDO_RENT_EXEMPT_RESERVE;
let dest_meta = Meta {
#[allow(deprecated)]
rent_exempt_reserve: PSEUDO_RENT_EXEMPT_RESERVE,
..source_meta
};

(is_active_or_activating, Some(dest_meta))
}
Expand All @@ -555,8 +559,11 @@ impl Processor {
.check(&signers, StakeAuthorize::Staker)
.map_err(to_program_error)?;

let mut dest_meta = source_meta;
dest_meta.rent_exempt_reserve = PSEUDO_RENT_EXEMPT_RESERVE;
let dest_meta = Meta {
#[allow(deprecated)]
rent_exempt_reserve: PSEUDO_RENT_EXEMPT_RESERVE,
..source_meta
};

(false, Some(dest_meta))
}
Expand Down
10 changes: 7 additions & 3 deletions program/tests/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ use {
solana_stake_interface::{
instruction::{self, LockupArgs},
stake_flags::StakeFlags,
stake_history::{StakeHistory, StakeHistoryEntry},
stake_history::StakeHistory,
state::{
warmup_cooldown_rate, Authorized, Delegation, Lockup, Meta, Stake, StakeAuthorize,
StakeStateV2, NEW_WARMUP_COOLDOWN_RATE,
},
},
solana_stake_interface_v2::stake_history::StakeHistoryEntry as MolluskStakeHistoryEntry,
solana_stake_program::{get_minimum_delegation, id},
solana_svm_log_collector::LogCollector,
solana_sysvar_id::SysvarId,
Expand Down Expand Up @@ -166,7 +167,7 @@ impl Env {
for epoch in 0..EXECUTION_EPOCH {
mollusk.sysvars.stake_history.add(
epoch,
StakeHistoryEntry {
MolluskStakeHistoryEntry {
effective: PERSISTENT_ACTIVE_STAKE,
activating: stake_delta_amount,
deactivating: stake_delta_amount,
Expand Down Expand Up @@ -943,6 +944,7 @@ fn fully_configurable_stake(
};

let meta = Meta {
#[allow(deprecated)]
rent_exempt_reserve: PSEUDO_RENT_EXEMPT_RESERVE,
authorized,
lockup,
Expand Down Expand Up @@ -1232,7 +1234,9 @@ fn test_all_success_non_default_rent(lamports_per_byte_year: u64) {

match account.deserialize_data::<StakeStateV2>().unwrap() {
StakeStateV2::Initialized(meta) | StakeStateV2::Stake(meta, _, _) => {
assert_eq!(meta.rent_exempt_reserve, PSEUDO_RENT_EXEMPT_RESERVE)
#[allow(deprecated)]
let rent_exempt_reserve = meta.rent_exempt_reserve;
assert_eq!(rent_exempt_reserve, PSEUDO_RENT_EXEMPT_RESERVE)
}
StakeStateV2::Uninitialized => (),
StakeStateV2::RewardsPool => unreachable!(),
Expand Down
1 change: 1 addition & 0 deletions program/tests/program_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,7 @@ async fn program_test_stake_initialize() {
stake_state,
StakeStateV2::Initialized(Meta {
authorized,
#[allow(deprecated)]
rent_exempt_reserve,
lockup,
}),
Expand Down
32 changes: 28 additions & 4 deletions program/tests/stake_instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1098,6 +1098,7 @@ fn test_stake_initialize() {
from(&accounts[0]).unwrap(),
StakeStateV2::Initialized(Meta {
authorized: Authorized::auto(&stake_address),
#[allow(deprecated)]
rent_exempt_reserve,
lockup,
}),
Expand Down Expand Up @@ -2031,6 +2032,7 @@ fn test_redelegate_consider_balance_changes() {
let stake_account = AccountSharedData::new_data_with_space(
stake_lamports,
&StakeStateV2::Initialized(Meta {
#[allow(deprecated)]
rent_exempt_reserve,
..Meta::auto(&authority_address)
}),
Expand Down Expand Up @@ -2270,6 +2272,7 @@ fn test_split() {
];

let meta = Meta {
#[allow(deprecated)]
rent_exempt_reserve: default_stake_rent(),
..Meta::auto(&stake_address)
};
Expand Down Expand Up @@ -2620,6 +2623,7 @@ fn test_withdraw_stake() {
let stake_account = AccountSharedData::new_data_with_space(
1_000_000_000,
&StakeStateV2::Initialized(Meta {
#[allow(deprecated)]
rent_exempt_reserve,
authorized: Authorized {
staker: authority_address,
Expand Down Expand Up @@ -2930,6 +2934,7 @@ fn test_withdraw_rent_exempt() {
let stake_account = AccountSharedData::new_data_with_space(
stake_lamports + rent_exempt_reserve,
&StakeStateV2::Initialized(Meta {
#[allow(deprecated)]
rent_exempt_reserve,
..Meta::auto(&stake_address)
}),
Expand Down Expand Up @@ -3491,6 +3496,7 @@ fn test_delegate_minimum_stake_delegation() {
let rent_exempt_reserve = rent.minimum_balance(StakeStateV2::size_of());
let stake_address = solana_pubkey::new_rand();
let meta = Meta {
#[allow(deprecated)]
rent_exempt_reserve,
..Meta::auto(&stake_address)
};
Expand Down Expand Up @@ -3598,6 +3604,7 @@ fn test_split_minimum_stake_delegation() {
};
let source_address = Pubkey::new_unique();
let source_meta = Meta {
#[allow(deprecated)]
rent_exempt_reserve,
..Meta::auto(&source_address)
};
Expand Down Expand Up @@ -3708,6 +3715,7 @@ fn test_split_full_amount_minimum_stake_delegation() {
};
let source_address = Pubkey::new_unique();
let source_meta = Meta {
#[allow(deprecated)]
rent_exempt_reserve,
..Meta::auto(&source_address)
};
Expand Down Expand Up @@ -3844,6 +3852,7 @@ fn test_initialized_split_destination_minimum_balance() {
// balance meets all the requirements
let source_balance = rent_exempt_reserve + split_amount;
let source_meta = Meta {
#[allow(deprecated)]
rent_exempt_reserve,
..Meta::auto(&source_address)
};
Expand Down Expand Up @@ -3987,6 +3996,7 @@ fn test_staked_split_destination_minimum_balance() {
// balance meets all the requirements
let source_balance = rent_exempt_reserve + minimum_delegation + split_amount;
let source_meta = Meta {
#[allow(deprecated)]
rent_exempt_reserve,
..Meta::auto(&source_address)
};
Expand Down Expand Up @@ -4067,6 +4077,7 @@ fn test_withdraw_minimum_stake_delegation() {
let rent_exempt_reserve = default_stake_rent();
let stake_address = solana_pubkey::new_rand();
let meta = Meta {
#[allow(deprecated)]
rent_exempt_reserve,
..Meta::auto(&stake_address)
};
Expand Down Expand Up @@ -4903,6 +4914,7 @@ fn test_split_more_than_staked() {
stake_lamports,
&just_stake(
Meta {
#[allow(deprecated)]
rent_exempt_reserve,
..Meta::auto(&stake_address)
},
Expand Down Expand Up @@ -4998,6 +5010,7 @@ fn test_split_with_rent() {
];
let meta = Meta {
authorized: Authorized::auto(&stake_address),
#[allow(deprecated)]
rent_exempt_reserve,
..Meta::default()
};
Expand Down Expand Up @@ -5111,6 +5124,7 @@ fn test_split_to_account_with_rent_exempt_reserve() {
let stake_address = solana_pubkey::new_rand();
let meta = Meta {
authorized: Authorized::auto(&stake_address),
#[allow(deprecated)]
rent_exempt_reserve,
..Meta::default()
};
Expand Down Expand Up @@ -5286,6 +5300,7 @@ fn test_split_from_larger_sized_account() {
let stake_address = solana_pubkey::new_rand();
let meta = Meta {
authorized: Authorized::auto(&stake_address),
#[allow(deprecated)]
rent_exempt_reserve: source_larger_rent_exempt_reserve,
..Meta::default()
};
Expand Down Expand Up @@ -5394,6 +5409,7 @@ fn test_split_from_larger_sized_account() {
if let StakeStateV2::Stake(meta, stake, stake_flags) = state {
let expected_split_meta = Meta {
authorized: Authorized::auto(&stake_address),
#[allow(deprecated)]
rent_exempt_reserve: split_rent_exempt_reserve,
..Meta::default()
};
Expand Down Expand Up @@ -5451,6 +5467,7 @@ fn test_split_from_smaller_sized_account() {
let stake_address = solana_pubkey::new_rand();
let meta = Meta {
authorized: Authorized::auto(&stake_address),
#[allow(deprecated)]
rent_exempt_reserve: source_smaller_rent_exempt_reserve,
..Meta::default()
};
Expand Down Expand Up @@ -5549,6 +5566,7 @@ fn test_split_100_percent_of_source() {
let stake_address = solana_pubkey::new_rand();
let meta = Meta {
authorized: Authorized::auto(&stake_address),
#[allow(deprecated)]
rent_exempt_reserve,
..Meta::default()
};
Expand Down Expand Up @@ -5669,6 +5687,7 @@ fn test_split_100_percent_of_source_to_account_with_lamports() {
let stake_address = solana_pubkey::new_rand();
let meta = Meta {
authorized: Authorized::auto(&stake_address),
#[allow(deprecated)]
rent_exempt_reserve,
..Meta::default()
};
Expand Down Expand Up @@ -5790,6 +5809,7 @@ fn test_split_rent_exemptness() {
let stake_address = solana_pubkey::new_rand();
let meta = Meta {
authorized: Authorized::auto(&stake_address),
#[allow(deprecated)]
rent_exempt_reserve: source_rent_exempt_reserve,
..Meta::default()
};
Expand Down Expand Up @@ -5904,6 +5924,7 @@ fn test_split_rent_exemptness() {

let expected_split_meta = Meta {
authorized: Authorized::auto(&stake_address),
#[allow(deprecated)]
rent_exempt_reserve: split_rent_exempt_reserve,
..Meta::default()
};
Expand Down Expand Up @@ -5963,6 +5984,7 @@ fn test_split_require_rent_exempt_destination() {
let destination_address = Pubkey::new_unique();
let meta = Meta {
authorized: Authorized::auto(&source_address),
#[allow(deprecated)]
rent_exempt_reserve,
..Meta::default()
};
Expand Down Expand Up @@ -6246,14 +6268,14 @@ fn test_merge() {
assert_eq!(accounts[0].state(), Ok(StakeStateV2::Initialized(*meta)),);
}
StakeStateV2::Stake(meta, stake, stake_flags) => {
#[allow(deprecated)]
let merge_from_rent_exempt_reserve =
merge_from_state.meta().unwrap().rent_exempt_reserve;
let expected_stake = stake.delegation.stake
+ merge_from_state
.stake()
.map(|stake| stake.delegation.stake)
.unwrap_or_else(|| {
stake_lamports
- merge_from_state.meta().unwrap().rent_exempt_reserve
});
.unwrap_or(stake_lamports - merge_from_rent_exempt_reserve);
assert_eq!(
accounts[0].state(),
Ok(StakeStateV2::Stake(
Expand Down Expand Up @@ -6287,6 +6309,7 @@ fn test_merge_self_fails() {
let stake_amount = 4242424242;
let stake_lamports = rent_exempt_reserve + stake_amount;
let meta = Meta {
#[allow(deprecated)]
rent_exempt_reserve,
..Meta::auto(&authorized_address)
};
Expand Down Expand Up @@ -6626,6 +6649,7 @@ fn test_merge_active_stake() {
let merge_from_amount = base_lamports;
let merge_from_lamports = rent_exempt_reserve + merge_from_amount;
let meta = Meta {
#[allow(deprecated)]
rent_exempt_reserve,
..Meta::auto(&authorized_address)
};
Expand Down
Loading