我正在开发一个 Hyperledger Fabric 应用程序,使用 Java SDK 与智能合约进行交互。我的查询事务工作正常,但是当我尝试执行创建事务时,它失败并出现“合同异常”。并显示消息“无效交易”。
详情如下:
智能合约代码(Go):
我的 Fabric 网络上部署了智能合约。 CreateContract函数如下:
此函数使用提供的参数创建一个新合约,如果合约已存在,则抛出错误。
func (s *SmartContract) CreateContract(ctx contractapi.TransactionContextInterface, contractId string, client string, supplier string, description string) (string, error) {
if contractId == "" {
return "", fmt.Errorf("Contract Id cannot be empty.")
}
if client == "" {
return "", fmt.Errorf("Client field cannot be empty.")
}
if supplier == "" {
return "", fmt.Errorf("Supplier field cannot be empty.")
}
chatAsBytes, err := ctx.GetStub().GetState(contractId)
if err != nil {
return "", fmt.Errorf("Failed to read from world state. %s", err.Error())
}
if chatAsBytes == nil {
newContract := LegalContractSchema{
DocType: "Legal Contract",
Participants: []string{client, supplier},
Description: description,
}
newContractAsBytes, _ := json.Marshal(newContract)
err := ctx.GetStub().PutState(contractId, newContractAsBytes)
if err != nil {
return "", fmt.Errorf("Failed writing to world state. %s", err.Error())
}
return "Successfully created contract", nil
} else {
return "", fmt.Errorf("Failed to create contract schema, contract already exists.")
}
}
Java SDK代码:
我正在使用 Java SDK 与智能合约交互。我调用CreateContract函数的代码如下:
Gateway.Builder builder = Gateway.createBuilder()
.identity(wallet, "admin")
.networkConfig(networkConfigFile)
.discovery(true)
.commitTimeout(60, TimeUnit.SECONDS);
try (Gateway gateway = builder.connect()) {
Network network = gateway.getNetwork("mychannel");
Contract contract = network.getContract("legalContract");
// Submit a create transaction
byte[] createResult = contract.createTransaction("CreateContract")
.submit("contractId123", "ClientName", "SupplierName", "This is a test description");
System.out.println("Create Transaction Result: " + new String(createResult, StandardCharsets.UTF_8));
}
查询交易:
查询事务 (GetLegalContractCert) 使用相同的 Java 代码结构完美运行:
byte[] queryResult = contract.evaluateTransaction("GetLegalContractCert", "contractId123");
System.out.println("Query Result: " + new String(queryResult, StandardCharsets.UTF_8));
问题: 当我调用 CreateContract 函数时,出现以下错误:
Invalid transaction Contract Exception
查询事务工作正常,但创建事务失败。
我尝试过的:
环境:
我的连接配置文件如下所示:
{
"name": "test-network-org1",
"version": "1.0.0",
"client": {
"organization": "Org1",
"connection": {
"timeout": {
"peer": {
"endorser": "300"
}
}
}
},
"organizations": {
"Org1": {
"mspid": "Org1MSP",
"peers": [
"peer0.org1.example.com"
],
"certificateAuthorities": [
"ca.org1.example.com"
]
}
},
"peers": {
"peer0.org1.example.com": {
"url": "grpcs://localhost:7051",
"tlsCACerts": {
"pem": "-----BEGIN CERTIFICATE-----\XYF\n-----END CERTIFICATE-----\n"
},
"grpcOptions": {
"ssl-target-name-override": "peer0.org1.example.com",
"hostnameOverride": "peer0.org1.example.com"
}
}
},
"certificateAuthorities": {
"ca.org1.example.com": {
"url": "https://localhost:7054",
"caName": "ca-org1",
"tlsCACerts": {
"pem": ["-----BEGIN CERTIFICATE-----\XYZ\n-----END CERTIFICATE-----\n"]
},
"httpOptions": {
"verify": false
}
}
}
}
如果您正在使用(或可以使用)Fabric v2.4 或更高版本,则最佳解决方案是使用 Fabric Gateway 客户端 API 而不是 旧版 Java SDK 来构建客户端应用程序。
如果您确实无法迁移到当前的 Fabric 版本并且必须继续使用旧版 Java SDK,我怀疑您的问题可能是需要设置
as_localhost
配置属性以进行服务发现。这基于您的连接配置文件,列出了您的同级和订购者的 localhost 地址。请参阅 API 文档,了解需要此设置的场景以及如何使用环境变量进行配置。