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 các chữ ký
  • message: Thông tin giao dịch, bao gồm danh sách các lệnh cần đượ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

Các giao dịch có giới hạn tổng kích thước 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 được thiết kế để tránh phân mảnh gói tin trên cơ sở hạ tầng internet thông thường. Mặc dù IPv6 hỗ trợ MTU lớn hơn 9000 byte, hầu hết các bộ định tuyến internet sử dụng MTU mặc định là 1500 byte (Ethernet tiêu chuẩn). Để đảm bảo các giao dịch vừa với một gói tin mà không bị phân mảnh, Solana sử dụng 1280 byte (MTU tối thiểu yêu cầu cho IPv6) trừ đi 48 byte cho các tiêu đề mạng (40 byte IPv6 + 8 byte tiêu đề phân mảnh/UDP), dẫn đến giới hạn kích thước giao dịch là 1232 byte.

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 bằng cách ký Message của giao dịch với khóa riêng của tài khoản. Một chữ ký phải được cung cấp cho mỗi tài khoản ký được bao gồm trong bất kỳ lệnh 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: Header của thông điệp
  • account_keys: Một mảng các địa chỉ tài khoản được yêu cầu bởi các lệnh 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 các lệnh

Để 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 message là một mảng các địa chỉ tài khoản, được gửi theo định dạng mảng compact. Tiền tố của mảng cho biết độ dài của nó. Mỗi phần tử trong mảng là một public key, trỏ đến một tài khoản được sử dụng bởi các instruction của nó. Mảng accounts_keys phải đầy đủ 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

Thứ tự 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 message để xác định quyền cho từng 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ị hash hoạt động như dấu thời gian của transaction và ngăn chặn các transaction trùng lặp. Một blockhash hết hạn sau 150 block. (Tương đương một phút—giả sử mỗi block là 400ms.) Sau khi block hết hạn, transaction sẽ 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à block height cuối cùng mà tại đó blockhash sẽ còn hợp lệ.

Các chỉ thị

instructions của message là một mảng tất cả các instruction cần được xử lý, được gửi theo định dạng mảng compact. Tiền tố của mảng cho biết độ dài của nó. Mỗi phần tử 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ỉ số trỏ đến một địa chỉ trong mảng account_keys. Giá trị này cho biết địa chỉ của program xử lý instruction.
  2. accounts: Một mảng các chỉ số trỏ đến các địa chỉ trong mảng account_keys. Mỗi chỉ số trỏ đến địa chỉ của một tài khoản cần thiết cho instruction này.
  3. data: Một mảng byte chỉ định instruction nào sẽ được gọi trên program. Nó cũng bao gồm bất kỳ dữ liệu bổ sung nào cần thiết cho instruction. (Ví dụ: các tham số của 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

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