आज हम Solidity के सभी block वेरिएबल्स के एनालॉग्स (समानताओं) को कवर करेंगे। इनमें से सभी के 1-1 एनालॉग्स नहीं होते हैं। Solidity में, हमारे पास निम्नलिखित आमतौर पर उपयोग किए जाने वाले block वेरिएबल्स हैं:
- block.timestamp
- block.number
- blockhash()
और कुछ कम जाने-माने वेरिएबल्स:
- block.coinbase
- block.basefee
- block.chainid
- block.difficulty / block.prevrandao
हम मान कर चलते हैं कि आप पहले से ही जानते हैं कि ये क्या करते हैं, लेकिन अगर आपको रीफ्रेशर की आवश्यकता है, तो उन्हें Solidity global variables doc में समझाया गया है।
Solana में block.timestamp
Clock sysvar के भीतर unix_timestamp फील्ड का उपयोग करके, हम Solana में block timestamp को एक्सेस कर सकते हैं।
सबसे पहले हम एक नया Anchor प्रोजेक्ट इनिशियलाइज़ करते हैं:
anchor init sysvar
initialize फंक्शन को इससे बदलें:
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
let clock: Clock = Clock::get()?;
msg!(
"Block timestamp: {}",
// Get block.timestamp
clock.unix_timestamp,
);
Ok(())
}
Anchor के prelude मॉड्यूल में Clock स्ट्रक्ट होता है, जो डिफ़ॉल्ट रूप से अपने आप इम्पोर्ट हो जाता है:
use anchor_lang::prelude::*;
थोड़ा भ्रमित करने वाली बात यह है कि unix_timestamp द्वारा रिटर्न किया गया टाइप i64 है, न कि u64, जिसका अर्थ है कि यह नेगेटिव नंबर्स को सपोर्ट करता है, भले ही समय नेगेटिव नहीं हो सकता। हालाँकि, टाइम डेल्टा (time deltas) नेगेटिव हो सकते हैं।
सप्ताह का दिन प्राप्त करना
अब एक ऐसा प्रोग्राम बनाते हैं जो हमें Clock sysvar से unix_timestamp का उपयोग करके सप्ताह का वर्तमान दिन बताता है।
Rust में डेट्स और टाइम्स पर ऑपरेशन्स के लिए chrono क्रेट फंक्शनैलिटी प्रदान करता है।
प्रोग्राम डायरेक्टरी ./sysvar/Cargo.toml में हमारी Cargo.toml फ़ाइल में एक डिपेंडेंसी के रूप में chrono क्रेट जोड़ें:
[dependencies]
chrono = "0.4.31"
sysvar मॉड्यूल के अंदर chrono क्रेट इम्पोर्ट करें:
// ...other code
#[program]
pub mod sysvar {
use super::*;
use chrono::*; // new line here
// ...
}
अब, हम अपने प्रोग्राम में नीचे दिया गया फंक्शन जोड़ते हैं:
pub fn get_day_of_the_week(
_ctx: Context<Initialize>) -> Result<()> {
let clock = Clock::get()?;
let time_stamp = clock.unix_timestamp; // current timestamp
let date_time = chrono::NaiveDateTime::from_timestamp_opt(time_stamp, 0).unwrap();
let day_of_the_week = date_time.weekday();
msg!("Week day is: {}", day_of_the_week);
Ok(())
}
हम Clock sysvar से प्राप्त वर्तमान unix timestamp को from_timestamp_opt फंक्शन में एक आर्गुमेंट के रूप में पास करते हैं जो एक NaiveDateTime स्ट्रक्ट रिटर्न करता है जिसमें एक डेट और टाइम होता है। फिर हम पास किए गए timestamp के आधार पर वर्तमान सप्ताह का दिन प्राप्त करने के लिए weekday मेथड को कॉल करते हैं।
और अपने टेस्ट को अपडेट करें:
it("Get day of the week", async () => {
const tx = await program.methods.getDayOfTheWeek().rpc();
console.log("Your transaction signature", tx);
});
टेस्ट को फिर से रन करें और निम्नलिखित लॉग्स प्राप्त करें:
Transaction executed in slot 36:
Signature: 5HVAjmo85Yi3yeQX5t6fNorU1da4H1zvgcJN7BaiPGnRwQhjbKd5YHsVE8bppU9Bg2toF4iVBvhbwkAtMo4NJm7V
Status: Ok
Log Messages:
Program H52ppiSyiZyYVn1Yr9DgeUKeChktUiPwDfuuo932Uqxy invoke [1]
Program log: Instruction: GetDayOfTheWeek
Program log: Week day is: Wed
Program H52ppiSyiZyYVn1Yr9DgeUKeChktUiPwDfuuo932Uqxy consumed 1597 of 200000 compute units
“Week day is: Wed” लॉग पर ध्यान दें।
Solana में block.number
Solana में “slot number” की एक अवधारणा है जो “block number” से बहुत संबंधित है लेकिन यह एक ही चीज़ नहीं है। इनके बीच के अंतर को अगले ट्यूटोरियल में कवर किया जाएगा, इसलिए हम तब तक “block number” प्राप्त करने के तरीके पर पूरी चर्चा को टाल देते हैं।
block.coinbase
Ethereum में, “Block Coinbase” उस माइनर के एड्रेस को दर्शाता है जिसने Proof of Work (PoW) में सफलतापूर्वक एक ब्लॉक माइन किया है। दूसरी ओर, Solana एक लीडर-आधारित कंसेंसस मैकेनिज़्म (leader-based consensus mechanism) का उपयोग करता है जो Proof of History (PoH) और Proof of Stake (PoS) दोनों का संयोजन है, जो माइनिंग की अवधारणा को हटा देता है। इसके बजाय, कुछ अंतरालों के दौरान ट्रांज़ैक्शन को वैलिडेट करने और ब्लॉक प्रस्तावित करने के लिए एक ब्लॉक या स्लॉट लीडर नियुक्त किया जाता है, जिसे लीडर शेड्यूल के रूप में जानी जाने वाली प्रणाली के तहत किया जाता है। यह शेड्यूल निर्धारित करता है कि एक निश्चित समय पर ब्लॉक प्रोड्यूसर कौन होगा।
हालाँकि, वर्तमान में, Solana प्रोग्राम्स में ब्लॉक लीडर के एड्रेस को एक्सेस करने का कोई विशिष्ट तरीका नहीं है।
blockhash
हम पूर्णता (completeness) के लिए इस अनुभाग को शामिल कर रहे हैं, लेकिन इसे जल्द ही डेप्रिकेट (deprecated) कर दिया जाएगा।
इस अनुभाग को छोड़ देने पर उन पाठकों के लिए कोई परिणाम नहीं होगा जिन्हें इसमें रुचि नहीं है।
Solana में एक RecentBlockhashes sysvar होता है जो एक्टिव रीसेंट ब्लॉक हैशेज (active recent block hashes) के साथ-साथ उनके संबंधित फ़ीस कैलकुलेटर्स को होल्ड करता है। हालाँकि, यह sysvar डेप्रिकेट (deprecated) हो चुका है और भविष्य की Solana रिलीज़ में इसे सपोर्ट नहीं किया जाएगा। RecentBlockhashes sysvar, Clock sysvar की तरह कोई get मेथड प्रदान नहीं करता है। हालाँकि, जिन sysvar में यह मेथड नहीं होता है, उन्हें sysvar_name::from_account_info का उपयोग करके एक्सेस किया जा सकता है।
हम कुछ नए सिंटैक्स भी पेश करेंगे जिन्हें बाद में समझाया जाएगा। अभी के लिए, कृपया इसे बॉयलरप्लेट (boilerplate) मानें:
#[derive(Accounts)]
pub struct Initialize<'info> {
/// CHECK: readonly
pub recent_blockhashes: AccountInfo<'info>,
}
यहाँ बताया गया है कि हम Solana में नवीनतम ब्लॉक हैश कैसे प्राप्त करते हैं:
use anchor_lang::{prelude::*, solana_program::sysvar::recent_blockhashes::RecentBlockhashes};
// replace program id
declare_id!("H52ppiSyiZyYVn1Yr9DgeUKeChktUiPwDfuuo932Uqxy");
#[program]
pub mod sysvar {
use super::*;
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
// RECENT BLOCK HASHES
let arr = [ctx.accounts.recent_blockhashes.clone()];
let accounts_iter = &mut arr.iter();
let sh_sysvar_info = next_account_info(accounts_iter)?;
let recent_blockhashes = RecentBlockhashes::from_account_info(sh_sysvar_info)?;
let data = recent_blockhashes.last().unwrap();
msg!("The recent block hash is: {:?}", data.blockhash);
Ok(())
}
}
#[derive(Accounts)]
pub struct Initialize<'info> {
/// CHECK: readonly
pub recent_blockhashes: AccountInfo<'info>,
}
टेस्ट फ़ाइल:
import * as anchor from "@coral-xyz/anchor";
import { Program } from "@coral-xyz/anchor";
import { Sysvar } from "../target/types/sysvar";
describe("sysvar", () => {
// Configure the client to use the local cluster.
anchor.setProvider(anchor.AnchorProvider.env());
const program = anchor.workspace.Sysvar as Program<Sysvar>;
it("Is initialized!", async () => {
// Add your test here.
const tx = await program.methods
.initialize()
.accounts({
recentBlockhashes: anchor.web3.SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
})
.rpc();
console.log("Transaction hash:", tx);
});
});
हम टेस्ट रन करते हैं और निम्नलिखित लॉग प्राप्त करते हैं:
Log Messages:
Program H52ppiSyiZyYVn1Yr9DgeUKeChktUiPwDfuuo932Uqxy invoke [1]
Program log: Instruction: Initialize
Program log: The recent block hash is: erVQHJdJ11oL4igkQwDnv7oPZoxt88j7u8DCwHkVFnC
Program H52ppiSyiZyYVn1Yr9DgeUKeChktUiPwDfuuo932Uqxy consumed 46181 of 200000 compute units
Program H52ppiSyiZyYVn1Yr9DgeUKeChktUiPwDfuuo932Uqxy success
हम नवीनतम ब्लॉक हैश देख सकते हैं। ध्यान दें कि क्योंकि हम अपने लोकल नोड (local node) पर डिप्लॉय कर रहे हैं, जो ब्लॉक हैश हमें मिलता है वह हमारे लोकल नोड का होता है न कि Solana मेननेट (mainnet) का।
टाइम स्ट्रक्चरिंग (time structuring) के संदर्भ में, Solana एक निश्चित टाइमलाइन पर काम करता है जिसे स्लॉट्स (slots) में विभाजित किया जाता है, जहाँ प्रत्येक स्लॉट किसी लीडर को ब्लॉक प्रस्तावित करने के लिए आवंटित समय का हिस्सा होता है। इन स्लॉट्स को आगे इपॉक्स (epochs) में व्यवस्थित किया जाता है, जो पहले से परिभाषित अवधियाँ होती हैं जिनके दौरान लीडर शेड्यूल अपरिवर्तित रहता है।
block.gaslimit
Solana में प्रति-ब्लॉक कंप्यूट यूनिट की 48 मिलियन की सीमा है। प्रत्येक ट्रांज़ैक्शन डिफ़ॉल्ट रूप से 200,000 कंप्यूट यूनिट्स तक सीमित होता है, हालाँकि इसे बढ़ाकर 1.4 मिलियन कंप्यूट यूनिट्स तक किया जा सकता है (हम इसके बारे में बाद के ट्यूटोरियल में चर्चा करेंगे, हालाँकि आप यहाँ एक उदाहरण देख सकते हैं)।
Rust प्रोग्राम से इस सीमा (limit) को एक्सेस करना संभव नहीं है।
block.basefee
Ethereum में, EIP-1559 के अनुसार basefee डायनामिक होती है; यह पिछले ब्लॉक के उपयोग (utilization) का एक फंक्शन है। Solana में, ट्रांज़ैक्शन का बेस प्राइस (base price) स्टैटिक होता है, इसलिए इस तरह के किसी वेरिएबल की कोई आवश्यकता नहीं है।
block.difficulty
Block difficulty एक ऐसी अवधारणा है जो Proof of Work (PoW) ब्लॉकचेन से जुड़ी है। दूसरी ओर, Solana, Proof of History (PoH) और Proof of Stake (PoS) के संयोजन वाले कंसेंसस मैकेनिज़्म पर काम करता है, जिसमें block difficulty की अवधारणा शामिल नहीं है।
block.chainid
Solana में कोई chain id नहीं होती है क्योंकि यह एक EVM कम्पेटिबल (EVM compatible) ब्लॉकचेन नहीं है। block.chainid वह तरीका है जिससे Solidity स्मार्ट कॉन्ट्रैक्ट्स यह जानते हैं कि वे किसी टेस्टनेट (testnet), L2, मेननेट (mainnet) या किसी अन्य EVM कम्पेटिबल चेन पर हैं या नहीं।
Solana Devnet, Testnet, और Mainnet के लिए अलग-अलग क्लस्टर्स चलाता है, लेकिन प्रोग्राम्स के पास यह जानने का कोई मैकेनिज़्म नहीं है कि वे किस क्लस्टर पर हैं। हालाँकि, आप डिप्लॉयमेंट के समय Rust की cfg सुविधा का उपयोग करके अपने कोड को प्रोग्रामेटिक रूप से एडजस्ट कर सकते हैं ताकि जिस क्लस्टर पर इसे डिप्लॉय किया गया है, उसके आधार पर अलग-अलग फीचर्स प्राप्त किए जा सकें। यहाँ क्लस्टर के आधार पर प्रोग्राम आईडी बदलने का एक उदाहरण दिया गया है।
और जानें
यह ट्यूटोरियल हमारे मुफ़्त Solana कोर्स का हिस्सा है।
मूल रूप से 18 फरवरी, 2024 को प्रकाशित