Solana में, sysvars रीड-ओनली (read-only) सिस्टम अकाउंट्स हैं जो Solana प्रोग्राम्स को ब्लॉकचेन स्टेट और नेटवर्क की जानकारी तक पहुंच प्रदान करते हैं। ये Ethereum ग्लोबल वेरिएबल्स के समान हैं, जो स्मार्ट कॉन्ट्रैक्ट्स को नेटवर्क या ब्लॉकचेन स्टेट की जानकारी तक पहुंचने में सक्षम बनाते हैं, लेकिन इनमें Ethereum precompiles की तरह अद्वितीय पब्लिक एड्रेस (unique public addresses) होते हैं।
Anchor प्रोग्राम्स में, आप sysvars को दो तरीकों से एक्सेस कर सकते हैं: या तो Anchor के get मेथड रैपर का उपयोग करके, या इसके पब्लिक एड्रेस का उपयोग करते हुए इसे अपने #[Derive(Accounts)] में एक अकाउंट के रूप में मानकर।
सभी sysvars get मेथड को सपोर्ट नहीं करते हैं, और कुछ deprecated (अप्रचलित) हो गए हैं (deprecation के बारे में जानकारी इस गाइड में निर्दिष्ट की जाएगी)। जिन sysvars में get मेथड नहीं है, उन्हें हम उनके पब्लिक एड्रेस का उपयोग करके एक्सेस करेंगे।
- Clock: समय से संबंधित ऑपरेशन्स के लिए उपयोग किया जाता है जैसे वर्तमान समय या स्लॉट नंबर प्राप्त करना।
- EpochSchedule: इसमें epoch शेड्यूलिंग के बारे में जानकारी होती है, जिसमें किसी विशेष स्लॉट के लिए epoch भी शामिल है।
- Rent: इसमें रेंटल रेट और अकाउंट को rent exempt (किराए से मुक्त) रखने के लिए न्यूनतम बैलेंस आवश्यकताओं जैसी जानकारी होती है।
- Fees: इसमें वर्तमान स्लॉट के लिए फी कैलकुलेटर (fee calculator) होता है। फी कैलकुलेटर यह जानकारी प्रदान करता है कि Solana ट्रांजेक्शन में प्रति सिग्नेचर कितने lamports का भुगतान किया जाता है।
- EpochRewards: EpochRewards sysvar Solana में epoch रिवॉर्ड्स के वितरण का रिकॉर्ड रखता है, जिसमें ब्लॉक रिवॉर्ड्स और स्टेकिंग रिवॉर्ड्स शामिल हैं।
- RecentBlockhashes: इसमें एक्टिव रीसेंट ब्लॉक हैशेस (active recent block hashes) शामिल होते हैं।
- SlotHashes: इसमें रीसेंट स्लॉट हैशेस (recent slot hashes) का इतिहास होता है।
- SlotHistory: Solana में सबसे हालिया epoch के दौरान उपलब्ध स्लॉट्स का एक ऐरे (array) रखता है, और जब भी कोई नया स्लॉट प्रोसेस होता है तो यह अपडेट होता है।
- StakeHistory: पूरे नेटवर्क के लिए प्रति-epoch आधार पर स्टेक एक्टिवेशन और डीएक्टिवेशन का रिकॉर्ड रखता है, जो प्रत्येक epoch की शुरुआत में अपडेट होता है।
- Instructions: वर्तमान ट्रांजेक्शन का हिस्सा होने वाले सीरियलाइज्ड इंस्ट्रक्शन्स (serialized instructions) तक पहुंच प्राप्त करने के लिए।
- LastRestartSlot: इसमें अंतिम रीस्टार्ट (पिछली बार जब Solana रीस्टार्ट हुआ था) का स्लॉट नंबर होता है, या यदि कभी रीस्टार्ट नहीं हुआ है तो यह शून्य (zero) होता है। यदि Solana ब्लॉकचेन क्रैश हो जाए और रीस्टार्ट हो, तो कोई एप्लिकेशन इस जानकारी का उपयोग यह निर्धारित करने के लिए कर सकता है कि क्या उसे चीजें स्थिर होने तक प्रतीक्षा करनी चाहिए।
Solana स्लॉट्स और ब्लॉक्स के बीच अंतर करना
एक स्लॉट समय की एक विंडो (लगभग 400ms) है जहाँ एक नामित लीडर (designated leader) ब्लॉक का उत्पादन कर सकता है। एक स्लॉट में एक ब्लॉक होता है (Ethereum पर समान प्रकार का ब्लॉक, यानी ट्रांजेक्शन्स की एक सूची)। हालाँकि, यदि ब्लॉक लीडर उस स्लॉट के दौरान ब्लॉक का उत्पादन करने में विफल रहता है, तो उस स्लॉट में ब्लॉक नहीं हो सकता है। उनके बीच का संबंध नीचे दर्शाया गया है:

