Περίληψη
Μια εντολή έχει 3 πεδία: program_id (ποιο πρόγραμμα να κληθεί), accounts
(λίστα AccountMeta με σημαίες is_signer/is_writable) και data (πίνακας byte
δεδομένων που ερμηνεύει το πρόγραμμα).
Δομή εντολής
Μια
Instruction
αποτελείται από τρία πεδία:
program_id: Το ID του προγράμματος που καλείται.accounts: Ένας πίνακας μεταδεδομένων λογαριασμούdata: Ένας πίνακας byte με πρόσθετα δεδομένα για χρήση από την εντολή.
pub struct Instruction {/// Pubkey of the program that executes this instruction.pub program_id: Pubkey,/// Metadata describing accounts that should be passed to the program.pub accounts: Vec<AccountMeta>,/// Opaque data passed to the program for its own interpretation.pub data: Vec<u8>,}
Program ID
Το program_id της εντολής είναι η
δημόσια διεύθυνση κλειδιού του προγράμματος που περιέχει τη λογική εκτέλεσης της
εντολής. Το runtime χρησιμοποιεί αυτό το πεδίο για να δρομολογήσει την εντολή
στο σωστό πρόγραμμα για επεξεργασία.
Μεταδεδομένα λογαριασμού
Ο πίνακας accounts της εντολής είναι μια ταξινομημένη λίστα από δομές
AccountMeta.
Πρέπει να παρέχονται μεταδεδομένα για κάθε λογαριασμό με τον οποίο αλληλεπιδρά η
εντολή. Ο validator χρησιμοποιεί αυτά τα μεταδεδομένα για να καθορίσει ποιες
συναλλαγές μπορούν να εκτελεστούν παράλληλα. Συναλλαγές που γράφουν σε
διαφορετικούς λογαριασμούς μπορούν να εκτελεστούν παράλληλα.
Το παρακάτω διάγραμμα απεικονίζει μια συναλλαγή που περιέχει μία μόνο εντολή. Ο
πίνακας accounts της εντολής περιέχει μεταδεδομένα για δύο λογαριασμούς.
Μια συναλλαγή με μία εντολή. Η εντολή περιέχει δύο δομές AccountMeta στον πίνακα accounts της.
Κάθε AccountMeta έχει τρία πεδία:
- pubkey: Η δημόσια διεύθυνση κλειδιού του λογαριασμού
- is_signer: Ορίζεται σε
trueαν ο λογαριασμός πρέπει να υπογράψει τη συναλλαγή - is_writable: Ορίζεται σε
trueαν η εντολή τροποποιεί τα δεδομένα του λογαριασμού
Για να μάθετε ποιους λογαριασμούς απαιτεί μια εντολή, συμπεριλαμβανομένων ποιοι πρέπει να είναι εγγράψιμοι, μόνο για ανάγνωση ή να υπογράφουν τη συναλλαγή, πρέπει να ανατρέξετε στην υλοποίηση της εντολής, όπως ορίζεται από το πρόγραμμα.
pub struct AccountMeta {/// An account's public key.pub pubkey: Pubkey,/// True if an `Instruction` requires a `Transaction` signature matching `pubkey`.pub is_signer: bool,/// True if the account data or metadata may be mutated during program execution.pub is_writable: bool,}
Δεδομένα
Το πεδίο data της εντολής είναι ένας πίνακας bytes που υποδεικνύει στο
πρόγραμμα ποια συνάρτηση να καλέσει και παρέχει τα ορίσματα για αυτή τη
συνάρτηση. Τα δεδομένα τυπικά ξεκινούν με ένα discriminator ή index byte(s) που
προσδιορίζει τη στοχευόμενη συνάρτηση, ακολουθούμενο από τα σειριοποιημένα
ορίσματα. Η μορφή κωδικοποίησης ορίζεται από κάθε πρόγραμμα (για παράδειγμα,
σειριοποίηση Borsh ή προσαρμοσμένη διάταξη).
Κοινές συμβάσεις κωδικοποίησης:
- Βασικά προγράμματα (System, Stake, Vote): Χρησιμοποιούν ένα δείκτη παραλλαγής enum σειριοποιημένο με Bincode ακολουθούμενο από σειριοποιημένα ορίσματα.
- Προγράμματα Anchor: Χρησιμοποιούν ένα discriminator 8-byte (τα πρώτα 8
bytes του SHA-256 hash του
"global:<function_name>") ακολουθούμενο από ορίσματα σειριοποιημένα με Borsh.
Το runtime δεν ερμηνεύει το πεδίο data. Μεταβιβάζεται ως έχει στο σημείο
εισόδου process_instruction του προγράμματος.
Μεταγλωττισμένη εντολή
Όταν οι εντολές σειριοποιούνται σε ένα μήνυμα συναλλαγής, μετατρέπονται σε δομές
CompiledInstruction
που αντικαθιστούν όλα τα δημόσια κλειδιά με συμπαγείς ακέραιους δείκτες στον
πίνακα account_keys του μηνύματος.
Παράδειγμα: εντολή μεταφοράς SOL
Το παρακάτω παράδειγμα δείχνει τη δομή μιας εντολής μεταφοράς SOL.
import { generateKeyPairSigner, lamports } from "@solana/kit";import { getTransferSolInstruction } from "@solana-program/system";// Generate sender and recipient keypairsconst sender = await generateKeyPairSigner();const recipient = await generateKeyPairSigner();// Define the amount to transferconst LAMPORTS_PER_SOL = 1_000_000_000n;const transferAmount = lamports(LAMPORTS_PER_SOL / 100n); // 0.01 SOL// Create a transfer instruction for transferring SOL from sender to recipientconst transferInstruction = getTransferSolInstruction({source: sender,destination: recipient.address,amount: transferAmount});console.log(JSON.stringify(transferInstruction, null, 2));
Ο παρακάτω κώδικας δείχνει το αποτέλεσμα από τα προηγούμενα αποσπάσματα κώδικα.
Η μορφή θα διαφέρει μεταξύ των SDK, αλλά παρατηρήστε ότι κάθε εντολή περιέχει τα
ίδια τρία απαιτούμενα στοιχεία πληροφοριών: program_id,
accounts, data.
{"accounts": [{"address": "Hu28vRMGWpQXN56eaE7jRiDDRRz3vCXEs7EKHRfL6bC","role": 3,"signer": {"address": "Hu28vRMGWpQXN56eaE7jRiDDRRz3vCXEs7EKHRfL6bC","keyPair": {"privateKey": {},"publicKey": {}}}},{"address": "2mBY6CTgeyJNJDzo6d2Umipw2aGUquUA7hLdFttNEj7p","role": 1}],"programAddress": "11111111111111111111111111111111","data": {"0": 2,"1": 0,"2": 0,"3": 0,"4": 128,"5": 150,"6": 152,"7": 0,"8": 0,"9": 0,"10": 0,"11": 0}}
Τα παρακάτω παραδείγματα δείχνουν πώς να δημιουργήσετε χειροκίνητα την εντολή
μεταφοράς. (Η καρτέλα Expanded Instruction είναι λειτουργικά ισοδύναμη με την
καρτέλα Instruction.)
Στην πράξη, συνήθως δεν χρειάζεται να κατασκευάσετε ένα Instruction
χειροκίνητα. Τα περισσότερα προγράμματα παρέχουν βιβλιοθήκες client με
βοηθητικές συναρτήσεις που δημιουργούν τις εντολές για εσάς. Εάν δεν είναι
διαθέσιμη κάποια βιβλιοθήκη, μπορείτε να δημιουργήσετε χειροκίνητα την εντολή.
const transferAmount = 0.01; // 0.01 SOLconst transferInstruction = getTransferSolInstruction({source: sender,destination: recipient.address,amount: transferAmount * LAMPORTS_PER_SOL});
Is this page helpful?