go-sdk
go-sdk copied to clipboard
从配置文件读取合约时,可以进行数据上链。但读取的时候出现0x1a的问题。
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 官方的解释为:被调用的合约地址不存在。
效果见图片
新增几张图片可能有效解决问题的图片
检查你存下来的合约地址格式,如果存的是hex的字符串,应该使用common.HexToAddress
问题已解决,感谢您们的热情帮助!
问题已解决,感谢您们的热情帮助!
请问我也出现了这个问题,您是怎么解决的?
我的合约地址是以十六进制的字符串写入的,读取的时候是以byte进行读取的,在合约地址转换时使用的是byte,解决办法就是转换为合约地址时把转换变为16进制字符串common.HexToAddress
转换就好了。
我的合约地址是以十六进制的字符串写入的,读取的时候是以byte进行读取的,在合约地址转换时使用的是byte,解决办法就是转换为合约地址时把转换变为16进制字符串
common.HexToAddress
转换就好了。
感谢解答,我这边解决了,虽然问题不同。