Skip to content

Commit 3f9faf0

Browse files
authored
Merge branch 'rustopian/eisodos-sdk' into main
2 parents c7ba5f7 + 844ebff commit 3f9faf0

28 files changed

Lines changed: 3105 additions & 473 deletions

Cargo.lock

Lines changed: 1681 additions & 363 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,27 @@ Entrypoint implementation currently included in the benchmark:
3636
| _CPI_ |
3737
| CreateAccount | 🟨 1,449 (+142) | 🟨 1,494 (+187) | 🟥 2,786 (+1,479) | 🟩 **1,307** |
3838
| Transfer | 🟨 1,439 (+140) | 🟨 1,487 (+180) | 🟥 2,379 (+1,080) | 🟩 **1,299** |
39+
=======
40+
| Benchmark | `pinocchio` | `solana-nostd-entrypoint` | `solana-program` |
41+
| ------------- | -------------- | ------------------------- | ------------------ |
42+
| _Entrypoint_ |
43+
| Ping | 🟩 **14** | 🟩 15 (+1) | 🟥 117 (+103) |
44+
| Log | 🟩 **119** | 🟩 120 (+1) | 🟥 222 (+103) |
45+
| Account (1) | 🟩 **38** | 🟩 42 (+4) | 🟥 317 (+279) |
46+
| Account (3) | 🟩 **66** | 🟩 72 (+6) | 🟥 641 (+575) |
47+
| Account (5) | 🟩 **94** | 🟩 102 (+8) | 🟥 965 (+871) |
48+
| Account (10) | 🟩 **164** | 🟩 177 (+13) | 🟥 1,775 (+1,611) |
49+
| Account (20) | 🟩 **304** | 🟨 327 (+23) | 🟥 3,395 (+3,091) |
50+
| Account (32) | 🟩 **472** | 🟨 507 (+35) | 🟥 5,339 (+4,867) |
51+
| Account (64) | 🟩 **920** | 🟨 988 (+68) | 🟥 10,523 (+9,603) |
52+
| _CPI_ |
53+
| CreateAccount | 🟩 **1,311** | 🟩 1,314 (+3) | 🟥 2,866 (+1,555) |
54+
| Transfer | 🟩 **1,307** | 🟩 1,309 (+2) | 🟥 2,459 (+1,152) |
3955

4056
> [!IMPORTANT]
4157
> Values correspond to compute units (CUs) consumed by the entrypoint. The delta in relation to the lowest consumption is shown in brackets.
4258
>
43-
> Solana CLI `v2.2.6` was used in the bench tests.
59+
> Solana CLI `v2.2.13` was used in the bench tests.
4460
4561
## Binary Sizes
4662

benchmark/Cargo.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
[package]
22
name = "eisodos"
3+
edition = "2021"
34
publish = false
45

56
[[bin]]
@@ -11,11 +12,13 @@ eisodos-jiminy = { path="../programs/jiminy" }
1112
eisodos-pinocchio = { path="../programs/pinocchio" }
1213
eisodos-solana-nostd-entrypoint = { path="../programs/solana-nostd-entrypoint" }
1314
eisodos-solana-program = { path="../programs/solana-program" }
14-
mollusk-svm = "0.1.4"
15-
mollusk-svm-bencher = "0.1.4"
15+
mollusk-svm = "0.1.5"
16+
mollusk-svm-bencher = "0.1.5"
1617
solana-account = "2.2"
1718
solana-instruction = "2.2"
1819
solana-logger = "2.2"
20+
solana-program = "2.2"
1921
solana-pubkey = "2.2"
22+
solana-sdk = "2.2"
2023
solana-system-interface = { version = "1.0" }
2124

benchmark/benches/setup/mod.rs

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,41 @@
11
pub mod runner;
22

3+
// Bring crates into scope
34
use mollusk_svm::{program::keyed_account_for_system_program, Mollusk};
45
use solana_account::Account;
56
use solana_instruction::{AccountMeta, Instruction};
7+
use solana_program;
8+
// Imports needed for SlotHashes construction
9+
// Use correct paths for 1.18
10+
use solana_program::clock::Slot;
11+
use solana_program::hash::Hash;
12+
// SlotHash is a type alias (Slot, Hash)
13+
use solana_program::slot_hashes::SlotHash;
14+
// Use Sysvar ID from solana_program
15+
use solana_program::sysvar::ID as SYSVAR_PROGRAM_ID;
616
use solana_pubkey::Pubkey;
717
use std::vec;
818

19+
// Enum to control slot decrement behavior in mock data generation
20+
#[derive(Clone, Copy, Debug)]
21+
enum DecrementStrategy {
22+
Strictly1,
23+
Average1_05,
24+
Average2,
25+
}
26+
927
pub const BASE_LAMPORTS: u64 = 2_000_000_000u64;
28+
const NUM_BENCH_SLOT_HASH_ENTRIES: usize = 512;
29+
const BENCH_SLOT_HASH_START_SLOT: u64 = 10000;
30+
31+
// Simple deterministic PRNG for varied decrements
32+
// Using a basic Lehmer / MINSTD generator approach
33+
fn simple_prng(seed: u64) -> u64 {
34+
const A: u64 = 16807; // Multiplier
35+
const M: u64 = 2147483647; // Modulus (2^31 - 1)
36+
let initial_state = if seed == 0 { 1 } else { seed };
37+
(A.wrapping_mul(initial_state)) % M
38+
}
1039

