使用w3.eth.sendSignedTransaction提交交易后区块哈希为0x0000...的问题
已提交签名交易但区块哈希显示为0x0000...的原因分析
先梳理下你的场景:你用w3.eth.sendSignedTransaction提交了一笔签名交易,Geth日志已经显示交易被提交:
INFO [05-24|12:01:44] Submitted transaction fullhash=0xd6ad180c709ce93f5884070f28488925e9b944a24fc6ab737c79d8e66dfd9dca recipient=0xF06c0a4A9fafddA7b8B25F986e1C0dfEC62e1E84
但查询交易时发现区块哈希是0x0000...,你的提交代码如下:
w3.eth.sendSignedTransaction( data ) .once( 'transactionHash', (hash) => { console.log(hash) }) .on('receipt', (receipt) => { console.log('receipt'); }) .on('confirmation', (confirmationNumber, receipt) => { console.log('confirmation'); }) .on('error', (err) => { console.log(err); }) .then( (receipt) => { console.log('finally got the receipt!'); }) .catch(e => { console.log('err'); })
下面来分析可能的原因,以及对应的排查方向:
可能的问题原因
- 交易还在内存池等待打包:Geth里的
Submitted transaction日志只是告诉你,交易已经成功进入节点的内存池(mempool),但矿工还没把它打包进区块。这种情况下交易处于待确认状态,blockHash自然是0x0000...。你可以耐心等一会儿,或者用w3.eth.getTransaction(你的交易哈希)定期查询交易状态,看看blockHash是否更新。 - 交易被内存池拒绝或丢弃:如果你的交易gas价格设置得太低,远低于当前网络的最低gas费门槛,或者nonce值有问题(比如重复使用了同一个nonce、nonce顺序不对),矿工根本不会优先打包它,甚至会被内存池清理掉。这种情况交易永远不会被打包,
blockHash会一直是空的。你可以检查交易的gasPrice/gasLimit设置,以及nonce是否正确。 - 节点同步不完整:如果你用来查询交易的节点还在同步区块,没有跟上最新的链状态,可能会出现查询不到交易区块信息的情况。你可以用
w3.eth.syncing查看节点是否在同步,或者换一个已经同步完成的节点重试查询。 - 交易潜在执行失败:有些交易虽然进入了内存池,但实际执行时会失败(比如账户余额不足、合约调用参数错误),但在矿工尝试打包前不会触发错误回调。这种情况交易还是会处于待打包状态,
blockHash为空,直到矿工打包时发现执行失败,交易可能会被退回。
针对你的代码的优化建议
你的代码已经监听了receipt和confirmation事件,这两个事件只有在交易被成功打包进区块后才会触发。如果一直没收到这些事件,大概率是交易没被打包:
- 可以在
transactionHash事件触发后,增加一个定时查询逻辑,用w3.eth.getTransaction(hash)检查交易状态,同时也能查看gasPrice是否符合当前网络的要求。 - 确认nonce的正确性:同一个账户的多笔交易,nonce必须严格按顺序递增,不能重复也不能跳跃。你可以用
w3.eth.getTransactionCount(你的账户地址)获取当前账户的下一个可用nonce,确保交易使用的nonce是正确的。 - 调整gas设置:用
w3.eth.gasPrice获取当前网络的平均gas价格,然后把交易的gasPrice设置得稍高一点,提升交易被矿工打包的优先级。
内容的提问来源于stack exchange,提问作者1110
相关产品推荐
相关产品推荐

