智能合约 | 使用GO语言调用合约签名

597 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第20天,点击查看活动详情

调用合约时如何签名

我们知道,合约的调用一般分为两种,一种不消耗gas,一种消耗gas。不消耗gas的也就意味着不会改变存储状态,因此调用的时候可以不用明确身份也是可行的。但是,我们想要调用消耗gas的方法,就需要使用私钥签名来明确自己的身份。每一个账户都要私钥,我们可以让Geth将私钥加密后生成一个keystore文件。当使用这个文件时,就需要使用密码解密。 该文件一般在geth初始化数据下面(也有可能不小心搞C盘去了) image.png

image.png

导包

我们现在拥有了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
}