Skip to content
Open
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: 2 additions & 0 deletions dlp-api/src/args/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mod commit_state;
mod delegate;
mod delegate_ephemeral_balance;
mod delegate_with_actions;
mod preallocate_buffer;
mod top_up_ephemeral_balance;
mod types;
mod validator_claim_fees;
Expand All @@ -13,6 +14,7 @@ pub use commit_state::*;
pub use delegate::*;
pub use delegate_ephemeral_balance::*;
pub use delegate_with_actions::*;
pub use preallocate_buffer::*;
pub use top_up_ephemeral_balance::*;
pub use types::*;
pub use validator_claim_fees::*;
Expand Down
26 changes: 26 additions & 0 deletions dlp-api/src/args/preallocate_buffer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use borsh::{BorshDeserialize, BorshSerialize};

use crate::compat::borsh;

/// Which DLP-owned buffer (or the delegated account itself) a
/// `PreallocateBuffer` instruction should grow.
#[derive(
Default, Debug, Clone, Copy, PartialEq, Eq, BorshSerialize, BorshDeserialize,
)]
pub enum PreallocateBufferKind {
/// The `commit_state` PDA (seeds: `[COMMIT_STATE_TAG, delegated_account]`).
#[default]
CommitState,
/// The `undelegate_buffer` PDA (seeds: `[UNDELEGATE_BUFFER_TAG, delegated_account]`).
UndelegateBuffer,
/// Pre-allocating delegated account itself
DelegatedAccount,
}

#[derive(Default, Debug, BorshSerialize, BorshDeserialize)]
pub struct PreallocateBufferArgs {
/// Which buffer to grow.
pub kind: PreallocateBufferKind,
/// The final size the buffer should reach
pub target_size: u32,
}
3 changes: 3 additions & 0 deletions dlp-api/src/discriminator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ pub enum DlpDiscriminator {

/// See [crate::processor::process_undelegate_with_rollback_after_timeout] for docs.
UndelegateWithRollbackAfterTimeout = 27,

/// See [crate::processor::process_preallocate_buffer] for docs.
PreallocateBuffer = 28,
}

