Solana主网sendRawTransaction发送交易未被集群收录且无报错
Solana主网交易静默丢弃排查方案
你描述的100%复现、仅主网触发、删除单条指令+对应签名者即可恢复、web3.js无报错、devnet运行正常的特征,完全匹配Solana主网2023年下半年全量上线的交易入口硬拦截规则,这类拦截不会返回错误码,RPC节点收到违规交易直接静默丢包,所以区块浏览器查不到任何txid记录,和网络拥堵、重试次数无关。
按优先级排查以下问题
- 第一优先级:校验序列化后交易字节长度
Solana主网单交易序列化后的硬体积上限为1232字节(匹配UDP传输MTU阈值),超过该体积的交易会被RPC入口直接丢弃,不会进入广播队列。
直接在发送交易前加日志打印长度即可确认:
该体积校验规则主网全量上线时间比devnet早3周左右,刚好对应你提到的问题出现时间,devnet早期未严格拦截超体积交易,才会出现测试环境正常、主网异常的差异。你删除一条指令+对应签名者后交易恢复,大概率就是刚好把体积压到了阈值以下。// 签名完成后先序列化,不要直接传给sendRawTransaction const rawTransaction = transaction.serialize({ requireAllSignatures: true, verifySignatures: true }); console.log('交易字节长度:', rawTransaction.length); // 长度>1232 必然被拦截 - 第二优先级:校验交易内唯一账户总数
主网交易入口另一项硬限制是单交易最多包含64个唯一关联账户(含指令涉及的所有用户账户、程序ID),超过数量的交易同样会被静默拦截。你可以遍历所有指令的keys数组去重后计数,超过64就会触发规则。 - 第三优先级:修正web3.js发送配置吞错问题
你使用的@solana/web3.js@1.44.1存在默认配置缺陷:调用sendRawTransaction()时默认预检查宽松,且不会透传节点返回的拦截报错,只会返回本地计算的txid,让调用方误以为交易已广播。发送时调整配置即可拿到明确的错误提示:const txSig = await connection.sendRawTransaction(rawTransaction, { skipPreflight: false, // 必须关,否则预检查报错全被吞 preflightCommitment: 'confirmed', maxRetries: 0 // 触发硬拦截的交易重试无意义,先关了排查问题 });
修复方案
- 临时修复:将超限制的交易拆分为多笔发送,或合并指令内重复声明的关联账户,预留30字节左右的体积冗余(防止最近区块哈希变动带来的序列化体积波动),把单交易字节控制在1200字节以内即可正常上链。
- 长期修复:将
@solana/web3.js升级至1.73及以上版本,新版本在本地序列化阶段就会校验交易体积、账户数限制,超限直接本地抛错,不会出现交易发出去石沉大海的问题。
提示:触发硬规则拦截的交易无论重试多少次、换多少个RPC节点都不会上链,不要靠堆重试次数排查,纯浪费请求额度。
内容的提问来源于stack exchange,提问作者Alfonso Gomez Jordana Manas
相关产品推荐
相关产品推荐

