From acb567dcd6ed8d97bc35db25e6655d8f2412547c Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Thu, 22 Oct 2026 01:21:12 +0530 Subject: [PATCH 1/6] feat: Implement Delegate for the primary protocol Add the shared one-byte Delegate instruction and initialize a cluster-bound, wheels-based DelegationState. Validate delegated account seeds with supplied bumps, preserve delegation lifecycle data, and leave the legacy delegation path unchanged. --- interface/src/args/delegate.rs | 48 +++ interface/src/args/mod.rs | 2 + interface/src/instruction.rs | 2 + interface/src/instruction_builder/delegate.rs | 52 ++++ interface/src/instruction_builder/mod.rs | 2 + interface/src/pda.rs | 9 + interface/src/state/delegation_state.rs | 93 ++++++ interface/src/state/mod.rs | 2 + program/src/processor/delegate.rs | 227 ++++++++++++++ program/src/processor/mod.rs | 3 + program/tests/test_primary_delegate.rs | 278 ++++++++++++++++++ 11 files changed, 718 insertions(+) create mode 100644 interface/src/args/delegate.rs create mode 100644 interface/src/instruction_builder/delegate.rs create mode 100644 interface/src/state/delegation_state.rs create mode 100644 program/src/processor/delegate.rs create mode 100644 program/tests/test_primary_delegate.rs diff --git a/interface/src/args/delegate.rs b/interface/src/args/delegate.rs new file mode 100644 index 00000000..bda44a87 --- /dev/null +++ b/interface/src/args/delegate.rs @@ -0,0 +1,48 @@ +use wheels::variable_offset_layout; + +/// One owner-program seed used to derive the delegated account. +#[derive(Clone, Debug, PartialEq, Eq)] +#[variable_offset_layout(buffer_offset = unknown)] +pub struct DelegationSeed { + #[flexible = 1] + pub value: Vec, +} + +impl<'a> DelegationSeedView<'a> { + /// Returns the seed without its one-byte variable-layout length prefix. + pub fn as_slice(&self) -> &'a [u8] { + &self.bytes()[1..] + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +#[variable_offset_layout(buffer_offset = 1)] +pub struct DelegateArgs { + /// Bump for the owner-program delegate buffer PDA. + /// Set by the instruction builder. + pub delegate_buffer_bump: u8, + + /// Bump for the DLP-owned DelegationState PDA. + /// Set by the instruction builder. + pub delegation_state_bump: u8, + + /// Bump used with `seeds` to derive an off-curve delegated account. + /// Must be zero for an on-curve delegated account. + pub delegated_account_bump: u8, + + /// Owner-program seeds used to derive an off-curve delegated account. + #[flexible = 1] + #[element_size = variable] + pub seeds: Vec, +} + +impl DelegateArgs { + pub fn new(delegated_account_bump: u8, seeds: Vec) -> Self { + Self { + delegate_buffer_bump: 0, + delegation_state_bump: 0, + delegated_account_bump, + seeds, + } + } +} diff --git a/interface/src/args/mod.rs b/interface/src/args/mod.rs index 68103ced..127da0fc 100644 --- a/interface/src/args/mod.rs +++ b/interface/src/args/mod.rs @@ -2,6 +2,7 @@ // instruction tag, so v2 instruction args use `buffer_offset = 1`. mod challenger_reveal; +mod delegate; mod init_delegation_cluster; mod propose_commitment; mod raise_challenge; @@ -13,6 +14,7 @@ mod update_verifier_registry; mod write_state_buffer; pub use challenger_reveal::*; +pub use delegate::*; pub use init_delegation_cluster::*; pub use propose_commitment::*; pub use raise_challenge::*; diff --git a/interface/src/instruction.rs b/interface/src/instruction.rs index 33241858..e0a65cb9 100644 --- a/interface/src/instruction.rs +++ b/interface/src/instruction.rs @@ -33,6 +33,8 @@ pub enum DlpV2Instruction { ChallengerReveal = 110, /// Applies resolver decision for a v2 challenge. ResolveDispute = 111, + /// Delegates an account to one delegation cluster. + Delegate = 112, } impl DlpV2Instruction { diff --git a/interface/src/instruction_builder/delegate.rs b/interface/src/instruction_builder/delegate.rs new file mode 100644 index 00000000..768245f8 --- /dev/null +++ b/interface/src/instruction_builder/delegate.rs @@ -0,0 +1,52 @@ +use solana_program::{ + instruction::{AccountMeta, Instruction}, + pubkey::Pubkey, +}; +use solana_sdk_ids::system_program; +use wheels::layout::Encodable; + +use crate::{ + compat::{Compatize, Modernize}, + legacy::pda::DELEGATE_BUFFER_TAG, + pda::{delegation_state_pda, DELEGATION_STATE_SEED}, + DelegateArgs, DlpV2Instruction, +}; + +/// Builds the shared instruction that delegates an account to one cluster. +pub fn delegate( + payer: Pubkey, + delegated_account: Pubkey, + original_owner: Pubkey, + delegation_cluster: Pubkey, + mut args: DelegateArgs, +) -> Instruction { + let (delegate_buffer, delegate_buffer_bump) = Pubkey::find_program_address( + &[DELEGATE_BUFFER_TAG, delegated_account.as_ref()], + &original_owner, + ); + let (_, delegation_state_bump) = Pubkey::find_program_address( + &[DELEGATION_STATE_SEED, delegated_account.as_ref()], + &crate::id().modernize(), + ); + args.delegate_buffer_bump = delegate_buffer_bump; + args.delegation_state_bump = delegation_state_bump; + + Instruction { + program_id: crate::id().modernize(), + accounts: vec![ + AccountMeta::new(payer, true), + AccountMeta::new(delegated_account, true), + AccountMeta::new_readonly(original_owner, false), + AccountMeta::new(delegate_buffer, false), + AccountMeta::new( + delegation_state_pda(&delegated_account.compatize()) + .modernize(), + false, + ), + AccountMeta::new_readonly(delegation_cluster, false), + AccountMeta::new_readonly(system_program::id(), false), + ], + data: [DlpV2Instruction::Delegate.to_vec(), args.encode().unwrap()] + .concat(), + } +} diff --git a/interface/src/instruction_builder/mod.rs b/interface/src/instruction_builder/mod.rs index 5479da8b..2a4b5eb0 100644 --- a/interface/src/instruction_builder/mod.rs +++ b/interface/src/instruction_builder/mod.rs @@ -1,5 +1,6 @@ mod approve_commitment; mod challenger_reveal; +mod delegate; mod finalize_commitment; mod init_delegation_cluster; mod propose_commitment; @@ -13,6 +14,7 @@ mod write_state_buffer; pub use approve_commitment::*; pub use challenger_reveal::*; +pub use delegate::*; pub use finalize_commitment::*; pub use init_delegation_cluster::*; pub use propose_commitment::*; diff --git a/interface/src/pda.rs b/interface/src/pda.rs index c728409b..6a46cb0c 100644 --- a/interface/src/pda.rs +++ b/interface/src/pda.rs @@ -1,6 +1,7 @@ use crate::compat::Pubkey; pub const DELEGATION_CLUSTER_SEED: &[u8] = b"delegation-cluster"; +pub const DELEGATION_STATE_SEED: &[u8] = b"delegation-state"; pub const OPERATOR_BOND_SEED: &[u8] = b"operator-bond"; pub const VERIFIER_BOND_SEED: &[u8] = b"verifier-bond"; pub const VERIFIER_REGISTRY_SEED: &[u8] = b"verifier-registry"; @@ -18,6 +19,14 @@ pub fn delegation_cluster_pda(cluster_id: &Pubkey) -> Pubkey { .0 } +pub fn delegation_state_pda(delegated_account: &Pubkey) -> Pubkey { + Pubkey::find_program_address( + &[DELEGATION_STATE_SEED, delegated_account.as_ref()], + &crate::id(), + ) + .0 +} + pub fn verifier_registry_pda(delegation_cluster: &Pubkey) -> Pubkey { Pubkey::find_program_address( &[VERIFIER_REGISTRY_SEED, delegation_cluster.as_ref()], diff --git a/interface/src/state/delegation_state.rs b/interface/src/state/delegation_state.rs new file mode 100644 index 00000000..0c645f6e --- /dev/null +++ b/interface/src/state/delegation_state.rs @@ -0,0 +1,93 @@ +use wheels::{ + fixed_offset_layout, layout::VariableLayoutSlice, DataLayoutError, +}; + +use crate::{compat::Pubkey, error::DlpError, DelegationSeed}; + +/// PDA: `["delegation-state", delegated_account]`. +/// Created by `Delegate`; closed when the account is undelegated. +#[derive(Clone, Debug, PartialEq, Eq)] +#[fixed_offset_layout(buffer_offset = 0)] +pub struct DelegationState { + /// Account type marker. + pub discriminator: [u8; 8], + + /// Canonical PDA bump for this account. + pub bump: u8, + + /// Account controlled by this delegation state. + pub delegated_account: Pubkey, + + /// Stable cluster authority for this delegation. + pub delegation_cluster: Pubkey, + + /// Program that owned the account before delegation. + pub original_owner: Pubkey, + + /// Account that paid to create this delegation state. + pub rent_payer: Pubkey, + + /// Slot in which this delegation was created. + pub delegation_slot: u64, + + /// Account lamports at delegation or after the latest finalization. + pub lamports: u64, + + /// Latest finalized commit id applied to the delegated account. + pub last_commit_id: u64, + + /// Who requested undelegation, stored as `UndelegationRequester::value()`. + pub undelegation_requester: u8, + + /// Bump used with the stored seeds for an off-curve delegated account. + pub delegated_account_bump: u8, + + /// Number of owner-program seeds encoded in `encoded_seeds`. + pub seed_count: u8, + + /// Self-delimiting `DelegationSeed` values used to derive the account. + #[extendable = 2] + pub encoded_seeds: Vec, +} + +impl DelegationState { + pub const DISCRIMINATOR: [u8; 8] = *b"v2delst0"; + pub const MAX_SEEDS: usize = 8; + pub const MAX_SEED_LEN: usize = 32; + pub const ENCODED_SEEDS_LEN_HEADER_LEN: usize = 2; + + pub fn data_len_from_encoded_seeds_len( + encoded_seeds_len: usize, + ) -> Result { + Self::MIN_DATA_LEN + .checked_add(Self::ENCODED_SEEDS_LEN_HEADER_LEN) + .and_then(|len| len.checked_add(encoded_seeds_len)) + .ok_or(DlpError::Overflow) + } +} + +impl<'a> DelegationStateView<'a> { + pub fn seeds( + &self, + ) -> Result, DataLayoutError> { + VariableLayoutSlice::new( + self.encoded_seeds().as_slice(), + self.seed_count() as usize, + ) + } +} + +/// Identifies who requested that a delegated account be undelegated. +#[repr(u8)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum UndelegationRequester { + None = 0, + Validator = 1, + OwnerProgram = 2, +} + +impl UndelegationRequester { + pub const fn value(self) -> u8 { + self as u8 + } +} diff --git a/interface/src/state/mod.rs b/interface/src/state/mod.rs index 9dfc0921..652e2755 100644 --- a/interface/src/state/mod.rs +++ b/interface/src/state/mod.rs @@ -1,5 +1,6 @@ mod challenge; mod delegation_cluster; +mod delegation_state; mod operator_bond; mod pending_commitment; mod state_buffer; @@ -8,6 +9,7 @@ mod verifier_registry; pub use challenge::*; pub use delegation_cluster::*; +pub use delegation_state::*; pub use operator_bond::*; pub use pending_commitment::*; pub use state_buffer::*; diff --git a/program/src/processor/delegate.rs b/program/src/processor/delegate.rs new file mode 100644 index 00000000..324e005e --- /dev/null +++ b/program/src/processor/delegate.rs @@ -0,0 +1,227 @@ +use delegation_program_interface as dpi; +use dpi::{ + error::DlpError, + legacy::pda::DELEGATE_BUFFER_TAG, + pda::{DELEGATION_CLUSTER_SEED, DELEGATION_STATE_SEED}, + DelegateArgs, DelegationCluster, DelegationState, UndelegationRequester, +}; +use pinocchio::{ + address::{address_eq, Address}, + cpi::{Seed, Signer}, + error::ProgramError, + sysvars::{clock::Clock, rent::Rent, Sysvar}, + AccountView, ProgramResult, +}; +use pinocchio_system::instructions as system; +use wheels::{ + layout::Decodable, require, require_eq, require_eq_keys, require_le, + require_n_accounts, require_owned_by, require_signer, +}; + +use crate::{ + legacy::processor::{ + fast::utils::pda::{create_pda, AccountSpace}, + utils::curve::is_on_curve_fast, + }, + requires::{require_uninitialized_account, StandardCtx}, +}; + +/// Delegate an account to one delegation cluster. +/// +/// Accounts: +/// 0: `[signer, writable]` delegation-state rent payer +/// 1: `[signer, writable]` delegated account, signed by its owner program +/// 2: `[]` original owner program +/// 3: `[writable]` owner-program delegate buffer PDA +/// 4: `[writable]` DelegationState PDA +/// 5: `[]` DelegationCluster PDA +/// 6: `[]` system program, required by system CPI +#[inline(never)] +pub fn process_delegate( + accounts: &[AccountView], + data: &[u8], +) -> ProgramResult { + let [ + payer, // force multi-line + delegated_account, + original_owner, + delegate_buffer, + delegation_state, + delegation_cluster, + _system_program, + ] = require_n_accounts!(accounts, 7); + + require_signer!(payer); + require_signer!(delegated_account); + require_owned_by!(delegated_account, &crate::fast::ID); + + let args = DelegateArgs::decode(data)?; + validate_delegated_account(delegated_account, original_owner, &args)?; + + let delegate_buffer_bump = [args.delegate_buffer_bump()]; + dpi::require_pda!( + delegate_buffer, + &[ + DELEGATE_BUFFER_TAG, + delegated_account.address().as_ref(), + &delegate_buffer_bump, + ], + original_owner.address(), + true + ); + + let delegation_state_bump = [args.delegation_state_bump()]; + dpi::require_pda!( + delegation_state, + &[ + DELEGATION_STATE_SEED, + delegated_account.address().as_ref(), + &delegation_state_bump, + ], + &crate::fast::ID, + true + ); + require_uninitialized_account( + delegation_state, + true, + StandardCtx::new("delegation state"), + )?; + + let delegation_cluster_data = delegation_cluster.try_borrow()?; + let delegation_cluster_state = + DelegationCluster::decode(delegation_cluster_data.as_ref())?; + let delegation_cluster_bump = [delegation_cluster_state.bump()]; + dpi::require_initialized_pda!( + delegation_cluster, + &[ + DELEGATION_CLUSTER_SEED, + delegation_cluster_state.cluster_id().as_ref(), + &delegation_cluster_bump, + ], + &crate::fast::ID, + false + ); + require_eq!( + &delegation_cluster_state.discriminator(), + &DelegationCluster::DISCRIMINATOR, + ProgramError::InvalidAccountData + ); + require!( + !delegation_cluster_state.paused(), + ProgramError::InvalidAccountData + ); + drop(delegation_cluster_data); + + let seeds = args.seeds(); + let encoded_seeds = seeds.as_bytes(); + let state_len = + DelegationState::data_len_from_encoded_seeds_len(encoded_seeds.len())?; + let delegated_account_lamports = delegated_account.lamports(); + + create_pda( + delegation_state, + &crate::fast::ID, + AccountSpace::CurrentRent(state_len), + &[Signer::from(&[ + Seed::from(DELEGATION_STATE_SEED), + Seed::from(delegated_account.address().as_ref()), + Seed::from(&delegation_state_bump), + ])], + payer, + )?; + + let mut state = DelegationState::decode_mut(delegation_state)?; + *state.discriminator_mut()? = DelegationState::DISCRIMINATOR; + *state.bump_mut()? = args.delegation_state_bump(); + *state.delegated_account_mut()? = *delegated_account.address(); + *state.delegation_cluster_mut()? = *delegation_cluster.address(); + *state.original_owner_mut()? = *original_owner.address(); + *state.rent_payer_mut()? = *payer.address(); + state.delegation_slot_mut()?.set(Clock::get()?.slot)?; + state.lamports_mut()?.set(delegated_account_lamports)?; + state.last_commit_id_mut()?.set(0)?; + *state.undelegation_requester_mut()? = UndelegationRequester::None.value(); + *state.delegated_account_bump_mut()? = args.delegated_account_bump(); + *state.seed_count_mut()? = seeds.len() as u8; + state + .encoded_seeds_mut()? + .extend_from_slice(encoded_seeds)?; + + if !delegate_buffer.is_data_empty() { + require_eq!( + delegate_buffer.data_len(), + delegated_account.data_len(), + ProgramError::InvalidAccountData + ); + delegated_account + .try_borrow_mut()? + .copy_from_slice(delegate_buffer.try_borrow()?.as_ref()); + } + + // Preserve the original zero-lamport state in DelegationState, then fund + // an empty delegated account enough to keep it alive on the base layer. + if delegated_account_lamports == 0 && delegated_account.is_data_empty() { + system::Transfer { + from: payer, + to: delegated_account, + lamports: Rent::get()?.try_minimum_balance(0)?, + } + .invoke()?; + } + + Ok(()) +} + +fn validate_delegated_account( + delegated_account: &AccountView, + original_owner: &AccountView, + args: &dpi::DelegateArgsView<'_>, +) -> ProgramResult { + let seeds = args.seeds(); + require_le!( + seeds.len(), + DelegationState::MAX_SEEDS, + DlpError::TooManySeeds + ); + + if is_on_curve_fast(delegated_account.address()) { + require_eq!(seeds.len(), 0, ProgramError::InvalidInstructionData); + require_eq!( + args.delegated_account_bump(), + 0, + ProgramError::InvalidInstructionData + ); + return Ok(()); + } + + require!(!seeds.is_empty(), ProgramError::InvalidInstructionData); + + let mut pda_seeds: [&[u8]; DelegationState::MAX_SEEDS + 1] = + [&[]; DelegationState::MAX_SEEDS + 1]; + for (index, seed) in seeds.iter().enumerate() { + require_le!( + seed.as_slice().len(), + DelegationState::MAX_SEED_LEN, + ProgramError::MaxSeedLengthExceeded + ); + pda_seeds[index] = seed.as_slice(); + } + let delegated_account_bump = [args.delegated_account_bump()]; + pda_seeds[seeds.len()] = &delegated_account_bump; + + let owner = if address_eq(original_owner.address(), &pinocchio_system::ID) { + &crate::fast::ID + } else { + original_owner.address() + }; + let derived_account = + Address::create_program_address(&pda_seeds[..=seeds.len()], owner) + .map_err(|_| ProgramError::InvalidSeeds)?; + require_eq_keys!( + &derived_account, + delegated_account.address(), + ProgramError::InvalidSeeds + ); + + Ok(()) +} diff --git a/program/src/processor/mod.rs b/program/src/processor/mod.rs index ed630dbb..11fbba97 100644 --- a/program/src/processor/mod.rs +++ b/program/src/processor/mod.rs @@ -1,8 +1,10 @@ use delegation_program_interface as dpi; mod bootstrap; +mod delegate; mod fraud_proofs; pub use bootstrap::*; +pub use delegate::*; use dpi::DlpV2Instruction; pub use fraud_proofs::*; use pinocchio::{AccountView, ProgramResult}; @@ -50,5 +52,6 @@ pub fn process_instruction( DlpV2Instruction::ResolveDispute => { process_resolve_dispute(accounts, data) } + DlpV2Instruction::Delegate => process_delegate(accounts, data), } } diff --git a/program/tests/test_primary_delegate.rs b/program/tests/test_primary_delegate.rs new file mode 100644 index 00000000..b03d14fa --- /dev/null +++ b/program/tests/test_primary_delegate.rs @@ -0,0 +1,278 @@ +use delegation_program::solana_program; +use delegation_program_interface as dpi; +use dpi::{ + instruction_builder::delegate, + legacy::pda::DELEGATE_BUFFER_TAG, + pda::{delegation_state_pda, DELEGATION_STATE_SEED}, + DelegateArgs, DelegationSeed, DelegationState, UndelegationRequester, +}; +use solana_program::{ + account_info::AccountInfo, + entrypoint::ProgramResult, + instruction::{AccountMeta, Instruction}, + native_token::LAMPORTS_PER_SOL, + program::invoke_signed, + program_error::ProgramError, + pubkey::Pubkey, + rent::Rent, +}; +use solana_program_test::{processor, BanksClient, ProgramTest}; +use solana_sdk::{ + account::Account, + signature::{Keypair, Signer}, + transaction::Transaction, +}; +use solana_sdk_ids::system_program; +use wheels::layout::Decodable; + +#[allow(dead_code)] +mod fixtures; + +use crate::fixtures::v2::{direct_cluster_args, initialize_delegation_cluster}; + +const OWNER_PROGRAM_ID: Pubkey = + solana_sdk::pubkey!("4vJ9JU1bJJE96FWSJKvHsmmFADCg4gpZQff4EVRtnYHk"); +const DELEGATED_ACCOUNT_SEED: &[u8] = b"primary-delegated"; +const DELEGATED_ACCOUNT_DATA: &[u8] = b"primary account data"; + +struct DelegateTestContext { + banks: BanksClient, + payer: Keypair, + delegated_account: Pubkey, + delegated_account_bump: u8, + delegation_cluster: Pubkey, +} + +#[tokio::test] +async fn test_delegate_creates_cluster_bound_delegation_state() { + let context = setup_delegate_test().await; + let delegation_state = + delegation_state_pda(&context.delegated_account.to_bytes().into()); + let (_, expected_state_bump) = Pubkey::find_program_address( + &[DELEGATION_STATE_SEED, context.delegated_account.as_ref()], + &dpi::id(), + ); + + let result = submit_delegate( + &context, + DelegateArgs::new( + context.delegated_account_bump, + vec![DelegationSeed { + value: DELEGATED_ACCOUNT_SEED.to_vec(), + }], + ), + ) + .await; + assert!(result.is_ok()); + + let delegated_account = context + .banks + .get_account(context.delegated_account) + .await + .unwrap() + .unwrap(); + assert_eq!(delegated_account.owner, dpi::id()); + assert_eq!(delegated_account.data, DELEGATED_ACCOUNT_DATA); + + let state_account = context + .banks + .get_account(delegation_state) + .await + .unwrap() + .unwrap(); + let state = DelegationState::decode(&state_account.data).unwrap(); + let seeds = state.seeds().unwrap(); + + assert_eq!(state.discriminator(), DelegationState::DISCRIMINATOR); + assert_eq!(state.bump(), expected_state_bump); + assert_eq!(*state.delegated_account(), context.delegated_account); + assert_eq!(*state.delegation_cluster(), context.delegation_cluster); + assert_eq!(*state.original_owner(), OWNER_PROGRAM_ID); + assert_eq!(*state.rent_payer(), context.payer.pubkey()); + assert_eq!(state.lamports(), delegated_account.lamports); + assert_eq!(state.last_commit_id(), 0); + assert_eq!( + state.undelegation_requester(), + UndelegationRequester::None.value() + ); + assert_eq!( + state.delegated_account_bump(), + context.delegated_account_bump + ); + assert_eq!(seeds.len(), 1); + assert_eq!(seeds.get(0).unwrap().as_slice(), DELEGATED_ACCOUNT_SEED); + assert_eq!( + state_account.lamports, + Rent::default().minimum_balance(state_account.data.len()) + ); +} + +#[tokio::test] +async fn test_delegate_rejects_wrong_delegated_account_seeds() { + let context = setup_delegate_test().await; + let result = submit_delegate( + &context, + DelegateArgs::new( + context.delegated_account_bump, + vec![DelegationSeed { + value: b"wrong-seed".to_vec(), + }], + ), + ) + .await; + + assert!(result.is_err()); + assert!(context + .banks + .get_account(delegation_state_pda( + &context.delegated_account.to_bytes().into() + )) + .await + .unwrap() + .is_none()); +} + +async fn setup_delegate_test() -> DelegateTestContext { + let mut program_test = ProgramTest::default(); + program_test.prefer_bpf(true); + program_test.add_program("delegation_program", dpi::ID, None); + program_test.prefer_bpf(false); + program_test.add_program( + "primary-delegate-owner", + OWNER_PROGRAM_ID, + processor!(owner_program_processor), + ); + program_test.prefer_bpf(true); + + let (delegated_account, delegated_account_bump) = + Pubkey::find_program_address( + &[DELEGATED_ACCOUNT_SEED], + &OWNER_PROGRAM_ID, + ); + let delegate_buffer = Pubkey::find_program_address( + &[DELEGATE_BUFFER_TAG, delegated_account.as_ref()], + &OWNER_PROGRAM_ID, + ) + .0; + let config_authority = Keypair::new(); + + program_test.add_account( + delegated_account, + Account { + lamports: Rent::default() + .minimum_balance(DELEGATED_ACCOUNT_DATA.len()), + data: DELEGATED_ACCOUNT_DATA.to_vec(), + owner: dpi::id(), + executable: false, + rent_epoch: 0, + }, + ); + program_test.add_account( + delegate_buffer, + Account { + lamports: Rent::default() + .minimum_balance(DELEGATED_ACCOUNT_DATA.len()), + data: DELEGATED_ACCOUNT_DATA.to_vec(), + owner: OWNER_PROGRAM_ID, + executable: false, + rent_epoch: 0, + }, + ); + program_test.add_account( + config_authority.pubkey(), + Account { + lamports: LAMPORTS_PER_SOL, + data: vec![], + owner: system_program::id(), + executable: false, + rent_epoch: 0, + }, + ); + + let (banks, payer, blockhash) = program_test.start().await; + let delegation_cluster = initialize_delegation_cluster( + &banks, + &payer, + &config_authority, + blockhash, + direct_cluster_args(Pubkey::new_unique()), + ) + .await; + + DelegateTestContext { + banks, + payer, + delegated_account, + delegated_account_bump, + delegation_cluster, + } +} + +async fn submit_delegate( + context: &DelegateTestContext, + args: DelegateArgs, +) -> Result<(), solana_program_test::BanksClientError> { + let inner = delegate( + context.payer.pubkey(), + context.delegated_account, + OWNER_PROGRAM_ID, + context.delegation_cluster, + args, + ); + let mut accounts = inner.accounts; + accounts[1].is_signer = false; + accounts.push(AccountMeta::new_readonly(dpi::id(), false)); + let outer = Instruction { + program_id: OWNER_PROGRAM_ID, + accounts, + data: inner.data, + }; + let transaction = Transaction::new_signed_with_payer( + &[outer], + Some(&context.payer.pubkey()), + &[&context.payer], + context.banks.get_latest_blockhash().await.unwrap(), + ); + + context.banks.process_transaction(transaction).await +} + +fn owner_program_processor( + program_id: &Pubkey, + accounts: &[AccountInfo], + data: &[u8], +) -> ProgramResult { + let [payer, delegated_account, original_owner, delegate_buffer, delegation_state, delegation_cluster, system_program, dlp_program] = + accounts + else { + return Err(ProgramError::NotEnoughAccountKeys); + }; + if original_owner.key != program_id || dlp_program.key != &dpi::id() { + return Err(ProgramError::IncorrectProgramId); + } + + let instruction = Instruction { + program_id: dpi::id(), + accounts: vec![ + AccountMeta::new(*payer.key, true), + AccountMeta::new(*delegated_account.key, true), + AccountMeta::new_readonly(*original_owner.key, false), + AccountMeta::new(*delegate_buffer.key, false), + AccountMeta::new(*delegation_state.key, false), + AccountMeta::new_readonly(*delegation_cluster.key, false), + AccountMeta::new_readonly(*system_program.key, false), + ], + data: data.to_vec(), + }; + let delegated_account_bump = + [ + Pubkey::find_program_address(&[DELEGATED_ACCOUNT_SEED], program_id) + .1, + ]; + + invoke_signed( + &instruction, + accounts, + &[&[DELEGATED_ACCOUNT_SEED, &delegated_account_bump]], + ) +} From c03f894167a39b734d441b9d54ef727b56f3e2ef Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Thu, 22 Oct 2026 01:44:29 +0530 Subject: [PATCH 2/6] Address Delegate review feedback Propagate instruction encoding failures from the public builder, constrain on-curve delegations to their valid system-program owner, and strengthen tests for buffer copying and exact validation errors. --- interface/src/instruction_builder/delegate.rs | 12 +-- program/src/processor/delegate.rs | 5 + program/tests/test_primary_delegate.rs | 98 +++++++++++++++++-- 3 files changed, 102 insertions(+), 13 deletions(-) diff --git a/interface/src/instruction_builder/delegate.rs b/interface/src/instruction_builder/delegate.rs index 768245f8..9bae73fd 100644 --- a/interface/src/instruction_builder/delegate.rs +++ b/interface/src/instruction_builder/delegate.rs @@ -3,7 +3,7 @@ use solana_program::{ pubkey::Pubkey, }; use solana_sdk_ids::system_program; -use wheels::layout::Encodable; +use wheels::{layout::Encodable, DataLayoutError}; use crate::{ compat::{Compatize, Modernize}, @@ -19,7 +19,7 @@ pub fn delegate( original_owner: Pubkey, delegation_cluster: Pubkey, mut args: DelegateArgs, -) -> Instruction { +) -> Result { let (delegate_buffer, delegate_buffer_bump) = Pubkey::find_program_address( &[DELEGATE_BUFFER_TAG, delegated_account.as_ref()], &original_owner, @@ -30,8 +30,9 @@ pub fn delegate( ); args.delegate_buffer_bump = delegate_buffer_bump; args.delegation_state_bump = delegation_state_bump; + let data = [DlpV2Instruction::Delegate.to_vec(), args.encode()?].concat(); - Instruction { + Ok(Instruction { program_id: crate::id().modernize(), accounts: vec![ AccountMeta::new(payer, true), @@ -46,7 +47,6 @@ pub fn delegate( AccountMeta::new_readonly(delegation_cluster, false), AccountMeta::new_readonly(system_program::id(), false), ], - data: [DlpV2Instruction::Delegate.to_vec(), args.encode().unwrap()] - .concat(), - } + data, + }) } diff --git a/program/src/processor/delegate.rs b/program/src/processor/delegate.rs index 324e005e..502710dd 100644 --- a/program/src/processor/delegate.rs +++ b/program/src/processor/delegate.rs @@ -185,6 +185,11 @@ fn validate_delegated_account( ); if is_on_curve_fast(delegated_account.address()) { + require_eq_keys!( + original_owner.address(), + &pinocchio_system::ID, + ProgramError::IncorrectProgramId + ); require_eq!(seeds.len(), 0, ProgramError::InvalidInstructionData); require_eq!( args.delegated_account_bump(), diff --git a/program/tests/test_primary_delegate.rs b/program/tests/test_primary_delegate.rs index b03d14fa..b930350a 100644 --- a/program/tests/test_primary_delegate.rs +++ b/program/tests/test_primary_delegate.rs @@ -16,11 +16,14 @@ use solana_program::{ pubkey::Pubkey, rent::Rent, }; -use solana_program_test::{processor, BanksClient, ProgramTest}; +use solana_program_test::{ + processor, BanksClient, BanksClientError, ProgramTest, +}; use solana_sdk::{ account::Account, + instruction::InstructionError, signature::{Keypair, Signer}, - transaction::Transaction, + transaction::{Transaction, TransactionError}, }; use solana_sdk_ids::system_program; use wheels::layout::Decodable; @@ -34,6 +37,7 @@ const OWNER_PROGRAM_ID: Pubkey = solana_sdk::pubkey!("4vJ9JU1bJJE96FWSJKvHsmmFADCg4gpZQff4EVRtnYHk"); const DELEGATED_ACCOUNT_SEED: &[u8] = b"primary-delegated"; const DELEGATED_ACCOUNT_DATA: &[u8] = b"primary account data"; +const DELEGATE_BUFFER_DATA: &[u8] = b"delegate buffer data"; struct DelegateTestContext { banks: BanksClient, @@ -72,7 +76,7 @@ async fn test_delegate_creates_cluster_bound_delegation_state() { .unwrap() .unwrap(); assert_eq!(delegated_account.owner, dpi::id()); - assert_eq!(delegated_account.data, DELEGATED_ACCOUNT_DATA); + assert_eq!(delegated_account.data, DELEGATE_BUFFER_DATA); let state_account = context .banks @@ -121,7 +125,18 @@ async fn test_delegate_rejects_wrong_delegated_account_seeds() { ) .await; - assert!(result.is_err()); + assert!( + matches!( + &result, + Err(BanksClientError::TransactionError( + TransactionError::InstructionError( + 0, + InstructionError::InvalidSeeds + ) + )) + ), + "unexpected result: {result:?}" + ); assert!(context .banks .get_account(delegation_state_pda( @@ -132,6 +147,74 @@ async fn test_delegate_rejects_wrong_delegated_account_seeds() { .is_none()); } +#[tokio::test] +async fn test_delegate_rejects_non_system_owner_for_on_curve_account() { + let mut program_test = ProgramTest::default(); + program_test.prefer_bpf(true); + program_test.add_program("delegation_program", dpi::ID, None); + + let delegated_account = Keypair::new(); + let config_authority = Keypair::new(); + program_test.add_account( + delegated_account.pubkey(), + Account { + lamports: Rent::default().minimum_balance(0), + data: vec![], + owner: dpi::id(), + executable: false, + rent_epoch: 0, + }, + ); + program_test.add_account( + config_authority.pubkey(), + Account { + lamports: LAMPORTS_PER_SOL, + data: vec![], + owner: system_program::id(), + executable: false, + rent_epoch: 0, + }, + ); + + let (banks, payer, blockhash) = program_test.start().await; + let delegation_cluster = initialize_delegation_cluster( + &banks, + &payer, + &config_authority, + blockhash, + direct_cluster_args(Pubkey::new_unique()), + ) + .await; + let instruction = delegate( + payer.pubkey(), + delegated_account.pubkey(), + OWNER_PROGRAM_ID, + delegation_cluster, + DelegateArgs::new(0, vec![]), + ) + .unwrap(); + let transaction = Transaction::new_signed_with_payer( + &[instruction], + Some(&payer.pubkey()), + &[&payer, &delegated_account], + banks.get_latest_blockhash().await.unwrap(), + ); + let result = banks.process_transaction(transaction).await; + + assert!( + matches!( + &result, + Err(BanksClientError::TransactionError( + TransactionError::InstructionError( + 0, + InstructionError::IncorrectProgramId + ) + )) + ), + "unexpected result: {result:?}" + ); +} + async fn setup_delegate_test() -> DelegateTestContext { let mut program_test = ProgramTest::default(); program_test.prefer_bpf(true); @@ -171,8 +254,8 @@ async fn setup_delegate_test() -> DelegateTestContext { delegate_buffer, Account { lamports: Rent::default() - .minimum_balance(DELEGATED_ACCOUNT_DATA.len()), - data: DELEGATED_ACCOUNT_DATA.to_vec(), + .minimum_balance(DELEGATE_BUFFER_DATA.len()), + data: DELEGATE_BUFFER_DATA.to_vec(), owner: OWNER_PROGRAM_ID, executable: false, rent_epoch: 0, @@ -218,7 +301,8 @@ async fn submit_delegate( OWNER_PROGRAM_ID, context.delegation_cluster, args, - ); + ) + .unwrap(); let mut accounts = inner.accounts; accounts[1].is_signer = false; accounts.push(AccountMeta::new_readonly(dpi::id(), false)); From 5b3fd94933c4da50f4827553faad6ec7b3e0b04f Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Fri, 30 Oct 2026 22:47:56 +0530 Subject: [PATCH 3/6] Use commit sequence terminology in v2 Rename v2 commit identifiers to commit sequences so the API makes their strict ordering explicit. Preserve legacy names, serialized layouts, instruction encoding, PDA derivation, and runtime behavior. --- docs/design/mimd-0024-fraud-proofs.md | 36 +++++------ interface/src/args/propose_commitment.rs | 2 +- interface/src/args/write_state_buffer.rs | 2 +- .../instruction_builder/approve_commitment.rs | 4 +- .../instruction_builder/challenger_reveal.rs | 10 ++-- .../finalize_commitment.rs | 24 ++++---- .../instruction_builder/propose_commitment.rs | 4 +- .../instruction_builder/raise_challenge.rs | 6 +- .../instruction_builder/resolve_dispute.rs | 6 +- .../instruction_builder/write_state_buffer.rs | 2 +- interface/src/pda.rs | 12 ++-- interface/src/state/challenge.rs | 2 +- interface/src/state/delegation_state.rs | 2 +- interface/src/state/pending_commitment.rs | 4 +- interface/src/state/state_buffer.rs | 4 +- program/src/processor/delegate.rs | 2 +- .../fraud_proofs/approve_commitment.rs | 4 +- .../fraud_proofs/challenger_reveal.rs | 24 ++++---- .../fraud_proofs/finalize_commitment.rs | 30 +++++----- .../fraud_proofs/propose_commitment.rs | 26 ++++---- .../processor/fraud_proofs/raise_challenge.rs | 10 ++-- .../processor/fraud_proofs/resolve_dispute.rs | 8 +-- .../fraud_proofs/write_state_buffer.rs | 12 ++-- program/tests/test_approve_commitment.rs | 28 ++++----- program/tests/test_challenger_reveal.rs | 38 ++++++------ program/tests/test_finalize_commitment.rs | 20 +++---- program/tests/test_primary_delegate.rs | 2 +- program/tests/test_propose_commitment.rs | 16 ++--- program/tests/test_raise_challenge.rs | 26 ++++---- program/tests/test_resolve_dispute.rs | 42 ++++++------- program/tests/test_v2_write_state_buffer.rs | 60 +++++++++---------- 31 files changed, 236 insertions(+), 232 deletions(-) diff --git a/docs/design/mimd-0024-fraud-proofs.md b/docs/design/mimd-0024-fraud-proofs.md index 6e84e459..ba6d3b9f 100644 --- a/docs/design/mimd-0024-fraud-proofs.md +++ b/docs/design/mimd-0024-fraud-proofs.md @@ -163,7 +163,7 @@ state_commitment_hash = H( delegation_cluster, operator_identity, account_pubkey, - commit_id, + commit_seq, delegation_record, da_pointer_hash, account_state_hash, @@ -177,7 +177,7 @@ challenge_hash = H( operator_identity, challenger_identity, account_pubkey, - commit_id, + commit_seq, challenger_lamports, challenger_owner, challenger_data_hash, @@ -198,9 +198,9 @@ Seed strings are placeholders until frozen. | `OperatorBond` | `["operator-bond", delegation_cluster]` | Cluster-scoped operator stake for the challenge flow that survives validator rotation. | | `VerifierBond` | `["verifier-bond", delegation_cluster, verifier]` | Verifier stake isolated to one cluster. | | `VerifierRegistry` | `["verifier-registry", delegation_cluster]` | Verifiers selectable for one challenge-enabled cluster. | -| `PendingCommitment` | `["pending-commitment", account, commit_id]` | Main commitment state machine. | -| `StateBuffer` | `["state-buffer", account, commit_id, authority]` | Chunked state payload opened by an operator or challenger. The payload may be full `Account::data` bytes or an encoded diff. | -| `Challenge` | `["challenge", account, commit_id, challenger]` | One challenge against one pending commitment. | +| `PendingCommitment` | `["pending-commitment", account, commit_seq]` | Main commitment state machine. | +| `StateBuffer` | `["state-buffer", account, commit_seq, authority]` | Chunked state payload opened by an operator or challenger. The payload may be full `Account::data` bytes or an encoded diff. | +| `Challenge` | `["challenge", account, commit_seq, challenger]` | One challenge against one pending commitment. | | `PayoutTimelock` | `["payout-timelock", challenge]` | Delayed payout for correct challenger. | ### Essential Fields @@ -376,7 +376,7 @@ pub enum ResolvedStateSource { ChallengerReveal, } -/// PDA: `["pending-commitment", account, commit_id]` +/// PDA: `["pending-commitment", account, commit_seq]` /// Created by: `ProposeCommitment`. /// Closed by: `CloseTerminalAccounts` after finalize, cancel, or expiry. /// @@ -393,7 +393,7 @@ pub struct PendingCommitment { /// Delegated account whose base-layer state will be finalized. pub account_pubkey: Pubkey, /// Validator-chosen nonce for this account commitment. - pub commit_id: u64, + pub commit_seq: u64, /// Delegation metadata tying this account to the ER context. pub delegation_record: Pubkey, /// Hash of replay/data-availability pointer bytes. @@ -454,7 +454,7 @@ pub struct SelectedVerifier { // Review: `challenge_window_id` should be kept only if window extensions or // retries need an explicit round id. -/// PDA: `["state-buffer", account, commit_id, authority]` +/// PDA: `["state-buffer", account, commit_seq, authority]` /// Created by: first `WriteStateBuffer`. /// Frozen by: final `WriteStateBuffer` chunk. /// Closed by: `CloseTerminalAccounts`. @@ -470,7 +470,7 @@ pub struct StateBuffer { pub account_pubkey: Pubkey, /// Commitment this buffer belongs to. - pub commit_id: u64, + pub commit_seq: u64, /// Hash of the uploaded payload. Zero until finalized. pub data_hash: [u8; 32], @@ -509,7 +509,7 @@ pub enum ChallengeOutcome { ChallengerCorrectOperatorSlashed, } -/// PDA: `["challenge", account, commit_id, challenger]` +/// PDA: `["challenge", account, commit_seq, challenger]` /// Created by: `RaiseChallenge`. /// Closed by: `CloseTerminalAccounts` after a terminal challenge outcome. /// @@ -596,8 +596,8 @@ Commitment, approval, challenge, resolution, and finalization instructions. | Instruction | Expected invoker | Description | | --- | --- | --- | -| `WriteStateBuffer`
  • ix-data: commit_id, total_len, offset, chunk
  • accounts: payer signer, authority signer, StateBuffer, delegated account, system program
