Return 交易类型?
Return type of transaction?
我是来自 fabric-samples 的 运行 chaincode-java。
@Transaction(intent = Transaction.TYPE.EVALUATE)
public ArrayList<Asset> GetAllAssets(final Context ctx) {
ChaincodeStub stub = ctx.getStub();
ArrayList<Asset> queryResults = new ArrayList<Asset>();
// To retrieve all assets from the ledger use getStateByRange with empty startKey & endKey.
// Giving empty startKey & endKey is interpreted as all the keys from beginning to end.
// As another example, if you use startKey = 'asset0', endKey = 'asset9' ,
// then getStateByRange will retrieve asset with keys between asset0 (inclusive) and asset9 (exclusive) in lexical order.
QueryResultsIterator<KeyValue> results = stub.getStateByRange("", "");
for (KeyValue result: results) {
Asset asset = genson.deserialize(result.getStringValue(), Asset.class);
System.out.println(asset);
queryResults.add(asset);
}
// final String response = genson.serialize(queryResults);
return queryResults;
}
GetAllAssets() 方法是 returning String,但我将其更改为 ArrayList。
因此,调用 GetAllAssets 时会抛出错误。
$ peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllAssets"]}'
Error: endorsement failure during query. response: status:500 message:"Unexpected error"
日志说
Thread[fabric-txinvoke:2,5,main] 11:15:01:224 INFO org.hyperledger.fabric.contract.ContractRouter processRequest Got invoke routing request
Thread[fabric-txinvoke:2,5,main] 11:15:01:226 INFO org.hyperledger.fabric.contract.ContractRouter processRequest Got the invoke request for:GetAllAssets []
Thread[fabric-txinvoke:2,5,main] 11:15:01:234 INFO org.hyperledger.fabric.contract.ContractRouter processRequest Got routing:GetAllAssets:org.hyperledger.fabric.samples.assettransfer.AssetTransfer
Thread[fabric-txinvoke:2,5,main] 11:15:01:274 SEVERE org.hyperledger.fabric.Logger error nulljava.lang.NullPointerException
at org.hyperledger.fabric.contract.execution.JSONTransactionSerializer.toBuffer(JSONTransactionSerializer.java:84)
at org.hyperledger.fabric.contract.execution.impl.ContractExecutionService.convertReturn(ContractExecutionService.java:89)
at org.hyperledger.fabric.contract.execution.impl.ContractExecutionService.executeRequest(ContractExecutionService.java:67)
at org.hyperledger.fabric.contract.ContractRouter.processRequest(ContractRouter.java:123)
at org.hyperledger.fabric.contract.ContractRouter.invoke(ContractRouter.java:134)
at org.hyperledger.fabric.shim.impl.ChaincodeInvocationTask.call(ChaincodeInvocationTask.java:106)
at org.hyperledger.fabric.shim.impl.InvocationTaskManager.lambda$newTask(InvocationTaskManager.java:265)
at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1736)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Thread[fabric-txinvoke:2,5,main] 11:15:01:276 SEVERE org.hyperledger.fabric.shim.impl.ChaincodeInvocationTask call [13733a23] Invoke failed with error code 500. Sending ERROR
我可以从交易中 return List
吗?除了String
,我还能return什么类型?有没有我可以看一下的文档?
先介绍一些背景知识; Java 中可用的 ContractAPI,Go 和 Typescript 用于生成 'model'整个合同的一部分,包括从交易功能传递和 returned 的数据类型。 (Java脚本根据其输入尽可能支持有限的子集)。
为了支持这一点,必须有某种 'serializer' 来处理数据。 'invoke(byte[]): byte[]' 的底层链代码 API 赋予开发人员序列化他们希望的方式的能力,尽管并非所有人都需要使用这种能力。
合约中有默认值'serializer'API;如果需要,可以换掉它。
具体回答问题;
return 类型可以是:
- 字符串,
- 数字(对于 Java 这是任何原始 'number' 类型)
- 布尔值,
- 已标注的其他类型
- 上面的数组
对于 'other types',有注释可用于定义类型,这些类型也可以传入和传出事务函数。
您可能会看到这样的内容:
@DataType()
public final class Complex {
@Property()
private final String id;
@Property()
private final Description description;
@Property()
private final int value;
public String getID() {
return id;
}
public int getValue() {
return value;
}
public Description getDescription(){
return description;
}
}
描述还有一个class以类似的方式注释。
这将生成如下所示的合同元数据
"Description": {
"$id": "Description",
"type": "object",
"properties": {
"colour": {
"type": "string"
},
"owners": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"Complex": {
"$id": "Complex",
"type": "object",
"properties": {
"id": {
"type": "string"
},
"value": {
"type": "number"
},
"description": {
"$ref": "Description"
}
}
}
关于合约模型,或合约元数据
在
处有一个 JSON 架构
https://github.com/hyperledger/fabric-chaincode-node/blob/main/apis/fabric-contract-api/schema/contract-schema.json
这不是限制吗?列表呢?
这是一个公平的评论,从 Java 的角度来看,像 ArrayList 或 Map 这样的东西对 return 来说是合理的。然而,挑战在于合同可能以不同的语言实施。此外,一旦部署,合约将 运行 一段时间,因此元数据在智能合约和客户端应用程序之间提供了强大的 'API Definition'。
哪些交易功能(也在元数据中)将被明确定义。
总结
我想提供更多示例(和文档!),但想先把它写下来。我们可以进行一些扩展和更改,并且愿意进行但时间有限!
作为这些存储库的维护者,如果这是一个感兴趣的领域,我们很乐意让人们加入进来。
我是来自 fabric-samples 的 运行 chaincode-java。
@Transaction(intent = Transaction.TYPE.EVALUATE)
public ArrayList<Asset> GetAllAssets(final Context ctx) {
ChaincodeStub stub = ctx.getStub();
ArrayList<Asset> queryResults = new ArrayList<Asset>();
// To retrieve all assets from the ledger use getStateByRange with empty startKey & endKey.
// Giving empty startKey & endKey is interpreted as all the keys from beginning to end.
// As another example, if you use startKey = 'asset0', endKey = 'asset9' ,
// then getStateByRange will retrieve asset with keys between asset0 (inclusive) and asset9 (exclusive) in lexical order.
QueryResultsIterator<KeyValue> results = stub.getStateByRange("", "");
for (KeyValue result: results) {
Asset asset = genson.deserialize(result.getStringValue(), Asset.class);
System.out.println(asset);
queryResults.add(asset);
}
// final String response = genson.serialize(queryResults);
return queryResults;
}
GetAllAssets() 方法是 returning String,但我将其更改为 ArrayList。
因此,调用 GetAllAssets 时会抛出错误。
$ peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllAssets"]}'
Error: endorsement failure during query. response: status:500 message:"Unexpected error"
日志说
Thread[fabric-txinvoke:2,5,main] 11:15:01:224 INFO org.hyperledger.fabric.contract.ContractRouter processRequest Got invoke routing request
Thread[fabric-txinvoke:2,5,main] 11:15:01:226 INFO org.hyperledger.fabric.contract.ContractRouter processRequest Got the invoke request for:GetAllAssets []
Thread[fabric-txinvoke:2,5,main] 11:15:01:234 INFO org.hyperledger.fabric.contract.ContractRouter processRequest Got routing:GetAllAssets:org.hyperledger.fabric.samples.assettransfer.AssetTransfer
Thread[fabric-txinvoke:2,5,main] 11:15:01:274 SEVERE org.hyperledger.fabric.Logger error nulljava.lang.NullPointerException
at org.hyperledger.fabric.contract.execution.JSONTransactionSerializer.toBuffer(JSONTransactionSerializer.java:84)
at org.hyperledger.fabric.contract.execution.impl.ContractExecutionService.convertReturn(ContractExecutionService.java:89)
at org.hyperledger.fabric.contract.execution.impl.ContractExecutionService.executeRequest(ContractExecutionService.java:67)
at org.hyperledger.fabric.contract.ContractRouter.processRequest(ContractRouter.java:123)
at org.hyperledger.fabric.contract.ContractRouter.invoke(ContractRouter.java:134)
at org.hyperledger.fabric.shim.impl.ChaincodeInvocationTask.call(ChaincodeInvocationTask.java:106)
at org.hyperledger.fabric.shim.impl.InvocationTaskManager.lambda$newTask(InvocationTaskManager.java:265)
at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1736)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Thread[fabric-txinvoke:2,5,main] 11:15:01:276 SEVERE org.hyperledger.fabric.shim.impl.ChaincodeInvocationTask call [13733a23] Invoke failed with error code 500. Sending ERROR
我可以从交易中 return List
吗?除了String
,我还能return什么类型?有没有我可以看一下的文档?
先介绍一些背景知识; Java 中可用的 ContractAPI,Go 和 Typescript 用于生成 'model'整个合同的一部分,包括从交易功能传递和 returned 的数据类型。 (Java脚本根据其输入尽可能支持有限的子集)。
为了支持这一点,必须有某种 'serializer' 来处理数据。 'invoke(byte[]): byte[]' 的底层链代码 API 赋予开发人员序列化他们希望的方式的能力,尽管并非所有人都需要使用这种能力。
合约中有默认值'serializer'API;如果需要,可以换掉它。
具体回答问题;
return 类型可以是:
- 字符串,
- 数字(对于 Java 这是任何原始 'number' 类型)
- 布尔值,
- 已标注的其他类型
- 上面的数组
对于 'other types',有注释可用于定义类型,这些类型也可以传入和传出事务函数。
您可能会看到这样的内容:
@DataType()
public final class Complex {
@Property()
private final String id;
@Property()
private final Description description;
@Property()
private final int value;
public String getID() {
return id;
}
public int getValue() {
return value;
}
public Description getDescription(){
return description;
}
}
描述还有一个class以类似的方式注释。
这将生成如下所示的合同元数据
"Description": {
"$id": "Description",
"type": "object",
"properties": {
"colour": {
"type": "string"
},
"owners": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"Complex": {
"$id": "Complex",
"type": "object",
"properties": {
"id": {
"type": "string"
},
"value": {
"type": "number"
},
"description": {
"$ref": "Description"
}
}
}
关于合约模型,或合约元数据
在
处有一个 JSON 架构
https://github.com/hyperledger/fabric-chaincode-node/blob/main/apis/fabric-contract-api/schema/contract-schema.json
这不是限制吗?列表呢? 这是一个公平的评论,从 Java 的角度来看,像 ArrayList 或 Map 这样的东西对 return 来说是合理的。然而,挑战在于合同可能以不同的语言实施。此外,一旦部署,合约将 运行 一段时间,因此元数据在智能合约和客户端应用程序之间提供了强大的 'API Definition'。
哪些交易功能(也在元数据中)将被明确定义。
总结 我想提供更多示例(和文档!),但想先把它写下来。我们可以进行一些扩展和更改,并且愿意进行但时间有限!
作为这些存储库的维护者,如果这是一个感兴趣的领域,我们很乐意让人们加入进来。