1139 words
6 minutes

深入理解Solana账户与交易机制

一、为什么 Solana 的账户模型如此特别?#

Solana 与 EVM 的最大不同,是账户不仅是资产容器,还是数据存储单元

它更像是一种“文件系统模型”,每个账户都是一个独立的文件:

  • Program Account —— 类似可执行文件(智能合约逻辑)。
  • Data Account —— 存储数据的账户,由特定程序控制读写权限。
  • System Account —— 系统级账户,用于创建新账户或转账 SOL。

在 Solana 上,一笔交易的执行过程更像是:

“程序被加载进多个账户的上下文中,然后对其中的账户进行读写操作。”


二、账户的基本结构#

每个账户在链上的核心字段如下:

字段含义
lamports账户余额,单位为 lamports(1 SOL = 1e9 lamports)
owner该账户由哪个 Program 拥有(例如 SystemProgram
data原始二进制数据,由程序自定义结构
executable是否是可执行账户(即 Program)
rentEpoch租金周期,用于回收长期闲置账户

你可以理解为:

“每个账户既能存钱,又能存数据,还能指定由谁来控制它。”


三、交易的三层结构:Transaction → Message → Instruction#

Solana 的交易不是单条指令,而是一组“批处理操作”。

它包含多个指令(Instruction),每条指令由一个 Program 执行。

1️⃣ Transaction#

最外层结构,包含签名、公钥集合和消息。

2️⃣ Message#

打包了一系列要执行的指令(Instructions),以及这些指令涉及的账户。

3️⃣ Instruction#

单个操作,由:

  • Program ID(哪个程序执行)
  • Accounts(涉及哪些账户)
  • Data(操作参数)

整体结构如下:

Transaction
└── Message
├── AccountKeys
├── RecentBlockhash
└── Instructions[]
├── ProgramID
├── AccountIndices[]
└── Data[]

四、Solana 的签名机制#

Solana 使用 Ed25519 签名算法。

每笔交易必须由至少一个签名者授权(通常是付款方的账户私钥)。

签名的目标数据是 Message 的哈希,而不是交易体。

这样做的好处是可快速验证交易签名的正确性,且支持批量签名验证。

简单来说:签名的是 Message,广播的是 Transaction。


五、构造一笔转账交易(Go 实战)#

现在我们通过 Go SDK 来构造并发送一笔简单的 SOL 转账。

导入依赖#

import (
"context"
"fmt"
"log"
"github.com/gagliardetto/solana-go"
"github.com/gagliardetto/solana-go/rpc"
"github.com/gagliardetto/solana-go/rpc/jsonrpc"
"github.com/gagliardetto/solana-go/text"
)

构建核心逻辑#

func main() {
ctx := context.Background()
client := rpc.New(rpc.DevNet_RPC)
// 1️⃣ 加载本地私钥(从 solana-keygen 生成的钱包)
sender, err := solana.PrivateKeyFromSolanaKeygenFile("/Users/alan/.config/solana/devnet.json")
if err != nil {
log.Fatalf("加载钱包失败: %v", err)
}
receiver := solana.MustPublicKeyFromBase58("接收者钱包地址")
// 2️⃣ 构造转账指令
instruction := solana.NewInstruction(
solana.SystemProgramID,
solana.MustToAccountMeta(sender.PublicKey(), true, true),
solana.MustToAccountMeta(receiver, false, true),
).SetData(
solana.MustEncodeSystemTransfer(
solana.NewSystemTransferInstruction(
sender.PublicKey(),
receiver,
1_000_000_000, // 转账 1 SOL = 1e9 lamports
),
),
)
// 3️⃣ 获取最新区块哈希
recent, err := client.GetRecentBlockhash(ctx, rpc.CommitmentFinalized)
if err != nil {
log.Fatalf("获取区块哈希失败: %v", err)
}
// 4️⃣ 构造交易消息
tx, err := solana.NewTransaction(
[]solana.Instruction{instruction},
recent.Value.Blockhash,
sender.PublicKey(),
)
if err != nil {
log.Fatalf("创建交易失败: %v", err)
}
// 5️⃣ 签名交易
_, err = tx.Sign(func(key solana.PublicKey) *solana.PrivateKey {
if sender.PublicKey().Equals(key) {
return &sender
}
return nil
})
if err != nil {
log.Fatalf("签名失败: %v", err)
}
// 6️⃣ 广播交易
sig, err := client.SendTransaction(ctx, tx)
if err != nil {
log.Fatalf("广播失败: %v", err)
}
fmt.Println("✅ 交易已提交,签名哈希:", sig)
}

六、用 Go 工具查看交易结构#

SDK 提供了一个非常有用的调试工具 text.NewEncoder()

encoder := text.NewEncoder(os.Stdout)
encoder.Encode(tx.Message)

输出结构大致如下:

Message {
recent_blockhash: 7dMjeDkBmw6axbiTzA8npPQfLszDQAJhz3fWQ4XgG9b5
account_keys: [
1. Sender
2. Receiver
3. SystemProgram
]
instructions: [
0: Program(SystemProgram) -> Transfer 1 SOL
]
}

这能帮助我们理解交易内部的账户引用关系,非常适合调试复杂合约调用。


七、RPC 与 gRPC 接口的使用#

Solana 节点支持两种交互方式:

模式协议适合场景
JSON-RPCHTTP(S)简单查询与交易提交
gRPCBinary over HTTP/2高并发、低延迟的链上同步与监听

在 Go SDK 中:

  • rpc.New() → JSON-RPC 客户端
  • jsonrpc.NewClient() → gRPC 模式客户端

例如,我们可以通过 gRPC 订阅区块事件:

grpcClient := jsonrpc.NewClient("https://api.devnet.solana.com:443")
stream, err := grpcClient.SubscribeSlotUpdates(ctx)
if err != nil {
log.Fatalf("订阅失败: %v", err)
}
for {
slotUpdate, err := stream.Recv()
if err != nil {
log.Fatalf("接收错误: %v", err)
}
fmt.Printf("新区块 Slot: %v\n", slotUpdate.Slot)
}

这种方式非常适合写区块监听器、价格同步服务等需要实时响应的业务。


八、小结#

模块内容
账户模型通用账户体系、数据可存储与执行控制
交易结构Transaction → Message → Instruction
签名机制Ed25519,对 Message 哈希签名
Go 实战构造与发送转账交易
通信接口JSON-RPC + gRPC 双模式支持

Share

If this article helped you, please share it with others!

深入理解Solana账户与交易机制
https://blog.ithuo.net/posts/solana-accounts-and-transactions/
Author
Derick
Published at
2024-12-12
License
CC BY-NC-SA 4.0
Last updated on 2024-12-12,410 days ago

Some content may be outdated

Table of Contents