Go语言与智能合约的交互

Go语言与智能合约的交互

实现步骤

  1. 首先要编写一份智能合约
  2. 将智能合约通过工具转化为go文件
  3. 自己编写go文件调用智能合约转化成的go文件提供的接口

具体实现

  • 编写一份智能合约

智能合约使用solidity语言写的,可以用在线的remix编辑器进行编辑。

pragma solidity >=0.4.22 <0.6.0;



contract DataStorage {

   
    bytes32 public fheAddressHash ;
    bytes32 public rsaPublicKeyHash;
    bytes32 public dataHash;
    bytes32 public modelHash;
    bytes32 public encryptedAesKeyHash;
    bytes32 public trainedResultHash;
    bytes32 public finalDistance;
    bytes32 public modelParamsHash;
   
    
    constructor() public{
        
    }
    
    function setFheAddressHash(bytes32 _fheAddressHash) payable public {
        fheAddressHash=_fheAddressHash;
        emit LogSetFheAddressHash(fheAddressHash);
    }
    
    function setModelHash(bytes32 _modelHash) payable public {
        modelHash=_modelHash;
        emit LogSetModelHash(modelHash);
    }
    
    function setRsaPublicKeyHash(bytes32 _rsaPublicKeyHash) payable public{
        rsaPublicKeyHash=_rsaPublicKeyHash;
        emit LogSetRsaPublicKeyHash(rsaPublicKeyHash);
    }
    function setDataHash(bytes32 _dataHash) payable public{
        dataHash=_dataHash;
        emit LogSetDataHash(dataHash);
    }
    
    function setEncryptedAesKeyHash(bytes32 _encryptedAesKeyHash) payable public{
        encryptedAesKeyHash=_encryptedAesKeyHash;
        emit LogEncryptedAesKeyHash(encryptedAesKeyHash);
    }
    
    function setTrainedResultHash(bytes32 _trainedResultHash) payable public{
        trainedResultHash=_trainedResultHash;
        emit LogTrainedResultHash(trainedResultHash);
    }
    
    function setFinalDistance(bytes32 _finalDistance) payable public{
        finalDistance=_finalDistance;
        emit LogSetFinalDistance(finalDistance);
    }
    
    function setModelParamsHash(bytes32 _modelParamsHash) payable public{
        modelParamsHash=_modelParamsHash;
        emit LogSetModelParamsHash(modelParamsHash);
    }
    
    event LogSetFheAddressHash(bytes32 _fheAddressHash);
    event LogSetModelHash(bytes32 _modelHash);
    event LogSetRsaPublicKeyHash(bytes32 _rsaPublicKeyHash);
    event LogSetDataHash(bytes32 _dataHash);
    event LogEncryptedAesKeyHash(bytes32 _encryptedAesKeyHash);
    event LogTrainedResultHash(bytes32 _trainedResultHash);
    event LogSetFinalDistance(bytes32 _finalDistance);
    event LogSetModelParamsHash(bytes32 _modelParamsHash);
}

remix编辑器

  • 将智能合约用工具转化为go语言:

我们用abigen将智能合约转化为go文件

abigen安装的方式如下:

go get github.com/ethereum/go-ethereum
cd $GOPATH/src/github.com/ethereum/go-ethereum/
make
make devtools

接着我们用如下命令将智能合约转化为go语言文件:

DataStorage.sol为智能合约文件,filedir为生成的文件的保存目录。

#第一行命令会生成.abi文件在filedir目录中
solcjs DataStorage.sol -o filedir --abi
#第二行命令会生成.bin文件在filedir目录中
solcjs  DataStorage.sol -o filedir --bin
#第三行命令用filedir中的.abi文件和.bin文件生成一个package 为main的名为DataStorage.go的go语言文件.该文件保存在/Users/huyifan/DAI中.
abigen --abi  DataStorage_sol_ DataStorage.abi --bin  DataStorage_sol_ DataStorage.bin --pkg main --out /Users/huyifan/DAI/ DataStorage.go
  • 自己编写go文件调用智能合约转化成的go文件提供的接口

我这里只调用了setDataHash这个智能合约函数,将字符串存进区块链智能合约中,然后再从区块链中获取我们存进去的字符串。其他的函数以此类推。

package main

