以太坊中的两个nonce值

以太坊中的两个nonce

第一个nonce:每一个区块有一个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"`
}

【Block】中有个【Header】,【Header】最后一行的nonce,就是挖矿的随机数。
区块上的nonce是一个无意义的随机数,用于工作量证明,与挖矿的难度有关。
矿工要想成功挖出一个区块,必须不停的穷举随机数nonce,直到通过哈希算法得到的区块hash值小于或等于目标值target,目标值越低,发现随机数需要的时间越多,难度值越高。

第二个nonce,每一个账户的每笔交易有一个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{}
}

// Transactions is a Transaction slice type for basic sorting.
type Transactions []*Transaction

type Transaction struct {
	data txdata
	// caches
	hash atomic.Value
	size atomic.Value
	from atomic.Value
}

type txdata struct {
	AccountNonce uint64          `json:"nonce"    gencodec:"required"`
	Price        *big.Int        `json:"gasPrice" gencodec:"required"`
	GasLimit     uint64          `json:"gas"      gencodec:"required"`
	Recipient    *common.Address `json:"to"       rlp:"nil"` // nil means contract creation
	Amount       *big.Int        `json:"value"    gencodec:"required"`
	Payload      []byte          `json:"input"    gencodec:"required"`

	// Signature values
	V *big.Int `json:"v" gencodec:"required"`
	R *big.Int `json:"r" gencodec:"required"`
	S *big.Int `json:"s" gencodec:"required"`

	// This is only used when marshaling to JSON.
	Hash *common.Hash `json:"hash" rlp:"-"`
}

每一个【Block】中都有很多个【Transaction】,而【Transaction】中的【txdata】就是每一笔交易,每一笔交易都有一个【AccountNonce】,用于解决双花问题,即防止多重交易。

为了防止多重交易,以太坊节点要求每笔交易必须有一个nonce数值。每一个账户从同一个节点发起交易时,这个nonce值从0开始计数,每发送一笔交易nonce值加1。只有当前面nonce值较小的交易处理完成之后才会处理后面nonce值较大的交易。
注意【相同的地址在相同的节点发送交易】。
nonce使用的规则

  1. 当nonce太小(小于之前已有交易的nonce值),交易会被直接拒绝。
  2. 当nonce太大,交易会一直处于队列之中,长久得不到执行。
  3. 当发送一个比较大的nonce值,然后补齐开始的nonce到那个nonce之间的nonce,那么交易依旧可以被执行。
  4. 当交易处于队列中时,停止geth客户端,那么交易队列中的交易会被清除。
  5. 当有一笔处于pending状态的交易,新的一笔交易与其拥有相同的nonce值,如果新交易的gas price太小,无法覆盖pending状态的交易,如果新交易的gas price高于原交易的110%,则原交易会被覆盖掉。
  6. 交易队列只保存最多64个从同一个账户发出的交易,The transaction pool queue will only hold a maximum of 64 transactions with the same From:address with nonces out of sequence. 也就是说,如果要批量转账,同一节点不要发出超过64笔交易。
  7. 当前nonce合适,但是账户余额不足时,会被以太坊拒绝;
  8. 如果发起一笔交易,但是因为gwei比较低或者网络比较忙的时候,该交易还没矿工挖出,可以通过使用相同的nonce和较高的gas费用,从而“覆盖”前一笔交易。
在以太坊客户端geth中连续转账两笔,查看nonce
> eth.getTransaction("0xd6f23949a9cf1a7589bb7eb7b02b16f78b8a29ddbdddf0e3722c147bbfbd9301")
{
  blockHash: "0x5264afd8c81cb239cdf3f776371b00e79b688c7c00ce38cfb95664674179cc38",
  blockNumber: 4443,
  from: "0x59d2ee00982934e28ee74e292e2fc4da4a8a5bd1",
  gas: 90000,
  gasPrice: 18000000000,
  hash: "0xd6f23949a9cf1a7589bb7eb7b02b16f78b8a29ddbdddf0e3722c147bbfbd9301",
  input: "0x",
  nonce: 0,
  r: "0xcf8825845603f51c42e928243ed8174e86472046d55e94a3f3a6e65e1bb33007",
  s: "0x4abe05a3d869c0f67c9c1f0fa35d860c7c75c61f6388fa1a44b37e8f7f8a49af",
  to: "0xa0ba1d045f45eccfc1989615d22727d2124299e9",
  transactionIndex: 0,
  v: "0x38",
  value: 12345000
}
> eth.getTransaction("0x4a7d0a5075939db5d3e9c4539a206d22e63adaf1993521f3cdcca0dc287b39ff")
{
  blockHash: "0x186269bafa7ef5918a81dbbf731ad7e4609798bd3d9b34be4b329aa57ec7e279",
  blockNumber: 4455,
  from: "0x59d2ee00982934e28ee74e292e2fc4da4a8a5bd1",
  gas: 90000,
  gasPrice: 18000000000,
  hash: "0x4a7d0a5075939db5d3e9c4539a206d22e63adaf1993521f3cdcca0dc287b39ff",
  input: "0x",
  nonce: 1,
  r: "0x2018b43c281a895c34d2c99081e7ec1137625fdf01f9c396515a36469f2079bb",
  s: "0x45a27df14d531ca421529702cf76066e47e0d350209e8603337f3b56de2ac21a",
  to: "0xa0ba1d045f45eccfc1989615d22727d2124299e9",
  transactionIndex: 0,
  v: "0x38",
  value: 15000000000000000000
}
> 

根据交易id,即交易hash查看交易eth.getTransaction,会看到第一笔转账的nonce是0,第二笔是1。

参考文章

以太坊实战之《如何正确处理nonce》
以太坊实战|再谈nonce使用陷阱
以太坊nonce详解
以太坊rpc接口调用之nonce
转账以太币ETH
区块hash,随机数nonce,目标值target,难度值difficulty
以太坊入门(一)账户和nonce的关系
精通以太坊之nonce值,真的能避免51%攻击吗||技术贴
[以太坊源码]3.Block结构
关于nonce你应该知道的一些事
以太坊nonce值问题分析

猜你喜欢

转载自blog.csdn.net/Charliewolf/article/details/87158602
今日推荐