在 Hedera 上部署合约时出现 ERROR_DECODING_BYTESTRING 错误。

huangapple go评论81阅读模式
英文:

ERROR_DECODING_BYTESTRING Error When Deploying Contract On Hedera

问题

我正在尝试在Hedera上部署一个合约;文件大小为9766字节,所以我创建了一个文件并将合约附加到其中,但现在我收到错误信息"exceptional receipt status: ERROR_DECODING_BYTESTRING: error retrieving contract creation record"。我相信我在代码中做错了什么。任何帮助将不胜感激。

package blockchain

import (
	"encoding/json"
	"fmt"
	"io/ioutil"

	"github.com/.../scanner/env"
	"github.com/hashgraph/hedera-sdk-go/v2"
)

type contract struct {
	Abi string `json:"abi"`
	Bin string `json:"bin"`
}

type contracts struct {
	Contracts map[string]contract `json:"contracts"`
	Version   string              `json:"version"`
}

func DeployContract() {
	var client *hedera.Client
	var err error

	// 从环境变量 HEDERA_NETWORK 中获取网络类型
	client, err = hedera.ClientForName(env.GetEnv["HEDERA_NETWORK"])
	if err != nil {
		println(err.Error(), ": error creating client")
		return
	}

	// 从环境变量 OPERATOR_ID 中获取操作员账户ID
	operatorAccountID, err := hedera.AccountIDFromString(env.GetEnv["OPERATOR_ID"])
	if err != nil {
		println(err.Error(), ": error converting string to AccountID")
		return
	}

	// 从环境变量 OPERATOR_KEY 中获取操作员私钥
	operatorKey, err := hedera.PrivateKeyFromString(env.GetEnv["OPERATOR_KEY"])
	if err != nil {
		println(err.Error(), ": error converting string to PrivateKey")
		return
	}

	// 设置客户端的操作员ID和私钥
	client.SetOperator(operatorAccountID, operatorKey)

	// 运行结束后记得关闭客户端
	defer func() {
		err = client.Close()
		if err != nil {
			println(err.Error(), ": error closing client")
			return
		}
	}()

	// 从 contract.json 文件中读取编译后的合约
	rawSmartContract, err := ioutil.ReadFile("./contract/contract.json")
	if err != nil {
		println(err.Error(), ": error reading contract.json")
		return
	}

	// 初始化 contracts
	var smartContract contracts = contracts{}

	// 将 rawSmartContract 解析为 smartContract
	err = json.Unmarshal([]byte(rawSmartContract), &smartContract)
	if err != nil {
		println(err.Error(), ": error unmarshaling")
		return
	}

	// 从解析后的智能合约中获取字节码
	smartContractByteCode := smartContract.Contracts["contract.sol:ScanInput"].Bin

	// 输出合约字节码大小
	fmt.Printf("合约字节码大小:%v 字节\n", len(smartContractByteCode))

	// 创建一个新文件
	newFileResponse, err := hedera.NewFileCreateTransaction().
		// 接受 Key 或 []Key
		// 在顶级 key 列表中的所有密钥都必须签名以创建或修改文件。在顶级 key 列表中的任何一个密钥都可以签名以删除文件。
		SetKeys(client.GetOperatorPublicKey()).
		// 设置初始文件内容
		SetContents([]byte("Initializing file.")).
		SetMemo("go file append test").
		// 如果不想被过高收费,可以设置最大交易费用
		SetMaxTransactionFee(hedera.NewHbar(2)).
		Execute(client)
	if err != nil {
		println(err.Error(), ": error creating file")
		return
	}

	// 获取收据以确保交易成功
	receipt, err := newFileResponse.GetReceipt(client)
	if err != nil {
		println(err.Error(), ": error retrieving file creation receipt")
		return
	}

	// 从收据中获取文件ID
	fileID := *receipt.FileID

	// 文件附加
	fileResponse, err := hedera.NewFileAppendTransaction().
		// 确保节点与新文件相同,这样我们就不必等待传播
		SetNodeAccountIDs([]hedera.AccountID{newFileResponse.NodeID}).
		// 要附加的文件ID
		SetFileID(fileID).
		// 要附加到文件末尾的内容
		SetContents([]byte(smartContractByteCode)).
		// 当你不确定交易费用时,可以设置最大交易费用
		SetMaxTransactionFee(hedera.NewHbar(5)).
		Execute(client)
	if err != nil {
		println(err.Error(), ": error executing file append transaction")
		return
	}

	// 检查交易是否成功
	receipt, err = fileResponse.GetReceipt(client)
	if err != nil {
		println(err.Error(), ": error retrieving file append transaction receipt")
		return
	}

	// 检查附加是否成功
	println(receipt.Status.String())
	info, err := hedera.NewFileInfoQuery().
		// 再次使用相同的节点账户ID
		SetNodeAccountIDs([]hedera.AccountID{fileResponse.NodeID}).
		// 只需要文件ID
		SetFileID(fileID).
		Execute(client)

	if err != nil {
		println(err.Error(), ": error executing file info query")
		return
	}

	println("根据 `FileInfoQuery` 的文件大小:", info.Size)
	println("根据 `FileInfoQuery` 的文件备注:", info.FileMemo)

	// 获取收据以确保交易成功并获取字节码文件ID
	byteCodeTransactionReceipt, err := newFileResponse.GetReceipt(client)
	if err != nil {
		println(err.Error(), ": error getting file create transaction receipt")
		return
	}

	// 从收据中获取字节码文件ID
	byteCodeFileID := *byteCodeTransactionReceipt.FileID

	fmt.Printf("合约字节码文件:%v\n", byteCodeFileID)

	// 实例化合约实例
	contractTransactionID, err := hedera.NewContractCreateTransaction().
		// 设置创建合约的 gas
		// 如果未设置足够的 gas,将返回 "INSUFFICIENT_GAS" 状态
		SetGas(100000).
		// 合约字节码必须设置为包含合约字节码的文件ID
		SetBytecodeFileID(byteCodeFileID).
		// 在合约中设置管理员密钥,以便将来可以删除或更新合约
		SetAdminKey(client.GetOperatorPublicKey()).
		Execute(client)

	if err != nil {
		println(err.Error(), ": error creating contract")
		return
	}

	// 获取新合约记录以确保交易成功
	contractRecord, err := contractTransactionID.GetRecord(client)
	if err != nil {
		println(err.Error(), ": error retrieving contract creation record")
		return
	}

	// 从记录中获取合约创建结果
	contractCreateResult, err := contractRecord.GetContractCreateResult()
	if err != nil {
		println(err.Error(), ": error retrieving contract creation result")
		return
	}

	// 从收据中获取新合约ID
	newContractID := *contractRecord.Receipt.ContractID

	fmt.Printf("合约创建使用的 gas:%v\n", contractCreateResult.GasUsed)
	fmt.Printf("合约创建交易费用:%v\n", contractRecord.TransactionFee)
	fmt.Printf("合约:%v\n", newContractID)

}

