这篇应该是正式写代码前最后的理论知识了,我这篇绝对比看官网文档效率高,官网像一个冰冷的机器,而我的是一个有温度的肉体Solana交易入门:从拼装参数到SVM执行我之前学过BTC、Sui和CKB的开发,感觉区块链交易这东西其实挺简单的。说白了,跟Web2调用接口没啥本质
这篇应该是正式写代码前最后的理论知识了, 我这篇绝对比看官网文档效率高, 官网像一个冰冷的机器, 而我的是一个有温度的肉体
我之前学过 BTC、Sui 和 CKB 的开发,感觉区块链交易这东西其实挺简单的。说白了,跟 Web2 调用接口没啥本质区别,就是拼装参数,扔给网络执行。Solana 也不例外,无论是用 SDK 的高级方法直接调用业务逻辑,还是手动拼装底层交易结构,最终都是为了生成一个符合规范的交易包。
下面我结合官方文档和自己的理解,梳理一下 Solana 交易的要点,顺便分享一个转账 SOL 的 JSON 示例,帮你快速入门。
Solana 的交易(Transaction)本质上是一个数据包,提交后会在 Solana 虚拟机(SVM)中执行。执行者是当前 slot 的 Leader,执行完后广播给其他 Validator 验证。出于网络性能考虑,交易数据包大小被控制在 1232 字节以内,比 IPv4/IPv6 的 1500 字节 MTU 小得多,避免了分片或重组失败的风险。
一个 Transaction 可以包含多个指令(Instruction),这些指令按你在代码中添加的顺序依次执行,整个交易是原子性的——要么全成功,要么全失败,跟数据库事务或银行转账一个道理。
每个 Instruction 是交易的基本单元,定义了:
programIdIndex 指定。accounts 指定账户索引。data 定义具体方法和参数。用代码调用时,SDK 提供两种方式:
SystemProgram.transfer,简单省事。Instruction,写起来复杂,但灵活性更高。我们来看一个实际的转账交易 JSON(发送时是二进制形式,这里是人类可读的表示):
{
"transaction": {
"message": {
"accountKeys": [
"3z9vL1zjN6qyAFHhHQdWYRTFAcy69pJydkZmSFBKHg1R",
"5snoUseZG8s8CDFHrXY2ZHaCrJYsW457piktDmhyb5Jd",
"11111111111111111111111111111111"
],
"header": {
"numReadonlySignedAccounts": 0,
"numReadonlyUnsignedAccounts": 1,
"numRequiredSignatures": 1
},
"recentBlockhash": "DzfXchZJoLMG3cNftcf2sw7qatkkuwQf4xH15N5wkKAb",
"instructions": [
{
"accounts": [0, 1],
"programIdIndex": 2,
"data": "3Bxs4NN8M2Yn4TLb"
}
]
},
"signatures": [
"5LrcE2f6uvydKRquEJ8xp19heGxSvqsVbcqUeFoiWbXe8JNip7ftPQNTAVPyTK7ijVdpkzmKKaAQR7MWMmujAhXD"
]
}
}
这个交易是从账户 3z9v... 转账 100 lamports 到 5sno...,调用的是 SystemProgram 的 Transfer 方法。下面逐一拆解。
accountKeysinstructions 只需要用索引引用,避免重复写 32 字节的公钥。accountKeys[0]: "3z9v..."(付款方)。accountKeys[1]: "5sno..."(收款方)。accountKeys[2]: "1111..."(SystemProgram,程序也是账户!)。header作用:定义 accountKeys 中账户的角色和属性,分为四类:
排序规则:accountKeys 的顺序是固定的:先签名后非签名,先可写后只读。
示例解析:
numRequiredSignatures = 1:前 1 个账户(3z9v...)需要签名。numReadonlySignedAccounts = 0:签名账户中没有只读的,3z9v... 是可写的。numReadonlyUnsignedAccounts = 1:非签名账户(5sno... 和 1111...)中,最后 1 个(1111...)是只读的。3z9v...:签名 + 可写(付款方)。5sno...:无签名 + 可写(收款方)。1111...:无签名 + 只读(SystemProgram)。一个比较极限的例子:
accountKeys = [A, B, C, D, E, F, G, H, L, M](10 个账户):num_required_signatures = 5:[A, B, C, D, E] 需要签名。num_readonly_signed_accounts = 2:签名账户中后 2 个(D, E)是只读,[A, B, C] 是可写。num_readonly_unsigned_accounts = 2:非签名账户 [F, G, H, L, M] 中后 2 个(L, M)是只读,[F, G, H] 是可写。A, B, C:签名 + 可写。D, E:签名 + 只读。F, G, H:无签名 + 可写。L, M:无签名 + 只读。recentBlockhashmessage 中,签名者对其签名。getLatestBlockhash 从 RPC 获取(高层方法如 sendAndConfirmTransaction 会自动处理)。"DzfXchZJoLMG3cNftcf2sw7qatkkuwQf4xH15N5wkKAb" 是某个已确认区块的哈希。instructionsprogramIdIndex:指向 accountKeys 中的程序账户,决定调用哪个程序。2 -> accountKeys[2] -> SystemProgram。accounts:指向 accountKeys 的索引,指定操作哪些账户,顺序由程序定义。[0, 1] -> 操作 3z9v...(付款方)和 5sno...(收款方)。data:指定调用程序的哪个方法和参数。"3Bxs4NN8M2Yn4TLb" 解码为 [2, 0, 0, 0, 100, 0, 0, 0]:
[2, 0, 0, 0]:Transfer 指令(ID = 2)。[100, 0, 0, 0, 0, 0, 0, 0]:转账金额 100 lamports。SystemProgram 的 Transfer 从 accounts[0] 转账 100 lamports 到 accounts[1]。signaturesmessage 的签名,证明交易授权。accountKeys[0](3z9v...)。具体如何计算暂不深入,以后有需要再研究
Solana 的交易跟其他区块链类似,就是拼装参数扔给网络执行。核心是理解 accountKeys、header 和 instructions 的关系:
accountKeys 定义所有账户。header 指定账户角色。instructions 描述具体操作。用 SDK 时,高级方法省心,底层拼装灵活,选哪种看需求。希望这篇笔记能帮你快速上手 Solana 交易开发,有问题欢迎留言讨论!
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!