Giao dịch
Để tương tác với mạng Solana, bạn phải gửi một giao dịch. Bạn có thể coi giao dịch như một phong bì chứa nhiều biểu mẫu. Mỗi biểu mẫu là một chỉ thị báo cho mạng biết phải làm gì. Việc gửi giao dịch giống như gửi phong bì qua đường bưu điện để các biểu mẫu có thể được xử lý.
Ví dụ dưới đây cho thấy phiên bản đơn giản hóa của hai giao dịch. Khi giao dịch đầu tiên được xử lý, nó sẽ thực thi một chỉ thị duy nhất. Khi giao dịch thứ hai được xử lý, nó sẽ thực thi ba chỉ thị theo thứ tự tuần tự: đầu tiên là chỉ thị 1, tiếp theo là chỉ thị 2, và cuối cùng là chỉ thị 3.
Giao dịch là nguyên tử: Nếu một chỉ thị đơn lẻ thất bại, toàn bộ giao dịch sẽ thất bại và không có thay đổi nào xảy ra.
Sơ đồ đơn giản hóa hiển thị hai giao dịch
Một
Transaction
bao gồm các thông tin sau:
signatures: Một mảng chữ kýmessage: Thông tin giao dịch, bao gồm danh sách các chỉ thị sẽ được xử lý
pub struct Transaction {#[wasm_bindgen(skip)]#[serde(with = "short_vec")]pub signatures: Vec<Signature>,#[wasm_bindgen(skip)]pub message: Message,}
Sơ đồ hiển thị hai phần của một giao dịch
Giao dịch có giới hạn kích thước tổng cộng là
1232
byte. Giới hạn này bao gồm cả mảng signatures và cấu trúc
message.
Giới hạn này xuất phát từ kích thước Maximum Transmission Unit (MTU) của IPv6 là 1280 byte, trừ đi 48 byte cho các header mạng (40 byte IPv6 + 8 byte header).
Sơ đồ hiển thị định dạng giao dịch và giới hạn kích thước
Chữ ký
Mảng signatures của giao dịch chứa các cấu trúc Signature. Mỗi
Signature
có kích thước 64 byte và được tạo ra bằng cách ký Message của giao dịch với
khóa riêng tư của tài khoản. Một chữ ký phải được cung cấp cho mỗi
tài khoản người ký được bao gồm trong bất kỳ chỉ thị nào
của giao dịch.
Chữ ký đầu tiên thuộc về tài khoản sẽ thanh toán phí cơ bản của giao dịch và là chữ ký giao dịch. Chữ ký giao dịch có thể được sử dụng để tra cứu chi tiết giao dịch trên mạng.
Thông điệp
message của giao dịch là một cấu trúc
Message
chứa các thông tin sau:
header: Tiêu đề của thông điệpaccount_keys: Một mảng địa chỉ tài khoản được yêu cầu bởi các chỉ thị của giao dịchrecent_blockhash: Một blockhash đóng vai trò như dấu thời gian cho giao dịchinstructions: Một mảng chỉ thị
Để tiết kiệm không gian, giao dịch không lưu trữ quyền cho từng tài khoản
riêng lẻ. Thay vào đó, quyền của tài khoản được xác định bằng cách sử dụng
header và account_keys.
pub struct Message {/// The message header, identifying signed and read-only `account_keys`.pub header: MessageHeader,/// All the account keys used by this transaction.#[serde(with = "short_vec")]pub account_keys: Vec<Pubkey>,/// The id of a recent ledger entry.pub recent_blockhash: Hash,/// Programs that will be executed in sequence and committed in/// one atomic transaction if all succeed.#[serde(with = "short_vec")]pub instructions: Vec<CompiledInstruction>,}
Tiêu đề
header của thông điệp là một cấu trúc
MessageHeader.
Nó chứa các thông tin sau:
num_required_signatures: Tổng số chữ ký được yêu cầu bởi giao dịchnum_readonly_signed_accounts: Tổng số tài khoản chỉ đọc yêu cầu chữ kýnum_readonly_unsigned_accounts: Tổng số tài khoản chỉ đọc không yêu cầu chữ ký
pub struct MessageHeader {/// The number of signatures required for this message to be considered/// valid. The signers of those signatures must match the first/// `num_required_signatures` of [`Message::account_keys`].pub num_required_signatures: u8,/// The last `num_readonly_signed_accounts` of the signed keys are read-only/// accounts.pub num_readonly_signed_accounts: u8,/// The last `num_readonly_unsigned_accounts` of the unsigned keys are/// read-only accounts.pub num_readonly_unsigned_accounts: u8,}
Sơ đồ hiển thị ba phần của tiêu đề thông điệp
Địa chỉ tài khoản
account_keys
của thông điệp là một mảng các địa chỉ tài khoản, được gửi ở
định dạng mảng nhỏ gọn.
Tiền tố của mảng chỉ ra độ dài của nó. Mỗi mục trong mảng là một khóa công khai,
trỏ đến một tài khoản được sử dụng bởi các chỉ thị của nó. Mảng accounts_keys
phải hoàn chỉnh và được sắp xếp nghiêm ngặt như sau:
- Người ký + Có thể ghi
- Người ký + Chỉ đọc
- Không phải người ký + Có thể ghi
- Không phải người ký + Chỉ đọc
Việc sắp xếp nghiêm ngặt cho phép mảng account_keys được kết hợp với thông
tin trong header của thông điệp để xác định quyền cho mỗi tài
khoản.
Sơ đồ hiển thị thứ tự của mảng địa chỉ tài khoản
Blockhash gần đây
recent_blockhash của message là một giá trị băm hoạt động như dấu thời gian
của giao dịch và ngăn chặn các giao dịch trùng lặp. Một blockhash hết hạn sau
150 khối.
(Tương đương với một phút—giả định mỗi khối là 400ms.) Sau khi khối hết hạn,
giao dịch cũng hết hạn và không thể được xử lý.
Phương thức RPC getLatestBlockhash cho
phép bạn lấy blockhash hiện tại và chiều cao khối cuối cùng mà tại đó
blockhash sẽ còn hiệu lực.
Các chỉ thị
instructions
của message là một mảng tất cả các chỉ thị cần được xử lý, được gửi ở
định dạng mảng nhỏ gọn.
Tiền tố của mảng chỉ ra độ dài của nó. Mỗi mục trong mảng là một cấu trúc
CompiledInstruction
và bao gồm các thông tin sau:
program_id_index: Một chỉ mục trỏ đến một địa chỉ trong mảngaccount_keys. Giá trị này chỉ ra địa chỉ của chương trình xử lý chỉ thị.accounts: Một mảng các chỉ mục trỏ đến các địa chỉ trong mảngaccount_keys. Mỗi chỉ mục trỏ đến địa chỉ của một tài khoản cần thiết cho chỉ thị này.data: Một mảng byte chỉ định chỉ thị nào cần gọi trên chương trình. Nó cũng bao gồm bất kỳ dữ liệu bổ sung nào cần thiết cho chỉ thị. (Ví dụ, các đối số hàm)
pub struct CompiledInstruction {/// Index into the transaction keys array indicating the program account that executes this instruction.pub program_id_index: u8,/// Ordered indices into the transaction keys array indicating which accounts to pass to the program.#[serde(with = "short_vec")]pub accounts: Vec<u8>,/// The program input data.#[serde(with = "short_vec")]pub data: Vec<u8>,}
Mảng nhỏ gọn của các Chỉ thị
Cấu trúc giao dịch mẫu
Ví dụ sau đây cho thấy cấu trúc của một giao dịch chứa một chỉ thị chuyển SOL duy nhất.
import {createSolanaRpc,generateKeyPairSigner,lamports,createTransactionMessage,setTransactionMessageFeePayerSigner,setTransactionMessageLifetimeUsingBlockhash,appendTransactionMessageInstructions,pipe,signTransactionMessageWithSigners,getCompiledTransactionMessageDecoder} from "@solana/kit";import { getTransferSolInstruction } from "@solana-program/system";const rpc = createSolanaRpc("http://localhost:8899");const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();// 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});// Create transaction messageconst transactionMessage = pipe(createTransactionMessage({ version: 0 }),(tx) => setTransactionMessageFeePayerSigner(sender, tx),(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),(tx) => appendTransactionMessageInstructions([transferInstruction], tx));const signedTransaction =await signTransactionMessageWithSigners(transactionMessage);// Decode the messageBytesconst compiledTransactionMessage =getCompiledTransactionMessageDecoder().decode(signedTransaction.messageBytes);console.log(JSON.stringify(compiledTransactionMessage, null, 2));
Đoạn mã dưới đây hiển thị đầu ra từ các đoạn mã trước đó. Định dạng khác nhau giữa các SDK, nhưng lưu ý rằng mỗi chỉ thị đều chứa cùng thông tin cần thiết.
{"version": 0,"header": {"numSignerAccounts": 1,"numReadonlySignerAccounts": 0,"numReadonlyNonSignerAccounts": 1},"staticAccounts": ["HoCy8p5xxDDYTYWEbQZasEjVNM5rxvidx8AfyqA4ywBa","5T388jBjovy7d8mQ3emHxMDTbUF8b7nWvAnSiP3EAdFL","11111111111111111111111111111111"],"lifetimeToken": "EGCWPUEXhqHJWYBfDirq3mHZb4qDpATmYqBZMBy9TBC1","instructions": [{"programAddressIndex": 2,"accountIndices": [0, 1],"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}}]}
Sau khi một giao dịch được gửi đi, bạn có thể truy xuất chi tiết của nó bằng cách sử dụng chữ ký giao dịch và phương thức RPC getTransaction. Phản hồi sẽ có cấu trúc tương tự như đoạn mã dưới đây.
Bạn cũng có thể tìm giao dịch bằng cách sử dụng Solana Explorer.
{"blockTime": 1745196488,"meta": {"computeUnitsConsumed": 150,"err": null,"fee": 5000,"innerInstructions": [],"loadedAddresses": {"readonly": [],"writable": []},"logMessages": ["Program 11111111111111111111111111111111 invoke [1]","Program 11111111111111111111111111111111 success"],"postBalances": [989995000, 10000000, 1],"postTokenBalances": [],"preBalances": [1000000000, 0, 1],"preTokenBalances": [],"rewards": [],"status": {"Ok": null}},"slot": 13049,"transaction": {"message": {"header": {"numReadonlySignedAccounts": 0,"numReadonlyUnsignedAccounts": 1,"numRequiredSignatures": 1},"accountKeys": ["8PLdpLxkuv9Nt8w3XcGXvNa663LXDjSrSNon4EK7QSjQ","7GLg7bqgLBv1HVWXKgWAm6YoPf1LoWnyWGABbgk487Ma","11111111111111111111111111111111"],"recentBlockhash": "7ZCxc2SDhzV2bYgEQqdxTpweYJkpwshVSDtXuY7uPtjf","instructions": [{"accounts": [0, 1],"data": "3Bxs4NN8M2Yn4TLb","programIdIndex": 2,"stackHeight": null}],"indexToProgramIds": {}},"signatures": ["3jUKrQp1UGq5ih6FTDUUt2kkqUfoG2o4kY5T1DoVHK2tXXDLdxJSXzuJGY4JPoRivgbi45U2bc7LZfMa6C4R3szX"]},"version": "legacy"}
Is this page helpful?