12. sendTransaction和sendRawTransaction区别

一. 系列视频
二. 系列文章

1. Remix编写、编译、部署、测试Solidity ERC20合约 - 基础篇
2. Remix编写、编译、部署、测试Solidity ERC20合约 - 进阶篇
3. Hardhat编写、编译、部署、测试Solidity ERC20合约 - 基础篇
4. JSON-RPC调用区块链方法
5. JSON-RPC调用合约方法
6. JSON-RPC给合约账户同时转以太币和代币
7. web3.js调用区块链方法
8. web3.js调用合约方法
9. web3.js给合约账户同时转以太币和代币
10. Go-Ethereum调用区块链方法
11. Go-Ethereum调用合约方法
12. sendTransaction和sendRawTransaction区别
13. Metamask导入代币,转账ETH,转账代币 - 界面操作
14. Metamask连接hardhat本地节点
15. DAPP react界面-web3.js库-Metemask调用和显示-调用合约方法
16. web3js结合sepolia测试网
17. 总结

1. 环境配置和合约代码

参考文章12. Hardhat编写、编译、部署、测试Solidity ERC20合约 - 进阶篇 - Metamask导入代币,转账ETH,转账代币
GoLand 2025.2.4版本
go 1.25.4

2. 编写调试代码

可连接hardhat node本地网络和sepolia测试网络
为了突出业务逻辑,省略了错误处理。
在这里插入图片描述

2.1 hardhat node同以太坊主网、sepolia测试网络区别

hardhat node可以使用sendTransaction方法通信,会初始化10个持有私钥的账户。
以太坊主网、sepolia测试网络等不持有账户私钥,不支持sendTransaction方法通信。
hardhat node、以太坊主网、sepolia测试网络等都支持sendRawTransaction方法通信。

在这里插入图片描述

2.2 sendTransaction和sendRawTransaction区别

2.2.1 sendTransaction

在这里插入图片描述

sendTransaction方式。
发送原始JSON-RPC结构,以太坊接收节点持有私钥,对原始JSON-RPC结构进行签名。然后将签名后的数据广播到其他节点。

func (this *Geth) sendTransaction() {
	// 获取底层的 rpc.Client
	rpcClient := this.ethe.Client()

	// 发送交易
	tx := map[string]interface{}{
		"from":  fromAddress,
		"to":    toAddress,
		"value": valueETH, // 0.1 ETH
	}

	var txHash common.Hash
	_ = rpcClient.Call(&txHash, "eth_sendTransaction", tx)
}

调试代码,看到Go-Ethereum框架底层构建JSON-RPC结构,params字段是原始交易对象

在这里插入图片描述

2.2.2 sendRawTransaction

在这里插入图片描述

sendRawTransaction方式
发送私钥签名后的数据,以太坊节点收到后,将签名后的数据广播到其他节点。

// 区块链交易。hardhat node或sepolia,交易结构中的参数都需要,底层调用eth_sendRawTransaction,需要Nonce,需要私钥签名,不需要from。从私钥推导出账户地址
// web3.js web3.eth.sendTransaction底层调用eth_sendTransaction,节点自动填充Nonce和from。hardhat node不验证私钥签名,用默认第一个账户。但sepolia需要私钥签名,从私钥推导出账户地址
func (this *Geth) sendRawTransaction(toAddress common.Address, valueETH *big.Int, privateKey string) {
	// 解析私钥
	privateKey_, _ := crypto.HexToECDSA(privateKey[2:])
	// 获取公钥
	publicKey := privateKey_.Public()
	// 账户地址
	fromAddress := crypto.PubkeyToAddress(*publicKey.(*ecdsa.PublicKey))

	nonce, _ := this.ethe.PendingNonceAt(context.Background(), fromAddress)
	gasPrice, _ := this.ethe.SuggestGasPrice(context.Background())

	// 创建交易
	tx := types.NewTx(&types.LegacyTx{
		Nonce:    nonce,
		To:       &toAddress,
		Value:    valueETH,
		GasPrice: gasPrice,
		Gas:      21000,
	})

	chainID, _ := this.ethe.NetworkID(context.Background())
	// 签名
	signedTx, _ := types.SignTx(tx, types.NewEIP155Signer(chainID), privateKey_)
	// 发送交易
	_ = this.ethe.SendTransaction(context.Background(), signedTx)

	// 带超时的上下文
	waitCtx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
	defer cancel()
	// 等待挖矿成功
	_, _ = bind.WaitMined(waitCtx, this.ethe, signedTx)
}

