Skip to content
Draft
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
4 changes: 4 additions & 0 deletions src/instruction_builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,12 @@ pub use undelegate_confined_account::*;
pub use validator_claim_fees::*;
pub use whitelist_validator_for_program::*;

mod v2_commit;
mod v2_commit_finalize;
mod v2_commit_finalize_from_buffer;
mod v2_commit_from_buffer;

pub use v2_commit::*;
pub use v2_commit_finalize::*;
pub use v2_commit_finalize_from_buffer::*;
pub use v2_commit_from_buffer::*;
84 changes: 84 additions & 0 deletions src/instruction_builder/v2_commit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
use solana_program::{
instruction::{AccountMeta, Instruction},
pubkey::Pubkey,
system_program,
};

use crate::{
discriminator::DlpDiscriminator,
pda::{
commit_record_pda_from_delegated_account,
commit_state_pda_from_delegated_account,
delegation_metadata_pda_from_delegated_account,
delegation_record_pda_from_delegated_account,
program_config_from_program_id,
validator_fees_vault_pda_from_validator,
},
pod_view::PodView,
total_size_budget,
v2::CommitArgs,
AccountSizeClass, DLP_PROGRAM_DATA_SIZE_CLASS,
};

/// Builds a commit state instruction.
/// See [crate::processor::process_commit_state] for docs.
pub fn v2_commit(
validator: Pubkey,
delegated_account: Pubkey,
delegated_account_owner: Pubkey,
commit_args: CommitArgs,
state_or_diff: &[u8],
) -> Instruction {
let delegation_record_pda =
delegation_record_pda_from_delegated_account(&delegated_account);
let commit_state_pda =
commit_state_pda_from_delegated_account(&delegated_account);
let commit_record_pda =
commit_record_pda_from_delegated_account(&delegated_account);
let validator_fees_vault_pda =
validator_fees_vault_pda_from_validator(&validator);
let delegation_metadata_pda =
delegation_metadata_pda_from_delegated_account(&delegated_account);
let program_config_pda =
program_config_from_program_id(&delegated_account_owner);
Instruction {
program_id: crate::id(),
accounts: vec![
AccountMeta::new_readonly(validator, true),
AccountMeta::new_readonly(delegated_account, false),
AccountMeta::new(commit_state_pda, false),
AccountMeta::new(commit_record_pda, false),
AccountMeta::new_readonly(delegation_record_pda, false),
AccountMeta::new(delegation_metadata_pda, false),
AccountMeta::new_readonly(validator_fees_vault_pda, false),
AccountMeta::new_readonly(program_config_pda, false),
AccountMeta::new_readonly(system_program::id(), false),
],
data: [
DlpDiscriminator::CommitState.to_vec(),
commit_args.to_bytes(),
state_or_diff.to_vec(),
]
.concat(),
}
}

///
/// Returns accounts-data-size budget for commit_state instruction.
///
/// This value can be used with ComputeBudgetInstruction::SetLoadedAccountsDataSizeLimit
///
pub fn v2_commit_size_budget(delegated_account: AccountSizeClass) -> u32 {
total_size_budget(&[
DLP_PROGRAM_DATA_SIZE_CLASS,
AccountSizeClass::Tiny, // validator
delegated_account, // delegated_account
delegated_account, // commit_state_pda
AccountSizeClass::Tiny, // commit_record_pda
AccountSizeClass::Tiny, // delegation_record_pda
AccountSizeClass::Tiny, // delegation_metadata_pda
AccountSizeClass::Tiny, // validator_fees_vault_pda
AccountSizeClass::Tiny, // program_config_pda
AccountSizeClass::Tiny, // system_program
])
}
87 changes: 87 additions & 0 deletions src/instruction_builder/v2_commit_from_buffer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use solana_program::{
instruction::{AccountMeta, Instruction},
pubkey::Pubkey,
system_program,
};

use crate::{
discriminator::DlpDiscriminator,
pda::{
commit_record_pda_from_delegated_account,
commit_state_pda_from_delegated_account,
delegation_metadata_pda_from_delegated_account,
delegation_record_pda_from_delegated_account,
program_config_from_program_id,
validator_fees_vault_pda_from_validator,
},
pod_view::PodView,
total_size_budget,
v2::CommitArgs,
AccountSizeClass, DLP_PROGRAM_DATA_SIZE_CLASS,
};

