Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,078 changes: 1,974 additions & 104 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ mollusk-svm-bencher = "0.0.10-solana-2.0"
num-derive = "0.4"
num-traits = "0.2"
serde = "1.0.193"
solana-client = "2.0.1"
solana-program = "2.0.1"
solana-sdk = "2.0.1"
thiserror = "1.0.61"
8 changes: 6 additions & 2 deletions clients/rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,18 @@ license-file = { workspace = true }
edition = { workspace = true }

[features]
fetch = ["dep:solana-client", "dep:solana-sdk"]
serde = ["dep:bincode", "dep:serde", "kaigan/serde"]
test-sbf = []
serde = ["dep:serde"]

[dependencies]
bincode = { workspace = true, optional = true }
borsh = { workspace = true }
kaigan = { workspace = true, features = ["serde"] }
kaigan = { workspace = true }
serde = { workspace = true, features = ["derive"], optional = true }
solana-client = { workspace = true, optional = true }
solana-program = { workspace = true, features = ["borsh"] }
solana-sdk = { workspace = true, optional = true }

[dev-dependencies]
assert_matches = { workspace = true }
Expand Down
12 changes: 6 additions & 6 deletions clients/rust/src/generated/accounts/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ impl<'a> TryFrom<&solana_program::account_info::AccountInfo<'a>> for Config {
#[cfg(feature = "fetch")]
pub fn fetch_config(
rpc: &solana_client::rpc_client::RpcClient,
address: &Pubkey,
address: &solana_program::pubkey::Pubkey,
) -> Result<crate::shared::DecodedAccount<Config>, std::io::Error> {
let accounts = fetch_all_config(rpc, &[*address])?;
Ok(accounts[0].clone())
Expand All @@ -51,10 +51,10 @@ pub fn fetch_config(
#[cfg(feature = "fetch")]
pub fn fetch_all_config(
rpc: &solana_client::rpc_client::RpcClient,
addresses: &[Pubkey],
addresses: &[solana_program::pubkey::Pubkey],
) -> Result<Vec<crate::shared::DecodedAccount<Config>>, std::io::Error> {
let accounts = rpc
.get_multiple_accounts(&addresses)
.get_multiple_accounts(addresses)
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?;
let mut decoded_accounts: Vec<crate::shared::DecodedAccount<Config>> = Vec::new();
for i in 0..addresses.len() {
Expand All @@ -76,7 +76,7 @@ pub fn fetch_all_config(
#[cfg(feature = "fetch")]
pub fn fetch_maybe_config(
rpc: &solana_client::rpc_client::RpcClient,
address: &Pubkey,
address: &solana_program::pubkey::Pubkey,
) -> Result<crate::shared::MaybeAccount<Config>, std::io::Error> {
let accounts = fetch_all_maybe_config(rpc, &[*address])?;
Ok(accounts[0].clone())
Expand All @@ -85,10 +85,10 @@ pub fn fetch_maybe_config(
#[cfg(feature = "fetch")]
pub fn fetch_all_maybe_config(
rpc: &solana_client::rpc_client::RpcClient,
addresses: &[Pubkey],
addresses: &[solana_program::pubkey::Pubkey],
) -> Result<Vec<crate::shared::MaybeAccount<Config>>, std::io::Error> {
let accounts = rpc
.get_multiple_accounts(&addresses)
.get_multiple_accounts(addresses)
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?;
let mut decoded_accounts: Vec<crate::shared::MaybeAccount<Config>> = Vec::new();
for i in 0..addresses.len() {
Expand Down
17 changes: 15 additions & 2 deletions clients/rust/src/hooked/short_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,21 @@ impl<'de, T: Deserialize<'de>> Deserialize<'de> for ShortVec<T> {
}
}

/// ConfigKeys type - uses short vec.
pub type ConfigKeys = ShortVec<(Pubkey, bool)>;
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(BorshDeserialize, BorshSerialize, Clone, Debug, Eq, PartialEq)]
pub struct ConfigKeys {
/// Each key tuple comprises a unique `Pubkey` identifier,
/// and `bool` whether that key is a signer of the data.
pub keys: ShortVec<(Pubkey, bool)>,
}

/// Utility for extracting the `ConfigKeys` data from the account data.
#[cfg(feature = "serde")]
pub fn get_config_data(bytes: &[u8]) -> Result<&[u8], bincode::Error> {
bincode::deserialize::<ConfigKeys>(bytes)
.and_then(|keys| bincode::serialized_size(&keys))
.map(|offset| &bytes[offset as usize..])
}

#[cfg(test)]
mod tests {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,30 @@
//! Program instruction helpers.

use {
crate::{
id,
state::{ConfigKeys, ConfigState},
},
crate::{ConfigKeys, ShortVec, ID},
bincode::serialized_size,
solana_program::{
instruction::{AccountMeta, Instruction},
pubkey::Pubkey,
system_instruction,
},
};

/// Trait defining config state to be stored at the end of the account data.
pub trait ConfigState: serde::Serialize + Default {
/// Maximum space that the serialized representation will require
fn max_space() -> u64;
}

fn initialize_account<T: ConfigState>(config_pubkey: &Pubkey) -> Instruction {
let account_metas = vec![AccountMeta::new(*config_pubkey, true)];
let account_data = (ConfigKeys { keys: vec![] }, T::default());
Instruction::new_with_bincode(id(), &account_data, account_metas)
let account_data = (
ConfigKeys {
keys: ShortVec(vec![]),
},
T::default(),
);
Instruction::new_with_bincode(ID, &account_data, account_metas)
}

/// Create a new, empty configuration account
Expand All @@ -25,14 +34,19 @@ pub fn create_account<T: ConfigState>(
lamports: u64,
keys: Vec<(Pubkey, bool)>,
) -> Vec<Instruction> {
let space = T::max_space().saturating_add(ConfigKeys::serialized_size(keys));
let space = T::max_space().saturating_add(
serialized_size(&ConfigKeys {
keys: ShortVec(keys),
})
.unwrap(),
);
vec![
system_instruction::create_account(
from_account_pubkey,
config_account_pubkey,
lamports,
space,
&id(),
&ID,
),
initialize_account::<T>(config_account_pubkey),
]
Expand All @@ -51,6 +65,11 @@ pub fn store<T: ConfigState>(
account_metas.push(AccountMeta::new(*signer_pubkey, true));
}
}
let account_data = (ConfigKeys { keys }, data);
Instruction::new_with_bincode(id(), &account_data, account_metas)
let account_data = (
ConfigKeys {
keys: ShortVec(keys),
},
data,
);
Instruction::new_with_bincode(ID, &account_data, account_metas)
}
5 changes: 5 additions & 0 deletions clients/rust/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
#![allow(clippy::arithmetic_side_effects)]

mod generated;
mod hooked;

#[cfg(feature = "serde")]
pub mod instructions_bincode;

pub use {
generated::{programs::SOLANA_CONFIG_ID as ID, *},
hooked::*,
Expand Down
1 change: 1 addition & 0 deletions program/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ thiserror = { workspace = true }
[dev-dependencies]
mollusk-svm = { workspace = true, features = ["fuzz-fd"] }
mollusk-svm-bencher = { workspace = true }
solana-config-program-client = { path = "../clients/rust", features = ["serde"] }
solana-sdk = { workspace = true }

[lib]
Expand Down
41 changes: 41 additions & 0 deletions program/benches/compute_units.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,44 @@
#### Compute Units: 2025-03-17 16:28:15.510092129 UTC

| Name | CUs | Delta |
|------|------|-------|
| config_small_init_0_keys | 600 | -16 |
| config_small_init_1_keys | 1232 | -15 |
| config_small_init_5_keys | 2855 | -11 |
| config_small_init_10_keys | 4930 | -6 |
| config_small_init_25_keys | 11787 | +9 |
| config_small_init_37_keys | 16802 | +21 |
| config_small_store_0_keys | 600 | -16 |
| config_small_store_1_keys | 1487 | -14 |
| config_small_store_5_keys | 4014 | -22 |
| config_small_store_10_keys | 7219 | -32 |
| config_small_store_25_keys | 17466 | -62 |
| config_small_store_37_keys | 25193 | -86 |
| config_medium_init_0_keys | 591 | -16 |
| config_medium_init_1_keys | 1179 | -15 |
| config_medium_init_5_keys | 2855 | -11 |
| config_medium_init_10_keys | 4930 | -6 |
| config_medium_init_25_keys | 11787 | +9 |
| config_medium_init_37_keys | 16802 | +21 |
| config_medium_store_0_keys | 591 | -16 |
| config_medium_store_1_keys | 1434 | -14 |
| config_medium_store_5_keys | 4014 | -22 |
| config_medium_store_10_keys | 7219 | -32 |
| config_medium_store_25_keys | 17466 | -62 |
| config_medium_store_37_keys | 25193 | -86 |
| config_large_init_0_keys | 712 | -16 |
| config_large_init_1_keys | 1300 | -15 |
| config_large_init_5_keys | 2976 | -11 |
| config_large_init_10_keys | 5052 | -6 |
| config_large_init_25_keys | 11911 | +9 |
| config_large_init_37_keys | 16927 | +21 |
| config_large_store_0_keys | 712 | -16 |
| config_large_store_1_keys | 1555 | -14 |
| config_large_store_5_keys | 4135 | -22 |
| config_large_store_10_keys | 7341 | -32 |
| config_large_store_25_keys | 17590 | -62 |
| config_large_store_37_keys | 25318 | -86 |

#### Compute Units: 2024-11-08 12:36:57.438693 UTC

| Name | CUs | Delta |
Expand Down
8 changes: 3 additions & 5 deletions program/benches/setup.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use {
mollusk_svm_bencher::Bench,
serde::Serialize,
solana_config_program::{
instruction::store,
state::{ConfigKeys, ConfigState},
},
solana_config_program::state::ConfigKeys,
solana_config_program_client::instructions_bincode::{store, ConfigState},
solana_sdk::{
account::AccountSharedData,
hash::Hash,
Expand Down Expand Up @@ -39,7 +37,7 @@ pub trait BenchSetup: ConfigState + Default {

fn default_space(keys: Vec<(Pubkey, bool)>) -> usize {
(Self::max_space()
.checked_add(ConfigKeys::serialized_size(keys))
.checked_add(bincode::serialized_size(&ConfigKeys { keys }).unwrap())
.unwrap()) as usize
}

Expand Down
1 change: 0 additions & 1 deletion program/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#[cfg(all(target_os = "solana", feature = "bpf-entrypoint"))]
mod entrypoint;
pub mod error;
pub mod instruction;
pub mod processor;
pub mod state;

Expand Down
22 changes: 0 additions & 22 deletions program/src/state.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
//! Program state types.

use {
bincode::{deserialize, serialized_size},
serde::{Deserialize, Serialize},
solana_program::{pubkey::Pubkey, short_vec},
};

/// Trait defining config state to be stored at the end of the account data.
pub trait ConfigState: serde::Serialize + Default {
/// Maximum space that the serialized representation will require
fn max_space() -> u64;
}

/// A collection of keys to be stored in Config account data.
#[derive(Debug, Default, Deserialize, Serialize)]
pub struct ConfigKeys {
Expand All @@ -20,18 +13,3 @@ pub struct ConfigKeys {
#[serde(with = "short_vec")]
pub keys: Vec<(Pubkey, bool)>,
}

impl ConfigKeys {
/// Get the serialized size of the `ConfigKeys` struct,
/// given a list of keys.
pub fn serialized_size(keys: Vec<(Pubkey, bool)>) -> u64 {
serialized_size(&ConfigKeys { keys }).unwrap()
}
}

/// Utility for extracting the `ConfigKeys` data from the account data.
pub fn get_config_data(bytes: &[u8]) -> Result<&[u8], bincode::Error> {
deserialize::<ConfigKeys>(bytes)
.and_then(|keys| serialized_size(&keys))
.map(|offset| &bytes[offset as usize..])
}
Loading
Loading