यद्यपि प्रत्येक ब्लॉक ठीक एक स्लॉट पर मैप होता है, ब्लॉक हैश, स्लॉट हैश के समान नहीं होता है। यह अंतर तब स्पष्ट होता है जब एक्सप्लोरर (explorer) में किसी स्लॉट नंबर पर क्लिक किया जाता है, यह एक अलग हैश वाले ब्लॉक का विवरण खोलता है।
आइए Solana ब्लॉक एक्सप्लोरर से नीचे दी गई छवि से एक उदाहरण लें:

छवि में हाइलाइट किया गया हरा नंबर स्लॉट नंबर 237240962 है, और हाइलाइट किया गया पीला टेक्स्ट स्लॉट हैश DYFtWxEdLbos9E6SjZQCMq8z242Yv2bVoj6dzwskd5vZ है। नीचे लाल रंग में हाइलाइट किया गया ब्लॉक हैश FzHwFHDAXJBc55rpjShznGCBnC7DsTCjxf3KKAk6hk9T है।
(अन्य ब्लॉक विवरणों को क्रॉप कर दिया गया है):

हम एक ब्लॉक और एक स्लॉट के बीच उनके अद्वितीय हैशेस (unique hashes) द्वारा अंतर कर सकते हैं, भले ही उनके नंबर समान हों।
एक परीक्षण के रूप में, एक्सप्लोरर में यहाँ किसी भी स्लॉट नंबर पर क्लिक करें और आप देखेंगे कि एक ब्लॉक पेज खुलेगा। इस ब्लॉक का हैश, स्लॉट हैश से अलग होगा।
get मेथड का उपयोग करके, Anchor में Solana Sysvars को एक्सेस करना
जैसा कि पहले उल्लेख किया गया है, सभी sysvars को Anchor के get मेथड का उपयोग करके एक्सेस नहीं किया जा सकता है। Clock, EpochSchedule, और Rent जैसे sysvars को इस मेथड का उपयोग करके एक्सेस किया जा सकता है।
हालाँकि Solana डॉक्यूमेंटेशन में Fees और EpochRewards को ऐसे sysvars के रूप में शामिल किया गया है जिन्हें get मेथड से एक्सेस किया जा सकता है, लेकिन ये Anchor के नवीनतम संस्करण में deprecated हो गए हैं। इसलिए, उन्हें Anchor में get मेथड का उपयोग करके कॉल नहीं किया जा सकता है।
हम get मेथड का उपयोग करके वर्तमान में समर्थित सभी sysvars के कंटेंट को एक्सेस और लॉग करेंगे। शुरू करने के लिए, हम एक नया Anchor प्रोजेक्ट बनाते हैं:
anchor init sysvars
cd sysvars
anchor build
Clock sysvar
Clock sysvar का उपयोग करने के लिए, हम Clock::get() मेथड को इनवोक (invoke) कर सकते हैं (हमने पिछले ट्यूटोरियल में भी कुछ ऐसा ही किया था) जैसा कि नीचे दिखाया गया है।
हमारे प्रोजेक्ट के initialize फंक्शन में निम्नलिखित कोड जोड़ें:
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
// Get the Clock sysvar
let clock = Clock::get()?;
msg!(
"clock: {:?}",
// Retrieve all the details of the Clock sysvar
clock
);
Ok(())
}
अब, लोकल Solana नोड पर टेस्ट रन करें और लॉग चेक करें:

EpochSchedule sysvar
Solana में एक epoch लगभग दो दिनों की समयावधि होती है। SOL को केवल एक epoch की शुरुआत में ही स्टेक या अनस्टेक किया जा सकता है। यदि आप किसी epoch के समाप्त होने से पहले SOL स्टेक (या अनस्टेक) करते हैं, तो epoch के समाप्त होने की प्रतीक्षा करते समय SOL को “activating” या “deactivating” के रूप में चिह्नित किया जाता है।
Solana ने delegating SOL के अपने विवरण में इसका अधिक वर्णन किया है।
हम Clock sysvar के समान ही get मेथड का उपयोग करके EpochSchedule sysvar को एक्सेस कर सकते हैं।
निम्नलिखित कोड के साथ initialize फंक्शन को अपडेट करें:
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
// Get the EpochSchedule sysvar
let epoch_schedule = EpochSchedule::get()?;
msg!(
"epoch schedule: {:?}",
// Retrieve all the details of the EpochSchedule sysvar
epoch_schedule
);
Ok(())
}
टेस्ट को दोबारा रन करने के बाद, निम्नलिखित लॉग उत्पन्न होगा:

लॉग से, हम देख सकते हैं कि EpochSchedule sysvar में निम्नलिखित फील्ड्स शामिल हैं:
- पीले रंग में हाइलाइट किया गया slots_per_epoch प्रत्येक epoch में स्लॉट्स की संख्या को रखता है, जो यहाँ 432,000 स्लॉट्स है।
- लाल रंग में हाइलाइट किया गया leader_schedule_slot_offset अगले epoch के लीडर शेड्यूल का समय निर्धारित करता है (हमने पहले 11वें दिन में इसके बारे में बात की थी)। यह भी 432,000 पर सेट है।
- बैंगनी रंग में हाइलाइट किया गया warmup एक बुलियन (boolean) है जो इंगित करता है कि क्या Solana वार्म-अप चरण (warm-up phase) में है। इस चरण के दौरान, epochs छोटे शुरू होते हैं और धीरे-धीरे आकार में बढ़ते हैं। यह नेटवर्क को रीसेट के बाद या शुरुआती दिनों में सुचारू रूप से शुरू होने में मदद करता है।
- नारंगी रंग में हाइलाइट किया गया first_normal_epoch पहले epoch की पहचान करता है जिसकी अपनी स्लॉट संख्या हो सकती है, और नीले रंग में हाइलाइट किया गया
first_normal_slotवह स्लॉट है जो इस epoch को शुरू करता है। इस मामले में दोनों 0 (शून्य) हैं।
हमें first_normal_epoch और first_normal_slot 0 दिखने का कारण यह है कि टेस्ट वैलिडेटर (test validator) दो दिनों से नहीं चल रहा है। यदि हम इस कमांड को मेननेट (लिखते समय) पर रन करते, तो हम उम्मीद करते कि first_normal_epoch 576 होगा और first_normal_slot 248,832,000 होगा।

Rent sysvar
एक बार फिर, हम Rent sysvar को एक्सेस करने के लिए get मेथड का उपयोग करते हैं।
हम निम्नलिखित कोड के साथ initialize फंक्शन को अपडेट करते हैं:
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
// Previous code...
// Get the Rent sysvar
let rent_var = Rent::get()?;
msg!(
"Rent {:?}",
// Retrieve all the details of the Rent sysvar
rent_var
);
Ok(())
}
टेस्ट रन करें, हमें यह लॉग प्राप्त होता है:

Solana में Rent sysvar के तीन प्रमुख फील्ड्स हैं:
- lamports_per_byte_year
- exemption_threshold
- burn_percent
पीले रंग में हाइलाइट किया गया lamports_per_byte_year rent exemption (किराये की छूट) के लिए प्रति बाइट प्रति वर्ष आवश्यक lamports की संख्या को इंगित करता है।
लाल रंग में हाइलाइट किया गया exemption_threshold एक मल्टीप्लायर (multiplier) है जिसका उपयोग rent exemption के लिए आवश्यक न्यूनतम बैलेंस की गणना करने के लिए किया जाता है। इस उदाहरण में, हम देखते हैं कि एक नया अकाउंट बनाने के लिए हमें प्रति बाइट lamports का भुगतान करना होगा।
Solana की मुद्रास्फीति (inflation) को प्रबंधित करने के लिए इसका 50% बर्न कर दिया जाता है (बैंगनी रंग में हाइलाइट किया गया burn_percent)।
“rent” के कॉन्सेप्ट को बाद के ट्यूटोरियल में पूरी तरह से समझाया जाएगा।
Sysvar पब्लिक एड्रेस का उपयोग करके Anchor में Sysvars को एक्सेस करना
उन sysvars के लिए जो get मेथड का समर्थन नहीं करते हैं, हम उनके पब्लिक एड्रेस का उपयोग करके उन्हें एक्सेस कर सकते हैं। इसके किसी भी अपवाद को निर्दिष्ट किया जाएगा।
StakeHistory sysvar
याद करें कि हमने पहले उल्लेख किया था कि यह sysvar पूरे नेटवर्क के लिए प्रति-epoch आधार पर स्टेक एक्टिवेशन और डीएक्टिवेशन का रिकॉर्ड रखता है। हालाँकि, चूँकि हम एक लोकल वैलिडेटर नोड रन कर रहे हैं, इसलिए यह sysvar खाली डेटा लौटाएगा।
हम इस sysvar को इसके पब्लिक एड्रेस SysvarStakeHistory1111111111111111111111111 का उपयोग करके एक्सेस करेंगे।
सबसे पहले, हम अपने प्रोजेक्ट में Initialize अकाउंट स्ट्रक्ट (struct) को निम्नानुसार संशोधित करते हैं:
#[derive(Accounts)]
pub struct Initialize<'info> {
/// CHECK:
pub stake_history: AccountInfo<'info>, // We create an account for the StakeHistory sysvar
}
हम पाठक से अनुरोध करते हैं कि वे अभी के लिए नए सिंटैक्स को बॉयलरप्लेट (boilerplate) मानें। /// CHECK: और AccountInfo को बाद के ट्यूटोरियल में समझाया जाएगा। जिज्ञासु लोगों के लिए, <'info> टोकन एक Rust lifetime है।
इसके बाद, हम initialize फंक्शन में निम्नलिखित कोड जोड़ते हैं।
(Sysvar अकाउंट का रेफरेंस हमारे टेस्ट में ट्रांजेक्शन के हिस्से के रूप में पास किया जाएगा। पिछले उदाहरणों में वे Anchor फ्रेमवर्क में ही बिल्ट-इन थे)।
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
// Previous code...
// Accessing the StakeHistory sysvar
// Create an array to store the StakeHistory account
let arr = [ctx.accounts.stake_history.clone()];
// Create an iterator for the array
let accounts_iter = &mut arr.iter();
// Get the next account info from the iterator (still StakeHistory)
let sh_sysvar_info = next_account_info(accounts_iter)?;
// Create a StakeHistory instance from the account info
let stake_history = StakeHistory::from_account_info(sh_sysvar_info)?;
msg!("stake_history: {:?}", stake_history);
Ok(())
}
हम StakeHistory sysvar को इम्पोर्ट नहीं कर रहे हैं क्योंकि हम super::*; import के उपयोग के माध्यम से इसे एक्सेस कर सकते हैं। यदि ऐसा नहीं है, तो हम विशिष्ट sysvar को इम्पोर्ट करेंगे।
और टेस्ट को अपडेट करें:
import * as anchor from "@coral-xyz/anchor";
import { Program } from "@coral-xyz/anchor";
import { Sysvars } from "../target/types/sysvars";
describe("sysvars", () => {
// Configure the client to use the local cluster.
anchor.setProvider(anchor.AnchorProvider.env());
const program = anchor.workspace.Sysvars as Program<Sysvars>;
// Create a StakeHistory PublicKey object
const StakeHistory_PublicKey = new anchor.web3.PublicKey(
"SysvarStakeHistory1111111111111111111111111"
);
it("Is initialized!", async () => {
// Add your test here.
const tx = await program.methods
.initialize()
.accounts({
stakeHistory: StakeHistory_PublicKey,
})
.rpc();
console.log("Your transaction signature", tx);
});
});
अब, हम अपना टेस्ट फिर से रन करते हैं:

जैसा कि पहले बताया गया है, यह हमारे लोकल वैलिडेटर के लिए खाली डेटा लौटाता है।
हम अपने StakeHistory_PublicKey वेरिएबल को anchor.web3.SYSVAR_STAKE_HISTORY_PUBKEY से बदलकर Anchor Typescript क्लाइंट से StakeHistory sysvar की पब्लिक की (public key) भी प्राप्त कर सकते हैं।
RecentBlockhashes sysvar
इस sysvar को कैसे एक्सेस करें, इस पर हमारे पिछले ट्यूटोरियल में चर्चा की गई थी। एक रिमाइंडर के तौर पर, यह deprecated है और इसका सपोर्ट हटा दिया जाएगा।
Fees sysvar
Fees sysvar भी deprecated है।
Instruction sysvar
इस sysvar का उपयोग वर्तमान ट्रांजेक्शन के सीरियलाइज्ड इंस्ट्रक्शन्स (serialized instructions) और उस ट्रांजेक्शन का हिस्सा होने वाले कुछ मेटाडेटा को एक्सेस करने के लिए किया जा सकता है। हम इसे नीचे प्रदर्शित करेंगे।
सबसे पहले, हम अपने इम्पोर्ट्स को अपडेट करते हैं:
#[program]
pub mod sysvars {
use super::*;
use anchor_lang::solana_program::sysvar::{instructions, fees::Fees, recent_blockhashes::RecentBlockhashes};
// rest of the code
}
इसके बाद, हम Instruction sysvar अकाउंट को Initialize अकाउंट स्ट्रक्ट में जोड़ते हैं:
#[derive(Accounts)]
pub struct Initialize<'info> {
/// CHECK:
pub stake_history: AccountInfo<'info>, // We create an account for the StakeHistory sysvar
/// CHECK:
pub recent_blockhashes: AccountInfo<'info>,
/// CHECK:
pub instruction_sysvar: AccountInfo<'info>,
}
अब, number: u32 पैरामीटर को स्वीकार करने के लिए initialize फंक्शन को संशोधित करें और initialize फंक्शन में निम्नलिखित कोड जोड़ें।
pub fn initialize(ctx: Context<Initialize>, number: u32) -> Result<()> {
// Previous code...
// Get Instruction sysvar
let arr = [ctx.accounts.instruction_sysvar.clone()];
let account_info_iter = &mut arr.iter();
let instructions_sysvar_account = next_account_info(account_info_iter)?;
// Load the instruction details from the instruction sysvar account
let instruction_details =
instructions::load_instruction_at_checked(0, instructions_sysvar_account)?;
msg!(
"Instruction details of this transaction: {:?}",
instruction_details
);
msg!("Number is: {}", number);
Ok(())
}
पिछले sysvar के विपरीत, जहाँ हमने sysvar को पुनः प्राप्त करने के लिए <sysvar_name>::from_account_info() का उपयोग किया था, इस मामले में, हम Instruction sysvar से load_instruction_at_checked() मेथड का उपयोग करते हैं। इस मेथड को पैरामीटर के रूप में इंस्ट्रक्शन डेटा इंडेक्स (इस मामले में 0) और Instruction sysvar अकाउंट की आवश्यकता होती है।
टेस्ट को अपडेट करें:
import * as anchor from "@coral-xyz/anchor";
import { Program } from "@coral-xyz/anchor";
import { Sysvars } from "../target/types/sysvars";
describe("sysvars", () => {
// Configure the client to use the local cluster.
anchor.setProvider(anchor.AnchorProvider.env());
const program = anchor.workspace.Sysvars as Program<Sysvars>;
// Create a StakeHistory PublicKey object
const StakeHistory_PublicKey = new anchor.web3.PublicKey(
"SysvarStakeHistory1111111111111111111111111"
);
it("Is initialized!", async () => {
// Add your test here.
const tx = await program.methods
.initialize(3) // Call the initialze function with the number `3`
.accounts({
stakeHistory: StakeHistory_PublicKey, // pass the public key of StakeHistory sysvar to the list of accounts needed for the instruction
recentBlockhashes: anchor.web3.SYSVAR_RECENT_BLOCKHASHES_PUBKEY, // pass the public key of RecentBlockhashes sysvar to the list of accounts needed for the instruction
instructionSysvar: anchor.web3.SYSVAR_INSTRUCTIONS_PUBKEY, // Pass the public key of the Instruction sysvar to the list of accounts needed for the instruction
})
.rpc();
console.log("Your transaction signature", tx);
});
});
और टेस्ट रन करें:

यदि हम लॉग की बारीकी से जांच करें, तो हम प्रोग्राम Id (program Id), sysvar इंस्ट्रक्शन की पब्लिक की, सीरियलाइज्ड डेटा और अन्य मेटाडेटा देख सकते हैं।
हम सीरियलाइज्ड इंस्ट्रक्शन डेटा और हमारे स्वयं के प्रोग्राम लॉग दोनों में पीले तीर के साथ हाइलाइट किया गया नंबर 3 भी देख सकते हैं। लाल रंग में हाइलाइट किया गया सीरियलाइज्ड डेटा Anchor द्वारा इंजेक्ट किया गया एक discriminator है (हम उसे अनदेखा कर सकते हैं)।
Exercise: LastRestartSlot sysvar
ऊपर उपयोग किए गए मेथड का उपयोग करते हुए SysvarLastRestartS1ot1111111111111111111111। ध्यान दें कि Anchor के पास इस sysvar के लिए एड्रेस नहीं है, इसलिए आपको एक PublicKey ऑब्जेक्ट बनाने की आवश्यकता होगी।
Solana Sysvars जिन्हें Anchor के वर्तमान संस्करण में एक्सेस नहीं किया जा सकता है।
Anchor के वर्तमान संस्करण में, कुछ sysvars को एक्सेस करना संभव नहीं है। इन sysvars में EpochRewards, SlotHistory, और SlotHashes शामिल हैं। जब इन sysvars को एक्सेस करने का प्रयास किया जाता है, तो यह एक एरर (error) का कारण बनता है।
RareSkills के साथ और जानें
अधिक Solana ट्यूटोरियल्स के लिए हमारा Solana course देखें; यह ट्यूटोरियल उसी कोर्स का हिस्सा है।
मूल रूप से 19 फरवरी, 2024 को प्रकाशित