| Authority for a known state-buffer flow | System-level instruction. Creates, grows, writes, and finalizes a DLP-owned `StateBuffer` PDA using the fixed `["state-buffer", account, commit_id, authority]` seed pattern. The instruction remains cluster-neutral; consuming instructions validate the payload, authority, and cluster relationship. | -| `ProposeCommitment`
  • ix-data: commit_id, lamports, owner, da_pointer_hash, er_slot
  • accounts: current validator signer, OperatorBond, PendingCommitment, finalized operator StateBuffer, delegated account, DelegationRecord, DelegationMetadata, DelegationCluster, VerifierRegistry, system program
| Current validator | Requires `Challenge` mode, verifies the delegation's cluster and current validator, consumes only cluster-scoped bond and registry accounts, selects verifiers, and starts the challenge window. `DelegationRecord` and `DelegationMetadata` are temporary v1-layout dependencies until their v2 replacement exists. | +| `WriteStateBuffer`
  • ix-data: commit_seq, total_len, offset, chunk
  • accounts: payer signer, authority signer, StateBuffer, delegated account, system program
| Authority for a known state-buffer flow | System-level instruction. Creates, grows, writes, and finalizes a DLP-owned `StateBuffer` PDA using the fixed `["state-buffer", account, commit_seq, authority]` seed pattern. The instruction remains cluster-neutral; consuming instructions validate the payload, authority, and cluster relationship. | +| `ProposeCommitment`
  • ix-data: commit_seq, lamports, owner, da_pointer_hash, er_slot
  • accounts: current validator signer, OperatorBond, PendingCommitment, finalized operator StateBuffer, delegated account, DelegationRecord, DelegationMetadata, DelegationCluster, VerifierRegistry, system program
