go-sdk icon indicating copy to clipboard operation
go-sdk copied to clipboard

从配置文件读取合约时,可以进行数据上链。但读取的时候出现0x1a的问题。

Open wxj-cyber opened this issue 2 years ago • 6 comments

package models

import (
	"bufio"
	// "errors"
	"io"
	"log"
	"math/big"
	"os"
	manage "proj3/manage"

	"github.com/FISCO-BCOS/go-sdk/client"
	"github.com/FISCO-BCOS/go-sdk/conf"
	"github.com/FISCO-BCOS/go-sdk/core/types"
	"github.com/ethereum/go-ethereum/common"
	// import store
)

type ContractServiceType struct {
	// ConfigPath   string
	Client       *client.Client
	Instance     *manage.Manage
	Session      *manage.ManageSession
	isCreated    bool
	ContractAddr common.Address
}

// 判断所给路径文件/文件夹是否存在
func Exists(path string) bool {
	_, err := os.Stat(path) //os.Stat获取文件信息
	if err != nil {
		if os.IsExist(err) {
			return true
		}
		return false
	}
	return true
}

/*
	函数名:WriteString2File
	描述:将数据以字符串的形式写入到文件中。
*/
func WriteString2File(data string) {
	//创建文件,将部署的合约写进取
	fliePath := "./config.txt"
	file, err := os.OpenFile(fliePath, os.O_WRONLY|os.O_CREATE, 0666)
	if err != nil {
		log.Fatal("file open error:", err)
	}
	defer file.Close()
	write := bufio.NewWriter(file)
	_, err = write.WriteString(data)
	if err != nil {
		log.Fatal("write addr error:", err)
	}
	//刷新缓冲区
	write.Flush()
}

/*
	函数名:ReadStringFromFile
	描述:从之前写入的文件中读取部署的合约地址。
*/
func ReadStringFromFile() (contractAddr []byte, ret bool) {
	filePath := "./config.txt"
	file, err := os.Open(filePath)
	if err != nil {
		log.Fatal("file open error:", err)
		return nil, false
	}
	defer file.Close()

	var chunk []byte
	buf := make([]byte, 1024)
	//以字节的形式进行读取。
	for {
		//从file读取到buff中。
		n, err := file.Read(buf)
		if err != nil && err != io.EOF {
			log.Fatal("读取文件到缓冲区失败!")
			file.Close()
			return nil, false
		}

		if n == 0 {
			break
		}

		//读取到最终的缓冲区中。
		chunk = append(chunk, buf[:n]...)
	}
	return chunk, true
}

/*
	函数名:CreateConnectSession
	描述:基于配置文件与区块链节点创建会话,连接成功后,会将部署的合约地址进行文件写入操作。
*/
func (server *ContractServiceType) CreateConnectSession(config string) {

	if config == "" {
		return
	}

	//1.解析配置
	configs, err := conf.ParseConfigFile(config)
	if err != nil {
		log.Fatal("parse config file error:", err)
		return
	}
	//2.连接远程
	server.Client, err = client.Dial(&configs[0])
	if err != nil {
		log.Fatal("connect error:", err)
		return
	}
	if Exists("./config.txt") { //之前已经对其进行部署.

		//读取出之前部署的合约地址,将其与新的client进行绑定。
		contractAddrByte, ret := ReadStringFromFile()
		if !ret {
			log.Fatal("while read config from file error")
			return
		}
		server.ContractAddr = common.BytesToAddress(contractAddrByte)
		server.Instance, err = manage.NewManage(server.ContractAddr, server.Client)

		if err != nil {
			log.Fatal("create manange new instance error:", err)
			return
		}

	} else {
		//3.部署合约
		server.ContractAddr, _, server.Instance, err = manage.DeployManage(server.Client.GetTransactOpts(), server.Client)
		if err != nil {
			log.Fatal("deploy contract error:", err)
			return
		}
		//3.1将合约地址写入文件。
		WriteString2File(server.ContractAddr.String())
	}

	//4.连接合约
	server.Session = &manage.ManageSession{Contract: server.Instance, CallOpts: *server.Client.GetCallOpts(), TransactOpts: *server.Client.GetTransactOpts()}
	server.isCreated = true
}

/*
	函数名:NewVaccine
	描述:产生一个新的疫苗。
*/
func (server *ContractServiceType) NewVaccine(name string, id *big.Int, addr string, validity *big.Int) (*types.Transaction, *types.Receipt, error) {

	if server.Instance == nil || server.Client == nil || server.Session == nil || len(server.ContractAddr) == 0 {
		// log.Fatal("instance is null then constructor it again please.")
		// return nil, nil, errors.New("示例为空,是否存在没有为其进行合约部署。或者是client为空,没有正确的连接到区块链。Session为空,要确保有一个正确的连接。")
		server.CreateConnectSession("./conf/config.toml")
	}
	//ame string, id *big.Int, addr string, range1 *big.Int
	return server.Session.CreateVaccine(name, id, addr, validity)
}

/*
	函数名:GetVaccineById
	描述:基于id获取疫苗信息。
*/
func (server *ContractServiceType) GetVaccineById(id *big.Int) (string, *big.Int, string, *big.Int, *big.Int, error) {
	if server.Instance == nil || server.Client == nil || server.Session == nil || len(server.ContractAddr) == 0 {
		// log.Fatal("instance is null then constructor it again please.")
		// return "", nil, "", nil, nil, errors.New("示例为空,是否存在没有为其进行合约部署。或者是client为空,没有正确的连接到区块链。Session为空,要确保有一个正确的连接。")
		server.CreateConnectSession("./conf/config.toml")
	}

	return server.Session.GetVaccineInfo(id)
}

