问题描述
在编写一些链码时,我突然开始收到此错误:
2021-06-05T20:45:34.045Z - 错误:[交易]:错误:无效 来自任何同行的回应。错误: peer=peer1.local:7051,status=500,message=error in Simulation: 执行交易失败 c33493ce22005d9e73b02e2b99d1d19daceb04f0ee9fb8fede0a3e1081ca9943: 无法启动链码 basic_1.0:32ca3f181f42e66b77c1026c31c92049336315143142535955a3f256d0249c18:链码注册失败:容器以1退出
我的代码之前运行良好,并且 TypeScript 仍然可以正常编译。
使用 docker logs ...
检查状态时,我看到:
2021-06-05 19:33:09.259 UTC [生命周期] 工作 -> WARN 073 不能 启动链码 'basic_1.0:5a649b5a8d084d83c86b02231ffa1b8e3e32e95f99de46e52588244fb9c99c59':链码注册失败:容器以1退出
此外,即使无法启动容器,检查链码是否已成功安装的调用也会返回 true。
解决方法
在四处挖掘时,我注意到链码容器在加载失败后自动停止。为了找到崩溃的容器,我使用了 docker ps -a
。当在那个上运行 docker logs ...
或使用 docker run -it ... /bin/sh
跳入容器时,我能够获得更多信息:
******** FAILED to run the application: Error: error in simulation: failed to execute transaction 6caf98016e71974a987a7f3a5295b518026c1f25ac117646db3dfcad89d179f7: 无法启动链码 basic_1.0:5a649b5a8d084d83c86b02231ffa1b8e3e32e95f99de46e52588244fb9c99c59:链码注册失败:容器以1退出
fabric-chaincode-node start --peer.address localhost:7051 --chaincode-id-name mycc
选项:--help 显示帮助
[boolean] -v,--version 显示版本
number [boolean] --peer.address [string] [required]
--grpc.max_send_message_length [数字] [默认值:-1] --grpc.max_receive_message_length [数字] [默认值:-1] --grpc.keepalive_time_ms [数字] [默认值:110000] --grpc.http2.min_time_between_pings_ms [数字] ] [默认值:110000] --grpc.keepalive_timeout_ms [编号] [默认值:20000] --grpc.http2.max_pings_without_data [编号] [默认值:0] --grpc.keepalive_permit_without_calls [编号] [默认值:1] --ssl -target-name-override [string] --chaincode-id-name [string] [required] --module-path [string] [default: "/usr/local/src"]
[MissingRefError: 无法从 id 解析引用数组 SomeClass#] { 消息:“无法从 id SomeClass#",missingRef: 'Array',missingSchema: '数组' } npm 错误!代码 ELIFECYCLE npm ERR!错误1
不幸的是,这仍然不是很有帮助,因为我的代码中没有丢失对 Array
的引用,而且从我在网上看到的情况来看,这个错误是由 JSON 验证库引发的。 Hyperledger Fabric 似乎正在内部做一些导致一些冲突的事情。
我将范围缩小到这一点:如果您尝试从继承自 @Object
的类中引用用 Contract
修饰的类中的静态函数或静态变量,Hyperledger Fabric TypeScript SDK 将崩溃。
例如,不要这样做:
@Object()
export class SomeClass {
public static PREFIX: string = "TEST";
...
}
然后在合同类中:
export class SomeContract extends Contract {
@Transaction()
public async SomeFunction(ctx: Context): Promise<string> {
return SomeClass.PREFIX;
}
相反,将静态变量和函数从 SomeClass
重构为 SomeClassHelper
或其他一些文件。以这种方式重构时,完全相同的代码可以正常工作。