1140
/// Create a new Mollusk instance for the given program ID and name.
1241
pub fn setup(program_id: &Pubkey, name: &'static str) -> Mollusk {
@@ -17,12 +46,23 @@ pub fn setup(program_id: &Pubkey, name: &'static str) -> Mollusk {
1746
}
1847

1948
/// Instructions on the program to be executed.
49+
#[derive(Clone, Copy, Debug)]
2050
pub enum ProgramInstruction {
2151
Ping,
2252
Log,
2353
Account { expected: u64 },
2454
CreateAccount,
2555
Transfer,
56+
// --- SlotHashes (Safe/Checked Path - Primarily for SDK/Nostd now) ---
57+
SlotHashesGetEntryChecked, // ID 5
58+
SlotHashesGetHashChecked, /* ID 6 (Treat Interpolated/Midpoint same for SDK/Nostd manual
59+
* search) */
60+
SlotHashesPositionChecked, // ID 7
61+
// --- SlotHashes (Unsafe/Unchecked Path - For Pinocchio Benchmarking) ---
62+
SlotHashesGetEntryUnchecked, // ID 8
63+
SlotHashesGetHashInterpolatedUnchecked, // ID 9
64+
SlotHashesPositionInterpolatedUnchecked { target_slot: Slot }, // ID 10 <- Takes Slot
65+
SlotHashesPositionNaiveUnchecked { target_slot: Slot }, // ID 11 <- Takes Slot
2666
}
2767

2868
/// Returns the instruction data for the given instruction.
@@ -38,6 +78,27 @@ pub fn instruction_data(instruction: ProgramInstruction) -> Vec<u8> {
3878
}
3979
ProgramInstruction::CreateAccount => vec![3],
4080
ProgramInstruction::Transfer => vec![4],
81+
// Checked path instructions (match SDK/Nostd implementation)
82+
ProgramInstruction::SlotHashesGetEntryChecked => vec![5],
83+
ProgramInstruction::SlotHashesGetHashChecked => vec![6],
84+
ProgramInstruction::SlotHashesPositionChecked => vec![7],
85+
// Unchecked path instructions (Pinocchio specific tests)
86+
ProgramInstruction::SlotHashesGetEntryUnchecked => vec![8],
87+
ProgramInstruction::SlotHashesGetHashInterpolatedUnchecked => vec![9],
88+
ProgramInstruction::SlotHashesPositionInterpolatedUnchecked { target_slot } => {
89+
let mut data = Vec::with_capacity(1 + 8);
90+
data.push(10);
91+
data.extend_from_slice(&target_slot.to_le_bytes());
92+
data
93+
}
94+
ProgramInstruction::SlotHashesPositionNaiveUnchecked { target_slot } => {
95+
let mut data = Vec::with_capacity(1 + 8);
96+
data.push(11);
97+
data.extend_from_slice(&target_slot.to_le_bytes());
98+
data
99+
}
100+
// Default/Error case for unused IDs - or handle in processor
101+
_ => vec![255], // Or panic, or specific error instruction
41102
}
42103
}
43104

@@ -50,6 +111,47 @@ pub fn generate_pubkeys(count: usize) -> Vec<Pubkey> {
50111
keys
51112
}
52113