调试代码,看到Go-Ethereum框架底层构建JSON-RPC结构,params字段是私钥签名后的数据

在这里插入图片描述

需要传入转账接收地址toAddress,转账金额valueETH,私钥privateKey。其中privateKey可以获得v,r,s。其他参数可以通过接口获得。
{
	Nonce:    nonce,
	To:       &toAddress,
	Value:    valueETH,
	GasPrice: gasPrice,
	Gas:      21000,
}
{
	to: toAddress,
	value: valueETH,
	v,r,s: privateKey计算签名,
	nonce: 可内部获取,
	gas: 可内部获取,
	gasPrice:可内部获取,
	data: 不需要
}
接收端根据签名获得发送账户地址
package main

import (
	"context"
	"crypto/ecdsa"
	"fmt"
	"math/big"
	"time"

	"github.com/ethereum/go-ethereum/accounts/abi/bind"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/crypto"
	"github.com/ethereum/go-ethereum/ethclient"
)

var privateKey = "你自己的私钥"
var fromAddress = common.HexToAddress("0xc312c07abEb8246510412a7ce87A295E0ceC5D48")
var toAddress = common.HexToAddress("0xE78Ff27498c9a6Fd8BC3ff8170Ecf9a13ECBE49e")
var contractAddress = common.HexToAddress("0x5FbDB2315678afecb367f032d93F642f64180aa3")
var valueETH = big.NewInt(1e18)
var valueMTK = big.NewInt(1e18)
var isHardhatNode = true
var url = ""

type Geth struct {
	// 区块链调用
	ethe *ethclient.Client
}

func (this *Geth) init() {
	// hardhat 本地节点
	if isHardhatNode {
		// hardhat 默认账户地址1私钥
		privateKey = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
		// hardhat 默认账户地址1
		fromAddress = common.HexToAddress("0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266")
		// hardhat 默认账户地址2、合约地址、Metamask 账户地址
		toAddress = common.HexToAddress("0x70997970C51812dc3A010C7d01b50e0d17dc79C8")
		valueETH = big.NewInt(1e18) // 1ETH
		url = "http://localhost:8545"
	} else { // sepolia 测试网络节点
		// Metamask 账户地址1私钥
		privateKey = "你自己的私钥"
		// Metamask 账户地址1
		fromAddress = common.HexToAddress("0xc312c07abEb8246510412a7ce87A295E0ceC5D48")
		// Metamask 账户地址2
		toAddress = common.HexToAddress("0xE78Ff27498c9a6Fd8BC3ff8170Ecf9a13ECBE49e")
		contractAddress = common.HexToAddress("0x451Dc02Cee616361815253C858Df0a3028c42901")
		valueETH = big.NewInt(1e15) // 10 Gwei
		url = "https://ethereum-sepolia-rpc.publicnode.com"
	}
}

func (this *Geth) NewClient() *Geth {
	this.init()
	// 连接网络
	this.ethe, _ = ethclient.Dial(url)

	return this
}

// 区块链操作
func (this *Geth) BlockChain() {

	id, _ := this.ethe.ChainID(context.Background())
	fmt.Println(id)

	balance, _ := this.ethe.BalanceAt(context.Background(), fromAddress, nil)
	fmt.Println("发送前", this.weiToETH(balance))

	balance, _ = this.ethe.BalanceAt(context.Background(), toAddress, nil)
	fmt.Println("发送前", this.weiToETH(balance))

	/*
		{
			to: toAddress,
			value: valueETH,
			v,r,s: privateKey计算签名,
			nonce: 可内部获取,
			gas: 可内部获取,
			gasPrice:可内部获取,
			data: 不需要
		}
		接收端根据签名获得发送账户地址
	*/
	//this.transaction(toAddress, valueETH, privateKey)
	this.sendRawTransaction()

	balance, _ = this.ethe.BalanceAt(context.Background(), fromAddress, nil)
	fmt.Println("发送后", this.weiToETH(balance))

	balance, _ = this.ethe.BalanceAt(context.Background(), toAddress, nil)
	fmt.Println("发送后", this.weiToETH(balance))

}

