英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论