impl DlpDiscriminator {
Expand Down
9 changes: 9 additions & 0 deletions dlp-api/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,15 @@ pub enum DlpError {
#[error("Owner program requested undelegation")]
OwnerRequestedUndelegation = 55,

#[error("Cannot preallocate a buffer while a commit is in flight")]
PreallocateBufferCommitInFlight = 56,

#[error("Buffer must be preallocated to the exact required size ahead of time for accounts over the growth cap")]
BufferNotPreallocatedToExactSize = 57,

#[error("PreallocateBuffer target size does not exceed the growth cap; the buffer PDA is created directly by the consuming instruction instead")]
PreallocateBufferTargetTooSmall = 58,

#[error("An infallible error is encountered possibly due to logic error")]
InfallibleError = 100,
}
Expand Down
2 changes: 2 additions & 0 deletions dlp-api/src/instruction_builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ mod finalize;
mod init_magic_fee_vault;
mod init_protocol_fees_vault;
mod init_validator_fees_vault;
mod preallocate_buffer;
mod protocol_claim_fees;
mod request_undelegation;
mod top_up_ephemeral_balance;
Expand Down Expand Up @@ -46,6 +47,7 @@ pub use finalize::*;
pub use init_magic_fee_vault::*;
pub use init_protocol_fees_vault::*;
pub use init_validator_fees_vault::*;
pub use preallocate_buffer::*;
pub use protocol_claim_fees::*;
pub use request_undelegation::*;
pub use top_up_ephemeral_balance::*;
Expand Down
105 changes: 105 additions & 0 deletions dlp-api/src/instruction_builder/preallocate_buffer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
use dlp::{
args::{PreallocateBufferArgs, PreallocateBufferKind},
discriminator::DlpDiscriminator,
pda::{
commit_record_pda_from_delegated_account,
commit_state_pda_from_delegated_account,
delegation_record_pda_from_delegated_account,
undelegate_buffer_pda_from_delegated_account,
validator_fees_vault_pda_from_validator,
},
total_size_budget, AccountSizeClass, DLP_PROGRAM_DATA_SIZE_CLASS,
};
use solana_program::{
account_info::MAX_PERMITTED_DATA_INCREASE,
instruction::{AccountMeta, Instruction},
pubkey::Pubkey,
};
use solana_sdk_ids::system_program;

use crate::compat::{borsh::to_vec, Compatize, Modernize};

/// Builds a preallocate buffer instruction.
/// See [dlp::processor::process_preallocate_buffer] for docs.
pub fn preallocate_buffer(
validator: Pubkey,
delegated_account: Pubkey,
kind: PreallocateBufferKind,
target_size: u32,
) -> Instruction {
let args = to_vec(&PreallocateBufferArgs { kind, target_size }).unwrap();
Comment thread
taco-paco marked this conversation as resolved.
let validator_compat = validator.compatize();
let delegated_account_compat = delegated_account.compatize();
let delegation_record_pda =
delegation_record_pda_from_delegated_account(&delegated_account_compat)
.modernize();
let commit_record_pda =
commit_record_pda_from_delegated_account(&delegated_account_compat)
.modernize();
let validator_fees_vault_pda =
validator_fees_vault_pda_from_validator(&validator_compat).modernize();
let buffer_pda = match kind {
PreallocateBufferKind::CommitState => {
commit_state_pda_from_delegated_account(&delegated_account_compat)
.modernize()
}
PreallocateBufferKind::UndelegateBuffer => {
undelegate_buffer_pda_from_delegated_account(
&delegated_account_compat,
)
.modernize()
}
PreallocateBufferKind::DelegatedAccount => delegated_account,
};
Instruction {
program_id: dlp::id().modernize(),
accounts: vec![
AccountMeta::new(validator, true),
AccountMeta::new_readonly(delegated_account, false),
AccountMeta::new(delegation_record_pda, false),
AccountMeta::new(buffer_pda, false),
AccountMeta::new_readonly(commit_record_pda, false),
AccountMeta::new_readonly(validator_fees_vault_pda, false),
AccountMeta::new_readonly(system_program::id(), false),
],
data: [DlpDiscriminator::PreallocateBuffer.to_vec(), args].concat(),
}
}

/// Returns the sequence of `preallocate_buffer` instructions needed to grow
/// a buffer of `kind` from `current_size` up to `target_size`
pub fn preallocate_buffer_chunks(
validator: Pubkey,
delegated_account: Pubkey,
kind: PreallocateBufferKind,
current_size: u32,
target_size: u32,
) -> Vec<Instruction> {
let growth = target_size.saturating_sub(current_size);
let chunks = growth.div_ceil(MAX_PERMITTED_DATA_INCREASE as u32) as usize;
(0..chunks)
.map(|_| {
preallocate_buffer(validator, delegated_account, kind, target_size)
})
.collect()
}

///
/// Returns accounts-data-size budget for preallocate_buffer instruction.
///
/// This value can be used with ComputeBudgetInstruction::SetLoadedAccountsDataSizeLimit
///
pub fn preallocate_buffer_size_budget(
delegated_account: AccountSizeClass,
) -> u32 {
total_size_budget(&[
DLP_PROGRAM_DATA_SIZE_CLASS,
AccountSizeClass::Tiny, // validator
delegated_account, // delegated_account
AccountSizeClass::Tiny, // delegation_record_pda
delegated_account, // buffer_pda
AccountSizeClass::Tiny, // commit_record_pda
AccountSizeClass::Tiny, // validator_fees_vault_pda
AccountSizeClass::Tiny, // system_program
])
}
5 changes: 5 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,11 @@ pub fn fast_process_instruction(
program_id, accounts, data,
),
),
DlpDiscriminator::PreallocateBuffer => {
Some(processor::fast::process_preallocate_buffer(
program_id, accounts, data,
))
}
_ => None,
}
}
Expand Down
32 changes: 12 additions & 20 deletions src/processor/fast/commit_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ use crate::{
args::CommitStateArgs,
error::DlpError,
merge_diff_copy, pda,
processor::fast::utils::pda::create_pda,
processor::fast::utils::pda::{
create_or_verify_preallocated_pda, create_pda,
},
requires::{
require_initialized_delegation_metadata,
require_initialized_delegation_record,
require_initialized_validator_fees_vault, require_owned_pda,
require_program_config, require_signer, require_uninitialized_pda,
CommitRecordCtx, CommitStateAccountCtx,
CommitRecordCtx,
},
state::{
CommitRecord, DelegationMetadata, DelegationRecord, ProgramConfig,
Expand Down Expand Up @@ -257,17 +259,20 @@ pub(crate) fn process_commit_state_internal(
}
}

// Load the uninitialized PDAs
let commit_state_bump = require_uninitialized_pda(
// Handle commit state account
let commit_state_len = args.commit_state_bytes.data_len();
create_or_verify_preallocated_pda(
args.commit_state_account,
&[
pda::COMMIT_STATE_TAG,
args.delegated_account.address().as_ref(),
],
&crate::fast::ID,
true,
CommitStateAccountCtx,
commit_state_len,
args.validator,
"commit state",
)?;

// Ensure commit record isn't initialized
let commit_record_bump = require_uninitialized_pda(
args.commit_record_account,
&[
Expand All @@ -279,19 +284,6 @@ pub(crate) fn process_commit_state_internal(
CommitRecordCtx,
)?;

// Initialize the PDA containing the new committed state
create_pda(
args.commit_state_account,
&crate::fast::ID,
args.commit_state_bytes.data_len(),
&[Signer::from(&seeds!(
pda::COMMIT_STATE_TAG,
args.delegated_account.address().as_ref(),
&[commit_state_bump]
))],
args.validator,
)?;

// Initialize the PDA containing the record of the committed state
create_pda(
args.commit_record_account,
Expand Down
2 changes: 2 additions & 0 deletions src/processor/fast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ mod commit_state_from_buffer;
mod delegate;
mod delegate_with_actions;
mod finalize;
mod preallocate_buffer;
mod request_undelegation;
mod undelegate;
mod undelegate_confined_account;
Expand All @@ -24,6 +25,7 @@ pub use commit_state_from_buffer::*;
pub use delegate::*;
pub use delegate_with_actions::*;
pub use finalize::*;
pub use preallocate_buffer::*;
pub use request_undelegation::*;
pub use undelegate::*;
pub use undelegate_confined_account::*;
Expand Down
Loading
Loading