// 区块链交易。hardhat node或sepolia,交易结构中的参数都需要,底层调用eth_sendRawTransaction,需要Nonce,需要私钥签名,不需要from。从私钥推导出账户地址
// web3.js web3.eth.sendTransaction底层调用eth_sendTransaction,节点自动填充Nonce和from。hardhat node不验证私钥签名,用默认第一个账户。但sepolia需要私钥签名,从私钥推导出账户地址
func (this *Geth) transaction(toAddress common.Address, valueETH *big.Int, privateKey string) {
	// 解析私钥
	privateKey_, _ := crypto.HexToECDSA(privateKey[2:])
	// 获取公钥
	publicKey := privateKey_.Public()
	// 账户地址
	fromAddress := crypto.PubkeyToAddress(*publicKey.(*ecdsa.PublicKey))

	nonce, _ := this.ethe.PendingNonceAt(context.Background(), fromAddress)
	gasPrice, _ := this.ethe.SuggestGasPrice(context.Background())

	// 创建交易
	tx := types.NewTx(&types.LegacyTx{
		Nonce:    nonce,
		To:       &toAddress,
		Value:    valueETH,
		GasPrice: gasPrice,
		Gas:      21000,
	})

	chainID, _ := this.ethe.NetworkID(context.Background())
	// 签名
	signedTx, _ := types.SignTx(tx, types.NewEIP155Signer(chainID), privateKey_)
	// 发送交易
	_ = this.ethe.SendTransaction(context.Background(), signedTx)

	// 带超时的上下文
	waitCtx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
	defer cancel()
	// 等待挖矿成功
	_, _ = bind.WaitMined(waitCtx, this.ethe, signedTx)
}

// wei转ETH
func (this *Geth) weiToETH(wei *big.Int) *big.Float {
	return new(big.Float).Quo(new(big.Float).SetInt(wei), big.NewFloat(1e18))
}

// ETH转wei
func (this *Geth) EthToWei(eth float64) *big.Int {
	wei, _ := new(big.Int).SetString(new(big.Float).Mul(big.NewFloat(eth), big.NewFloat(1e18)).Text('f', 0), 10)
	return wei
}

func (this *Geth) sendRawTransaction() {
	// 获取底层的 rpc.Client
	rpcClient := this.ethe.Client()

	// 发送交易
	tx := map[string]interface{}{
		"from":  fromAddress,
		"to":    toAddress,
		"value": valueETH, // 0.1 ETH
	}

	var txHash common.Hash
	_ = rpcClient.Call(&txHash, "eth_sendTransaction", tx)
}

3. 合约部署到Solidity

hardhat配置文件

require("@nomicfoundation/hardhat-toolbox");

/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
  solidity: "0.8.28",
  networks: {
    hardhat: {
    },
    localhost: {
      url: "http://localhost:8545"
    },
    sepolia: {
      url: "https://ethereum-sepolia-rpc.publicnode.com",
      accounts: ["你自己的私钥"],
      chainId: 11155111,
    }
  }
};

hh run ignition\modules\Mytoken.js --network localhost

在这里插入图片描述
连接sepolia
在这里插入图片描述

一. 系列视频
二. 系列文章

