Skip to main content

FeatureManagementInstruction

Enum FeatureManagementInstruction 

Source
pub enum FeatureManagementInstruction {
    Enable {
        names: Vec<String>,
    },
    ScheduleEnable {
        names: Vec<String>,
        fire_at_ms: u64,
        request_id: u64,
    },
    FireScheduledEnable {
        request_id: u64,
    },
    Cancel {
        request_id: u64,
    },
    UpdateAuthority {
        new_authority: Pubkey,
    },
    ProposeAuthorityTransfer {
        new_authority: Pubkey,
    },
    AcceptAuthorityTransfer,
    CancelAuthorityTransfer,
}
Expand description

Instructions supported by the Feature Management Program

Wire-stable from this commit forward. Borsh assigns each variant a discriminant equal to its declaration index (the first byte on the wire), so reordering variants or inserting one in the middle silently shifts the discriminants of every following variant and breaks already-deployed clients. From now on, add new variants only at the tail with the next unused discriminant. The committed wire discriminants are pinned by the discriminants_are_stable test below.

Variants§

§

Enable

Enable one or more features by name.

Idempotent: re-submitting an existing name is a no-op. Activation is presence-based — a feature is active iff its name is in FeaturesState.entries.

Per-batch cap: names.len() MUST be <= MAX_NAMES_PER_BATCH and each name MUST satisfy validate_feature_name (which enforces <= MAX_FEATURE_NAME_LENGTH and the allowed character set). The MAX_NAMES_PER_BATCH × MAX_FEATURE_NAME_LENGTH payload is sized to fit inside the ~64 KB transaction limit alongside headers and signatures.

Accounts expected: 0. [writable] Storage account (PDA)

  1. [signer] The authority account

Fields

§names: Vec<String>

One or more feature names to add to the active set. See the per-batch / per-name caps above.

§

ScheduleEnable

Schedule one or more features to be enabled at a future wall-clock time, rather than immediately.

The caller supplies request_id: it is the subscription nonce and the Cancel handle. Because the subscription data account is a PDA derived from the authority + request_id, the client must know the id ahead of time to derive (and pass in) that account — so the id is chosen by the caller rather than allocated on-chain. The program rejects a request_id that already has a pending entry (with RequestAlreadyExists).

Records a pending request in FeaturesState.pending keyed by request_id, and registers a one-shot subscription (via the subscriber program) with a fire_at_ms..u64::MAX timestamp_range predicate — it fires on the first commit whose clock is at or after fire_at_ms (the Rialo clock advances in coarse subdag steps, so a narrow window could never match). When it fires, the subscription invokes this program’s own FeatureManagementInstruction::FireScheduledEnable for request_id, signed by the authority that scheduled it; that handler activates the names recorded in pending[request_id] and removes the pending entry, and the one-shot subscription then self-destroys.

Same per-batch / per-name caps as Enable (MAX_NAMES_PER_BATCH + validate_feature_name), except MAX_FEATURE_COUNT is enforced at fire time (in FireScheduledEnable), not at schedule time. fire_at_ms must be in the future (rejected with ScheduleInPast) and within MAX_SCHEDULE_HORIZON_MS of the current block time (rejected with ScheduleTooFarOut). The pending set is bounded by MAX_PENDING_REQUESTS (count) and by MAX_FEATURES_STATE_SIZE (bytes) — the byte cap is the binding one for non-trivial batches and is rejected explicitly with PendingStateTooLarge.

Stable across authority transfers. The subscription is created under, and fires signed by, a program-derived scheduler authority (get_scheduler_authority_address) — not the live human authority. The subscription data account is a PDA of (scheduler_authority, request_id), so an UpdateAuthority / two-step accept between schedule and cancel/fire does not orphan the pending entry: the program can still derive the same subscription account, and the matcher’s fired tx still satisfies FireScheduledEnable’s authority check (signer == scheduler PDA, independent of the human authority).

Accounts expected: 0. [writable] Storage account (PDA)

  1. [writable, signer] The authority account (pays rent for the subscription data account; the program top-ups the scheduler PDA just-in-time from the authority before the inner subscribe)
  2. [writable] Subscription data account (PDA from scheduler authority
    • request_id)
  3. [] Subscriber program
  4. [] System program
  5. [writable] Scheduler authority PDA (get_scheduler_authority_address) — funded by the authority and used as the subscription’s subscriber/signer

Fields

§names: Vec<String>

Feature names to enable when the schedule fires. See the per-batch / per-name caps above.

§fire_at_ms: u64

Wall-clock time (ms since the Unix epoch) at which the features activate.

§request_id: u64

Caller-chosen id for this schedule: the subscription nonce and the Cancel handle. Must not already have a pending entry.