/// Builds a commit state from buffer instruction.
/// See [crate::processor::process_commit_state_from_buffer] for docs.
pub fn v2_commit_from_buffer(
validator: Pubkey,
delegated_account: Pubkey,
delegated_account_owner: Pubkey,
commit_state_buffer: Pubkey,
commit_args: CommitArgs,
) -> Instruction {
let delegation_record_pda =
delegation_record_pda_from_delegated_account(&delegated_account);
let commit_state_pda =
commit_state_pda_from_delegated_account(&delegated_account);
let commit_record_pda =
commit_record_pda_from_delegated_account(&delegated_account);
let validator_fees_vault_pda =
validator_fees_vault_pda_from_validator(&validator);
let delegation_metadata_pda =
delegation_metadata_pda_from_delegated_account(&delegated_account);
let program_config_pda =
program_config_from_program_id(&delegated_account_owner);
Instruction {
program_id: crate::id(),
accounts: vec![
AccountMeta::new_readonly(validator, true),
AccountMeta::new_readonly(delegated_account, false),
AccountMeta::new(commit_state_pda, false),
AccountMeta::new(commit_record_pda, false),
AccountMeta::new_readonly(delegation_record_pda, false),
AccountMeta::new(delegation_metadata_pda, false),
AccountMeta::new_readonly(commit_state_buffer, false),
AccountMeta::new_readonly(validator_fees_vault_pda, false),
AccountMeta::new_readonly(program_config_pda, false),
AccountMeta::new_readonly(system_program::id(), false),
],
data: [
DlpDiscriminator::CommitStateFromBuffer.to_vec(),
commit_args.to_bytes(),
]
.concat(),
}
}

