以太坊nonce详解

1. nonce 是什么?

A scalar value equal to the number of transactions sent from this address or, in the case of accounts with associated code, the number of contract-creations made by this account. – 以太坊黄皮书

以太坊所有的交易都是基于 account ,不同于基于 utxo 的比特币,因此需要对每次交易都按顺序记录,nonce值就是这个顺序,nonce 是交易原始地址的属性。它不存储在以太坊区块链上,而是通过计算从一个地址发送的交易数量来计。

nonce +1

每发起一笔交易,nonce就会加一。对于发起的解释:

  • 1.外部账户(EOA)每发送一笔交易;
  • 2.合约账户(Contract Wallet) 每创建一个合约

而转入交易、合约调用其他合约等属于内部调用,因此 nonce 值不变。

作用 1:交易顺序

假设您要发送两个值为 1 和 4 ETH 的交易,并希望它们被顺序打包。发送一笔交易后,你继续发送第二笔交易。

现在如果没有随机数,矿工将不可能知道您维护交易顺序的意图。

如果您的第一笔交易(1 ETH)的 nonce 为0(假设是新帐户),那么 4 ETH交易的 nonce 为 1。矿工即可按照 nonce 的顺序打包交易。

作用 2:防止重放攻击

假如转账时,没有 nonce,参数如下:

{ 
    "gasPrice":"10000000000", 
    "to":"0xf4587a39edbb10b32952bcd656ba489f1a857450,
    " value":" 10000000000000000000“, // 10 ETH
    " data":"",
    " v,r,s":"您的ECDSA签名的某些字节"
}

交易被序列化后(交易字符串转换为byte),例如:

25de0d5a1693d4e45ce0305d42774b5bf73cbd9e14230194c35545e0f01ee45ce0305d42774b5bf73cbd9e0d5a1693d4e45ce0305d427

该交易被打包后,对方将收到 10 ETH,但是任何人都可以看到这笔交易,然后复制粘贴,重复提交给以太坊的网络,耗尽你的余额,也就是所谓的重放攻击。

如果有交易中包含 nonce,则同一 nonce 的交易只能被打包一次。

2.如何使用 nonce?

