Λογαριασμοί
Όλα τα δεδομένα στο δίκτυο Solana αποθηκεύονται σε λογαριασμούς. Μπορείτε να σκεφτείτε το δίκτυο Solana ως μια δημόσια βάση δεδομένων με έναν μοναδικό πίνακα Λογαριασμών. Η σχέση μεταξύ ενός λογαριασμού και της διεύθυνσής του είναι παρόμοια με αυτή ενός ζεύγους κλειδιού-τιμής, όπου το κλειδί είναι η διεύθυνση και η τιμή είναι ο λογαριασμός.
Κάθε λογαριασμός έχει την ίδια βασική δομή και μπορεί να εντοπιστεί χρησιμοποιώντας τη διεύθυνσή του.
Διάγραμμα 3 λογαριασμών και των διευθύνσεών τους. Περιλαμβάνει τον ορισμό της δομής λογαριασμού.
Διεύθυνση λογαριασμού
Η διεύθυνση του λογαριασμού είναι ένα μοναδικό αναγνωριστικό 32 byte που χρησιμοποιείται για τον εντοπισμό του λογαριασμού στο blockchain της Solana. Οι διευθύνσεις λογαριασμών συχνά εμφανίζονται ως συμβολοσειρές κωδικοποιημένες σε base58. Οι περισσότεροι λογαριασμοί χρησιμοποιούν ένα δημόσιο κλειδί Ed25519 ως διεύθυνσή τους, αλλά αυτό δεν είναι απαραίτητο, καθώς η Solana υποστηρίζει επίσης διευθύνσεις παραγόμενες από προγράμματα.
Ένας λογαριασμός με τη διεύθυνση δημόσιου κλειδιού του κωδικοποιημένη σε base58
Δημόσιο κλειδί
Το παρακάτω παράδειγμα δείχνει πώς να χρησιμοποιήσετε το Solana SDK για να
δημιουργήσετε ένα keypair. Ένα Keypair περιλαμβάνει:
- Ένα δημόσιο κλειδί που λειτουργεί ως διεύθυνση λογαριασμού
- Ένα ιδιωτικό κλειδί που χρησιμοποιείται για την υπογραφή συναλλαγών
import { generateKeyPairSigner } from "@solana/kit";// Kit does not enable extractable private keysconst keypairSigner = await generateKeyPairSigner();console.log(keypairSigner);
Program derived address
Μια program derived address (PDA) είναι μια διεύθυνση που προκύπτει ντετερμινιστικά χρησιμοποιώντας ένα αναγνωριστικό προγράμματος και μία ή περισσότερες προαιρετικές εισόδους (seeds). Το παρακάτω παράδειγμα δείχνει πώς να χρησιμοποιήσετε το Solana SDK για να δημιουργήσετε μια program derived address.
import { Address, getProgramDerivedAddress } from "@solana/kit";const programAddress = "11111111111111111111111111111111" as Address;const seeds = ["helloWorld"];const [pda, bump] = await getProgramDerivedAddress({programAddress,seeds});console.log(`PDA: ${pda}`);console.log(`Bump: ${bump}`);
Δομή λογαριασμού
Κάθε
Account
έχει μέγιστο μέγεθος
10MiB
και περιέχει τις ακόλουθες πληροφορίες:
lamports: Ο αριθμός των lamports στον λογαριασμόdata: Τα δεδομένα του λογαριασμούowner: Το αναγνωριστικό του προγράμματος που κατέχει τον λογαριασμόexecutable: Υποδεικνύει εάν ο λογαριασμός περιέχει εκτελέσιμο δυαδικό αρχείοrent_epoch: Το παρωχημένο πεδίο rent epoch
pub struct Account {/// lamports in the accountpub lamports: u64,/// data held in this account#[cfg_attr(feature = "serde", serde(with = "serde_bytes"))]pub data: Vec<u8>,/// the program that owns this account. If executable, the program that loads this account.pub owner: Pubkey,/// this account's data contains a loaded program (and is now read-only)pub executable: bool,/// the epoch at which this account will next owe rentpub rent_epoch: Epoch,}
Lamports
Το υπόλοιπο του λογαριασμού σε lamports.
Κάθε λογαριασμός πρέπει να έχει ένα ελάχιστο υπόλοιπο lamport, που ονομάζεται rent, το οποίο επιτρέπει την αποθήκευση των δεδομένων του στην αλυσίδα. Το rent είναι ανάλογο με το μέγεθος του λογαριασμού.
Παρόλο που αυτό το υπόλοιπο ονομάζεται rent, λειτουργεί περισσότερο σαν εγγύηση, καθώς το πλήρες υπόλοιπο μπορεί να ανακτηθεί όταν ο λογαριασμός κλείσει. (Το όνομα "rent" προέρχεται από το πλέον παρωχημένο πεδίο rent epoch.)
(Δείτε τον τύπο για το ελάχιστο υπόλοιπο και τις σχετικές σταθερές.)
Δεδομένα
Αυτό το πεδίο συνήθως αναφέρεται ως "δεδομένα λογαριασμού". Τα data σε αυτό το
πεδίο θεωρούνται αυθαίρετα καθώς μπορούν να περιέχουν οποιαδήποτε ακολουθία
bytes. Κάθε πρόγραμμα καθορίζει τη δομή των δεδομένων που αποθηκεύονται σε αυτό
το πεδίο.
- Program accounts: Αυτό το πεδίο περιέχει είτε εκτελέσιμο κώδικα προγράμματος είτε τη διεύθυνση ενός λογαριασμού δεδομένων προγράμματος που αποθηκεύει τον εκτελέσιμο κώδικα προγράμματος.
- Data accounts: Αυτό το πεδίο γενικά αποθηκεύει δεδομένα κατάστασης, που προορίζονται για ανάγνωση.
Η ανάγνωση δεδομένων από έναν λογαριασμό Solana περιλαμβάνει δύο βήματα:
- Ανάκτηση του λογαριασμού χρησιμοποιώντας τη διεύθυνσή του
- Αποσειριοποίηση του πεδίου
dataτου λογαριασμού από ακατέργαστα bytes στην κατάλληλη δομή δεδομένων, όπως ορίζεται από το πρόγραμμα που κατέχει τον λογαριασμό.
Ιδιοκτήτης
Αυτό το πεδίο περιέχει το αναγνωριστικό προγράμματος του ιδιοκτήτη του λογαριασμού.
Κάθε λογαριασμός Solana έχει ένα πρόγραμμα που ορίζεται
ως ιδιοκτήτης του. Ο ιδιοκτήτης του λογαριασμού είναι το μόνο πρόγραμμα που
μπορεί να αλλάξει τα data του λογαριασμού ή να αφαιρέσει lamports, όπως
υποδεικνύεται από τις οδηγίες του προγράμματος.
(Στην περίπτωση ενός program account, ο ιδιοκτήτης είναι το πρόγραμμα φόρτωσης.)
Εκτελέσιμο
Αυτό το πεδίο υποδεικνύει εάν ένας λογαριασμός είναι program account ή data account
- Αν
true: Ο λογαριασμός είναι program account - Αν
false: Ο λογαριασμός είναι data account
Epoch ενοικίου
Το πεδίο rent_epoch είναι παρωχημένο.
Στο παρελθόν, αυτό το πεδίο παρακολουθούσε πότε ένας λογαριασμός θα χρειαζόταν να πληρώσει rent. Ωστόσο, αυτός ο μηχανισμός είσπραξης rent έχει πλέον καταργηθεί.
Τύποι λογαριασμών
Υπάρχουν δύο βασικές κατηγορίες στις οποίες εμπίπτουν οι λογαριασμοί:
- Λογαριασμοί προγραμμάτων: Λογαριασμοί που περιέχουν εκτελέσιμο κώδικα
- Λογαριασμοί δεδομένων: Λογαριασμοί που δεν περιέχουν εκτελέσιμο κώδικα
Αυτός ο διαχωρισμός του κώδικα ενός προγράμματος και της κατάστασής του είναι ένα βασικό χαρακτηριστικό του μοντέλου λογαριασμών της Solana. (Παρόμοια με τα λειτουργικά συστήματα, τα οποία συνήθως έχουν ξεχωριστά αρχεία για τα προγράμματα και τα δεδομένα τους.)
Λογαριασμοί προγραμμάτων
Κάθε πρόγραμμα ανήκει σε ένα πρόγραμμα φόρτωσης, το οποίο χρησιμοποιείται για την ανάπτυξη και διαχείριση του λογαριασμού. Όταν αναπτύσσεται ένα νέο πρόγραμμα, δημιουργείται ένας λογαριασμός για την αποθήκευση του εκτελέσιμου κώδικά του. Αυτός ονομάζεται λογαριασμός προγράμματος. (Για απλότητα, μπορείτε να θεωρήσετε τον λογαριασμό προγράμματος ως το ίδιο το πρόγραμμα.)
Στο παρακάτω διάγραμμα, μπορείτε να δείτε ότι ένα πρόγραμμα φόρτωσης
χρησιμοποιείται για την ανάπτυξη ενός λογαριασμού προγράμματος. Το πεδίο data
του λογαριασμού προγράμματος περιέχει τον εκτελέσιμο κώδικα του προγράμματος.
Διάγραμμα ενός λογαριασμού προγράμματος, των 4 συστατικών του και του προγράμματος φόρτωσής του.
Λογαριασμοί δεδομένων προγράμματος
Τα προγράμματα που αναπτύσσονται με το loader-v3 δεν περιέχουν κώδικα
προγράμματος στο πεδίο data τους. Αντίθετα, το πεδίο data τους δείχνει σε
έναν ξεχωριστό λογαριασμό δεδομένων προγράμματος, ο οποίος περιέχει τον
κώδικα του προγράμματος. (Δείτε το παρακάτω διάγραμμα.)
Ένας λογαριασμός προγράμματος με δεδομένα. Τα δεδομένα δείχνουν σε έναν ξεχωριστό λογαριασμό δεδομένων προγράμματος
Κατά την ανάπτυξη ή αναβάθμιση προγραμμάτων, χρησιμοποιούνται λογαριασμοί buffer για την προσωρινή σταδιοποίηση της μεταφόρτωσης.
Το παρακάτω παράδειγμα ανακτά τον λογαριασμό του Token Program. Παρατηρήστε ότι
το πεδίο executable έχει οριστεί ως true, υποδεικνύοντας ότι ο λογαριασμός
είναι πρόγραμμα.
import { Address, createSolanaRpc } from "@solana/kit";const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");const programId = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" as Address;const accountInfo = await rpc.getAccountInfo(programId, { encoding: "base64" }).send();console.log(accountInfo);
Λογαριασμοί δεδομένων
Οι λογαριασμοί δεδομένων δεν περιέχουν εκτελέσιμο κώδικα. Αντίθετα, αποθηκεύουν πληροφορίες.
Λογαριασμός κατάστασης προγράμματος
Τα προγράμματα χρησιμοποιούν λογαριασμούς δεδομένων για να διατηρούν την κατάστασή τους. Για να το κάνουν αυτό, πρέπει πρώτα να δημιουργήσουν έναν νέο λογαριασμό δεδομένων. Η διαδικασία δημιουργίας ενός λογαριασμού κατάστασης προγράμματος συχνά αφαιρείται, αλλά είναι χρήσιμο να κατανοήσουμε την υποκείμενη διαδικασία.
Για να διαχειριστεί την κατάστασή του, ένα νέο πρόγραμμα πρέπει:
- Να επικαλεστεί το System Program για να δημιουργήσει έναν λογαριασμό. (Το System Program στη συνέχεια μεταφέρει την ιδιοκτησία στο νέο πρόγραμμα.)
- Να αρχικοποιήσει τα δεδομένα του λογαριασμού, όπως ορίζεται από τις οδηγίες του.
Διάγραμμα ενός λογαριασμού δεδομένων που ανήκει σε έναν λογαριασμό προγράμματος
Το παρακάτω παράδειγμα δημιουργεί και ανακτά έναν λογαριασμό Token Mint που ανήκει στο πρόγραμμα Token 2022.
import {airdropFactory,appendTransactionMessageInstructions,createSolanaRpc,createSolanaRpcSubscriptions,createTransactionMessage,generateKeyPairSigner,getSignatureFromTransaction,lamports,pipe,sendAndConfirmTransactionFactory,setTransactionMessageFeePayerSigner,setTransactionMessageLifetimeUsingBlockhash,signTransactionMessageWithSigners} from "@solana/kit";import { getCreateAccountInstruction } from "@solana-program/system";import {getInitializeMintInstruction,getMintSize,TOKEN_2022_PROGRAM_ADDRESS,fetchMint} from "@solana-program/token-2022";// Create Connection, local validator in this exampleconst rpc = createSolanaRpc("http://localhost:8899");const rpcSubscriptions = createSolanaRpcSubscriptions("ws://localhost:8900");// Generate keypairs for fee payerconst feePayer = await generateKeyPairSigner();// Fund fee payerawait airdropFactory({ rpc, rpcSubscriptions })({recipientAddress: feePayer.address,lamports: lamports(1_000_000_000n),commitment: "confirmed"});// Generate keypair to use as address of mintconst mint = await generateKeyPairSigner();// Get default mint account size (in bytes), no extensions enabledconst space = BigInt(getMintSize());// Get minimum balance for rent exemptionconst rent = await rpc.getMinimumBalanceForRentExemption(space).send();// Instruction to create new account for mint (token 2022 program)// Invokes the system programconst createAccountInstruction = getCreateAccountInstruction({payer: feePayer,newAccount: mint,lamports: rent,space,programAddress: TOKEN_2022_PROGRAM_ADDRESS});// Instruction to initialize mint account data// Invokes the token 2022 programconst initializeMintInstruction = getInitializeMintInstruction({mint: mint.address,decimals: 9,mintAuthority: feePayer.address});const instructions = [createAccountInstruction, initializeMintInstruction];// Get latest blockhash to include in transactionconst { value: latestBlockhash } = await rpc.getLatestBlockhash().send();// Create transaction messageconst transactionMessage = pipe(createTransactionMessage({ version: 0 }), // Create transaction message(tx) => setTransactionMessageFeePayerSigner(feePayer, tx), // Set fee payer(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx), // Set transaction blockhash(tx) => appendTransactionMessageInstructions(instructions, tx) // Append instructions);// Sign transaction message with required signers (fee payer and mint keypair)const signedTransaction =await signTransactionMessageWithSigners(transactionMessage);// Send and confirm transactionawait sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(signedTransaction,{ commitment: "confirmed" });// Get transaction signatureconst transactionSignature = getSignatureFromTransaction(signedTransaction);console.log("Mint Address:", mint.address);console.log("Transaction Signature:", transactionSignature);const accountInfo = await rpc.getAccountInfo(mint.address).send();console.log(accountInfo);const mintAccount = await fetchMint(rpc, mint.address);console.log(mintAccount);
Λογαριασμοί συστήματος
Δεν ανατίθενται όλοι οι λογαριασμοί σε νέο ιδιοκτήτη μετά τη δημιουργία τους από το System Program. Οι λογαριασμοί που ανήκουν στο System Program ονομάζονται λογαριασμοί συστήματος. Όλοι οι λογαριασμοί πορτοφολιού είναι λογαριασμοί συστήματος, γεγονός που τους επιτρέπει να πληρώνουν χρεώσεις συναλλαγών.
Ένα πορτοφόλι που ανήκει στο System Program και περιέχει 1.000.000 lamports
Όταν το SOL αποστέλλεται σε μια νέα διεύθυνση για πρώτη φορά, δημιουργείται ένας λογαριασμός σε αυτή τη διεύθυνση που ανήκει στο System Program.
Στο παρακάτω παράδειγμα, δημιουργείται ένα νέο keypair και χρηματοδοτείται με
SOL. Μετά την εκτέλεση του κώδικα, μπορείτε να δείτε ότι η διεύθυνση του owner
του λογαριασμού είναι 11111111111111111111111111111111 (το
System Program).
import {airdropFactory,createSolanaRpc,createSolanaRpcSubscriptions,generateKeyPairSigner,lamports} from "@solana/kit";// Create a connection to Solana clusterconst rpc = createSolanaRpc("http://localhost:8899");const rpcSubscriptions = createSolanaRpcSubscriptions("ws://localhost:8900");// Generate a new keypairconst keypair = await generateKeyPairSigner();console.log(`Public Key: ${keypair.address}`);// Funding an address with SOL automatically creates an accountconst signature = await airdropFactory({ rpc, rpcSubscriptions })({recipientAddress: keypair.address,lamports: lamports(1_000_000_000n),commitment: "confirmed"});const accountInfo = await rpc.getAccountInfo(keypair.address).send();console.log(accountInfo);
Λογαριασμοί Sysvar
Οι λογαριασμοί Sysvar υπάρχουν σε προκαθορισμένες διευθύνσεις και παρέχουν πρόσβαση σε δεδομένα κατάστασης του συμπλέγματος. Ενημερώνονται δυναμικά με δεδομένα σχετικά με το σύμπλεγμα του δικτύου. Δείτε την πλήρη λίστα των Λογαριασμών Sysvar.
Το παρακάτω παράδειγμα ανακτά και αποσειριοποιεί δεδομένα από τον λογαριασμό Sysvar Clock.
import { createSolanaRpc } from "@solana/kit";import { fetchSysvarClock, SYSVAR_CLOCK_ADDRESS } from "@solana/sysvars";const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");const accountInfo = await rpc.getAccountInfo(SYSVAR_CLOCK_ADDRESS, { encoding: "base64" }).send();console.log(accountInfo);// Automatically fetch and deserialize the account dataconst clock = await fetchSysvarClock(rpc);console.log(clock);
Is this page helpful?