SVM Series 02: SVM Feature Activation & Management

448-OG448-OG
5 min read

What are features?

Feature activation refers to a community-governed process for enabling new non-controversial network primitives on the Solana network through validator voting based on stake weight. An example of this is SIMD 220 which improves validator performance by using Accounts Lattice Hash for snapshots instead of the Merkle-based account hash.

SPL tokens that represent the total active stake on the network are minted and distributed to all validtors based on their stake. Validators then transfer their vote tokens to a certain predetermined address, in the case of SIMD 220 address LTsNA...3mSQ2 on mainnet-beta. Once vote threshold is met the feature is activated at the beginning of a predetermined epoch. The built-in Feature program present in all validators is responsible for activating new features simultaneously to avoid hard forks that break consensus.

Feature proposal

A feature proposal is added to the code base using a feature id. Feature IDs can be accessed using the agave-feature-set Rust crate. The feature ID is generated in the following steps:

  1. Create a Solana keypair for the proposal

     solana-keygen new --outfile <feature-proposal-name>.json --silent --no-passphrase
    
  2. Install the (note you need libudev installed) and then run

     # install spl-feature-proposal-cli
     $ cargo install spl-feature-proposal-cli --git https://github.com/solana-program/feature-proposal.git
    
     # Derive the feature ID
     $ spl-feature-proposal address feature-proposal.json
    

    Deriving the feature ID prints the details; example:

     Feature Id: AMJPdBjeCf1694FJcGsYNsGZaXogXuSVRVUVTAX28PEi
     Token Mint Address: 3vYBgFztMaEPByNsk8acEjfjLauswW46hm2ZuMkh3WFy
     Acceptance Token Address: EhfPUgpY4sKPqy8i488cXGxwKwMQ7YcMa5CMMHyzn6w9
    

    where: Feature Id: is the identifier added to the code base for that feature and is also retrieved by solana feature status subcommand of the solana command line tool. Note that only the feature proposal program can activate this feature since there is no private key for the address identified by the Feature id.

  3. Initializing the feature - This is only possible after the feature is deployed to a Solana cluster (devnet, testnet or mainnet-beta). Note that features are first deployed to testnet cluster. Running solana feature status should show this feature's ID.

     # Example from Solana docs. Running this mints SPL tokens for the feature proposal and the 
     # `feature proposer` is required to finance creating all the 
     # SPL token accounts (about 0.00204 SOL per account) for all validators
     $ spl-feature-proposal propose feature-proposal.
    
     # The output of the above command example from Solana docs
     Feature Id: HQ3baDfNU7WKCyWvtMYZmi51YPs7vhSiLn1ESYp3jhiA
     Token Mint Address: ALvA7Lv9jbo8JFhxqnRpjWWuR3aD12uCb5KBJst4uc3d 
     Distributor Token Address: GK55hNft4TGc3Hg4KzbjEmju8VfaNuXK8jQNDTZKcsNF 
     Acceptance Token Address: AdqKm3mSJf8AtTWjfpA5ZbJszWQPcwyLA2XkRyLbf3Di 
     Number of validators: 376 
     Tokens to be minted: 134575791.53064314 
     Tokens required for acceptance: 90165780.3255309 (67%) 
     Token distribution file: feature-proposal.csv 
     JSON RPC URL: http://api.mainnet-beta.solana.com
    
     Distribute the proposal tokens to all validators by running: 
         $ solana-tokens distribute-spl-tokens --from GK55hNft4TGc3Hg4KzbjEmju8VfaNuXK8jQNDTZKcsNF --input-csv feature-proposal.csv --db-path db.8CyUVvio --fee-payer ~/.config/solana/id.json --owner <FEATURE_PROPOSAL_KEYPAIR> 
         $ solana-tokens spl-token-balances --mint ALvA7Lv9jbo8JFhxqnRpjWWuR3aD12uCb5KBJst4uc3d --input-csv feature-proposal.csv
    
     Once the distribution is complete, request validators vote for the proposal. To vote, validators should first look up their token account address: 
         $ spl-token --owner ~/validator-keypair.json accounts ALvA7Lv9jbo8JFhxqnRpjWWuR3aD12uCb5KBJst4uc3d 
     and then submit their vote by running: 
         $ spl-token --owner ~/validator-keypair.json transfer <TOKEN_ACCOUNT_ADDRESS> ALL AdqKm3mSJf8AtTWjfpA5ZbJszWQPcwyLA2XkRyLbf3Di
    
     Periodically the votes must be tallied by running: 
         $ spl-feature-proposal tally 8CyUVvio2oYAP28ZkMBPHq88ikhRgWet6i4NYsCW5Cxa
     Tallying is permissionless and may be run by anybody.
     Once this feature proposal is accepted, the HQ3baDfNU7WKCyWvtMYZmi51YPs7vhSiLn1ESYp3jhiA feature will be activated at the next epoch.
    
     Add --confirm flag to initiate the feature proposal
    
  4. Tally the votes - anyone can tally the votes to enable the feature to be automatically activated at the start of the next epoch

      $ spl-feature-proposal tally
    