Solidity合约:点击此处

英文:

I am trying to deploy a contract on Hedera; the file is 9766 bytes, so I created a file and appended the contract to it, but now I get the error "exceptional receipt status: ERROR_DECODING_BYTESTRING: error retrieving contract creation record". I believe I did something wrong in my code. Any help will be appreciated.

package blockchain
import (
"encoding/json"
"fmt"
"io/ioutil"
"github.com/.../scanner/env"
"github.com/hashgraph/hedera-sdk-go/v2"
)
type contract struct {
Abi string `json:"abi"`
Bin string `json:"bin"`
}
type contracts struct {
Contracts map[string]contract `json:"contracts"`
Version   string              `json:"version"`
}
func DeployContract() {
var client *hedera.Client
var err error
// Retrieving network type from environment variable HEDERA_NETWORK
client, err = hedera.ClientForName(env.GetEnv["HEDERA_NETWORK"])
if err != nil {
println(err.Error(), ": error creating client")
return
}
// Retrieving operator ID from environment variable OPERATOR_ID
operatorAccountID, err := hedera.AccountIDFromString(env.GetEnv["OPERATOR_ID"])
if err != nil {
println(err.Error(), ": error converting string to AccountID")
return
}
// Retrieving operator key from environment variable OPERATOR_KEY
operatorKey, err := hedera.PrivateKeyFromString(env.GetEnv["OPERATOR_KEY"])
if err != nil {
println(err.Error(), ": error converting string to PrivateKey")
return
}
// Setting the client operator ID and key
client.SetOperator(operatorAccountID, operatorKey)
// Make sure to close client after running
defer func() {
err = client.Close()
if err != nil {
println(err.Error(), ": error closing client")
return
}
}()
// Read in the compiled contract from contract.json
rawSmartContract, err := ioutil.ReadFile("./contract/contract.json")
if err != nil {
println(err.Error(), ": error reading contract.json")
return
}
// Initialize contracts
var smartContract contracts = contracts{}
// Parse the rawSmartContract into smartContract
err = json.Unmarshal([]byte(rawSmartContract), &smartContract)
if err != nil {
println(err.Error(), ": error unmarshaling")
return
}
// Retrieve the bytecode from the parsed smart contract
smartContractByteCode := smartContract.Contracts["contract.sol:ScanInput"].Bin
//output contract bytecode size
fmt.Printf("Contract bytecode size: %v bytes\n", len(smartContractByteCode))
// Create a new file
newFileResponse, err := hedera.NewFileCreateTransaction().
// Accepts both Key and []Key
// All keys at the top level of a key list must sign to create or modify the file. Any one of
// the keys at the top level key list can sign to delete the file.
SetKeys(client.GetOperatorPublicKey()).
// Basic starting file content
SetContents([]byte("Initializing file.")).
SetMemo("go file append test").
// Set max fee if we don't want to get overcharged
SetMaxTransactionFee(hedera.NewHbar(2)).
Execute(client)
if err != nil {
println(err.Error(), ": error creating file")
return
}
// Get receipt to make sure the transaction worked
receipt, err := newFileResponse.GetReceipt(client)
if err != nil {
println(err.Error(), ": error retrieving file creation receipt")
return
}
// Retrieve file ID from the receipt
fileID := *receipt.FileID
// File append
fileResponse, err := hedera.NewFileAppendTransaction().
// Make sure the node is the same as the new file, as we don't have to wait for propagation
SetNodeAccountIDs([]hedera.AccountID{newFileResponse.NodeID}).
// File ID to append to
SetFileID(fileID).
// Contents that will be appended to the end of the file
SetContents([]byte(smartContractByteCode)).
// Set max transaction when you are not sure how much it will cost.
SetMaxTransactionFee(hedera.NewHbar(5)).
Execute(client)
if err != nil {
println(err.Error(), ": error executing file append transaction")
return
}
// Checking if transaction went through
receipt, err = fileResponse.GetReceipt(client)
if err != nil {
println(err.Error(), ": error retrieving file append transaction receipt")
return
}
// Checking if append succeeded
println(receipt.Status.String())
info, err := hedera.NewFileInfoQuery().
// Once again same node account ID
SetNodeAccountIDs([]hedera.AccountID{fileResponse.NodeID}).
// Only the file ID is required for this
SetFileID(fileID).
Execute(client)
if err != nil {
println(err.Error(), ": error executing file info query")
return
}
println("File size according to `FileInfoQuery`:", info.Size)
println("File memo according to `FileInfoQuery`:", info.FileMemo)
// Retrieve the receipt to make sure the transaction went through and to get bytecode file ID
byteCodeTransactionReceipt, err := newFileResponse.GetReceipt(client)
if err != nil {
println(err.Error(), ": error getting file create transaction receipt")
return
}
// Retrieve bytecode file ID from the receipt
byteCodeFileID := *byteCodeTransactionReceipt.FileID
fmt.Printf("contract bytecode file: %v\n", byteCodeFileID)
// Instantiate the contract instance
contractTransactionID, err := hedera.NewContractCreateTransaction().
// Set gas to create the contract
// Failing to set this to a sufficient amount will result in "INSUFFICIENT_GAS" status
SetGas(100000).
// The contract bytecode must be set to the file ID containing the contract bytecode
SetBytecodeFileID(byteCodeFileID).
// Set the admin key on the contract in case the contract should be deleted or
// updated in the future
SetAdminKey(client.GetOperatorPublicKey()).
Execute(client)
if err != nil {
println(err.Error(), ": error creating contract")
return
}
// Get the new contract record to make sure the transaction ran successfully
contractRecord, err := contractTransactionID.GetRecord(client)
if err != nil {
println(err.Error(), ": error retrieving contract creation record")
return
}
// Get the contract create result from the record
contractCreateResult, err := contractRecord.GetContractCreateResult()
if err != nil {
println(err.Error(), ": error retrieving contract creation result")
return
}
// Get the new contract ID from the receipt contained in the record
newContractID := *contractRecord.Receipt.ContractID
fmt.Printf("Contract create gas used: %v\n", contractCreateResult.GasUsed)
fmt.Printf("Contract create transaction fee: %v\n", contractRecord.TransactionFee)
fmt.Printf("contract: %v\n", newContractID)
}

Solidity Contract: https://drive.google.com/file/d/1YQ5B9Z2CL4i3R_4eSS3OQSEAbzSooehr/view?usp=sharing

答案1

得分: 0

我认为我在Discord上已经回答了这个问题,但为了完整起见,我认为问题在于你的代码在Json中寻找Bin时应该是bin

将以下代码:

smartContractByteCode := smartContract.Contracts["contract.sol:ScanInput"].Bin

改为:

smartContractByteCode := smartContract.Contracts["contract.sol:ScanInput"].bin

英文:

I think I responded to this in Discord, but here goes for completion. I think the issue is that your code looks for Bin in the Json when it's bin.

Switch
smartContractByteCode := smartContract.Contracts["contract.sol:ScanInput"].Bin

for

smartContractByteCode := smartContract.Contracts["contract.sol:ScanInput"].bin

huangapple
  • 本文由 发表于 2022年9月17日 02:58:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/73749265.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定