Anchor Rust में एक account balance पढ़ना
किसी Solana प्रोग्राम के अंदर किसी address का Solana balance पढ़ने के लिए, निम्नलिखित कोड का उपयोग करें:
use anchor_lang::prelude::*;
declare_id!("Gnf6u7S7fGJbqEGH9PuDE5Prq6f6ZrDxHY3jNJ4SYySQ");
#[program]
pub mod balance {
use super::*;
pub fn read_balance(ctx: Context<ReadBalance>) -> Result<()> {
let balance = ctx.accounts.acct.to_account_info().lamports();
msg!("balance in Lamports is {}", balance);
Ok(())
}
}
#[derive(Accounts)]
pub struct ReadBalance<'info> {
/// CHECK: although we read this account's balance, we don't do anything with the information
pub acct: UncheckedAccount<'info>,
}
और इसे ट्रिगर करने के लिए निम्नलिखित web3 js कोड है:
import * as anchor from "@coral-xyz/anchor";
import { Program } from "@coral-xyz/anchor";
import { Balance } from "../target/types/balance";
describe("balance", () => {
// Configure the client to use the local cluster.
anchor.setProvider(anchor.AnchorProvider.env());
const program = anchor.workspace.Balance as Program<Balance>;
// the following is the Solana wallet we are using
let pubkey = new anchor.web3.PublicKey("5jmigjgt77kAfKsHri3MHpMMFPo6UuiAMF19VdDfrrTj");
it("Tests the balance", async () => {
const tx = await program.methods.readBalance().accounts({ acct: pubkey }).rpc();
});
});
इस उदाहरण के कुछ अंश पहले के ट्यूटोरियल्स से भिन्न हैं, विशेष रूप से UncheckedAccount का उपयोग।
Solana Anchor में UncheckedAccount क्या है?
UncheckedAccount प्रकार Anchor को यह बताता है कि यह जांच न करे कि जो account पढ़ा जा रहा है वह प्रोग्राम के स्वामित्व (owned) में है या नहीं।
ध्यान दें कि जो account हमने Context struct के माध्यम से पास किया है, वह ऐसा account नहीं है जिसे इस प्रोग्राम ने इनिशियलाइज़ (initialize) किया हो, इसलिए यह प्रोग्राम इसका स्वामी (owner) नहीं है।
जब Anchor #[derive(Accounts)] में Account प्रकार का कोई account पढ़ता है, तो वह (पर्दे के पीछे) जांच करेगा कि क्या वह account उस प्रोग्राम के स्वामित्व में है। यदि नहीं, तो निष्पादन (execution) रुक जाएगा।
यह एक महत्वपूर्ण सुरक्षा जांच (safety check) के रूप में कार्य करता है।
यदि कोई दुर्भावनापूर्ण उपयोगकर्ता (malicious user) कोई ऐसा account बनाता है जिसे प्रोग्राम ने नहीं बनाया है और फिर उसे Solana प्रोग्राम में पास करता है, और Solana प्रोग्राम आंख मूंदकर account के डेटा पर भरोसा कर लेता है, तो गंभीर त्रुटियां (critical errors) हो सकती हैं।
उदाहरण के लिए, यदि प्रोग्राम एक बैंक है, और account यह संग्रहीत कर रहा है कि किसी उपयोगकर्ता के पास कितना balance है, तो एक हैकर एक अलग account प्रदान कर सकता है जिसमें कृत्रिम रूप से उनके वास्तविक balance से अधिक balance हो।
हालांकि, इस हैक को अंजाम देने के लिए, उपयोगकर्ता को एक अलग ट्रांज़ैक्शन में फर्जी account बनाना होगा, और फिर उसे Solana प्रोग्राम में पास करना होगा। लेकिन, Anchor फ्रेमवर्क पर्दे के पीछे यह जांचता है कि account प्रोग्राम के स्वामित्व में है या नहीं, और account को पढ़ने से अस्वीकार कर देता है।
UncheckedAccount इस सुरक्षा जांच को बायपास कर देता है।
महत्वपूर्ण: AccountInfo और UncheckedAccount एक-दूसरे के एलियास (aliases) हैं और AccountInfo में भी समान सुरक्षा विचार (security considerations) लागू होते हैं।
हमारे मामले में, हम ऐसे accounts पास कर रहे हैं जो निश्चित रूप से प्रोग्राम के स्वामित्व में नहीं हैं — हम एक मनमाने account (arbitrary account) का balance जाँचना चाहते हैं। इसलिए, हमें यह सुनिश्चित करना चाहिए कि इस सुरक्षा जांच को हटाने से किसी भी महत्वपूर्ण लॉजिक (critical logic) के साथ छेड़छाड़ न की जा सके।
हमारे मामले में, हम केवल कंसोल में balance को लॉग कर रहे हैं, लेकिन वास्तविक दुनिया के अधिकांश उपयोग के मामलों (use cases) में अधिक जटिल लॉजिक होगा।
/// CHECK: क्या है?
UncheckedAccount का उपयोग करने के खतरे के कारण, Anchor आपको इस टिप्पणी (comment) को शामिल करने के लिए बाध्य करता है ताकि आप सुरक्षा विचारों को नज़रअंदाज़ न करें।
अभ्यास: /// Check: कमेंट को हटा दें और anchor build चलाएं, आपको बिल्ड रुकता हुआ दिखाई देगा और यह आपसे वापस कमेंट जोड़ने के लिए कहेगा जिसमें यह स्पष्टीकरण हो कि एक Unchecked Account सुरक्षित क्यों है। अर्थात, किसी अविश्वसनीय (untrusted) account को पढ़ना खतरनाक हो सकता है, Anchor यह सुनिश्चित करना चाहता है कि आप account में मौजूद डेटा के साथ कोई महत्वपूर्ण या खतरनाक कार्य नहीं कर रहे हैं।
प्रोग्राम में कोई #[account] struct क्यों नहीं है?
#[account] struct Anchor को बताता है कि डेटा रखने वाले account को डीसीरियलाइज़ (deserialize) कैसे किया जाए। उदाहरण के लिए, एक account struct जो निम्न जैसा दिखता है, Anchor को सूचित करेगा कि उसे account में संग्रहीत डेटा को सिंगल u64 में डीसीरियलाइज़ करना चाहिए:
#[account]
pub struct Counter {
counter: u64
}
हालाँकि, हमारे मामले में, हम account से डेटा नहीं पढ़ रहे हैं — हम केवल balance पढ़ रहे हैं। यह वैसा ही है जैसे हम किसी Ethereum address का balance तो पढ़ सकते हैं लेकिन उसका कोई कोड नहीं पढ़ सकते। चूँकि हम डेटा को डीसीरियलाइज़ नहीं करना चाहते हैं, इसलिए हम #[account] struct प्रदान नहीं करते हैं।
किसी account का सारा SOL खर्च करने योग्य नहीं होता है
Solana account rent पर हमारी चर्चा को याद करें कि “rent exempt” होने के लिए account को SOL का एक निश्चित balance बनाए रखना चाहिए, अन्यथा रनटाइम account को हटा देगा। सिर्फ इसलिए कि account में “1 SOL” है, इसका मतलब यह नहीं है कि account पूरे 1 SOL को खर्च कर सकता है।
उदाहरण के लिए, यदि आप कोई स्टेकिंग (staking) या बैंक एप्लिकेशन बना रहे हैं जहाँ उपयोगकर्ता का जमा किया गया SOL अलग-अलग accounts में रखा जाता है, तो केवल उन accounts के SOL balance को मापना सटीक नहीं है क्योंकि balance में rent भी शामिल होगा।
RareSkills के साथ और जानें
अधिक Solana सामग्री के लिए हमारा Solana developer course देखें।
मूल रूप से 29 फरवरी, 2024 को प्रकाशित