基于区块链的 Dapp 开发笔记(1)-如何解决以太坊中的 nounce 冲突问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
duimi
V2EX    程序员

基于区块链的 Dapp 开发笔记(1)-如何解决以太坊中的 nounce 冲突问题

  •  
  •   duimi 2018-06-25 11:15:27 +08:00 4511 次点击
    这是一个创建于 2680 天前的主题,其中的信息可能已经有所发展或是发生改变。

    基于区块链的 Dapp 开发笔记( 1 )

    如何解决以太坊中的 nounce 冲突问题

    近期我们做了一个小的基于以太坊的 DAPP-告白世界,一共 4 个独立页面(见下图),其中主要是将告白信息上链,来做到对告白信息永久保存。

    P98TEt.th.jpg P98H4f.th.jpg P987UP.th.jpg P98IHI.th.jpg

    这个 DAPP 我们使用了 web3js。我们并没有设置自己以太坊全节点,所以使用使用了 infura 提供的 HttpProvider。

    const web3 = new Web3( https://mainnet.infura.io/<infuraAccessToken>) 

    由于 infura 并没有提供 private key 的存储,所以默认的 HttpProvider 并不能发起交易,只能进行查询操作。要进行交易有两个选择,第一是使用一个能保存 private key 并签名交易的 provider,比如 truffle-hdwallet-provider。 但是这个 provider 要求我们将助记词传递给它。

    var HDWalletProvider = require("truffle-hdwallet-provider"); var provider = new HDWalletProvider(mnemonic, "https://mainnet.infura.io/<infuraAccessToken>"); 

    这样做一方面感觉不太放心,另外一方面也不够灵活。所以我们采用了第二个办法,自己签名交易并发送。

    自己签名交易的时候必须填写每个交易的 nonce 值。 由于以太坊设计的技术特点,要求从同一个账号产生的每个交易都有一个不同的 nonce,对交易进行区分。这个 nonce 并不是随意选择的,而是必须从 0 开始递增。而且每个被以太坊网络记录的交易的 nonce 都必须比该账号产生的前一个交易大 1。

    听起来很简单,同时,web3 也提供了一个接口,getTransactionCount 让我们查询一个特定账号在网络中已经确认了多少笔交易。所以一个最简单的产生 nonce 的策略就是使用 getTransactionCount() 的返回值。

    async function sendTransaction(data, account) { data.nOnce= web.eth.getTransactionCount(account); await signAndSend(data); } 

    不幸的是,以太网是一个弱一致性分布式系统。这里面有太多的不确定性。 试想,由于以太坊网络确认一笔交易需要数分钟的时间。如果在一个很短的时间内(比如 10 秒之内)我们产生了两笔交易,我们连续调用了两次 getTransactionCount() 来产生两个 nonce。我们会惊奇的发现两个 nonce 会是完全一样,因为系统根本还没有来得及确认上一笔交易。那么我们广播出去的这两笔交易,最终只会有一笔得到确认。

    P9GK56.md.png

    所以我们改进一下策略,如果我们在自己的服务器上记录 nonce,每签名一次交易就增加一次怎么样?

    var nOnce= 0; async function initializeNonce() { nOnce= await web3.eth.getTransactionCount(account); } function sendTransaction(data) { data.nOnce= nonce; nonce += 1; await signAndSend(data); } 

    在一个分布式网络中,即使不考虑本地出错的可能性,网络传输随时都可能产生错误。设想我们签名好一个交易,并且发送出去,然后增加 nonce 等待下一次签名。在这个时候,如果刚刚送处去的那个交易失败了怎么办?比如 transaction fail 或者 gas 太低直接被系统丢弃了怎么办?如果我们继续增加 nonce,由于 nonce 的不连续会导致后面的交易都得不到处理。

    在刚才改进的策略之上,我们的解决方式是不停的监听所有没有被确认的交易,如果超过一定的时间(比如 15 分钟)交易都没有得到确认。该交易对应的 nonce 会被重新使用来发送下一个交易。 在网络中查询一个交易是否得到确认可以使用getTransactionReceipt()方法。

    solution

    最后,对我们的小玩具感兴趣的,可以用微信扫描二维码来尝试一下:

    P9GQPK.jpg

    最后,欢迎对开发 DAPP 感兴趣的开发者们来关注我们的 github ( https://github.com/rrtoken/DAPP_Blog ), 接下来我们的心得会在这里总结。

    12 条回复    2020-01-02 15:35:13 +08:00
    epicnoob
        1
    epicnoob  
       2018-06-25 11:30:25 +08:00
    1.积累几条交易,同时发送,每次 nonce+1
    2.使用多个地址,每次选取其中之一广播交易。
    epicnoob
        2
    epicnoob  
       2018-06-25 11:31:12 +08:00
    3.提升 gas,增加处理速度
    chy373180
        3
    chy373180  
       2018-06-25 13:04:52 +08:00
    1 楼正解
    duimi
        4
    duimi  
    OP
    2018-06-25 13:16:06 +08:00
    @epicnoob 谢谢提议,我们的想法如下:

    1 )我们觉得第一点建议有价值,也有问题:
    积累几条消息,同时发送,那么就是要等待。人家消息来了不能立即发送,同时会遇到一样的情况,你并不知道发送成功了没有。
    2 )第二点的话比较麻烦,本来你要管理一个账号的 nonce,现在要管理好几个账号的 nonce。不会是一个简单的解决方案。
    3 )哈哈,有钱的确怎么样都行:)
    phpcxy
        5
    phpcxy  
       2018-06-25 13:29:08 +08:00
    getTransactionCount 我取"pending"的记录,不知有没有问题?
    duimi
        6
    duimi  
    OP
       2018-06-25 13:36:08 +08:00
    @phpcxy 会好一些的, 然而不能完全解决。因为这个 pending 记录并不准确。
    duimi
        7
    duimi  
    OP
       2018-06-25 13:36:28 +08:00
    @phpcxy pending 表示即将被 confirm 的交易,但是这都取决于下一个出块者。
    leyle
        8
    leyle  
       2018-06-25 16:27:52 +08:00
    现在推广都要这样了,我猜这个 ( 1 ) 就是绝唱了。
    mingyun
        9
    mingyun  
       2018-06-25 22:26:57 +08:00
    还以为 https://github.com/rrtoken/DAPP_Blog 是源码 分享学习下
    duimi
        10
    duimi  
    OP
       2018-06-25 22:47:36 +08:00
    @mingyun 哈哈,是文章内容,觉得 github 好用。
    duimi
        11
    duimi  
    OP
       2018-06-25 22:47:56 +08:00
    @leyle ( 2 )已经有了一部分了:)
    iamfirst
        12
    iamfirst  
       2020-01-02 15:35:13 +08:00
    @duimi 积累几条交易,同时发送。再加一个超时机制,检查已经有累积的交易,并且等待时间超过指定的时间,一并发出去
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2488 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 10:39 PVG 18:39 LAX 03:39 JFK 06:39
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86