///
/// Returns accounts-data-size budget for commit_state_from_buffer instruction.
///
/// This value can be used with ComputeBudgetInstruction::SetLoadedAccountsDataSizeLimit
///
pub fn v2_commit_from_buffer_size_budget(
delegated_account: AccountSizeClass,
) -> u32 {
total_size_budget(&[
DLP_PROGRAM_DATA_SIZE_CLASS,
AccountSizeClass::Tiny, // validator
delegated_account, // delegated_account
delegated_account, // commit_state_pda
AccountSizeClass::Tiny, // commit_record_pda
AccountSizeClass::Tiny, // delegation_record_pda
AccountSizeClass::Tiny, // delegation_metadata_pda
delegated_account, // commit_state_buffer
AccountSizeClass::Tiny, // validator_fees_vault_pda
AccountSizeClass::Tiny, // program_config_pda
AccountSizeClass::Tiny, // system_program
])
}
2 changes: 2 additions & 0 deletions src/v2/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ pub const IX_TABLE: [Processor; 256] = {
table[DelegateWithAnyValidator.index()] = process_delegate_with_any_validator;

// Commit group
table[Commit.index()] = process_commit;
table[CommitFromBuffer.index()] = process_commit_from_buffer;
table[CommitFinalize.index()] = process_commit_finalize;
table[CommitFinalizeFromBuffer.index()] = process_commit_finalize_from_buffer;
table[CommitFinalizeInline.index()] = |accounts, data| {
Expand Down
94 changes: 94 additions & 0 deletions src/v2/processor/commit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
use bytemuck::{Pod, Zeroable};
use pinocchio::{AccountView, ProgramResult};
use pinocchio_log::log;

use crate::{
args::Boolean,
processor::fast::NewState,
require_n_accounts,
v2::{
processor::internal::{process_commit_internal, CommitInternalArgs},
HeaderWithBuffer,
},
DiffSet,
};

/// Commit a new state, or a diff, directly to the delegated account. Unlike, CommitState and
/// CommitDiff variants, this instruction does not write to any temporary account first. In other
/// words, this instruction commits and finalizes both.
///
/// Accounts:
///
/// 0: `[signer]` the validator requesting the commit
/// 1: `[]` the delegated account
/// 2: `[]` the delegation record
/// 3: `[writable]` the delegation metadata
/// 4: `[]` the validator fees vault
/// 5: `[]` the program config account
/// 6: `[]` system program
///
/// Instruction Data: CommitFinalizeArgsWithBuffer
///

#[repr(C)]
#[derive(Copy, Clone, Pod, Zeroable)]
pub struct CommitArgs {
/// the commit_id ensures correct ordering of commits
pub commit_id: u64,

/// the lamports that the delegated account holds in the ephemeral validator
pub lamports: u64,

/// whether the account can be undelegated after the commit completes
pub allow_undelegation: Boolean,

/// whether the data (in the ixdata or in the data account) is diff or full state.
pub data_is_diff: Boolean,

pub reserved_padding: [u8; 6],
}

/// buffer is the diff-data or the full-bytes data
pub type CommitArgsWithBuffer<'a> = HeaderWithBuffer<'a, CommitArgs>;

pub fn process_commit(accounts: &[AccountView], data: &[u8]) -> ProgramResult {
let [
validator, // force multi-line
delegated_account,
delegation_state,
validator_fees_vault,
_system_program,
] = require_n_accounts!(accounts, 5);

let args = CommitArgsWithBuffer::from_bytes(data)?;

if args.data_is_diff.is_true() {
let commit_args = CommitInternalArgs {
new_state: {
let diffset = DiffSet::try_new(args.buffer)?;
if diffset.segments_count() == 0 {
log!("WARN: noop; empty diff sent");
}
NewState::Diff(diffset)
},
commit_id: args.commit_id,
allow_undelegation: args.allow_undelegation.is_true(),
validator,
delegated_account,
delegation_state,
validator_fees_vault,
};
process_commit_internal(commit_args)
} else {
let commit_args = CommitInternalArgs {
new_state: NewState::FullBytes(args.buffer),
commit_id: args.commit_id,
allow_undelegation: args.allow_undelegation.is_true(),
validator,
delegated_account,
delegation_state,
validator_fees_vault,
};
process_commit_internal(commit_args)
}
}
75 changes: 75 additions & 0 deletions src/v2/processor/commit_from_buffer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
use pinocchio::{AccountView, ProgramResult};
use pinocchio_log::log;

use crate::{
pod_view::PodView,
processor::fast::NewState,
require_n_accounts,
v2::{
processor::internal::{process_commit_internal, CommitInternalArgs},
CommitArgs,
},
DiffSet,
};

/// Just like Commit, commit a new state, or a diff, directly to the delegated account. Unlike Commit, the state or diff comes from a buffer account.
///
/// Accounts:
///
/// 0: `[signer]` the validator requesting the commit
/// 1: `[]` the delegated account
/// 2: `[]` the delegation record
/// 3: `[writable]` the delegation metadata
/// 4: `[]` the validator fees vault
/// 5: `[]` the program config account
/// 6: `[]` system program
///
/// Instruction Data: CommitArgs
///
pub fn process_commit_from_buffer(
accounts: &[AccountView],
data: &[u8],
) -> ProgramResult {
let [
validator, // force multi-line
delegated_account,
delegation_state,
buffer_account,
validator_fees_vault,
_system_program,
] = require_n_accounts!(accounts, 6);

let args = CommitArgs::try_view_from(data)?;

let data = buffer_account.try_borrow()?;

if args.data_is_diff.is_true() {
let commit_args = CommitInternalArgs {
new_state: {
let diffset = DiffSet::try_new(&data)?;
if diffset.segments_count() == 0 {
log!("WARN: noop; empty diff sent");
}
NewState::Diff(diffset)
},
commit_id: args.commit_id,
allow_undelegation: args.allow_undelegation.is_true(),
validator,
delegated_account,
delegation_state,
validator_fees_vault,
};
process_commit_internal(commit_args)
} else {
let commit_args = CommitInternalArgs {
new_state: NewState::FullBytes(&data),
commit_id: args.commit_id,
allow_undelegation: args.allow_undelegation.is_true(),
validator,
delegated_account,
delegation_state,
validator_fees_vault,
};
process_commit_internal(commit_args)
}
}
Loading
Loading