目录
前言
以太坊中的主要有2类nonce,一类是和矿工比较密切的区块nonce,即挖矿时使用;另一类和普通使用提交提交的关系比较密切的用户事务nonce。
用户事务nonce
- 为了防⽌交易重播,ETH节点要求每笔交易必须有⼀个nonce数值。每⼀个账户从同⼀个节点发起交易时,这个nonce值从0开始计数,发送⼀笔nonce对应加1。当前⾯的nonce处理完成之后才会处理后⾯的nonce。集群环境下,不同节点共同维护同⼀个⽤户的nonce值。
- txpool中由两部分构成pending和queued组成,⼀个为待打包状态,⼀个为队列中。如果传⼊的nonce就是某⽤户下笔交易应该传⼊的nonce,那么该笔交易就会放置在pending中,等待节点打包。其次,如果传⼊的nonce值过⼤,在进⼊txpool中检查到它之前的nonce并没有使⽤过,那么此笔交易不会发送到pending中,⽽且放置在queued中。只有当前⾯的nonce补齐之后,才会进⼊到pending中。
从一个集群的AB节点试验说起。
- 集群环境下,写⼊节点A的pending交易会⼴播到节点B中,因nonce问题写⼊节点A的queued交易,不会被⼴播。
- 集群环境下,节点B连上节点A(admin.addPeer(节点A)),节点A停掉的情况下再次启动,会很快恢复集群,但是如果是节点B停掉的情况下,却不会再次恢复集群,只能重新连接节点,才能恢复集群B。
1、发送⼀笔nonce为0的交易给节点A,会返回交易hash,并能在节点A的txpool中pending看到,因为⼴播⾜够快,节点B中也能看到。
2、再次发送nonce为0的交易(交易⾦额和gas price等全部保持不变)给节点A,响应code=-32000,表明并没有提交成功。
5、我们为了测试提交到queued的交易,继续发送nonce为2(跳过1)的交易到节点A中,会被提交进去,并且可以拿到交易hash,只是交易会被放⼊queued中,并且不会被⼴播到节点B。
6、再次发送nonce为2(跳过1)的交易到节点A中,提交不进去该笔交易。
7、因为节点B的queued并不会去同步节点A之前提交的nonce为2的交易,我们再次把同样的交易提交给节点B,我们可以看到该笔交易可以被提交进去,但交易hash和节点A中相应的是⼀模⼀样的,也就是说我们依然认为是同⼀笔交易。
9、在我们补齐nonce为1的交易后,我们观察到节点A和节点B的queued虽然都维护着nonce为3的交易(hash不同), 但最终进⼊pending中会是gas price价格⾼的交易,⾄此两个节点⼜保持⼀致。结论是gas price价格⾼的会被加⼊到pending中。
某⽤户的区块链提交的交易nonce已经到10了,但依然提交⼀笔交易nonce为10的交易, 如果不改变之前交易的任何信息继续提交(两笔交易的hash是⼀样的),会提示错误,code=-32000。如果改变交易⾦额提交(交易hash不⼀样),也会提示错误,code=-32000。
总结
区块nonce
具体的数据结构:
// Block represents an entire block in the Ethereum blockchain. type Block struct { header *Header uncles []*Header transactions Transactions // caches hash atomic.Value size atomic.Value // Td is used by package core to store the total difficulty // of the chain up to and including the block. td *big.Int // These fields are used by package eth to track // inter-peer block relay. ReceivedAt time.Time ReceivedFrom interface{} } // Header represents a block header in the Ethereum blockchain. type Header struct { ParentHash common.Hash `json:"parentHash" gencodec:"required"` UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"` Coinbase common.Address `json:"miner" gencodec:"required"` Root common.Hash `json:"stateRoot" gencodec:"required"` TxHash common.Hash `json:"transactionsRoot" gencodec:"required"` ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"` Bloom Bloom `json:"logsBloom" gencodec:"required"` Difficulty *big.Int `json:"difficulty" gencodec:"required"` Number *big.Int `json:"number" gencodec:"required"` GasLimit uint64 `json:"gasLimit" gencodec:"required"` GasUsed uint64 `json:"gasUsed" gencodec:"required"` Time *big.Int `json:"timestamp" gencodec:"required"` Extra []byte `json:"extraData" gencodec:"required"` MixDigest common.Hash `json:"mixHash" gencodec:"required"` Nonce BlockNonce `json:"nonce" gencodec:"required"` }
参考
https://wenku.baidu.com/view/c5440a5702f69e3143323968011ca300a6c3f63b.html
以太坊中的两个nonce值_Elonjelinek的博客-CSDN博客
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/231260.html原文链接:https://javaforall.net
