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ịchSơ đồ đơ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ý
Transaction
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ịchSơ đồ 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ướcSơ đồ 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ệp
  • account_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ịch
  • recent_blockhash: Một blockhash đóng vai trò như dấu thời gian cho giao dịch
  • instructions: 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 headeraccount_keys.

Message
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ịch
  • num_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ý
MessageHeader
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ệpSơ đồ 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:

  1. Người ký + Có thể ghi
  2. Người ký + Chỉ đọc
  3. Không phải người ký + Có thể ghi
  4. 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ảnSơ đồ 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:

  1. program_id_index: Một chỉ mục trỏ đến một địa chỉ trong mảng account_keys. Giá trị này chỉ ra địa chỉ của chương trình xử lý chỉ thị.
  2. accounts: Một mảng các chỉ mục trỏ đến các địa chỉ trong mảng account_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.
  3. 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)
CompiledInstruction
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ị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 keypairs
const sender = await generateKeyPairSigner();
const recipient = await generateKeyPairSigner();
// Define the amount to transfer
const 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 recipient
const transferInstruction = getTransferSolInstruction({
source: sender,
destination: recipient.address,
amount: transferAmount
});
// Create transaction message
const transactionMessage = pipe(
createTransactionMessage({ version: 0 }),
(tx) => setTransactionMessageFeePayerSigner(sender, tx),
(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
(tx) => appendTransactionMessageInstructions([transferInstruction], tx)
);
const signedTransaction =
await signTransactionMessageWithSigners(transactionMessage);
// Decode the messageBytes
const compiledTransactionMessage =
getCompiledTransactionMessageDecoder().decode(signedTransaction.messageBytes);
console.log(JSON.stringify(compiledTransactionMessage, null, 2));
Console
Click to execute the code.

Đ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.

Transaction Data
{
"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?

Mục lục

Chỉnh sửa trang

Quản lý bởi

© 2025 Solana Foundation.
Đã đăng ký bản quyền.
Kết nối