| Current validator | Requires `Challenge` mode, verifies the delegation's cluster and current validator, consumes only cluster-scoped bond and registry accounts, selects verifiers, and starts the challenge window. `DelegationRecord` and `DelegationMetadata` are temporary v1-layout dependencies until their v2 replacement exists. | | `ApproveCommitment`
  • ix-data: empty
  • accounts: verifier signer, VerifierBond, PendingCommitment
| Selected verifier | Records approval from the selected verifier. v2 MVP requires exactly one selected verifier, so no verifier index is needed. Duplicate approvals do not increase the count. | | `RaiseChallenge`
  • ix-data: state_commitment_hash, challenge_hash, stake_lamports
  • accounts: challenger signer, Challenge, PendingCommitment, DelegationCluster, system program
| Challenger | Requires the cluster stored by the pending commitment, locks challenger stake, stores the salted `challenge_hash`, and blocks normal finalization until reveal, timeout, or resolution. It does not consume challenger state bytes. | | `ChallengerReveal`
  • ix-data: lamports, owner, data_hash, salt
  • accounts: challenger signer, Challenge, PendingCommitment, finalized operator StateBuffer, finalized challenger StateBuffer, DelegationCluster, protocol fee vault
| Challenger | Opens the challenged state and salt, validates both state buffers and the stored `challenge_hash`, penalizes invalid or matching reveals, or moves mismatches to resolver decision. | @@ -653,10 +653,10 @@ create and write accounts in the `StateBuffer` namespace, using the fixed seed pattern: ```text -["state-buffer", account, commit_id, authority] +["state-buffer", account, commit_seq, authority] ``` -The header must bind the same `authority`, `account_pubkey`, and `commit_id`. +The header must bind the same `authority`, `account_pubkey`, and `commit_seq`. The buffer is inert until a consuming instruction validates the authority role: - `ProposeCommitment` accepts a finalized buffer whose authority is the operator; @@ -666,7 +666,7 @@ The buffer is inert until a consuming instruction validates the authority role: needs buffered transport, and validates authority against the challenger. If future protocol flows need multiple buffer purposes for the same -`account + commit_id + authority`, add an explicit `buffer_kind` or purpose seed +`account + commit_seq + authority`, add an explicit `buffer_kind` or purpose seed and matching header field. Reusing the same address space for unrelated opened state can create collisions or confused-consumer bugs. @@ -676,7 +676,7 @@ duplicate retries remain valid. Consuming instructions must check: -- buffer PDA seeds match `account_pubkey`, `commit_id`, and `authority`; +- buffer PDA seeds match `account_pubkey`, `commit_seq`, and `authority`; - buffer is finalized; - buffer commitment matches the `PendingCommitment`; - authority matches the operator for `ProposeCommitment` and happy-path @@ -692,7 +692,7 @@ are too slow. ```rust pub struct WriteStateBufferArgs<'a> { - pub commit_id: u64, + pub commit_seq: u64, pub total_len: u32, /// Must equal StateBuffer.payload.len(), unless retrying an exact old chunk. pub offset: u32, @@ -700,7 +700,7 @@ pub struct WriteStateBufferArgs<'a> { } pub struct ProposeCommitmentArgs { - pub commit_id: u64, + pub commit_seq: u64, pub lamports: u64, pub owner: Pubkey, pub da_pointer_hash: [u8; 32], diff --git a/interface/src/args/propose_commitment.rs b/interface/src/args/propose_commitment.rs index ba6face9..21d9b138 100644 --- a/interface/src/args/propose_commitment.rs +++ b/interface/src/args/propose_commitment.rs @@ -5,7 +5,7 @@ use crate::compat::Pubkey; #[derive(Clone, Debug, PartialEq, Eq)] #[variable_offset_layout(buffer_offset = 1)] pub struct ProposeCommitmentArgs { - pub commit_id: u64, + pub commit_seq: u64, pub lamports: u64, diff --git a/interface/src/args/write_state_buffer.rs b/interface/src/args/write_state_buffer.rs index ce6781bc..6df48fad 100644 --- a/interface/src/args/write_state_buffer.rs +++ b/interface/src/args/write_state_buffer.rs @@ -3,7 +3,7 @@ use wheels::variable_offset_layout; #[derive(Clone, Debug, PartialEq, Eq)] #[variable_offset_layout(buffer_offset = 1)] pub struct WriteStateBufferArgs { - pub commit_id: u64, + pub commit_seq: u64, pub total_len: u32, diff --git a/interface/src/instruction_builder/approve_commitment.rs b/interface/src/instruction_builder/approve_commitment.rs index 400d0478..9e959a9e 100644 --- a/interface/src/instruction_builder/approve_commitment.rs +++ b/interface/src/instruction_builder/approve_commitment.rs @@ -14,7 +14,7 @@ pub fn approve_commitment( verifier: Pubkey, delegation_cluster: Pubkey, account: Pubkey, - commit_id: u64, + commit_seq: u64, ) -> Instruction { Instruction { program_id: crate::id().modernize(), @@ -29,7 +29,7 @@ pub fn approve_commitment( false, ), AccountMeta::new( - pending_commitment_pda(&account.compatize(), commit_id) + pending_commitment_pda(&account.compatize(), commit_seq) .modernize(), false, ), diff --git a/interface/src/instruction_builder/challenger_reveal.rs b/interface/src/instruction_builder/challenger_reveal.rs index bf86d698..8d7ed34b 100644 --- a/interface/src/instruction_builder/challenger_reveal.rs +++ b/interface/src/instruction_builder/challenger_reveal.rs @@ -17,7 +17,7 @@ pub fn challenger_reveal( operator: Pubkey, delegation_cluster: Pubkey, account: Pubkey, - commit_id: u64, + commit_seq: u64, args: ChallengerRevealArgs, ) -> Instruction { Instruction { @@ -27,21 +27,21 @@ pub fn challenger_reveal( AccountMeta::new( challenge_pda( &account.compatize(), - commit_id, + commit_seq, &challenger.compatize(), ) .modernize(), false, ), AccountMeta::new( - pending_commitment_pda(&account.compatize(), commit_id) + pending_commitment_pda(&account.compatize(), commit_seq) .modernize(), false, ), AccountMeta::new_readonly( state_buffer_pda( &account.compatize(), - commit_id, + commit_seq, &operator.compatize(), ) .modernize(), @@ -50,7 +50,7 @@ pub fn challenger_reveal( AccountMeta::new_readonly( state_buffer_pda( &account.compatize(), - commit_id, + commit_seq, &challenger.compatize(), ) .modernize(), diff --git a/interface/src/instruction_builder/finalize_commitment.rs b/interface/src/instruction_builder/finalize_commitment.rs index 4d3d73c4..7c5c21eb 100644 --- a/interface/src/instruction_builder/finalize_commitment.rs +++ b/interface/src/instruction_builder/finalize_commitment.rs @@ -19,13 +19,13 @@ pub fn finalize_commitment( operator: Pubkey, delegation_cluster: Pubkey, account: Pubkey, - commit_id: u64, + commit_seq: u64, ) -> Instruction { finalize_commitment_with_state_authority( operator, delegation_cluster, account, - commit_id, + commit_seq, None, ) } @@ -35,17 +35,20 @@ pub fn finalize_challenger_commitment( challenger: Pubkey, delegation_cluster: Pubkey, account: Pubkey, - commit_id: u64, + commit_seq: u64, ) -> Instruction { - let challenge = - challenge_pda(&account.compatize(), commit_id, &challenger.compatize()) - .modernize(); + let challenge = challenge_pda( + &account.compatize(), + commit_seq, + &challenger.compatize(), + ) + .modernize(); finalize_commitment_with_state_authority( challenger, delegation_cluster, account, - commit_id, + commit_seq, Some(challenge), ) } @@ -54,13 +57,14 @@ fn finalize_commitment_with_state_authority( state_authority: Pubkey, delegation_cluster: Pubkey, account: Pubkey, - commit_id: u64, + commit_seq: u64, challenge: Option, ) -> Instruction { let mut accounts = vec![ AccountMeta::new(state_authority, true), AccountMeta::new( - pending_commitment_pda(&account.compatize(), commit_id).modernize(), + pending_commitment_pda(&account.compatize(), commit_seq) + .modernize(), false, ), AccountMeta::new(account, false), @@ -79,7 +83,7 @@ fn finalize_commitment_with_state_authority( AccountMeta::new_readonly( state_buffer_pda( &account.compatize(), - commit_id, + commit_seq, &state_authority.compatize(), ) .modernize(), diff --git a/interface/src/instruction_builder/propose_commitment.rs b/interface/src/instruction_builder/propose_commitment.rs index 046559bd..d4bd7b94 100644 --- a/interface/src/instruction_builder/propose_commitment.rs +++ b/interface/src/instruction_builder/propose_commitment.rs @@ -34,14 +34,14 @@ pub fn propose_commitment( false, ), AccountMeta::new( - pending_commitment_pda(&account.compatize(), args.commit_id) + pending_commitment_pda(&account.compatize(), args.commit_seq) .modernize(), false, ), AccountMeta::new_readonly( state_buffer_pda( &account.compatize(), - args.commit_id, + args.commit_seq, ¤t_validator.compatize(), ) .modernize(), diff --git a/interface/src/instruction_builder/raise_challenge.rs b/interface/src/instruction_builder/raise_challenge.rs index c2f4c844..594b250a 100644 --- a/interface/src/instruction_builder/raise_challenge.rs +++ b/interface/src/instruction_builder/raise_challenge.rs @@ -16,7 +16,7 @@ pub fn raise_challenge( challenger: Pubkey, delegation_cluster: Pubkey, account: Pubkey, - commit_id: u64, + commit_seq: u64, args: RaiseChallengeArgs, ) -> Instruction { Instruction { @@ -26,14 +26,14 @@ pub fn raise_challenge( AccountMeta::new( challenge_pda( &account.compatize(), - commit_id, + commit_seq, &challenger.compatize(), ) .modernize(), false, ), AccountMeta::new( - pending_commitment_pda(&account.compatize(), commit_id) + pending_commitment_pda(&account.compatize(), commit_seq) .modernize(), false, ), diff --git a/interface/src/instruction_builder/resolve_dispute.rs b/interface/src/instruction_builder/resolve_dispute.rs index da155e75..be4aaac5 100644 --- a/interface/src/instruction_builder/resolve_dispute.rs +++ b/interface/src/instruction_builder/resolve_dispute.rs @@ -17,7 +17,7 @@ pub fn resolve_dispute( delegation_cluster: Pubkey, challenger: Pubkey, account: Pubkey, - commit_id: u64, + commit_seq: u64, args: ResolveDisputeArgs, ) -> Instruction { Instruction { @@ -27,14 +27,14 @@ pub fn resolve_dispute( AccountMeta::new( challenge_pda( &account.compatize(), - commit_id, + commit_seq, &challenger.compatize(), ) .modernize(), false, ), AccountMeta::new( - pending_commitment_pda(&account.compatize(), commit_id) + pending_commitment_pda(&account.compatize(), commit_seq) .modernize(), false, ), diff --git a/interface/src/instruction_builder/write_state_buffer.rs b/interface/src/instruction_builder/write_state_buffer.rs index 903b3f94..4c5417be 100644 --- a/interface/src/instruction_builder/write_state_buffer.rs +++ b/interface/src/instruction_builder/write_state_buffer.rs @@ -26,7 +26,7 @@ pub fn write_state_buffer( AccountMeta::new( state_buffer_pda( &account.compatize(), - args.commit_id, + args.commit_seq, &authority.compatize(), ) .modernize(), diff --git a/interface/src/pda.rs b/interface/src/pda.rs index 6a46cb0c..c0812a2b 100644 --- a/interface/src/pda.rs +++ b/interface/src/pda.rs @@ -60,14 +60,14 @@ pub fn verifier_bond_pda( pub fn state_buffer_pda( account: &Pubkey, - commit_id: u64, + commit_seq: u64, authority: &Pubkey, ) -> Pubkey { Pubkey::find_program_address( &[ STATE_BUFFER_SEED, account.as_ref(), - &commit_id.to_le_bytes(), + &commit_seq.to_le_bytes(), authority.as_ref(), ], &crate::id(), @@ -75,12 +75,12 @@ pub fn state_buffer_pda( .0 } -pub fn pending_commitment_pda(account: &Pubkey, commit_id: u64) -> Pubkey { +pub fn pending_commitment_pda(account: &Pubkey, commit_seq: u64) -> Pubkey { Pubkey::find_program_address( &[ PENDING_COMMITMENT_SEED, account.as_ref(), - &commit_id.to_le_bytes(), + &commit_seq.to_le_bytes(), ], &crate::id(), ) @@ -89,14 +89,14 @@ pub fn pending_commitment_pda(account: &Pubkey, commit_id: u64) -> Pubkey { pub fn challenge_pda( account: &Pubkey, - commit_id: u64, + commit_seq: u64, challenger: &Pubkey, ) -> Pubkey { Pubkey::find_program_address( &[ CHALLENGE_SEED, account.as_ref(), - &commit_id.to_le_bytes(), + &commit_seq.to_le_bytes(), challenger.as_ref(), ], &crate::id(), diff --git a/interface/src/state/challenge.rs b/interface/src/state/challenge.rs index eb38d797..b44f8df4 100644 --- a/interface/src/state/challenge.rs +++ b/interface/src/state/challenge.rs @@ -12,7 +12,7 @@ pub const CHALLENGE_OUTCOME_MATCHING_STATE_CHALLENGER_PENALIZED: u8 = 2; pub const CHALLENGE_OUTCOME_OPERATOR_CORRECT_CHALLENGER_SLASHED: u8 = 3; pub const CHALLENGE_OUTCOME_CHALLENGER_CORRECT_OPERATOR_SLASHED: u8 = 4; -/// PDA: `["challenge", account, commit_id, challenger]`. +/// PDA: `["challenge", account, commit_seq, challenger]`. /// Created by `RaiseChallenge`. /// Closed by `CloseTerminalAccounts` after terminal challenge outcome. #[derive(Clone, Debug, PartialEq, Eq)] diff --git a/interface/src/state/delegation_state.rs b/interface/src/state/delegation_state.rs index 0c645f6e..67b79d59 100644 --- a/interface/src/state/delegation_state.rs +++ b/interface/src/state/delegation_state.rs @@ -34,7 +34,7 @@ pub struct DelegationState { pub lamports: u64, /// Latest finalized commit id applied to the delegated account. - pub last_commit_id: u64, + pub last_commit_seq: u64, /// Who requested undelegation, stored as `UndelegationRequester::value()`. pub undelegation_requester: u8, diff --git a/interface/src/state/pending_commitment.rs b/interface/src/state/pending_commitment.rs index d423e0c8..06f1f129 100644 --- a/interface/src/state/pending_commitment.rs +++ b/interface/src/state/pending_commitment.rs @@ -15,7 +15,7 @@ pub const PENDING_COMMITMENT_STATUS_CANCELLED: u8 = 9; pub const RESOLVED_STATE_SOURCE_OPERATOR_COMMITMENT: u8 = 1; pub const RESOLVED_STATE_SOURCE_CHALLENGER_REVEAL: u8 = 2; -/// PDA: `["pending-commitment", account, commit_id]`. +/// PDA: `["pending-commitment", account, commit_seq]`. /// Created by `ProposeCommitment`. /// Closed by `CloseTerminalAccounts` after finalize, cancel, or expiry. /// @@ -42,7 +42,7 @@ pub struct PendingCommitment { pub account_pubkey: Pubkey, /// Operator-chosen nonce for this account commitment. - pub commit_id: u64, + pub commit_seq: u64, /// Delegation record tying this account to the ER context. pub delegation_record: Pubkey, diff --git a/interface/src/state/state_buffer.rs b/interface/src/state/state_buffer.rs index 6f97bb09..512944dc 100644 --- a/interface/src/state/state_buffer.rs +++ b/interface/src/state/state_buffer.rs @@ -2,7 +2,7 @@ use wheels::fixed_offset_layout; use crate::{compat::Pubkey, error::DlpError}; -/// PDA: `["state-buffer", account, commit_id, authority]`. +/// PDA: `["state-buffer", account, commit_seq, authority]`. /// Created by `WriteStateBuffer`. /// Closed by `CloseTerminalAccounts` after finalize, cancel, or expiry. #[derive(Clone, Debug, PartialEq, Eq)] @@ -21,7 +21,7 @@ pub struct StateBuffer { pub account_pubkey: Pubkey, /// Flow-specific nonce that identifies this opened buffer. - pub commit_id: u64, + pub commit_seq: u64, /// Hash of the finalized payload. Zero until finalized. pub data_hash: [u8; 32], diff --git a/program/src/processor/delegate.rs b/program/src/processor/delegate.rs index 502710dd..63323a70 100644 --- a/program/src/processor/delegate.rs +++ b/program/src/processor/delegate.rs @@ -139,7 +139,7 @@ pub fn process_delegate( *state.rent_payer_mut()? = *payer.address(); state.delegation_slot_mut()?.set(Clock::get()?.slot)?; state.lamports_mut()?.set(delegated_account_lamports)?; - state.last_commit_id_mut()?.set(0)?; + state.last_commit_seq_mut()?.set(0)?; *state.undelegation_requester_mut()? = UndelegationRequester::None.value(); *state.delegated_account_bump_mut()? = args.delegated_account_bump(); *state.seed_count_mut()? = seeds.len() as u8; diff --git a/program/src/processor/fraud_proofs/approve_commitment.rs b/program/src/processor/fraud_proofs/approve_commitment.rs index bf83c46e..1c586a03 100644 --- a/program/src/processor/fraud_proofs/approve_commitment.rs +++ b/program/src/processor/fraud_proofs/approve_commitment.rs @@ -149,13 +149,13 @@ fn validate_pending_commitment( return Err(ProgramError::InvalidAccountData); } - let commit_id_bytes = pending_commitment.commit_id().to_le_bytes(); + let commit_seq_bytes = pending_commitment.commit_seq().to_le_bytes(); require_initialized_pda( pending_commitment_account, &[ PENDING_COMMITMENT_SEED, pending_commitment.account_pubkey().as_ref(), - &commit_id_bytes, + &commit_seq_bytes, ], &crate::fast::ID, true, diff --git a/program/src/processor/fraud_proofs/challenger_reveal.rs b/program/src/processor/fraud_proofs/challenger_reveal.rs index b36627cd..cc49f7f8 100644 --- a/program/src/processor/fraud_proofs/challenger_reveal.rs +++ b/program/src/processor/fraud_proofs/challenger_reveal.rs @@ -99,7 +99,7 @@ pub fn process_challenger_reveal( operator_state_buffer, pending.operator_identity(), pending.account_pubkey(), - pending.commit_id(), + pending.commit_seq(), pending.data_hash(), )?; @@ -108,7 +108,7 @@ pub fn process_challenger_reveal( challenger_state_buffer, &challenger_identity, pending.account_pubkey(), - pending.commit_id(), + pending.commit_seq(), args.data_hash(), )?; @@ -229,13 +229,13 @@ fn validate_pending_commitment( return Err(ProgramError::InvalidAccountData); } - let commit_id_bytes = pending.commit_id().to_le_bytes(); + let commit_seq_bytes = pending.commit_seq().to_le_bytes(); require_initialized_pda( pending_commitment, &[ PENDING_COMMITMENT_SEED, pending.account_pubkey().as_ref(), - &commit_id_bytes, + &commit_seq_bytes, ], &crate::fast::ID, true, @@ -276,13 +276,13 @@ fn validate_challenge( return Err(ProgramError::InvalidAccountData); } - let commit_id_bytes = pending.commit_id().to_le_bytes(); + let commit_seq_bytes = pending.commit_seq().to_le_bytes(); require_initialized_pda( challenge, &[ CHALLENGE_SEED, pending.account_pubkey().as_ref(), - &commit_id_bytes, + &commit_seq_bytes, challenger.address().as_ref(), ], &crate::fast::ID, @@ -328,16 +328,16 @@ fn validate_state_buffer( state_buffer: &AccountView, authority: &dpi::compat::Pubkey, account_pubkey: &dpi::compat::Pubkey, - commit_id: u64, + commit_seq: u64, expected_data_hash: &[u8; 32], ) -> ProgramResult { - let commit_id_bytes = commit_id.to_le_bytes(); + let commit_seq_bytes = commit_seq.to_le_bytes(); require_initialized_pda( state_buffer, &[ STATE_BUFFER_SEED, account_pubkey.as_ref(), - &commit_id_bytes, + &commit_seq_bytes, authority.as_ref(), ], &crate::fast::ID, @@ -358,8 +358,8 @@ fn validate_state_buffer( ProgramError::InvalidAccountData ); require_eq!( - state.commit_id(), - commit_id, + state.commit_seq(), + commit_seq, ProgramError::InvalidInstructionData ); require_eq!( @@ -440,7 +440,7 @@ fn challenge_hash( pending.operator_identity().as_ref(), challenge.challenger_identity().as_ref(), pending.account_pubkey().as_ref(), - &pending.commit_id().to_le_bytes(), + &pending.commit_seq().to_le_bytes(), &args.lamports().to_le_bytes(), args.owner().as_ref(), args.data_hash(), diff --git a/program/src/processor/fraud_proofs/finalize_commitment.rs b/program/src/processor/fraud_proofs/finalize_commitment.rs index 4f7a6f33..31ba1202 100644 --- a/program/src/processor/fraud_proofs/finalize_commitment.rs +++ b/program/src/processor/fraud_proofs/finalize_commitment.rs @@ -198,13 +198,13 @@ pub fn process_finalize_commitment( true, )?; - let commit_id_bytes = pending.commit_id().to_le_bytes(); + let commit_seq_bytes = pending.commit_seq().to_le_bytes(); require_initialized_pda( state_buffer, &[ STATE_BUFFER_SEED, delegated_account.address().as_ref(), - &commit_id_bytes, + &commit_seq_bytes, state_authority.address().as_ref(), ], &crate::fast::ID, @@ -217,14 +217,14 @@ pub fn process_finalize_commitment( delegation_cluster, selected_state.owner, )?; - validate_delegation_metadata(delegation_metadata, pending.commit_id())?; + validate_delegation_metadata(delegation_metadata, pending.commit_seq())?; let state_buffer_data = state_buffer.try_borrow()?; let raw_state = validate_state_buffer( state_buffer_data.as_ref(), state_authority, delegated_account, - pending.commit_id(), + pending.commit_seq(), selected_state.data_hash, )?; @@ -256,7 +256,7 @@ pub fn process_finalize_commitment( { let mut metadata = DelegationMetadataFast::from_account(delegation_metadata)?; - metadata.set_last_commit_id(pending.commit_id()); + metadata.set_last_commit_id(pending.commit_seq()); } drop(delegation_cluster_data); @@ -276,13 +276,13 @@ fn validate_pending_commitment( return Err(ProgramError::InvalidAccountData); } - let commit_id_bytes = pending.commit_id().to_le_bytes(); + let commit_seq_bytes = pending.commit_seq().to_le_bytes(); require_initialized_pda( pending_commitment, &[ PENDING_COMMITMENT_SEED, pending.account_pubkey().as_ref(), - &commit_id_bytes, + &commit_seq_bytes, ], &crate::fast::ID, true, @@ -395,14 +395,14 @@ fn validate_delegation_record( fn validate_delegation_metadata( delegation_metadata: &AccountView, - commit_id: u64, + commit_seq: u64, ) -> ProgramResult { let metadata = DelegationMetadataFast::from_account(delegation_metadata)?; - let expected_commit_id = metadata + let expected_commit_seq = metadata .last_commit_id() .checked_add(1) .ok_or(DlpError::Overflow)?; - require_eq!(commit_id, expected_commit_id, DlpError::NonceOutOfOrder); + require_eq!(commit_seq, expected_commit_seq, DlpError::NonceOutOfOrder); match metadata.undelegation_requester()? { UndelegationRequester::None => Ok(()), @@ -419,7 +419,7 @@ fn validate_state_buffer<'a>( data: &'a [u8], state_authority: &AccountView, delegated_account: &AccountView, - commit_id: u64, + commit_seq: u64, expected_data_hash: &[u8; 32], ) -> Result<&'a [u8], ProgramError> { let state = StateBuffer::decode(data)?; @@ -438,8 +438,8 @@ fn validate_state_buffer<'a>( DlpError::InvalidDelegatedAccount ); require_eq!( - state.commit_id(), - commit_id, + state.commit_seq(), + commit_seq, ProgramError::InvalidInstructionData ); require_eq!( @@ -533,13 +533,13 @@ fn validate_challenge( return Err(ProgramError::InvalidAccountData); } - let commit_id_bytes = pending.commit_id().to_le_bytes(); + let commit_seq_bytes = pending.commit_seq().to_le_bytes(); require_initialized_pda( challenge_account, &[ CHALLENGE_SEED, pending.account_pubkey().as_ref(), - &commit_id_bytes, + &commit_seq_bytes, challenge.challenger_identity().as_ref(), ], &crate::fast::ID, diff --git a/program/src/processor/fraud_proofs/propose_commitment.rs b/program/src/processor/fraud_proofs/propose_commitment.rs index c977e743..373cd781 100644 --- a/program/src/processor/fraud_proofs/propose_commitment.rs +++ b/program/src/processor/fraud_proofs/propose_commitment.rs @@ -102,13 +102,13 @@ pub fn process_propose_commitment( false, "operator bond", )?; - let commit_id_bytes = args.commit_id().to_le_bytes(); + let commit_seq_bytes = args.commit_seq().to_le_bytes(); require_initialized_pda( state_buffer, &[ STATE_BUFFER_SEED, delegated_account.address().as_ref(), - &commit_id_bytes, + &commit_seq_bytes, current_validator.address().as_ref(), ], &crate::fast::ID, @@ -154,7 +154,7 @@ pub fn process_propose_commitment( &state_buffer_state, current_validator, delegated_account, - args.commit_id(), + args.commit_seq(), )?; drop(state_buffer_data); @@ -179,7 +179,7 @@ pub fn process_propose_commitment( let delegation_metadata = DelegationMetadataRef::from_account(delegation_metadata)?; require_eq!( - args.commit_id(), + args.commit_seq(), delegation_metadata .last_commit_id() .checked_add(1) @@ -238,7 +238,7 @@ pub fn process_propose_commitment( delegation_cluster: delegation_cluster.address(), operator_identity: current_validator.address(), account_pubkey: delegated_account.address(), - commit_id: args.commit_id(), + commit_seq: args.commit_seq(), delegation_record: delegation_record.address(), da_pointer_hash: args.da_pointer_hash(), account_state_hash: &account_state_hash, @@ -253,7 +253,7 @@ pub fn process_propose_commitment( operator_identity: *current_validator.address(), operator_bond: operator_bond.address().to_bytes().into(), account_pubkey: delegated_account.address().to_bytes().into(), - commit_id: args.commit_id(), + commit_seq: args.commit_seq(), delegation_record: delegation_record.address().to_bytes().into(), da_pointer_hash: *args.da_pointer_hash(), account_state_hash, @@ -290,7 +290,7 @@ pub fn process_propose_commitment( &[ PENDING_COMMITMENT_SEED, delegated_account.address().as_ref(), - &commit_id_bytes, + &commit_seq_bytes, ], &crate::fast::ID, true, @@ -304,7 +304,7 @@ pub fn process_propose_commitment( &[Signer::from(&[ Seed::from(PENDING_COMMITMENT_SEED), Seed::from(delegated_account.address().as_ref()), - Seed::from(&commit_id_bytes), + Seed::from(&commit_seq_bytes), Seed::from(&[pending_commitment_bump]), ])], current_validator, @@ -373,7 +373,7 @@ fn validate_state_buffer( state_buffer: &dpi::StateBufferView<'_>, operator: &AccountView, delegated_account: &AccountView, - commit_id: u64, + commit_seq: u64, ) -> Result<[u8; 32], ProgramError> { if state_buffer.discriminator() != StateBuffer::DISCRIMINATOR { return Err(ProgramError::InvalidAccountData); @@ -389,8 +389,8 @@ fn validate_state_buffer( ProgramError::InvalidAccountData ); require_eq!( - state_buffer.commit_id(), - commit_id, + state_buffer.commit_seq(), + commit_seq, ProgramError::InvalidInstructionData ); require_eq!( @@ -468,7 +468,7 @@ struct StateCommitmentHashInput<'a> { delegation_cluster: &'a Address, operator_identity: &'a Address, account_pubkey: &'a Address, - commit_id: u64, + commit_seq: u64, delegation_record: &'a Address, da_pointer_hash: &'a [u8; 32], account_state_hash: &'a [u8; 32], @@ -482,7 +482,7 @@ fn state_commitment_hash(input: StateCommitmentHashInput<'_>) -> [u8; 32] { input.delegation_cluster.as_ref(), input.operator_identity.as_ref(), input.account_pubkey.as_ref(), - &input.commit_id.to_le_bytes(), + &input.commit_seq.to_le_bytes(), input.delegation_record.as_ref(), input.da_pointer_hash, input.account_state_hash, diff --git a/program/src/processor/fraud_proofs/raise_challenge.rs b/program/src/processor/fraud_proofs/raise_challenge.rs index 5427ae2e..0849a78a 100644 --- a/program/src/processor/fraud_proofs/raise_challenge.rs +++ b/program/src/processor/fraud_proofs/raise_challenge.rs @@ -81,13 +81,13 @@ pub fn process_raise_challenge( )?; let pending_account_pubkey = *pending_state.account_pubkey(); - let commit_id_bytes = pending_state.commit_id().to_le_bytes(); + let commit_seq_bytes = pending_state.commit_seq().to_le_bytes(); let challenge_bump = require_uninitialized_pda( challenge, &[ CHALLENGE_SEED, pending_account_pubkey.as_ref(), - &commit_id_bytes, + &commit_seq_bytes, challenger.address().as_ref(), ], &crate::fast::ID, @@ -128,7 +128,7 @@ pub fn process_raise_challenge( &[Signer::from(&[ Seed::from(CHALLENGE_SEED), Seed::from(pending_account_pubkey.as_ref()), - Seed::from(&commit_id_bytes), + Seed::from(&commit_seq_bytes), Seed::from(challenger.address().as_ref()), Seed::from(&[challenge_bump]), ])], @@ -194,13 +194,13 @@ fn validate_pending_commitment( return Err(ProgramError::InvalidAccountData); } - let commit_id_bytes = pending_commitment.commit_id().to_le_bytes(); + let commit_seq_bytes = pending_commitment.commit_seq().to_le_bytes(); require_initialized_pda( pending_commitment_account, &[ PENDING_COMMITMENT_SEED, pending_commitment.account_pubkey().as_ref(), - &commit_id_bytes, + &commit_seq_bytes, ], &crate::fast::ID, true, diff --git a/program/src/processor/fraud_proofs/resolve_dispute.rs b/program/src/processor/fraud_proofs/resolve_dispute.rs index 0862aa9c..fb6fad36 100644 --- a/program/src/processor/fraud_proofs/resolve_dispute.rs +++ b/program/src/processor/fraud_proofs/resolve_dispute.rs @@ -254,13 +254,13 @@ fn validate_pending_commitment( return Err(ProgramError::InvalidAccountData); } - let commit_id_bytes = pending.commit_id().to_le_bytes(); + let commit_seq_bytes = pending.commit_seq().to_le_bytes(); require_initialized_pda( pending_commitment, &[ PENDING_COMMITMENT_SEED, pending.account_pubkey().as_ref(), - &commit_id_bytes, + &commit_seq_bytes, ], &crate::fast::ID, true, @@ -300,13 +300,13 @@ fn validate_challenge( return Err(ProgramError::InvalidAccountData); } - let commit_id_bytes = pending.commit_id().to_le_bytes(); + let commit_seq_bytes = pending.commit_seq().to_le_bytes(); require_initialized_pda( challenge, &[ CHALLENGE_SEED, pending.account_pubkey().as_ref(), - &commit_id_bytes, + &commit_seq_bytes, challenger.address().as_ref(), ], &crate::fast::ID, diff --git a/program/src/processor/fraud_proofs/write_state_buffer.rs b/program/src/processor/fraud_proofs/write_state_buffer.rs index 7d025459..54363e59 100644 --- a/program/src/processor/fraud_proofs/write_state_buffer.rs +++ b/program/src/processor/fraud_proofs/write_state_buffer.rs @@ -50,11 +50,11 @@ pub fn process_write_state_buffer( let args = WriteStateBufferArgs::decode(data)?; let (offset, write_end) = validate_args(&args)?; - let commit_id_bytes = args.commit_id().to_le_bytes(); + let commit_seq_bytes = args.commit_seq().to_le_bytes(); let state_buffer_seeds = [ STATE_BUFFER_SEED, delegated_account.address().as_ref(), - &commit_id_bytes, + &commit_seq_bytes, authority.address().as_ref(), ]; @@ -98,7 +98,7 @@ pub fn process_write_state_buffer( &[Signer::from(&[ Seed::from(STATE_BUFFER_SEED), Seed::from(delegated_account.address().as_ref()), - Seed::from(&commit_id_bytes), + Seed::from(&commit_seq_bytes), Seed::from(authority.address().as_ref()), Seed::from(&[state_buffer_bump]), ])], @@ -109,7 +109,7 @@ pub fn process_write_state_buffer( discriminator: StateBuffer::DISCRIMINATOR, authority: *authority.address(), account_pubkey: *delegated_account.address(), - commit_id: args.commit_id(), + commit_seq: args.commit_seq(), data_hash: [0; 32], total_len: args.total_len(), finalized: false, @@ -274,8 +274,8 @@ fn validate_state_buffer( ProgramError::InvalidAccountData ); require_eq!( - state.commit_id(), - args.commit_id(), + state.commit_seq(), + args.commit_seq(), ProgramError::InvalidInstructionData ); require_eq!( diff --git a/program/tests/test_approve_commitment.rs b/program/tests/test_approve_commitment.rs index 800195ba..3f107549 100644 --- a/program/tests/test_approve_commitment.rs +++ b/program/tests/test_approve_commitment.rs @@ -56,7 +56,7 @@ async fn test_approve_commitment() { &env.verifiers[0], env.delegation_cluster, env.delegated_account, - args.commit_id, + args.commit_seq, ) .await .unwrap(); @@ -64,7 +64,7 @@ async fn test_approve_commitment() { let pending_commitment_data = read_pending_commitment_data( &mut env.banks, env.delegated_account, - args.commit_id, + args.commit_seq, ) .await; let pending_commitment = @@ -103,7 +103,7 @@ async fn test_approve_commitment_duplicate_is_noop() { &env.verifiers[0], env.delegation_cluster, env.delegated_account, - args.commit_id, + args.commit_seq, ) .await .unwrap(); @@ -113,7 +113,7 @@ async fn test_approve_commitment_duplicate_is_noop() { &env.verifiers[0], env.delegation_cluster, env.delegated_account, - args.commit_id, + args.commit_seq, ) .await .unwrap(); @@ -121,7 +121,7 @@ async fn test_approve_commitment_duplicate_is_noop() { let pending_commitment_data = read_pending_commitment_data( &mut env.banks, env.delegated_account, - args.commit_id, + args.commit_seq, ) .await; let pending_commitment = @@ -157,7 +157,7 @@ async fn test_approve_commitment_fails_with_wrong_verifier() { &env.verifiers[1], env.delegation_cluster, env.delegated_account, - args.commit_id, + args.commit_seq, ) .await .is_err()); @@ -183,7 +183,7 @@ async fn test_approve_commitment_fails_without_verifier_signature() { env.verifiers[0].pubkey(), env.delegation_cluster, env.delegated_account, - args.commit_id, + args.commit_seq, ); ix.accounts[0].is_signer = false; @@ -218,7 +218,7 @@ async fn test_approve_commitment_fails_with_instruction_data() { env.verifiers[0].pubkey(), env.delegation_cluster, env.delegated_account, - args.commit_id, + args.commit_seq, ); ix.data.push(1); @@ -355,7 +355,7 @@ async fn setup_approve_commitment_env( &operator, delegated_account, WriteStateBufferArgs { - commit_id: propose_commitment_args().commit_id, + commit_seq: propose_commitment_args().commit_seq, total_len: state_data().len() as u32, offset: 0, chunk: state_data(), @@ -456,7 +456,7 @@ async fn register_and_add_verifier( fn propose_commitment_args() -> ProposeCommitmentArgs { ProposeCommitmentArgs { - commit_id: 1, + commit_seq: 1, lamports: 1_000, owner: Pubkey::new_from_array([7; 32]), da_pointer_hash: [9; 32], @@ -527,7 +527,7 @@ async fn approve( verifier: &Keypair, delegation_cluster: Pubkey, delegated_account: Pubkey, - commit_id: u64, + commit_seq: u64, ) -> Result<(), solana_program_test::BanksClientError> { let latest_blockhash: Hash = banks.get_latest_blockhash().await.unwrap(); let blockhash = banks @@ -538,7 +538,7 @@ async fn approve( verifier.pubkey(), delegation_cluster, delegated_account, - commit_id, + commit_seq, ); let tx = Transaction::new_signed_with_payer( &[ix], @@ -553,10 +553,10 @@ async fn approve( async fn read_pending_commitment_data( banks: &mut BanksClient, delegated_account: Pubkey, - commit_id: u64, + commit_seq: u64, ) -> Vec { let pending_commitment_account = banks - .get_account(pending_commitment_pda(&delegated_account, commit_id)) + .get_account(pending_commitment_pda(&delegated_account, commit_seq)) .await .unwrap() .unwrap(); diff --git a/program/tests/test_challenger_reveal.rs b/program/tests/test_challenger_reveal.rs index 511cad62..5b201d67 100644 --- a/program/tests/test_challenger_reveal.rs +++ b/program/tests/test_challenger_reveal.rs @@ -102,7 +102,7 @@ async fn test_challenger_reveal_matching_state_penalizes_and_reopens_commitment( challenge.challenger_state_buffer, state_buffer_pda( &env.delegated_account, - env.commit_id, + env.commit_seq, &env.challenger.pubkey() ) ); @@ -271,12 +271,12 @@ async fn test_challenger_reveal_fails_with_wrong_challenger_buffer() { env.operator.pubkey(), env.delegation_cluster, env.delegated_account, - env.commit_id, + env.commit_seq, reveal_args, ); ix.accounts[4].pubkey = state_buffer_pda( &env.delegated_account, - env.commit_id, + env.commit_seq, &env.operator.pubkey(), ); @@ -296,11 +296,11 @@ async fn test_challenger_reveal_fails_with_unfinalized_challenger_buffer() { env.committed_owner, account_data_hash(&expected_data), ); - let commit_id = env.commit_id; + let commit_seq = env.commit_seq; write_challenger_state_buffer_args( &mut env, WriteStateBufferArgs { - commit_id, + commit_seq, total_len: expected_data.len() as u32, offset: 0, chunk: expected_data[..2].to_vec(), @@ -339,7 +339,7 @@ async fn test_challenger_reveal_fails_with_wrong_fee_vault() { env.operator.pubkey(), env.delegation_cluster, env.delegated_account, - env.commit_id, + env.commit_seq, reveal_args, ); ix.accounts[6].pubkey = env.challenger.pubkey(); @@ -358,7 +358,7 @@ struct ChallengerRevealEnv { delegated_account: Pubkey, committed_owner: Pubkey, committed_lamports: u64, - commit_id: u64, + commit_seq: u64, challenge_config: ChallengeConfig, operator_state_data: Vec, } @@ -378,7 +378,7 @@ async fn setup_challenger_reveal_env() -> ChallengerRevealEnv { let delegation_cluster = dpi::pda::delegation_cluster_pda(&cluster_identity.pubkey()); let committed_owner = Pubkey::new_unique(); - let commit_id = 1; + let commit_seq = 1; let operator_state_data = vec![9, 8, 7, 6, 5]; let record_lamports = LAMPORTS_PER_SOL; let committed_lamports = LAMPORTS_PER_SOL; @@ -464,7 +464,7 @@ async fn setup_challenger_reveal_env() -> ChallengerRevealEnv { &operator, delegated_account, WriteStateBufferArgs { - commit_id, + commit_seq, total_len: operator_state_data.len() as u32, offset: 0, chunk: operator_state_data.clone(), @@ -482,7 +482,7 @@ async fn setup_challenger_reveal_env() -> ChallengerRevealEnv { delegated_account, committed_owner, committed_lamports, - commit_id, + commit_seq, challenge_config, operator_state_data, } @@ -496,7 +496,7 @@ async fn propose( env.delegation_cluster, env.delegated_account, ProposeCommitmentArgs { - commit_id: env.commit_id, + commit_seq: env.commit_seq, lamports: env.committed_lamports, owner: env.committed_owner, da_pointer_hash: [9; 32], @@ -517,7 +517,7 @@ async fn raise_for_reveal( env.challenger.pubkey(), env.delegation_cluster, env.delegated_account, - env.commit_id, + env.commit_seq, RaiseChallengeArgs { state_commitment_hash: pending.state_commitment_hash, challenge_hash: challenge_hash( @@ -525,7 +525,7 @@ async fn raise_for_reveal( env.operator.pubkey(), env.challenger.pubkey(), env.delegated_account, - env.commit_id, + env.commit_seq, reveal_args, ), stake_lamports, @@ -544,7 +544,7 @@ async fn reveal( env.operator.pubkey(), env.delegation_cluster, env.delegated_account, - env.commit_id, + env.commit_seq, args, ); @@ -558,7 +558,7 @@ async fn write_challenger_state_buffer( write_challenger_state_buffer_args( env, WriteStateBufferArgs { - commit_id: env.commit_id, + commit_seq: env.commit_seq, total_len: data.len() as u32, offset: 0, chunk: data, @@ -684,7 +684,7 @@ async fn read_pending_commitment( .banks_client .get_account(pending_commitment_pda( &env.delegated_account, - env.commit_id, + env.commit_seq, )) .await .unwrap() @@ -790,7 +790,7 @@ fn valid_reveal_args( fn challenge_address(env: &ChallengerRevealEnv) -> Pubkey { challenge_pda( &env.delegated_account, - env.commit_id, + env.commit_seq, &env.challenger.pubkey(), ) } @@ -805,7 +805,7 @@ fn challenge_hash( operator: Pubkey, challenger: Pubkey, account: Pubkey, - commit_id: u64, + commit_seq: u64, args: &ChallengerRevealArgs, ) -> [u8; 32] { solana_sha256_hasher::hashv(&[ @@ -814,7 +814,7 @@ fn challenge_hash( operator.as_ref(), challenger.as_ref(), account.as_ref(), - &commit_id.to_le_bytes(), + &commit_seq.to_le_bytes(), &args.lamports.to_le_bytes(), args.owner.as_ref(), &args.data_hash, diff --git a/program/tests/test_finalize_commitment.rs b/program/tests/test_finalize_commitment.rs index af254148..6446afc3 100644 --- a/program/tests/test_finalize_commitment.rs +++ b/program/tests/test_finalize_commitment.rs @@ -70,7 +70,7 @@ async fn test_finalize_commitment() { assert_eq!(delegation_record.lamports, env.committed_lamports); let delegation_metadata = read_delegation_metadata(&mut env).await; - assert_eq!(delegation_metadata.last_commit_id, env.commit_id); + assert_eq!(delegation_metadata.last_commit_id, env.commit_seq); } #[tokio::test] @@ -111,7 +111,7 @@ async fn test_finalize_commitment_fails_with_wrong_operator() { wrong_operator.pubkey(), env.delegation_cluster, env.delegated_account, - env.commit_id, + env.commit_seq, ); assert!(process_ix(&mut env.context, ix, &[&wrong_operator]) @@ -226,7 +226,7 @@ struct FinalizeCommitmentEnv { delegated_account: Pubkey, committed_owner: Pubkey, committed_lamports: u64, - commit_id: u64, + commit_seq: u64, final_state_data: Vec, } @@ -248,7 +248,7 @@ async fn setup_finalize_commitment_env( dpi::pda::delegation_cluster_pda(&cluster_identity.pubkey()); let account_owner = Pubkey::new_unique(); let committed_owner = account_owner; - let commit_id = 1; + let commit_seq = 1; let final_state_data = vec![9, 8, 7, 6, 5]; add_lamport_account(&mut program_test, authority.pubkey()); @@ -330,7 +330,7 @@ async fn setup_finalize_commitment_env( &operator, delegated_account, WriteStateBufferArgs { - commit_id, + commit_seq, total_len: final_state_data.len() as u32, offset: 0, chunk: final_state_data.clone(), @@ -347,7 +347,7 @@ async fn setup_finalize_commitment_env( delegated_account, committed_owner, committed_lamports, - commit_id, + commit_seq, final_state_data, } } @@ -360,7 +360,7 @@ async fn propose( env.delegation_cluster, env.delegated_account, ProposeCommitmentArgs { - commit_id: env.commit_id, + commit_seq: env.commit_seq, lamports: env.committed_lamports, owner: env.committed_owner, da_pointer_hash: [9; 32], @@ -378,7 +378,7 @@ async fn approve( env.verifier.pubkey(), env.delegation_cluster, env.delegated_account, - env.commit_id, + env.commit_seq, ); process_ix(&mut env.context, ix, &[&env.verifier]).await @@ -391,7 +391,7 @@ async fn finalize( env.operator.pubkey(), env.delegation_cluster, env.delegated_account, - env.commit_id, + env.commit_seq, ); process_ix(&mut env.context, ix, &[&env.operator]).await @@ -506,7 +506,7 @@ async fn read_pending_commitment( .banks_client .get_account(pending_commitment_pda( &env.delegated_account, - env.commit_id, + env.commit_seq, )) .await .unwrap() diff --git a/program/tests/test_primary_delegate.rs b/program/tests/test_primary_delegate.rs index b930350a..1ac4a668 100644 --- a/program/tests/test_primary_delegate.rs +++ b/program/tests/test_primary_delegate.rs @@ -94,7 +94,7 @@ async fn test_delegate_creates_cluster_bound_delegation_state() { assert_eq!(*state.original_owner(), OWNER_PROGRAM_ID); assert_eq!(*state.rent_payer(), context.payer.pubkey()); assert_eq!(state.lamports(), delegated_account.lamports); - assert_eq!(state.last_commit_id(), 0); + assert_eq!(state.last_commit_seq(), 0); assert_eq!( state.undelegation_requester(), UndelegationRequester::None.value() diff --git a/program/tests/test_propose_commitment.rs b/program/tests/test_propose_commitment.rs index 8eedb7b9..d453f4f8 100644 --- a/program/tests/test_propose_commitment.rs +++ b/program/tests/test_propose_commitment.rs @@ -55,7 +55,7 @@ async fn test_propose_commitment() { .banks .get_account(pending_commitment_pda( &env.delegated_account, - args.commit_id, + args.commit_seq, )) .await .unwrap() @@ -82,7 +82,7 @@ async fn test_propose_commitment() { env.operator.pubkey() ); assert_eq!(*pending_commitment.account_pubkey(), env.delegated_account); - assert_eq!(pending_commitment.commit_id(), args.commit_id); + assert_eq!(pending_commitment.commit_seq(), args.commit_seq); assert_eq!(pending_commitment.lamports(), args.lamports); assert_eq!(*pending_commitment.owner(), args.owner); assert_eq!( @@ -231,7 +231,7 @@ async fn test_propose_commitment_fails_without_state_buffer() { }) .await; let mut args = propose_commitment_args(); - args.commit_id = 99; + args.commit_seq = 99; assert!(propose(&mut env, args).await.is_err()); } @@ -264,7 +264,7 @@ async fn test_propose_commitment_rejects_wrong_owner() { } #[tokio::test] -async fn test_propose_commitment_rejects_out_of_order_commit_id() { +async fn test_propose_commitment_rejects_out_of_order_commit_seq() { let mut env = setup_propose_commitment_env(ProposeCommitmentSetup { verifier_count: 2, register_operator_as_verifier: true, @@ -272,14 +272,14 @@ async fn test_propose_commitment_rejects_out_of_order_commit_id() { }) .await; let mut args = propose_commitment_args(); - args.commit_id = 2; + args.commit_seq = 2; write_state( &mut env.banks, &env.payer, &env.operator, env.delegated_account, WriteStateBufferArgs { - commit_id: args.commit_id, + commit_seq: args.commit_seq, total_len: state_data().len() as u32, offset: 0, chunk: state_data(), @@ -442,7 +442,7 @@ async fn setup_propose_commitment_env( &operator, delegated_account, WriteStateBufferArgs { - commit_id: propose_commitment_args().commit_id, + commit_seq: propose_commitment_args().commit_seq, total_len: state_data().len() as u32, offset: 0, chunk: state_data(), @@ -545,7 +545,7 @@ async fn register_and_add_verifier( fn propose_commitment_args() -> ProposeCommitmentArgs { ProposeCommitmentArgs { - commit_id: 1, + commit_seq: 1, lamports: 1_000, owner: Pubkey::new_from_array([7; 32]), da_pointer_hash: [9; 32], diff --git a/program/tests/test_raise_challenge.rs b/program/tests/test_raise_challenge.rs index 01593483..070b2f1c 100644 --- a/program/tests/test_raise_challenge.rs +++ b/program/tests/test_raise_challenge.rs @@ -50,7 +50,7 @@ async fn test_raise_challenge() { let args = valid_raise_challenge_args(pending_before.state_commitment_hash); let challenge_address = challenge_pda( &env.delegated_account, - env.commit_id, + env.commit_seq, &env.challenger.pubkey(), ); @@ -71,7 +71,7 @@ async fn test_raise_challenge() { assert_eq!(challenge.outcome(), CHALLENGE_OUTCOME_NONE); assert_eq!( *challenge.pending_commitment(), - pending_commitment_pda(&env.delegated_account, env.commit_id) + pending_commitment_pda(&env.delegated_account, env.commit_seq) ); assert_eq!(*challenge.challenger_identity(), env.challenger.pubkey()); assert_eq!( @@ -114,7 +114,7 @@ async fn test_raise_challenge_fails_without_challenger_signature() { env.challenger.pubkey(), env.delegation_cluster, env.delegated_account, - env.commit_id, + env.commit_seq, args, ); ix.accounts[0].is_signer = false; @@ -164,7 +164,7 @@ async fn test_raise_challenge_uses_submitted_policy() { .banks_client .get_account(challenge_pda( &env.delegated_account, - env.commit_id, + env.commit_seq, &env.challenger.pubkey(), )) .await @@ -238,7 +238,7 @@ struct RaiseChallengeEnv { delegated_account: Pubkey, committed_owner: Pubkey, committed_lamports: u64, - commit_id: u64, + commit_seq: u64, challenge_config: ChallengeConfig, } @@ -257,7 +257,7 @@ async fn setup_raise_challenge_env() -> RaiseChallengeEnv { let delegation_cluster = dpi::pda::delegation_cluster_pda(&cluster_identity.pubkey()); let committed_owner = Pubkey::new_unique(); - let commit_id = 1; + let commit_seq = 1; let final_state_data = vec![9, 8, 7, 6, 5]; let record_lamports = LAMPORTS_PER_SOL; let committed_lamports = LAMPORTS_PER_SOL; @@ -342,7 +342,7 @@ async fn setup_raise_challenge_env() -> RaiseChallengeEnv { &operator, delegated_account, WriteStateBufferArgs { - commit_id, + commit_seq, total_len: final_state_data.len() as u32, offset: 0, chunk: final_state_data.clone(), @@ -361,7 +361,7 @@ async fn setup_raise_challenge_env() -> RaiseChallengeEnv { delegated_account, committed_owner, committed_lamports, - commit_id, + commit_seq, challenge_config, } } @@ -372,7 +372,7 @@ async fn propose(env: &mut RaiseChallengeEnv) -> Result<(), BanksClientError> { env.delegation_cluster, env.delegated_account, ProposeCommitmentArgs { - commit_id: env.commit_id, + commit_seq: env.commit_seq, lamports: env.committed_lamports, owner: env.committed_owner, da_pointer_hash: [9; 32], @@ -388,7 +388,7 @@ async fn approve(env: &mut RaiseChallengeEnv) -> Result<(), BanksClientError> { env.verifier.pubkey(), env.delegation_cluster, env.delegated_account, - env.commit_id, + env.commit_seq, ); process_ix(&mut env.context, ix, &[&env.verifier]).await @@ -402,7 +402,7 @@ async fn raise( env.challenger.pubkey(), env.delegation_cluster, env.delegated_account, - env.commit_id, + env.commit_seq, args, ); @@ -414,7 +414,7 @@ async fn finalize(env: &mut RaiseChallengeEnv) -> Result<(), BanksClientError> { env.operator.pubkey(), env.delegation_cluster, env.delegated_account, - env.commit_id, + env.commit_seq, ); process_ix(&mut env.context, ix, &[&env.operator]).await @@ -531,7 +531,7 @@ async fn read_pending_commitment( .banks_client .get_account(pending_commitment_pda( &env.delegated_account, - env.commit_id, + env.commit_seq, )) .await .unwrap() diff --git a/program/tests/test_resolve_dispute.rs b/program/tests/test_resolve_dispute.rs index 8f96de71..2441b40d 100644 --- a/program/tests/test_resolve_dispute.rs +++ b/program/tests/test_resolve_dispute.rs @@ -131,7 +131,7 @@ async fn test_resolve_dispute_operator_correct_slashes_challenger_and_selects_op env.challenger.pubkey(), env.delegation_cluster, env.delegated_account, - env.commit_id, + env.commit_seq, ); assert!(process_ix(&mut env.context, ix, &[&env.challenger]) .await @@ -141,7 +141,7 @@ async fn test_resolve_dispute_operator_correct_slashes_challenger_and_selects_op env.operator.pubkey(), env.delegation_cluster, env.delegated_account, - env.commit_id, + env.commit_seq, ); process_ix(&mut env.context, ix, &[&env.operator]) .await @@ -227,7 +227,7 @@ async fn test_resolve_dispute_challenger_correct_refunds_challenger_and_slashes_ env.operator.pubkey(), env.delegation_cluster, env.delegated_account, - env.commit_id, + env.commit_seq, ); assert!(process_ix(&mut env.context, ix, &[&env.operator]) .await @@ -237,7 +237,7 @@ async fn test_resolve_dispute_challenger_correct_refunds_challenger_and_slashes_ env.challenger.pubkey(), env.delegation_cluster, env.delegated_account, - env.commit_id, + env.commit_seq, ); process_ix(&mut env.context, ix, &[&env.challenger]) .await @@ -269,7 +269,7 @@ async fn test_resolve_dispute_fails_with_wrong_resolver() { env.delegation_cluster, env.challenger.pubkey(), env.delegated_account, - env.commit_id, + env.commit_seq, ResolveDisputeArgs { decision: DISPUTE_DECISION_OPERATOR_STATE_CORRECT, }, @@ -321,7 +321,7 @@ async fn test_resolve_dispute_fails_with_wrong_operator_bond() { env.delegation_cluster, env.challenger.pubkey(), env.delegated_account, - env.commit_id, + env.commit_seq, ResolveDisputeArgs { decision: DISPUTE_DECISION_OPERATOR_STATE_CORRECT, }, @@ -343,7 +343,7 @@ async fn test_resolve_dispute_fails_with_wrong_fee_vault() { env.delegation_cluster, env.challenger.pubkey(), env.delegated_account, - env.commit_id, + env.commit_seq, ResolveDisputeArgs { decision: DISPUTE_DECISION_OPERATOR_STATE_CORRECT, }, @@ -375,7 +375,7 @@ struct ResolveDisputeEnv { delegated_account: Pubkey, committed_owner: Pubkey, committed_lamports: u64, - commit_id: u64, + commit_seq: u64, challenge_config: ChallengeConfig, operator_state_data: Vec, challenger_state_data: Vec, @@ -401,7 +401,7 @@ async fn setup_resolve_dispute_env() -> ResolveDisputeEnv { dpi::pda::delegation_cluster_pda(&cluster_identity.pubkey()); let challenge_config = cluster_args.challenge_config.clone().unwrap(); let committed_owner = Pubkey::new_unique(); - let commit_id = 1; + let commit_seq = 1; let operator_state_data = vec![9, 8, 7, 6, 5]; let challenger_state_data = vec![4, 3, 2, 1]; let record_lamports = LAMPORTS_PER_SOL; @@ -492,7 +492,7 @@ async fn setup_resolve_dispute_env() -> ResolveDisputeEnv { &operator, delegated_account, WriteStateBufferArgs { - commit_id, + commit_seq, total_len: operator_state_data.len() as u32, offset: 0, chunk: operator_state_data.clone(), @@ -511,7 +511,7 @@ async fn setup_resolve_dispute_env() -> ResolveDisputeEnv { delegated_account, committed_owner, committed_lamports, - commit_id, + commit_seq, challenge_config, operator_state_data, challenger_state_data, @@ -549,7 +549,7 @@ async fn propose(env: &mut ResolveDisputeEnv) -> Result<(), BanksClientError> { env.delegation_cluster, env.delegated_account, ProposeCommitmentArgs { - commit_id: env.commit_id, + commit_seq: env.commit_seq, lamports: env.committed_lamports, owner: env.committed_owner, da_pointer_hash: [9; 32], @@ -570,7 +570,7 @@ async fn raise_for_reveal( env.challenger.pubkey(), env.delegation_cluster, env.delegated_account, - env.commit_id, + env.commit_seq, RaiseChallengeArgs { state_commitment_hash: pending.state_commitment_hash, challenge_hash: challenge_hash( @@ -578,7 +578,7 @@ async fn raise_for_reveal( env.operator.pubkey(), env.challenger.pubkey(), env.delegated_account, - env.commit_id, + env.commit_seq, reveal_args, ), stake_lamports, @@ -597,7 +597,7 @@ async fn reveal( env.operator.pubkey(), env.delegation_cluster, env.delegated_account, - env.commit_id, + env.commit_seq, args, ); @@ -613,7 +613,7 @@ async fn resolve( env.delegation_cluster, env.challenger.pubkey(), env.delegated_account, - env.commit_id, + env.commit_seq, args, ); @@ -629,7 +629,7 @@ async fn write_challenger_state_buffer( &env.challenger, env.delegated_account, WriteStateBufferArgs { - commit_id: env.commit_id, + commit_seq: env.commit_seq, total_len: data.len() as u32, offset: 0, chunk: data, @@ -742,7 +742,7 @@ async fn read_pending_commitment( .banks_client .get_account(pending_commitment_pda( &env.delegated_account, - env.commit_id, + env.commit_seq, )) .await .unwrap() @@ -867,7 +867,7 @@ fn valid_reveal_args( fn challenge_address(env: &ResolveDisputeEnv) -> Pubkey { challenge_pda( &env.delegated_account, - env.commit_id, + env.commit_seq, &env.challenger.pubkey(), ) } @@ -882,7 +882,7 @@ fn challenge_hash( operator: Pubkey, challenger: Pubkey, account: Pubkey, - commit_id: u64, + commit_seq: u64, args: &ChallengerRevealArgs, ) -> [u8; 32] { solana_sha256_hasher::hashv(&[ @@ -891,7 +891,7 @@ fn challenge_hash( operator.as_ref(), challenger.as_ref(), account.as_ref(), - &commit_id.to_le_bytes(), + &commit_seq.to_le_bytes(), &args.lamports.to_le_bytes(), args.owner.as_ref(), &args.data_hash, diff --git a/program/tests/test_v2_write_state_buffer.rs b/program/tests/test_v2_write_state_buffer.rs index 96113fa2..6d6b99b0 100644 --- a/program/tests/test_v2_write_state_buffer.rs +++ b/program/tests/test_v2_write_state_buffer.rs @@ -23,7 +23,7 @@ use crate::fixtures::v2::setup_program_test_env; #[tokio::test] async fn test_write_state_buffer_unregistered_authority_one_chunk_finalizes() { let mut env = setup_write_state_buffer_env().await; - let commit_id = 7; + let commit_seq = 7; let data = vec![1, 2, 3, 4]; write_buffer( @@ -32,7 +32,7 @@ async fn test_write_state_buffer_unregistered_authority_one_chunk_finalizes() { &env.writer, env.delegated.pubkey(), WriteStateBufferArgs { - commit_id, + commit_seq, total_len: data.len() as u32, offset: 0, chunk: data.clone(), @@ -43,7 +43,7 @@ async fn test_write_state_buffer_unregistered_authority_one_chunk_finalizes() { let state_buffer = state_buffer_pda( &env.delegated.pubkey(), - commit_id, + commit_seq, &env.writer.pubkey(), ); let state_buffer_account = @@ -53,7 +53,7 @@ async fn test_write_state_buffer_unregistered_authority_one_chunk_finalizes() { assert_eq!(state.discriminator(), StateBuffer::DISCRIMINATOR); assert_eq!(*state.authority(), env.writer.pubkey()); assert_eq!(*state.account_pubkey(), env.delegated.pubkey()); - assert_eq!(state.commit_id(), commit_id); + assert_eq!(state.commit_seq(), commit_seq); assert_eq!(state.total_len(), data.len() as u32); assert!(state.finalized()); assert_eq!(*state.data_hash(), account_data_hash(&data)); @@ -69,7 +69,7 @@ async fn test_write_state_buffer_unregistered_authority_one_chunk_finalizes() { #[tokio::test] async fn test_write_state_buffer_empty_payload_finalizes() { let mut env = setup_write_state_buffer_env().await; - let commit_id = 16; + let commit_seq = 16; write_buffer( &mut env.banks, @@ -77,7 +77,7 @@ async fn test_write_state_buffer_empty_payload_finalizes() { &env.writer, env.delegated.pubkey(), WriteStateBufferArgs { - commit_id, + commit_seq, total_len: 0, offset: 0, chunk: vec![], @@ -88,7 +88,7 @@ async fn test_write_state_buffer_empty_payload_finalizes() { let state_buffer = state_buffer_pda( &env.delegated.pubkey(), - commit_id, + commit_seq, &env.writer.pubkey(), ); let state_buffer_account = @@ -109,11 +109,11 @@ async fn test_write_state_buffer_empty_payload_finalizes() { #[tokio::test] async fn test_write_state_buffer_multiple_chunks_finalize() { let mut env = setup_write_state_buffer_env().await; - let commit_id = 8; + let commit_seq = 8; let total_len = 5; let state_buffer = state_buffer_pda( &env.delegated.pubkey(), - commit_id, + commit_seq, &env.writer.pubkey(), ); @@ -124,7 +124,7 @@ async fn test_write_state_buffer_multiple_chunks_finalize() { &env.writer, env.delegated.pubkey(), WriteStateBufferArgs { - commit_id, + commit_seq, total_len, offset: 0, chunk: vec![1, 2], @@ -167,7 +167,7 @@ async fn test_write_state_buffer_multiple_chunks_finalize() { &env.writer, env.delegated.pubkey(), WriteStateBufferArgs { - commit_id, + commit_seq, total_len, offset: 2, chunk: vec![3, 4, 5], @@ -198,10 +198,10 @@ async fn test_write_state_buffer_multiple_chunks_finalize() { #[tokio::test] async fn test_write_state_buffer_grows_payload_span_past_initial_capacity() { let mut env = setup_write_state_buffer_env().await; - let commit_id = 15; + let commit_seq = 15; let state_buffer = state_buffer_pda( &env.delegated.pubkey(), - commit_id, + commit_seq, &env.writer.pubkey(), ); let initial_payload_capacity = StateBuffer::MAX_INITIAL_PAYLOAD_LEN; @@ -227,7 +227,7 @@ async fn test_write_state_buffer_grows_payload_span_past_initial_capacity() { &env.writer, env.delegated.pubkey(), WriteStateBufferArgs { - commit_id, + commit_seq, total_len: total_len as u32, offset: offset as u32, chunk, @@ -272,7 +272,7 @@ async fn test_write_state_buffer_grows_payload_span_past_initial_capacity() { &env.writer, env.delegated.pubkey(), WriteStateBufferArgs { - commit_id, + commit_seq, total_len: total_len as u32, offset: first_write_len as u32, chunk: crossing_chunk.clone(), @@ -306,7 +306,7 @@ async fn test_write_state_buffer_grows_payload_span_past_initial_capacity() { #[tokio::test] async fn test_write_state_buffer_duplicate_retry() { let mut env = setup_write_state_buffer_env().await; - let commit_id = 9; + let commit_seq = 9; let first_chunk = vec![1, 2]; write_buffer( @@ -315,7 +315,7 @@ async fn test_write_state_buffer_duplicate_retry() { &env.writer, env.delegated.pubkey(), WriteStateBufferArgs { - commit_id, + commit_seq, total_len: 4, offset: 0, chunk: first_chunk.clone(), @@ -330,7 +330,7 @@ async fn test_write_state_buffer_duplicate_retry() { &env.writer, env.delegated.pubkey(), WriteStateBufferArgs { - commit_id, + commit_seq, total_len: 4, offset: 0, chunk: first_chunk, @@ -341,7 +341,7 @@ async fn test_write_state_buffer_duplicate_retry() { let state_buffer = state_buffer_pda( &env.delegated.pubkey(), - commit_id, + commit_seq, &env.writer.pubkey(), ); let state_buffer_account = @@ -368,7 +368,7 @@ async fn test_write_state_buffer_duplicate_retry() { #[tokio::test] async fn test_write_state_buffer_rejects_mismatched_duplicate_retry() { let mut env = setup_write_state_buffer_env().await; - let commit_id = 10; + let commit_seq = 10; write_buffer( &mut env.banks, @@ -376,7 +376,7 @@ async fn test_write_state_buffer_rejects_mismatched_duplicate_retry() { &env.writer, env.delegated.pubkey(), WriteStateBufferArgs { - commit_id, + commit_seq, total_len: 4, offset: 0, chunk: vec![1, 2], @@ -391,7 +391,7 @@ async fn test_write_state_buffer_rejects_mismatched_duplicate_retry() { &env.writer, env.delegated.pubkey(), WriteStateBufferArgs { - commit_id, + commit_seq, total_len: 4, offset: 0, chunk: vec![1, 9], @@ -412,7 +412,7 @@ async fn test_write_state_buffer_rejects_wrong_offset() { &env.writer, env.delegated.pubkey(), WriteStateBufferArgs { - commit_id: 11, + commit_seq: 11, total_len: 4, offset: 1, chunk: vec![1, 2], @@ -433,7 +433,7 @@ async fn test_write_state_buffer_rejects_oversized_total_len() { &env.writer, env.delegated.pubkey(), WriteStateBufferArgs { - commit_id: 12, + commit_seq: 12, total_len: StateBuffer::MAX_TOTAL_PAYLOAD_LEN + 1, offset: 0, chunk: vec![1], @@ -447,7 +447,7 @@ async fn test_write_state_buffer_rejects_oversized_total_len() { #[tokio::test] async fn test_write_state_buffer_rejects_post_finalize_mutation() { let mut env = setup_write_state_buffer_env().await; - let commit_id = 13; + let commit_seq = 13; let data = vec![1, 2, 3]; write_buffer( @@ -456,7 +456,7 @@ async fn test_write_state_buffer_rejects_post_finalize_mutation() { &env.writer, env.delegated.pubkey(), WriteStateBufferArgs { - commit_id, + commit_seq, total_len: data.len() as u32, offset: 0, chunk: data.clone(), @@ -471,7 +471,7 @@ async fn test_write_state_buffer_rejects_post_finalize_mutation() { &env.writer, env.delegated.pubkey(), WriteStateBufferArgs { - commit_id, + commit_seq, total_len: data.len() as u32, offset: 0, chunk: data, @@ -486,7 +486,7 @@ async fn test_write_state_buffer_rejects_post_finalize_mutation() { &env.writer, env.delegated.pubkey(), WriteStateBufferArgs { - commit_id, + commit_seq, total_len: 3, offset: 3, chunk: vec![4], @@ -500,7 +500,7 @@ async fn test_write_state_buffer_rejects_post_finalize_mutation() { #[tokio::test] async fn test_write_state_buffer_rejects_wrong_authority_for_buffer() { let mut env = setup_write_state_buffer_env().await; - let commit_id = 14; + let commit_seq = 14; let wrong_authority = Keypair::new(); fund_account(&mut env.banks, &env.payer, &wrong_authority.pubkey()).await; @@ -509,7 +509,7 @@ async fn test_write_state_buffer_rejects_wrong_authority_for_buffer() { env.writer.pubkey(), env.delegated.pubkey(), WriteStateBufferArgs { - commit_id, + commit_seq, total_len: 2, offset: 0, chunk: vec![1, 2], From b0a6babb9204e3db602370f6540c16b73d6def63 Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Fri, 30 Oct 2026 22:55:30 +0530 Subject: [PATCH 4/6] Spell out commit sequence numbers in prose --- docs/design/mimd-0024-fraud-proofs.md | 10 +++++----- interface/src/state/delegation_state.rs | 2 +- interface/src/state/pending_commitment.rs | 7 ++++--- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/design/mimd-0024-fraud-proofs.md b/docs/design/mimd-0024-fraud-proofs.md index ba6d3b9f..9a8027bd 100644 --- a/docs/design/mimd-0024-fraud-proofs.md +++ b/docs/design/mimd-0024-fraud-proofs.md @@ -380,7 +380,7 @@ pub enum ResolvedStateSource { /// Created by: `ProposeCommitment`. /// Closed by: `CloseTerminalAccounts` after finalize, cancel, or expiry. /// -/// One account per delegated account and commit id. +/// One account per delegated account and commit sequence number. pub struct PendingCommitment { /// Current state-machine state for this commitment. pub status: PendingCommitmentStatus, @@ -392,7 +392,7 @@ pub struct PendingCommitment { pub operator_bond: Pubkey, /// Delegated account whose base-layer state will be finalized. pub account_pubkey: Pubkey, - /// Validator-chosen nonce for this account commitment. + /// Monotonically increasing sequence number for this account's commitments. pub commit_seq: u64, /// Delegation metadata tying this account to the ER context. pub delegation_record: Pubkey, @@ -406,8 +406,8 @@ pub struct PendingCommitment { pub lamports: u64, /// Owner committed by the operator. pub owner: Pubkey, - /// Hash binding cluster, validator, account, commit id, delegation, DA, - /// and state. + /// Hash binding cluster, validator, account, commit sequence number, + /// delegation, DA, and state. pub state_commitment_hash: [u8; 32], /// Registry account used when this commitment was posted. pub verifier_registry: Pubkey, @@ -743,7 +743,7 @@ pub struct ResolveDisputeArgs { instructions retain their validator-key authorization model. - `WriteStateBuffer` must run before `ProposeCommitment` for the operator state. `ProposeCommitment` rejects if the operator buffer is missing, unfinished, or - belongs to another account, commit id, or current validator. + belongs to another account, commit sequence number, or current validator. - `ProposeCommitment` reads `data_hash` from the finalized operator buffer, verifies that the delegation, operator bond, and verifier registry belong to the same cluster, computes `account_state_hash` and diff --git a/interface/src/state/delegation_state.rs b/interface/src/state/delegation_state.rs index 67b79d59..d0119b59 100644 --- a/interface/src/state/delegation_state.rs +++ b/interface/src/state/delegation_state.rs @@ -33,7 +33,7 @@ pub struct DelegationState { /// Account lamports at delegation or after the latest finalization. pub lamports: u64, - /// Latest finalized commit id applied to the delegated account. + /// Latest finalized commit sequence number applied to the delegated account. pub last_commit_seq: u64, /// Who requested undelegation, stored as `UndelegationRequester::value()`. diff --git a/interface/src/state/pending_commitment.rs b/interface/src/state/pending_commitment.rs index 06f1f129..7b0ee068 100644 --- a/interface/src/state/pending_commitment.rs +++ b/interface/src/state/pending_commitment.rs @@ -19,7 +19,7 @@ pub const RESOLVED_STATE_SOURCE_CHALLENGER_REVEAL: u8 = 2; /// Created by `ProposeCommitment`. /// Closed by `CloseTerminalAccounts` after finalize, cancel, or expiry. /// -/// One account per delegated account and commit id. +/// One account per delegated account and commit sequence number. #[derive(Clone, Debug, PartialEq, Eq)] #[fixed_offset_layout(buffer_offset = 0)] pub struct PendingCommitment { @@ -41,7 +41,7 @@ pub struct PendingCommitment { /// Delegated account whose base-layer state will be finalized. pub account_pubkey: Pubkey, - /// Operator-chosen nonce for this account commitment. + /// Monotonically increasing sequence number for this account's commitments. pub commit_seq: u64, /// Delegation record tying this account to the ER context. @@ -62,7 +62,8 @@ pub struct PendingCommitment { /// Owner committed by the operator. pub owner: Pubkey, - /// Hash binding operator, account, commit id, delegation, DA, and state. + /// Hash binding operator, account, commit sequence number, delegation, DA, + /// and state. pub state_commitment_hash: [u8; 32], /// Registry account used when this commitment was posted. From fc890fa2af245f9fa1f9eeca225d4254be748930 Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Sat, 31 Oct 2026 20:28:16 +0530 Subject: [PATCH 5/6] Use u32 for v2 commit sequences Reduce v2 commit sequence fields, instruction data, and PDA seed bytes from eight bytes to four. Keep temporary legacy metadata fields as u64 and convert only at that compatibility boundary. --- docs/design/mimd-0024-fraud-proofs.md | 8 ++++---- interface/src/args/propose_commitment.rs | 2 +- interface/src/args/write_state_buffer.rs | 2 +- .../src/instruction_builder/approve_commitment.rs | 2 +- .../src/instruction_builder/challenger_reveal.rs | 2 +- .../src/instruction_builder/finalize_commitment.rs | 6 +++--- interface/src/instruction_builder/raise_challenge.rs | 2 +- interface/src/instruction_builder/resolve_dispute.rs | 2 +- interface/src/pda.rs | 6 +++--- interface/src/state/delegation_state.rs | 2 +- interface/src/state/pending_commitment.rs | 2 +- interface/src/state/state_buffer.rs | 4 ++-- .../src/processor/fraud_proofs/challenger_reveal.rs | 2 +- .../processor/fraud_proofs/finalize_commitment.rs | 12 ++++++++---- .../src/processor/fraud_proofs/propose_commitment.rs | 6 +++--- program/tests/test_approve_commitment.rs | 4 ++-- program/tests/test_challenger_reveal.rs | 4 ++-- program/tests/test_finalize_commitment.rs | 7 +++++-- program/tests/test_raise_challenge.rs | 2 +- program/tests/test_resolve_dispute.rs | 4 ++-- 20 files changed, 44 insertions(+), 37 deletions(-) diff --git a/docs/design/mimd-0024-fraud-proofs.md b/docs/design/mimd-0024-fraud-proofs.md index 9a8027bd..ea2f6c97 100644 --- a/docs/design/mimd-0024-fraud-proofs.md +++ b/docs/design/mimd-0024-fraud-proofs.md @@ -393,7 +393,7 @@ pub struct PendingCommitment { /// Delegated account whose base-layer state will be finalized. pub account_pubkey: Pubkey, /// Monotonically increasing sequence number for this account's commitments. - pub commit_seq: u64, + pub commit_seq: u32, /// Delegation metadata tying this account to the ER context. pub delegation_record: Pubkey, /// Hash of replay/data-availability pointer bytes. @@ -470,7 +470,7 @@ pub struct StateBuffer { pub account_pubkey: Pubkey, /// Commitment this buffer belongs to. - pub commit_seq: u64, + pub commit_seq: u32, /// Hash of the uploaded payload. Zero until finalized. pub data_hash: [u8; 32], @@ -692,7 +692,7 @@ are too slow. ```rust pub struct WriteStateBufferArgs<'a> { - pub commit_seq: u64, + pub commit_seq: u32, pub total_len: u32, /// Must equal StateBuffer.payload.len(), unless retrying an exact old chunk. pub offset: u32, @@ -700,7 +700,7 @@ pub struct WriteStateBufferArgs<'a> { } pub struct ProposeCommitmentArgs { - pub commit_seq: u64, + pub commit_seq: u32, pub lamports: u64, pub owner: Pubkey, pub da_pointer_hash: [u8; 32], diff --git a/interface/src/args/propose_commitment.rs b/interface/src/args/propose_commitment.rs index 21d9b138..7c7b5f40 100644 --- a/interface/src/args/propose_commitment.rs +++ b/interface/src/args/propose_commitment.rs @@ -5,7 +5,7 @@ use crate::compat::Pubkey; #[derive(Clone, Debug, PartialEq, Eq)] #[variable_offset_layout(buffer_offset = 1)] pub struct ProposeCommitmentArgs { - pub commit_seq: u64, + pub commit_seq: u32, pub lamports: u64, diff --git a/interface/src/args/write_state_buffer.rs b/interface/src/args/write_state_buffer.rs index 6df48fad..4fed230e 100644 --- a/interface/src/args/write_state_buffer.rs +++ b/interface/src/args/write_state_buffer.rs @@ -3,7 +3,7 @@ use wheels::variable_offset_layout; #[derive(Clone, Debug, PartialEq, Eq)] #[variable_offset_layout(buffer_offset = 1)] pub struct WriteStateBufferArgs { - pub commit_seq: u64, + pub commit_seq: u32, pub total_len: u32, diff --git a/interface/src/instruction_builder/approve_commitment.rs b/interface/src/instruction_builder/approve_commitment.rs index 9e959a9e..b7b9efa1 100644 --- a/interface/src/instruction_builder/approve_commitment.rs +++ b/interface/src/instruction_builder/approve_commitment.rs @@ -14,7 +14,7 @@ pub fn approve_commitment( verifier: Pubkey, delegation_cluster: Pubkey, account: Pubkey, - commit_seq: u64, + commit_seq: u32, ) -> Instruction { Instruction { program_id: crate::id().modernize(), diff --git a/interface/src/instruction_builder/challenger_reveal.rs b/interface/src/instruction_builder/challenger_reveal.rs index 8d7ed34b..767c5397 100644 --- a/interface/src/instruction_builder/challenger_reveal.rs +++ b/interface/src/instruction_builder/challenger_reveal.rs @@ -17,7 +17,7 @@ pub fn challenger_reveal( operator: Pubkey, delegation_cluster: Pubkey, account: Pubkey, - commit_seq: u64, + commit_seq: u32, args: ChallengerRevealArgs, ) -> Instruction { Instruction { diff --git a/interface/src/instruction_builder/finalize_commitment.rs b/interface/src/instruction_builder/finalize_commitment.rs index 7c5c21eb..506d70b2 100644 --- a/interface/src/instruction_builder/finalize_commitment.rs +++ b/interface/src/instruction_builder/finalize_commitment.rs @@ -19,7 +19,7 @@ pub fn finalize_commitment( operator: Pubkey, delegation_cluster: Pubkey, account: Pubkey, - commit_seq: u64, + commit_seq: u32, ) -> Instruction { finalize_commitment_with_state_authority( operator, @@ -35,7 +35,7 @@ pub fn finalize_challenger_commitment( challenger: Pubkey, delegation_cluster: Pubkey, account: Pubkey, - commit_seq: u64, + commit_seq: u32, ) -> Instruction { let challenge = challenge_pda( &account.compatize(), @@ -57,7 +57,7 @@ fn finalize_commitment_with_state_authority( state_authority: Pubkey, delegation_cluster: Pubkey, account: Pubkey, - commit_seq: u64, + commit_seq: u32, challenge: Option, ) -> Instruction { let mut accounts = vec![ diff --git a/interface/src/instruction_builder/raise_challenge.rs b/interface/src/instruction_builder/raise_challenge.rs index 594b250a..04d6e12e 100644 --- a/interface/src/instruction_builder/raise_challenge.rs +++ b/interface/src/instruction_builder/raise_challenge.rs @@ -16,7 +16,7 @@ pub fn raise_challenge( challenger: Pubkey, delegation_cluster: Pubkey, account: Pubkey, - commit_seq: u64, + commit_seq: u32, args: RaiseChallengeArgs, ) -> Instruction { Instruction { diff --git a/interface/src/instruction_builder/resolve_dispute.rs b/interface/src/instruction_builder/resolve_dispute.rs index be4aaac5..8d65cc52 100644 --- a/interface/src/instruction_builder/resolve_dispute.rs +++ b/interface/src/instruction_builder/resolve_dispute.rs @@ -17,7 +17,7 @@ pub fn resolve_dispute( delegation_cluster: Pubkey, challenger: Pubkey, account: Pubkey, - commit_seq: u64, + commit_seq: u32, args: ResolveDisputeArgs, ) -> Instruction { Instruction { diff --git a/interface/src/pda.rs b/interface/src/pda.rs index c0812a2b..0bce2400 100644 --- a/interface/src/pda.rs +++ b/interface/src/pda.rs @@ -60,7 +60,7 @@ pub fn verifier_bond_pda( pub fn state_buffer_pda( account: &Pubkey, - commit_seq: u64, + commit_seq: u32, authority: &Pubkey, ) -> Pubkey { Pubkey::find_program_address( @@ -75,7 +75,7 @@ pub fn state_buffer_pda( .0 } -pub fn pending_commitment_pda(account: &Pubkey, commit_seq: u64) -> Pubkey { +pub fn pending_commitment_pda(account: &Pubkey, commit_seq: u32) -> Pubkey { Pubkey::find_program_address( &[ PENDING_COMMITMENT_SEED, @@ -89,7 +89,7 @@ pub fn pending_commitment_pda(account: &Pubkey, commit_seq: u64) -> Pubkey { pub fn challenge_pda( account: &Pubkey, - commit_seq: u64, + commit_seq: u32, challenger: &Pubkey, ) -> Pubkey { Pubkey::find_program_address( diff --git a/interface/src/state/delegation_state.rs b/interface/src/state/delegation_state.rs index d0119b59..0dcb0711 100644 --- a/interface/src/state/delegation_state.rs +++ b/interface/src/state/delegation_state.rs @@ -34,7 +34,7 @@ pub struct DelegationState { pub lamports: u64, /// Latest finalized commit sequence number applied to the delegated account. - pub last_commit_seq: u64, + pub last_commit_seq: u32, /// Who requested undelegation, stored as `UndelegationRequester::value()`. pub undelegation_requester: u8, diff --git a/interface/src/state/pending_commitment.rs b/interface/src/state/pending_commitment.rs index 7b0ee068..3a82b250 100644 --- a/interface/src/state/pending_commitment.rs +++ b/interface/src/state/pending_commitment.rs @@ -42,7 +42,7 @@ pub struct PendingCommitment { pub account_pubkey: Pubkey, /// Monotonically increasing sequence number for this account's commitments. - pub commit_seq: u64, + pub commit_seq: u32, /// Delegation record tying this account to the ER context. pub delegation_record: Pubkey, diff --git a/interface/src/state/state_buffer.rs b/interface/src/state/state_buffer.rs index 512944dc..f375f9d8 100644 --- a/interface/src/state/state_buffer.rs +++ b/interface/src/state/state_buffer.rs @@ -20,8 +20,8 @@ pub struct StateBuffer { /// Delegated account whose payload is stored after this header. pub account_pubkey: Pubkey, - /// Flow-specific nonce that identifies this opened buffer. - pub commit_seq: u64, + /// Commit sequence number that identifies this opened buffer. + pub commit_seq: u32, /// Hash of the finalized payload. Zero until finalized. pub data_hash: [u8; 32], diff --git a/program/src/processor/fraud_proofs/challenger_reveal.rs b/program/src/processor/fraud_proofs/challenger_reveal.rs index cc49f7f8..67e26212 100644 --- a/program/src/processor/fraud_proofs/challenger_reveal.rs +++ b/program/src/processor/fraud_proofs/challenger_reveal.rs @@ -328,7 +328,7 @@ fn validate_state_buffer( state_buffer: &AccountView, authority: &dpi::compat::Pubkey, account_pubkey: &dpi::compat::Pubkey, - commit_seq: u64, + commit_seq: u32, expected_data_hash: &[u8; 32], ) -> ProgramResult { let commit_seq_bytes = commit_seq.to_le_bytes(); diff --git a/program/src/processor/fraud_proofs/finalize_commitment.rs b/program/src/processor/fraud_proofs/finalize_commitment.rs index 31ba1202..ca5c4d19 100644 --- a/program/src/processor/fraud_proofs/finalize_commitment.rs +++ b/program/src/processor/fraud_proofs/finalize_commitment.rs @@ -256,7 +256,7 @@ pub fn process_finalize_commitment( { let mut metadata = DelegationMetadataFast::from_account(delegation_metadata)?; - metadata.set_last_commit_id(pending.commit_seq()); + metadata.set_last_commit_id(u64::from(pending.commit_seq())); } drop(delegation_cluster_data); @@ -395,14 +395,18 @@ fn validate_delegation_record( fn validate_delegation_metadata( delegation_metadata: &AccountView, - commit_seq: u64, + commit_seq: u32, ) -> ProgramResult { let metadata = DelegationMetadataFast::from_account(delegation_metadata)?; let expected_commit_seq = metadata .last_commit_id() .checked_add(1) .ok_or(DlpError::Overflow)?; - require_eq!(commit_seq, expected_commit_seq, DlpError::NonceOutOfOrder); + require_eq!( + u64::from(commit_seq), + expected_commit_seq, + DlpError::NonceOutOfOrder + ); match metadata.undelegation_requester()? { UndelegationRequester::None => Ok(()), @@ -419,7 +423,7 @@ fn validate_state_buffer<'a>( data: &'a [u8], state_authority: &AccountView, delegated_account: &AccountView, - commit_seq: u64, + commit_seq: u32, expected_data_hash: &[u8; 32], ) -> Result<&'a [u8], ProgramError> { let state = StateBuffer::decode(data)?; diff --git a/program/src/processor/fraud_proofs/propose_commitment.rs b/program/src/processor/fraud_proofs/propose_commitment.rs index 373cd781..ebea3cb8 100644 --- a/program/src/processor/fraud_proofs/propose_commitment.rs +++ b/program/src/processor/fraud_proofs/propose_commitment.rs @@ -179,7 +179,7 @@ pub fn process_propose_commitment( let delegation_metadata = DelegationMetadataRef::from_account(delegation_metadata)?; require_eq!( - args.commit_seq(), + u64::from(args.commit_seq()), delegation_metadata .last_commit_id() .checked_add(1) @@ -373,7 +373,7 @@ fn validate_state_buffer( state_buffer: &dpi::StateBufferView<'_>, operator: &AccountView, delegated_account: &AccountView, - commit_seq: u64, + commit_seq: u32, ) -> Result<[u8; 32], ProgramError> { if state_buffer.discriminator() != StateBuffer::DISCRIMINATOR { return Err(ProgramError::InvalidAccountData); @@ -468,7 +468,7 @@ struct StateCommitmentHashInput<'a> { delegation_cluster: &'a Address, operator_identity: &'a Address, account_pubkey: &'a Address, - commit_seq: u64, + commit_seq: u32, delegation_record: &'a Address, da_pointer_hash: &'a [u8; 32], account_state_hash: &'a [u8; 32], diff --git a/program/tests/test_approve_commitment.rs b/program/tests/test_approve_commitment.rs index 3f107549..c340eb79 100644 --- a/program/tests/test_approve_commitment.rs +++ b/program/tests/test_approve_commitment.rs @@ -527,7 +527,7 @@ async fn approve( verifier: &Keypair, delegation_cluster: Pubkey, delegated_account: Pubkey, - commit_seq: u64, + commit_seq: u32, ) -> Result<(), solana_program_test::BanksClientError> { let latest_blockhash: Hash = banks.get_latest_blockhash().await.unwrap(); let blockhash = banks @@ -553,7 +553,7 @@ async fn approve( async fn read_pending_commitment_data( banks: &mut BanksClient, delegated_account: Pubkey, - commit_seq: u64, + commit_seq: u32, ) -> Vec { let pending_commitment_account = banks .get_account(pending_commitment_pda(&delegated_account, commit_seq)) diff --git a/program/tests/test_challenger_reveal.rs b/program/tests/test_challenger_reveal.rs index 5b201d67..63b7be46 100644 --- a/program/tests/test_challenger_reveal.rs +++ b/program/tests/test_challenger_reveal.rs @@ -358,7 +358,7 @@ struct ChallengerRevealEnv { delegated_account: Pubkey, committed_owner: Pubkey, committed_lamports: u64, - commit_seq: u64, + commit_seq: u32, challenge_config: ChallengeConfig, operator_state_data: Vec, } @@ -805,7 +805,7 @@ fn challenge_hash( operator: Pubkey, challenger: Pubkey, account: Pubkey, - commit_seq: u64, + commit_seq: u32, args: &ChallengerRevealArgs, ) -> [u8; 32] { solana_sha256_hasher::hashv(&[ diff --git a/program/tests/test_finalize_commitment.rs b/program/tests/test_finalize_commitment.rs index 6446afc3..28d51c07 100644 --- a/program/tests/test_finalize_commitment.rs +++ b/program/tests/test_finalize_commitment.rs @@ -70,7 +70,10 @@ async fn test_finalize_commitment() { assert_eq!(delegation_record.lamports, env.committed_lamports); let delegation_metadata = read_delegation_metadata(&mut env).await; - assert_eq!(delegation_metadata.last_commit_id, env.commit_seq); + assert_eq!( + delegation_metadata.last_commit_id, + u64::from(env.commit_seq) + ); } #[tokio::test] @@ -226,7 +229,7 @@ struct FinalizeCommitmentEnv { delegated_account: Pubkey, committed_owner: Pubkey, committed_lamports: u64, - commit_seq: u64, + commit_seq: u32, final_state_data: Vec, } diff --git a/program/tests/test_raise_challenge.rs b/program/tests/test_raise_challenge.rs index 070b2f1c..4c832e1f 100644 --- a/program/tests/test_raise_challenge.rs +++ b/program/tests/test_raise_challenge.rs @@ -238,7 +238,7 @@ struct RaiseChallengeEnv { delegated_account: Pubkey, committed_owner: Pubkey, committed_lamports: u64, - commit_seq: u64, + commit_seq: u32, challenge_config: ChallengeConfig, } diff --git a/program/tests/test_resolve_dispute.rs b/program/tests/test_resolve_dispute.rs index 2441b40d..b865d8a1 100644 --- a/program/tests/test_resolve_dispute.rs +++ b/program/tests/test_resolve_dispute.rs @@ -375,7 +375,7 @@ struct ResolveDisputeEnv { delegated_account: Pubkey, committed_owner: Pubkey, committed_lamports: u64, - commit_seq: u64, + commit_seq: u32, challenge_config: ChallengeConfig, operator_state_data: Vec, challenger_state_data: Vec, @@ -882,7 +882,7 @@ fn challenge_hash( operator: Pubkey, challenger: Pubkey, account: Pubkey, - commit_seq: u64, + commit_seq: u32, args: &ChallengerRevealArgs, ) -> [u8; 32] { solana_sha256_hasher::hashv(&[ From be1af851f0e4deabb62c520c1477d9226bfe7a3a Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Thu, 5 Nov 2026 19:02:40 +0530 Subject: [PATCH 6/6] Realign verifier entries after shrinking commit sequences --- interface/src/state/pending_commitment.rs | 2 +- program/src/processor/fraud_proofs/propose_commitment.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/state/pending_commitment.rs b/interface/src/state/pending_commitment.rs index 3a82b250..4dc95937 100644 --- a/interface/src/state/pending_commitment.rs +++ b/interface/src/state/pending_commitment.rs @@ -109,7 +109,7 @@ pub struct PendingCommitment { pub er_slot: Option, /// Aligns selected verifier elements after the Vec length prefix. - pub _pad_before_selected_verifiers: [u8; 5], + pub _pad_before_selected_verifiers: [u8; 9], /// Verifiers selected by round-robin for this commitment. #[extendable = 2] diff --git a/program/src/processor/fraud_proofs/propose_commitment.rs b/program/src/processor/fraud_proofs/propose_commitment.rs index ebea3cb8..7dc49c2a 100644 --- a/program/src/processor/fraud_proofs/propose_commitment.rs +++ b/program/src/processor/fraud_proofs/propose_commitment.rs @@ -279,7 +279,7 @@ pub fn process_propose_commitment( active_challenge: None, resolved_state_source: None, er_slot: args.er_slot(), - _pad_before_selected_verifiers: [0; 5], + _pad_before_selected_verifiers: [0; 9], selected_verifiers, };