114+
/// Helper function to generate more realistic SlotHashes data
115+
fn generate_mock_slot_hashes_data(strategy: DecrementStrategy) -> Vec<(u64, [u8; 32])> {
116+
let mut entries = Vec::with_capacity(NUM_BENCH_SLOT_HASH_ENTRIES);
117+
let mut current_slot = BENCH_SLOT_HASH_START_SLOT;
118+
119+
for i in 0..NUM_BENCH_SLOT_HASH_ENTRIES {
120+
let hash_byte = (i % 256) as u8;
121+
let hash = [hash_byte; 32];
122+
entries.push((current_slot, hash));
123+
124+
let random_val = simple_prng(i as u64);
125+
let decrement = match strategy {
126+
DecrementStrategy::Strictly1 => 1,
127+
DecrementStrategy::Average1_05 => {
128+
if random_val % 20 == 0 {
129+
2
130+
} else {
131+
1
132+
}
133+
}
134+
DecrementStrategy::Average2 => {
135+
if random_val % 2 == 0 {
136+
1
137+
} else {
138+
3
139+
}
140+
}
141+
};
142+
143+
// Calculate next slot and check for saturation/no change
144+
let next_slot = current_slot.saturating_sub(decrement);
145+
if next_slot == current_slot {
146+
// If next slot is same as current (i.e., saturated at 0 or decrement was 0),
147+
// stop generating to ensure strict monotonicity.
148+
break;
149+
}
150+
current_slot = next_slot; // Update for the *next* iteration
151+
}
152+
entries
153+
}
154+
53155
/// Generates the instruction data and accounts for the
54156
/// `ProgramInstruction::Account` instruction.
55157
fn generate_account(program_id: Pubkey, expected: u64) -> (Instruction, Vec<(Pubkey, Account)>) {
@@ -154,3 +256,99 @@ fn generate_transfer(program_id: Pubkey) -> (Instruction, Vec<(Pubkey, Account)>
154256
accounts,
155257
)
156258
}
259+
260+
/// Generates the instruction data and accounts for the SlotHashes instructions
261+
/// (SDK version).
262+
fn generate_sdk_slot_hashes_ix(
263+
program_id: Pubkey,
264+
ix_type: ProgramInstruction,
265+
strategy: DecrementStrategy,
266+
) -> (Instruction, Vec<(Pubkey, Account)>) {
267+
// Use the well-known ID directly to avoid sdk dependency
268+
let sysvar_id = solana_pubkey::Pubkey::new_from_array([
269+
6, 167, 213, 23, 25, 47, 10, 175, 198, 242, 101, 227, 251, 119, 204, 122, 218, 130, 197,
270+
41, 208, 190, 59, 19, 110, 45, 0, 85, 32, 0, 0, 0,
271+
]);
272+
273+
// Generate realistic mock SlotHashes data
274+
let mock_entries_raw = generate_mock_slot_hashes_data(strategy);
275+
276+
// Manually serialize mock data according to layout: u64 len + [(u64 slot, [u8;
277+
// 32] hash)] (Using u64 len for consistency, as prefix didn't cause the
278+
// UnsupportedSysvar error)
279+
let num_entries = mock_entries_raw.len() as u64;
280+
let mut data = Vec::with_capacity(8 + mock_entries_raw.len() * (8 + 32)); // Use 8 for u64 len
281+
data.extend_from_slice(&(num_entries as u64).to_le_bytes());
282+
for (slot, hash) in &mock_entries_raw {
283+
data.extend_from_slice(&slot.to_le_bytes());
284+
data.extend_from_slice(hash);
285+
}
286+
287+
// Create the sysvar account owned by the Sysvar Program ID
288+
let mut sysvar_account = Account::new(1, data.len(), &SYSVAR_PROGRAM_ID);
289+
sysvar_account.data = data;
290+
sysvar_account.executable = false; // Sysvars aren't executable
291+
292+
let accounts = vec![(sysvar_id, sysvar_account)];
293+
294+
let account_metas = vec![AccountMeta::new_readonly(sysvar_id, false)];
295+
296+
(
297+
Instruction {
298+
program_id,
299+
accounts: account_metas,
300+
data: instruction_data(ix_type),
301+
},
302+
accounts,
303+
)
304+
}
305+
306+
/// Generates the instruction data and accounts for the SlotHashes instructions
307+
/// (Pinocchio version).
308+
fn generate_pinocchio_slot_hashes_ix(
309+
program_id: Pubkey,
310+
// ix_type now includes the target slot if needed
311+
ix_variant: ProgramInstruction,
312+
strategy: DecrementStrategy,
313+
// Pass the specific target_slot value IF the instruction needs it.
314+
// We'll determine this target_slot in the runner.rs logic.
315+
// Let's keep the function signature simpler for now and derive target inside if needed,
316+
// or modify runner.rs to pass it only when ix_variant requires it.
317+
// Simpler: Let runner.rs handle providing the full ix_variant including the target slot.
318+
) -> (Instruction, Vec<(Pubkey, Account)>) {
319+
let sysvar_id = solana_pubkey::Pubkey::new_from_array([
320+
6, 167, 213, 23, 25, 47, 10, 175, 198, 242, 101, 227, 251, 119, 204, 122, 218, 130, 197,
321+
41, 208, 190, 59, 19, 110, 45, 0, 85, 32, 0, 0, 0,
322+
]);
323+
324+
// Generate realistic mock SlotHashes data - needed for account setup
325+
let mock_entries = generate_mock_slot_hashes_data(strategy);
326+
327+
let num_entries = mock_entries.len() as u64;
328+
let mut account_data = Vec::with_capacity(8 + mock_entries.len() * (8 + 32));
329+
account_data.extend_from_slice(&(num_entries as u64).to_le_bytes());
330+
for (slot, hash) in &mock_entries {
331+
account_data.extend_from_slice(&slot.to_le_bytes());
332+
account_data.extend_from_slice(hash);
333+
}
334+
335+
// Create the sysvar account
336+
let mut sysvar_account = Account::new(1, account_data.len(), &SYSVAR_PROGRAM_ID);
337+
sysvar_account.data = account_data;
338+
sysvar_account.executable = false;
339+
340+
let accounts = vec![(sysvar_id, sysvar_account)];
341+
let account_metas = vec![AccountMeta::new_readonly(sysvar_id, false)];
342+
343+
// Generate instruction data using the provided full ix_variant
344+
let instruction_bytes = instruction_data(ix_variant);
345+
346+
(
347+
Instruction {
348+
program_id,
349+
accounts: account_metas,
350+
data: instruction_bytes,
351+
},
352+
accounts,
353+
)
354+
}

0 commit comments

Comments
 (0)