如何不使用Serum多签实现前端请求Nodejs后端联合签名Anchor交易
Solana + Anchor 前后端联合签名实现方案
依赖版本选择
没有所谓“通用正确版本”,核心遵循两个对齐规则即可:
- 全栈所有端(链上Anchor程序、前端、Nodejs后端)的依赖版本严格对齐:
- 部署链上程序用的Anchor CLI版本,必须和前后端安装的
@coral-xyz/anchor(Anchor 0.24+版本)/@project-serum/anchor(Anchor 0.23及更早版本)版本号完全一致 - 前后端安装的
@solana/web3.js版本必须完全一致,禁止跨大版本混装(比如一端用v1.x一端用v2.x)
- 部署链上程序用的Anchor CLI版本,必须和前后端安装的
- 生产环境可用的稳定版本组合参考:
- Anchor 0.29.x 配套
@coral-xyz/anchor@0.29.0+@solana/web3.js@1.91.7 - Anchor 0.26.x 配套
@coral-xyz/anchor@0.26.0+@solana/web3.js@1.78.5
初期不用多签的场景直接锁v1版本的web3.js即可,API稳定坑少,没必要追v2的新特性。
- Anchor 0.29.x 配套
签名追加全流程实现
整个流程不需要引入多签逻辑,用partialSign部分签名能力就能实现,步骤如下:
- 前端构造交易阶段,必须把后端公钥加入交易的必填签名账户列表,和Anchor程序里配置的指令签名校验规则保持一致,不然链上会直接报缺少签名的错误。
- 前端向后端传交易参数时,不要传签完名的交易,传关闭了全签名校验的序列化Buffer:
const serializedTxForBackend = tx.serialize({ requireAllSignatures: false, verifySignatures: false }) // 把这个Buffer通过接口传给后端
- 后端拿到Buffer后先反序列化,完成业务校验(比如校验交易指令参数、操作权限、转账额度是否符合规则),校验通过后用存储的keypair做部分签名:
import { Transaction } from '@solana/web3.js' const tx = Transaction.from(serializedTxBuf) // 业务校验逻辑写在这里,校验不通过直接返回错误 tx.partialSign(backendStoredKeypair) // 提取后端生成的签名返回给前端即可,不需要返回整笔交易 const backendSig = tx.signatures.find( item => item.publicKey.equals(backendStoredKeypair.publicKey) ).signature return { backendPubkey: backendStoredKeypair.publicKey.toBase58(), signature: backendSig }
- 前端拿到后端返回的签名后,直接追加到本地持有的原交易对象上,再调用户钱包完成签名即可上链:
import { PublicKey } from '@solana/web3.js' // 给本地原交易追加后端签名 originalTx.addSignature( new PublicKey(res.backendPubkey), Buffer.from(res.signature) ) // 调用户钱包签名 const userSignedTx = await window.solana.signTransaction(originalTx) // 发链 const txHash = await connection.sendRawTransaction(userSignedTx.serialize())
安全提示:前端拿到后端返回的签名后,一定要先校验签名是否匹配后端公钥、交易消息体有没有被篡改,确认无误后再唤起用户钱包签名,避免恶意构造交易造成资产损失。
这个方案下Anchor程序不需要做任何特殊改造,只要把后端公钥配置为对应指令的签名账户即可,链上runtime会自动校验所有必填签名是否存在,缺任意一个签名都会直接拒绝交易,完全满足初期“后端校验后才允许交易上链”的需求。
内容的提问来源于stack exchange,提问作者val.samonte
相关产品推荐
相关产品推荐