/*
	函数名:GetVaccineCnt
	描述:获取工厂疫苗的数量。
*/
func (server *ContractServiceType) GetVaccineCnt() (*big.Int, error) {
	if server.Instance == nil || server.Client == nil || server.Session == nil || len(server.ContractAddr) == 0 {
		// log.Fatal("instance is null then constructor it again please.")
		// return nil, errors.New("示例为空,是否存在没有为其进行合约部署。或者是client为空,没有正确的连接到区块链。Session为空,要确保有一个正确的连接。")
		server.CreateConnectSession("./conf/config.toml")
	}

	return server.Session.GetVaccineCount()
}

/*
	函数名:GetVaccineWithAll
	描述:获取所有疫苗信息。
*/
func (server *ContractServiceType) GetVaccineWithAll() ([]string, []*big.Int, []string, []*big.Int, []*big.Int, error) {
	if server.Instance == nil || server.Client == nil || server.Session == nil || len(server.ContractAddr) == 0 {
		// log.Fatal("instance is null then constructor it again please.")
		// return nil, nil, nil, nil, nil, errors.New("示例为空,是否存在没有为其进行合约部署。或者是client为空,没有正确的连接到区块链。Session为空,要确保有一个正确的连接。")
		server.CreateConnectSession("./conf/config.toml")
	}

	return server.Session.GetVaccineAll()
}

/*
	函数名:GetVaccineWithAll
	描述:获取疫苗的追踪链信息。
*/
func (server *ContractServiceType) GetTransitOfVaccineAll(id *big.Int) ([]string, []*big.Int, []string, error) {
	if server.Instance == nil || server.Client == nil || server.Session == nil || len(server.ContractAddr) == 0 {
		// log.Fatal("instance is null then constructor it again please.")
		// return nil, nil, nil, errors.New("示例为空,是否存在没有为其进行合约部署。或者是client为空,没有正确的连接到区块链。Session为空,要确保有一个正确的连接。")
		server.CreateConnectSession("./conf/config.toml")
	}
	return server.Session.GetVaccineTransit(id)
}

/*
	函数名:AddTransitForVaccineById
	描述:为疫苗的行径添加到区块链。
*/
func (server *ContractServiceType) AddTransitForVaccineById(id *big.Int, addr string, time *big.Int, remark string) (*types.Transaction, *types.Receipt, error) {
	if server.Instance == nil || server.Client == nil || server.Session == nil || len(server.ContractAddr) == 0 {
		// log.Fatal("instance is null then constructor it again please.")
		// return nil, nil, errors.New("示例为空,是否存在没有为其进行合约部署。或者是client为空,没有正确的连接到区块链。Session为空,要确保有一个正确的连接。")
		server.CreateConnectSession("./conf/config.toml")
	}
	return server.Session.AddTransit(id, addr, time, remark)
}



首先,简要介绍一下这个代码。 它根据配置文件进行解析,并进行连接,然后会根据config.txt是否存在来决定之前是否已经存在一个合约。 如果是,我们就会进行合约地址的读取,这里的读取是采用了以 字节 的形式进行读取,然后到绑定时,通过common.ByteToAddress()进行转换;如果为否,那么我就进行合约的部署并对其地址进行 文件写入。

现在,我们假定一个前提,就是已经存在config.txt,然后进行地址的转换。 在进行疫苗的创建时,我们可以看到:合约地址为:b0b46170F5f0FEC54e38,它是可以正常创建的。但对其进行合约读取时,就出现了问题:call error of status 0x1a 官方的解释为:被调用的合约地址不存在。

效果见图片

getting 问题

wxj-cyber avatar Oct 30 '22 03:10 wxj-cyber

新增几张图片可能有效解决问题的图片 fc78ff176ec3a864224b17f275dc3b8 64cddf01f284b98df3ffad9d1578ade 54adcd191dcfa3c916fd7c065f8e018

wxj-cyber avatar Oct 31 '22 06:10 wxj-cyber

检查你存下来的合约地址格式,如果存的是hex的字符串,应该使用common.HexToAddress

bxq2011hust avatar Oct 31 '22 07:10 bxq2011hust

问题已解决,感谢您们的热情帮助!

wxj-cyber avatar Oct 31 '22 07:10 wxj-cyber

问题已解决,感谢您们的热情帮助!

请问我也出现了这个问题,您是怎么解决的?

chaunsin avatar Nov 07 '22 16:11 chaunsin

我的合约地址是以十六进制的字符串写入的,读取的时候是以byte进行读取的,在合约地址转换时使用的是byte,解决办法就是转换为合约地址时把转换变为16进制字符串common.HexToAddress转换就好了。

wxj-cyber avatar Nov 07 '22 21:11 wxj-cyber

我的合约地址是以十六进制的字符串写入的,读取的时候是以byte进行读取的,在合约地址转换时使用的是byte,解决办法就是转换为合约地址时把转换变为16进制字符串common.HexToAddress转换就好了。

感谢解答,我这边解决了,虽然问题不同。

chaunsin avatar Nov 08 '22 06:11 chaunsin