import (
	"fmt"
	"log"
	"math/big"
	"strings"


	//"time"

	"github.com/ethereum/go-ethereum/accounts/abi/bind"
	"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
	"github.com/ethereum/go-ethereum/core"
	"github.com/ethereum/go-ethereum/ethclient"
	"github.com/ethereum/go-ethereum/common"
	//"github.com/oraclize/ethereum-api/oraclizeAPI.sol";
	//"github.com/ethereum/go-ethereum/crypto"
)

//本地以太坊私链的某一个账户,这里我用了coinbase对应的账户,这个账户信息在私链数据目录下的keystore目录里面
const key=`{"address":"12769c3419a7f491cf4e576e2e983e009d579076","crypto":{"cipher":"aes-128-ctr","ciphertext":"215430a18ab1132c6eaecdf966bc0d878a3be06cff5dce173d801afec5002db5","cipherparams":{"iv":"d41d87954da3dfca1f38e14111169fb8"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"d5268e70fbf8666435bf82ee53850f14486810f1944110de2aede933ae97fff1"},"mac":"a80e95fc657473f543bb989da9e8e2cde73e2b8bde52e6b05355b44a40c165ec"},"id":"5e034459-6e81-4208-9e26-c91641d20f5d","version":3}`

func main() {

	//我们要存进区块链智能合约的字符串
	dataHash := "testDataHash"

	//智能合约的在区块链上的地址
	contractAddress := "0x47d73709bf274160118f8f175695ac3616b7f08f"
	//连接本地的以太坊私链(一定要保证本地以太坊私链已经启动)
	conn, err := ethclient.Dial("http://127.0.0.1:8545")
	
	fmt.Println("connect to local geth node...", conn)
	if err != nil {
		log.Fatalf("could not connect to local node: %v", err)
	}
	//fmt.Println("get the contract object...")

	token, err := NewMain(common.HexToAddress(contractAddress), conn)
	if err != nil {
		log.Fatalf("Failed to instantiate a Token contract: %v", err)
	}
	fmt.Println("contract token======>:", token)

	//解锁对应账户
	auth, err := bind.NewTransactor(strings.NewReader(key), "abc")
	if err != nil {
		log.Fatalf("could not create auth: %v", err)
	}
	alloc := make(core.GenesisAlloc)
	alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(1337000000000)}
	sim := backends.NewSimulatedBackend(alloc, 100000000)
	// fmt.Println("token:=====>",token)


	var arr [32]byte
	for k, v := range []byte(dataHash) {
		arr[k] = byte(v)
	}

	fmt.Println(string(arr[:len(arr)]))

	//调用对应的go语言函数与以太坊私链进行交互
	fmt.Println("=========start put data=========")
	_, err = token.SetDataHash(&bind.TransactOpts{
		From:     auth.From,
		Signer:   auth.Signer,
		GasLimit: 288162,
		Value:    big.NewInt(30),
	}, arr)

	if err!=nil {
		log.Fatalf("transaction produce fail: %v", err)
	}
	//提交交易
	sim.Commit()

	

	if err != nil {
		log.Fatalf("put data to data pool err:%v", err)
	}

	fmt.Println("put data to smart contract success!")


	fmt.Println("==================================")
	fmt.Println("get data from smart contract")
	//从以太坊上获得之前存进去的值
	info, _ := token.DataHash(&bind.CallOpts{Pending: true})
	//fmt.Printf("the total data prices and desciption are: %s\n", info);
	fmt.Printf(string(info[:len(info)]))

}

结果如下所示:

以太坊产生的信息如下图所示:
以太坊对应信息

注意点:

  • 只要将想要从以太坊获得值的那个变量在智能合约中设置成public,智能合约转为go语言文件后会自动的生成相应的函数,调用那个函数就可以从以太坊中获得变量值。
  • 如果智能合约的某个函数会改变以太坊的状态(例如设置某个变量的值,更新了某个变量的值等等),那么在智能合约中这个函数就要用payable修饰,因为调用这个函数的时候必须要发起交易,待这个交易被确认后,调用的这个函数的产生的结果才生效。我们也可以从设置值的函数和获取值的函数的参数看出端倪:
    设置函数传入的参数
    获取函数传入的参数
  • 也可以事先不部署智能合约。这样的话,就需要调用DataStorage.go文件中的DeployMain函数自己手动的部署智能合约,代码修改如下:
    在这里插入图片描述
    以太坊的状态如下图所示:
    在这里插入图片描述
    这里再次提醒只要对区块链状态发生了改变的话,必须提交交易,并被验证通过才能算真正的改变了区块链.
  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值