下图为交易被打包的过程:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fDRviZ3B-1624539141545)(https://z3.ax1x.com/2021/06/24/RQ3MUs.png)]

以太坊内部有 txpool,即存放交易的池子。钱包或节点发生的交易会被加入到交易池里,在打包区块的时候,就从这个池子里提取,区块产生之后,共识区块,交易上链。所以交易会有 pending 的状态,或者被交易池丢弃。

发起转账或者创建合约的时候,通过 web3 从以太坊网络查询当前的 nonce 值,使用此值作为当前交易的 nonce 值,发送到以太坊网络即可。

发送交易 eth_sendTransaction

Creates new message call transaction or a contract creation, if the data field contains code.

需要传参数 nonce,官方文档对于 nonce 的说明

nonce: QUANTITY - (optional) Integer of a nonce. This allows to overwrite your own pending transactions that use the same nonce.

获取 nonce 获取 nonce

参数:

params: [
   address,
   QUANTITY  // latest, pending
]

demo


//请求:
curl -s -H Content-Type:application/json -X POST --data '{"jsonrpc":"2.0","method":"eth_getTransactionCount","params":["0xf4587a39edbb10b32952bcd656ba489f1a857450","pending"],"id":1}' http://127.0.0.1:8545

//返回:
{"jsonrpc":"2.0","id":1,"result":"0x351"}

//参数解释
第一个参数为需检查余额的地址
第二个参数为整数区块号,或者是字符串“latest","earliest"以及"pending"指代某个特殊的区块。
(latest:最新被挖矿的区块  earliest:最早区块  pending:挂起状态/交易 )

结果:

image

实际账户有 849 笔转出交易,最后一笔交易的 nonce 是 848。请注意 nonce 计数从 0 开始,所以如果你想继续发送交易,则直接使用 5 作为下一笔交易的 nonce 。

如果有处于 pending 状态的交易,即矿工未打包的交易,此时去读取 nonce,需要更换参数为 pending,否则将不能获得正确计数。没有区块确认数的交易可以被 ‘取消’ 或者被加速。

如果交易被打包,即非 pending 状态,则是不可逆的,就无法取消啦!

3.加速和取消以太坊的交易

Integer of a nonce. This allows to overwrite your own pending transactions that use the same nonce

基于 nonce 的特性,自增和唯一性,使用相同的 nonce 重新发起交易即可实现加速。

加速以太坊交易案例

  1. 假设有笔交易 A:gas price = 5,nonce = 1 ,由于 gas price 太低,广播后,交易一直处于 pending 状态。
  2. 创建交易 B,调整 gas price 为更合理的水平,例如 10、20 ,nonce = 1 ,再次发布交易。矿工就会选择 price 更高的交易 A 打包。
  3. 此时在矿工的交易池端,B 交易被打包了,矿工会检查 A 交易,发现 nonce 已经存在了,认为 A 是不合理的交易,则会自动丢弃该交易

取消交易

  1. 基于加速交易的案例。
  2. 创建交易 B,设置 value =0 ,收款方=发送方,设置更高的 gas price ,广播交易
  3. 原来的交易被丢弃了,新交易会被矿工打包,不会丢失任何资金。但是你还是需要为 B 交易付出矿工费

具体加速和取消以太坊交易的处理方式可参考:https://blog.csdn.net/cljdsc/article/details/116275499

4.异常处理

replacement transaction underpriced

原因

  1. 帐户中有待处理的待处理 pending 交易;
  2. 新交易和 pending 的交易 nonce 相同;
  3. 新交易的 gas price 更低,无法替换待处理的交易

image

5. nonce 使用的几条规则

  1. 当nonce太小(小于当前的nonce值),交易会被直接拒绝,Transactions with too low a nonce get immediately rejected;(nonce too low)
  2. 当 nonce 太大,大于当前 nonce,交易会一直处于队列之中,Transactions with too high a nonce get placed in the transaction pool queue;(nonce too high)
  3. 当发送一个比较大的nonce值,然后补齐开始 nonce 到那个值之间的nonce,那么交易依旧可以被执行,If transactions with nonces that fill the gap between the last valid nonce and the too high nonce are sent and the nonce sequence is complete, all the transactions in the sequence will get processed and mined.
  4. 交易队列只保存最多64个从同一个账户发出的交易,也就是说,如果要批量转账,同一节点不要发出超过64笔交易。 The transaction pool queue will only hold a maximum of 64 transactions with the same From:address with nonces out of sequence.
  5. 当某节点 queue 中还有交易,但此时停止 geth 客户端,queue 中的交易会被清除掉,When the geth instances are shut down and restarted, transactions in the transaction pool queue disappear.
  6. 当前 nonce 合适,但是账户余额不足时,会被以太坊拒绝;

6.参考资料

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
Python以太坊交易是指使用Python编程语言进行以太坊区块链上的交易操作。以太坊是一种基于区块链技术的智能合约平台,它允许开发者构建和部署去中心化应用程序(DApps)。 在Python中,可以使用以太坊的官方库web3.py来进行以太坊交易的编程操作。web3.py提供了一系列的API,可以与以太坊节点进行通信,并执行各种操作,包括创建账户、发送交易、查询余额等。 以下是一个简单的Python代码示例,展示了如何使用web3.py库发送以太坊交易: ```python from web3 import Web3 # 连接到以太坊节点 w3 = Web3(Web3.HTTPProvider('https://mainnet.infura.io/v3/your_infura_project_id')) # 设置发送方账户私钥和接收方地址 private_key = 'your_private_key' receiver_address = '0x1234567890abcdef1234567890abcdef12345678' # 构建交易参数 transaction = { 'to': receiver_address, 'value': w3.toWei(1, 'ether'), 'gas': 21000, 'gasPrice': w3.toWei('50', 'gwei'), 'nonce': w3.eth.getTransactionCount(w3.eth.accounts), } # 签名交易 signed_transaction = w3.eth.account.signTransaction(transaction, private_key) # 发送交易 transaction_hash = w3.eth.sendRawTransaction(signed_transaction.rawTransaction) # 等待交易确认 transaction_receipt = w3.eth.waitForTransactionReceipt(transaction_hash) # 打印交易结果 print('交易成功,交易哈希:', transaction_receipt.transactionHash.hex()) ``` 上述代码中,首先使用`Web3`类连接到以太坊节点。然后设置发送方账户的私钥和接收方地址。接下来,构建交易参数,包括接收方地址、转账金额、燃气限制、燃气价格和交易序号。然后使用发送方账户的私钥对交易进行签名,并发送签名后的交易到以太坊网络。最后,等待交易被确认,并打印交易结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杰哥的技术杂货铺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值