§

FireScheduledEnable

Program-internal: fire a previously-scheduled FeatureManagementInstruction::ScheduleEnable.

Not meant to be submitted by clients directly: it is registered as the handler instruction of the one-shot subscription created by ScheduleEnable, and is invoked when that subscription’s timestamp_range predicate fires. When it fires it activates the names recorded in pending[request_id] and removes that pending entry (so a fired schedule no longer lingers in FeaturesState.pending). Signed by the scheduling authority.

Rejected with RequestNotFound if no pending request has that id.

Accounts expected: 0. [writable] Storage account (PDA)

  1. [signer] The authority account

Fields

§request_id: u64

Id of the pending scheduled request to activate and drain. Matches the request_id recorded by ScheduleEnable.

§

Cancel

Cancel a previously-scheduled FeatureManagementInstruction::ScheduleEnable by its request_id.

Removes the pending entry from FeaturesState.pending and destroys the one-shot subscription so it never fires. Rejected with RequestNotFound if no pending request has that id. Signed by the authority.

A schedule that has already fired is gone from pending (the one-shot self-destructs), so cancelling it returns RequestNotFound — activation is append-only and cannot be undone.

Accounts expected: 0. [writable] Storage account (PDA)

  1. [signer] The authority account
  2. [writable] Subscription data account (PDA from scheduler authority
    • request_id)
  3. [] Subscriber program
  4. [writable] Scheduler authority PDA — receives the destroyed subscription’s kelvins back via the inner unsubscribe

Fields

§request_id: u64

Id of the pending scheduled request to cancel.

§

UpdateAuthority

Update the authority. Single-step path.

This instruction requires a valid signature from the current authority.

Accounts expected: 0. [writable] Storage account (PDA)

  1. [signer] The current authority account

Fields

§new_authority: Pubkey

The new authority that will control the feature management system.

§

ProposeAuthorityTransfer

Step 1 of the two-step authority handshake: propose a transfer.

Sets pending_authority = Some(new_authority). Rejected with PendingTransferExists if a previous proposal is still outstanding; rejected with InvalidTransferTarget if new_authority equals the current authority.

Accounts expected: 0. [writable] Storage account (PDA)

  1. [signer] The current authority

Fields

§new_authority: Pubkey

Pubkey that will become the next authority once it signs an AcceptAuthorityTransfer against this pending value.

§

AcceptAuthorityTransfer

Step 2 of the two-step authority handshake: commit a previously proposed transfer.

Requires the pending authority’s signature. On success the authority field moves to the pending value and pending_authority clears. Rejected with NoPendingTransfer if nothing is pending, Unauthorized if the signer is not the pending authority.

Accounts expected: 0. [writable] Storage account (PDA)

  1. [signer] The pending authority
§

CancelAuthorityTransfer

Cancel a previously proposed authority transfer.

Requires the current authority’s signature. Clears pending_authority. Rejected with NoPendingTransfer if nothing is pending.

Accounts expected: 0. [writable] Storage account (PDA)

  1. [signer] The current authority

Implementations§

Source§

impl FeatureManagementInstruction

Source

pub fn serialize(&self) -> Result<Vec<u8>, Error>

Serialize instruction data

Source

pub fn deserialize(data: &[u8]) -> Result<Self, Error>

Deserialize instruction data

Trait Implementations§

Source§

impl BorshDeserialize for FeatureManagementInstruction

Source§

fn deserialize_reader<__R: Read>(reader: &mut __R) -> Result<Self, Error>

Source§

fn deserialize(buf: &mut &[u8]) -> Result<Self, Error>

Deserializes this instance from a given slice of bytes. Updates the buffer to point at the remaining bytes.
Source§

fn try_from_slice(v: &[u8]) -> Result<Self, Error>

Deserialize this instance from a slice of bytes.
Source§

fn try_from_reader<R>(reader: &mut R) -> Result<Self, Error>
where R: Read,

Source§

impl BorshSerialize for FeatureManagementInstruction

Source§

fn serialize<__W: Write>(&self, writer: &mut __W) -> Result<(), Error>

Source§

impl Clone for FeatureManagementInstruction

Source§

fn clone(&self) -> FeatureManagementInstruction

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for FeatureManagementInstruction

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl EnumExt for FeatureManagementInstruction

Source§

fn deserialize_variant<__R: Read>( reader: &mut __R, variant_tag: u8, ) -> Result<Self, Error>

Deserialises given variant of an enum from the reader. Read more
Source§

impl Eq for FeatureManagementInstruction

Source§

impl PartialEq for FeatureManagementInstruction

Source§

fn eq(&self, other: &FeatureManagementInstruction) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl StructuralPartialEq for FeatureManagementInstruction

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.