携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第20天,点击查看活动详情
调用合约时如何签名
我们知道,合约的调用一般分为两种,一种不消耗gas,一种消耗gas。不消耗gas的也就意味着不会改变存储状态,因此调用的时候可以不用明确身份也是可行的。但是,我们想要调用消耗gas的方法,就需要使用私钥签名来明确自己的身份。每一个账户都要私钥,我们可以让Geth将私钥加密后生成一个keystore文件。当使用这个文件时,就需要使用密码解密。
该文件一般在geth初始化数据下面(也有可能不小心搞C盘去了)
导包
我们现在拥有了keystroe文件,接着我们就可以使用go-ethereum源码,先导入bind包,使用NewTransactor来构造TransactOpts。
"github.com/ethereum/go-ethereum/accounts/abi/bind"
连接geth
连接geth,为了简便给他写了一个独立的方法,我们可以之间在main中写下所有。
//获取client
func GetClient() (*ethclient.Client, error) {
// 连接到geth节点
client, err := ethclient.Dial("http://127.0.0.1:7545")
//连接到测试网
//client, err := ethclient.Dial("https://rinkeby.etherscan.io")
if err != nil {
log.Fatal(err)
}
//延时关闭
defer client.Close()
return client, nil
}
构造合约实例
生成合约实例,需要将部署后的合约地址写在代码中。
const{
gasLimit = 3000000
fileKeystore = "./UTC--2022-03-17T08-08-40.600466800Z--59b0f8a34d8f0dd0e0eef44d02cef0c12fffb9de"
Prikey = "c5b9c7fd467335bd829b3b2a3098a72ac39b7f5efa162220b7907cfc684df9a3"
privateKey = "111"
contAddress = "0x7D1672baDeA4825c4B8fFD938fFD29457D6aF6ae"
}
// 获取合约实例
func GetAddress(client *ethclient.Client) (*Agreement.User, error) {
//NewUser方法名一般与合约生成的.go文件名有关
contract, err := NewUser(common.HexToAddress(contAddress), client)
if err != nil {
log.Fatal(err)
}
fmt.Println("faucet:", contract)
return contract, err
}
利用keystroe文件生成交易者信息
在上面的代码中声明了常量fileKeystore文件地址和privateKey(密码)
- 部分代码
reader,_=os.Open(fileKeystore)
//构造交易者信息
opts,err:=bind.NewTransactor(reader,privateKey)
if err != nil {
log.Fatal(err)
}
签名调用
调用需要消耗gas的函数。
- 部分代码
tx,err:=contract.SetFunc(opts,···)
直接使用私钥进行生成交易信息
如果我们不使用keystore文件,可以直接使用私钥进行构造交易这信息。
- 部分代码
//获取私钥
func GetPrivateKey() *ecdsa.PrivateKey {
privateKey, err := crypto.HexToECDSA(Prikey)
if err != nil {
panic(err)
}
return privateKey
}
func GetMsgOpts(privateKey *ecdsa.PrivateKey) *bind.TransactOpts {
//该方法将要被弃用
opts := bind.NewKeyedTransactor(privateKey)
fmt.Println("opts:", opts)
return opts
}