Using features in SVM API

In this series we will use a mock Bank to coordinate the SVM execution pipeline. The agave-feature-set Rust crate will be used to activate features for transaction processing.

FeatureSet struct

Feature set is defined by the struct FeatureSet which contains a list of activated features in the active field and deactivated features in the inactive field.

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct FeatureSet {
    active: AHashMap<Pubkey, u64>,
    inactive: AHashSet<Pubkey>,
}

Default implementation for FeatureSet struct

Instantiating the FeatureSet struct using default method FeatureSet::default() makes all features inactive.


// Default implementation for `FeatureSet`
impl Default for FeatureSet {
    fn default() -> Self {
        Self {
            // All features disabled
            active: AHashMap::new(),
            inactive: AHashSet::from_iter((*FEATURE_NAMES).keys().cloned()),
        }
    }
}

The *FEATURE_NAMES is used to load all features since they are defined by agave_feature_set::FEATURE_NAMES constant which is a can be described as HashMap<Public Key of the feature, the description of the feature>.

Let’s explore this by creating a new Rust project and add the agave-feature-set crate

cargo new explore-feature-set
# Add agave-feature-set to Cargo.toml
cargo add agave-feature-set

Looping through the available features for SVM API

In the src/main.rs folder loop through the feature names

use agave_feature_set::FEATURE_NAMES;

fn main() {
    // Loop through the available features for the SVM version
    for (feature_name: &solana_pubkey::Pubkey, feature_description: &&str) in FEATURE_NAMES.iter() {
        println!("{feature_name} - {feature_description",);
    }
}

Instantiating the defaults for FeatureSet

use agave_feature_set::FeatureSet;

let feature_set_api = FeatureSet::default();

Methods on FeatureSet

FeatureSet methods on can activate or deactivate a feature by providing it’s public key. An example is activating SIMD 256 which raises the block limit to 60M . agave-feature-set crate provides constant modules that have a method id() which contains the Public Key for the feature activation. For SIMD 256, the module is agave_feature_set::raise_block_limits_to_60m .

The activate() method requires the feature public key and the slot that the feature will be activated.

use agave_feature_set::FeatureSet;

fn main() {
    let mut feature_manager = FeatureSet::default();

    // Activate SIMD 256 from slot zero
    feature_manager.activate(&agave_feature_set::raise_block_limits_to_60m::id(), 0);

    // To deactivate a feature, example  SIMD 256
    feature_manager.deactivate(&agave_feature_set::raise_block_limits_to_60m::id());

    // Some more useful methods are
    //

    // To check whether a feature is active, example  SIMD 256
    feature_manager.is_active(&agave_feature_set::raise_block_limits_to_60m::id());

    // To check the slot when a certain feature was activated, example  SIMD 256
    feature_manager.activated_slot(&agave_feature_set::raise_block_limits_to_60m::id());

    // To get all active features
    feature_manager.active();

    // To get all inactive features
    feature_manager.inactive();

    // To get all enabled features that trigger full inflation
    feature_manager.full_inflation_features_enabled();

    // To instantiate a `FeatureSet` struct with all features enabled at once
    let feature_manager = FeatureSet::all_enabled();
}

These methods can be used to instantiate a Bank with the features required in your SVM application.

The source code for this article can be found at - https://github.com/448-OG/SVM-Series/tree/master/svm-featues

< Previous Article - SVM Series 01: Introduction

Next Article - SVM Series 03: Compute Budget & Syscalls >

Resources

  1. Feature Proposal Program’s source code - https://github.com/solana-program/feature-proposal

  2. solana-feature-gate-interface - crate used within validator client to provide mechanism for features to be simultaneously activated across the network.
    https://crates.io/crates/solana-feature-gate-interface

  3. solana feature activate - subcommand part of the solana command line tool used to activate features. Run solana feature --help to show other arguments.

0
Subscribe to my newsletter

Read articles from 448-OG directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

448-OG
448-OG

<[Open Source, Rust, Decentralized Infrastructure]>::earth()