国密即国家密码局认定的国产密码算法,即商用密码。国密算法是国家密码局制定标准的一系列算法。其中包括了对称加密算法,椭圆曲线非对称加密算法,杂凑算法。具体包括SM1,SM2,SM3等,其中:SM2为国家密码管理局公布的公钥算法,其加密强度为256位。其它几个重要的商用密码算法包括:SM1,对称加密算法,加密强度为128位,采用硬件实现;SM3,密码杂凑算法,杂凑值长度为32字节,SM2算法同期公布,参见《国家密码管理局公告(第 22 号)》;SMS4,对称加密算法,随WAPI标准一起公布,可使用软件实现,加密强度为128位。商用密码,是指能够实现商用密码算法的加密、解密认证等功能的技术。(包括密码算法编程技术密码算法芯片、加密卡等的实现技术)。商用密码技术是商用密码的核心,国家将商用密码技术列入国家秘密,任何单位个人都有责任义务保护商用密码技术的秘密。商用密码的应用领域十分广泛,主要用于对不涉及国家秘密内容但又具有敏感性的内部信息、行政事务信息、经济信息等进行加密保护。比如:商用密码可用于企业门禁管理、企业内部的各类敏感信息的传输加密、存储加密,防止非法第三方获取信息内容;也可用于各种安全认证、网上银行、数字签名等。例如:在门禁应用中,采用SM1算法进行身份鉴别数据加密通讯,实现卡片合法性的验证,保证身份识别的真实性。 安全是关系国家、城市信息、行业用户、百姓利益的关键问题。国家密码管理局针对现有重要门禁系统建设升级改造应用也提出指导意见,加强芯片、卡片、系统的标准化建设。截止目前,国密门禁系统的升级的案例也逐渐增多,基于自主国产知识产权的CPU卡、CPU卡读写设备及密钥管理系统广泛受到关注。一些厂商如同方锐安在2009年推出CPU卡安全门禁系列产品,在2010年北京安博会上,该公司再次向业界展示出“御”系列CPU卡门禁系统、TF-DF6000系列安全门禁读卡器以及基于CPU卡技术的一卡通系统等主流产品系统。这些厂商是全国推广的国密门禁产品的先驱者,使“御”系列CPU卡门禁系统广泛应用于政府、监狱、司法、军工企业大型公共智能建筑等高安全领域。以太坊是互联网新时代的基础:内建货币与支付。用户拥有个人数据主权,且不会被各类应用监听或窃取数据。人人都有权使用开放金融系统。基于中立且开源的基础架构,不受任何组织或个人控制。以太坊主网于 2015 年上线,是世界头部的可编程区块链其它区块链一样,以太坊也拥有原生加密货币,叫作 ether (ETH)。 ETH 是一种数字货币, 比特币有许多相同的功能。 它是一种纯数字货币,可以即时发送给世界上任何地方的任何人。 ETH 的供应不受任何政府或组织控制,它是去中心化且具稀缺性的。 全世界的人们都在使用 ETH 进行支付,或将其作为价值存储抵押品。但与其它区块链不同的是,以太坊可以做更多的工作。 以太坊是可编程的,开发者可以用它来构建不同于以往的应用程序。这些去中心化的应用程序(或称“dapps”)基于加密货币与区块链技术, 因而值得信任,也就是说 dapps 一旦被“上传”到以太坊,它们将始终按照编好的程序运行。 这些应用程序可以控制数字资产,以便创造新的金融应用; 同时还是去中心化的,这意味着没有任何单一实体或个人可以控制它们。目前,全世界有成千上万名开发者正在以太坊上构建应用程序、发明新的应用程序,其中有许多现在已经可以使用:加密货币钱包:让你可以使用 ETH 或其他数字资产进行低成本的即时支付金融应用程序:让你可以借贷、投资数字资产去中心化市场:让你可以交易数字资产,甚至就现实世界事件的“预测”进行交易游戏:你可以拥有游戏内的资产,甚至可以由此获得现实收益以及更多,更多。以太坊社区是世界上最大最活跃的区块链社区。它包括核心协议开发者、加密经济研究员、密码朋克、挖矿组织、ETH 持有者、应用开发者、普通用户、无政府主义者、财富 500 强公司,以及现在的你。没有公司或中心化的组织能够控制以太坊。 一直以来,以太坊由多元化的全球性社区贡献者来协同进行维护改善,社区成员耕耘于以太坊的方方面面,从核心协议到应用程序。 这个网站,就像以太坊的其他部分一样,是由一群人共同构建的,并将持续构建下去。本课程定制符合国家标准的以太坊
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

OneFlyPig

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

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

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

打赏作者

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

抵扣说明:

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

余额充值