关于以太坊账户(外部账户&合约账户)的nonce值

本文介绍了Nonce值的概念及其在基于账户的区块链系统中的作用。Nonce值用于防止重放攻击,并且随着外部账户交易或合约账户创建而递增。文章还讨论了Nonce值在不同场景下的使用规则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

nonce值的存在主要是因为它是基于account的,不同于基于utxo的比特币。nonce值主要用来防止重放攻击。

  1. 外部账户每发送一笔交易nonce加一。
  2. 合约账户每创建一个合约nonce加一。而合约调用其他合约属于内部调用,因此nonce值不变。(A nonce of a contract is only incremented when that contract creates another contract. When a contract invokes a function on another contract, a so called “internal transaction” , the nonce is not incremented.)

nonce使用的几条规则

  1. 当nonce太小(小于之前已经有交易使用的nonce值),交易会被直接拒绝。
  2. 当nonce太大,交易会一直处于队列之中,这也就是导致我们上面描述的问题的原因;
  3. 当发送一个比较大的nonce值,然后补齐开始nonce到那个值之间的nonce,那么交易依旧可以被执行。
  4. 当交易处于queue中时停止geth客户端,那么交易queue中的交易会被清除掉。

更深的理解

### Go语言实现智能合约账户管理 在Go语言环境中管理和操作智能合约账户涉及到几个方面的工作,包括但不限于初始化账户、查询账户余额以及执行交易等。下面将详细介绍这些功能。 #### 初始化并连接至区块链网络 为了与基于以太坊或其他兼容EVM(以太坊虚拟机)的区块链上的智能合约互动,在Go程序中通常会利用`ethereum/go-ethereum`库来建立RPC客户端实例[^1]: ```go package main import ( "context" "fmt" "log" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" ) func initClient() *ethclient.Client { client, err := ethclient.Dial("https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID") if err != nil { log.Fatalf("Failed to connect to the Ethereum client: %v", err) } return client } ``` 此代码片段展示了如何通过Infura服务提供的公共API端点创建一个新的ETH客户端对象用于后续的操作。 #### 创建新账户 对于生成新的加密货币钱包地址而言,可以通过调用`crypto.GenerateKey()`函数轻松完成这一过程,并从中提取公钥和私钥信息[^4]: ```go // Generate a new account key pair. key, _ := crypto.GenerateKey() address := crypto.PubkeyToAddress(key.PublicKey).Hex() privateKey := fmt.Sprintf("%x", crypto.FromECDSA(key)) fmt.Printf("New Account Created:\n Address=%s\n Private Key=%s\n", address, privateKey) ``` 这段脚本负责生产一对随机密钥对,并将其转换为十六进制字符串形式展示给用户作为公开可见的钱包地址及其对应的私有秘钥材料。 #### 查询账户余额 一旦拥有了有效的账户地址之后就可以向远程节点请求该账号当前持有的资产数量了。这里采用的是异步的方式发送HTTP JSON-RPC请求获取最新区块高度下的特定账户余额情况: ```go balance, err := client.BalanceAt(context.Background(), common.HexToAddress(address), nil) if err != nil { log.Fatal(err) } fmt.Println(balance.String()) ``` 上述例子说明了怎样借助于之前定义好的客户端去检索指定位置处所含有的Ether数目,并最终打印出来供开发者查阅。 #### 执行转账交易 当需要发起一笔支付指令时,则需构建一个包含必要参数的对象——Transaction,再经由签名机制附加必要的验证资料后提交给目标网络等待确认处理完毕即可: ```go nonce, err := client.PendingNonceAt(context.Background(), senderAddress) if err != nil { log.Fatal(err) } value := big.NewInt(1e18) // 1 Ether gasLimit := uint64(21000) // Simple transfer of ETH between accounts gasPrice, err := client.SuggestGasPrice(context.Background()) if err != nil { log.Fatal(err) } tx := types.NewTransaction(nonce, recipientAddress, value, gasLimit, gasPrice, nil) chainID, err := client.NetworkID(context.Background()) if err != nil { log.Fatal(err) } signedTx, err := types.SignTx(tx, types.NewEIP155Signer(chainID), privateKey) if err != nil { log.Fatal(err) } err = client.SendTransaction(context.Background(), signedTx) if err != nil { log.Fatal(err) } fmt.Printf("Sent transaction with hash: %s\n", signedTx.Hash().Hex()) ``` 以上示例实现了从发送方到接收者的简单转账流程,涵盖了设置交易详情、计算手续费价格、签署消息以及广播出去等一系列动作。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值