0

我正在使用Hyperledger Fabric v1.4 first-network 示例来设置具有两个组织和四个对等点的区块链网络。是使用设置运行的 docker 进程的屏幕截图。

第一个网络示例使用背书策略,AND ('Org1MSP.peer','Org2MSP.peer')默认链码为chaincode_example02

为了与网络通信,我使用的是 JAVA SDK v1.4.1。我能够注册创建 HF 客户端和频道等,还能够创建用户和查询(读取)区块链而没有任何问题。

我面临的问题是尝试使用“调用”功能更新区块链时。

这是我在 JAVA 端看到的堆栈跟踪

2019-07-17 23:34:41,811 INFO  [http-nio-8080-exec-6] com.invincible.ngi.service.UtilityService: New channel initialized:mychannel
2019-07-17 23:34:41,812 INFO  [http-nio-8080-exec-6] com.invincible.ngi.service.UtilityService: Order added to the channel:orderer.example.com
2019-07-17 23:34:41,813 INFO  [http-nio-8080-exec-6] com.invincible.ngi.service.UtilityService: Peer added to the channel:peer0.org1.example.com
2019-07-17 23:34:43,570 INFO  [http-nio-8080-exec-6] org.hyperledger.fabric.sdk.Channel: Channel Channel{id: 6, name: mychannel} eventThread started shutdown: false  thread: null 
2019-07-17 23:34:46,696 ERROR [http-nio-8080-exec-6] com.invincible.ngi.service.QueryService: org.hyperledger.fabric.sdk.exception.TransactionEventException: Received invalid transaction event. Transaction ID 753436574ea481148f9d2da7d793f0ff1630c0c4b3106995240cf8b73aa1f1db status 10
java.util.concurrent.ExecutionException: org.hyperledger.fabric.sdk.exception.TransactionEventException: Received invalid transaction event. Transaction ID 753436574ea481148f9d2da7d793f0ff1630c0c4b3106995240cf8b73aa1f1db status 10
    at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
    at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
    at com.invincible.ngi.service.QueryService.updateBlockChain(QueryService.java:56)
    at com.invincible.ngi.resource.QueryResource.updateQuery(QueryResource.java:44)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1039)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:88)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:114)
    at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:104)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:853)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1587)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)
Caused by: org.hyperledger.fabric.sdk.exception.TransactionEventException: Received invalid transaction event. Transaction ID 753436574ea481148f9d2da7d793f0ff1630c0c4b3106995240cf8b73aa1f1db status 10
    at org.hyperledger.fabric.sdk.Channel$TL.lambda$fire$2(Channel.java:6227)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    ... 1 common frames omitted
2019-07-17 23:34:46,703 ERROR [http-nio-8080-exec-6] org.apache.juli.logging.DirectJDKLog: Servlet.service() for servlet [dispatcherServlet] in context with path [/api] threw exception [Request processing failed; nested exception is java.util.concurrent.ExecutionException: org.hyperledger.fabric.sdk.exception.TransactionEventException: Received invalid transaction event. Transaction ID 753436574ea481148f9d2da7d793f0ff1630c0c4b3106995240cf8b73aa1f1db status 10] with root cause
org.hyperledger.fabric.sdk.exception.TransactionEventException: Received invalid transaction event. Transaction ID 753436574ea481148f9d2da7d793f0ff1630c0c4b3106995240cf8b73aa1f1db status 10
    at org.hyperledger.fabric.sdk.Channel$TL.lambda$fire$2(Channel.java:6227)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

就是每个对等节点中出现的内容

在调查中,我发现这个问题是有效的,因为背书期望交易由每个组织的至少一个同行签署。这就是我初始化频道的方式。

    Channel channel = client.newChannel(ngiProperties.getChannel());
    logger.info("New channel initialized:" + ngiProperties.getChannel());
    Properties ordererProperties = new Properties();
    ordererProperties.setProperty("pemFile", ngiProperties.getOrdererServerCert());
    ordererProperties.setProperty("trustServerCertificate", ngiProperties.getOrdererTrustServerCertificate());
    ordererProperties.setProperty("hostnameOverride", ngiProperties.getOrdererHostnameOverride());
    ordererProperties.setProperty("sslProvider", ngiProperties.getOrdererSslProvider());
    ordererProperties.setProperty("negotiationType", ngiProperties.getOrdererNegotiationType());
    ordererProperties.put("grpc.NettyChannelBuilderOption.keepAliveTime", new Object[]{ngiProperties.getOrdererKeepAliveTime(), TimeUnit.MINUTES});
    ordererProperties.put("grpc.NettyChannelBuilderOption.keepAliveTimeout", new Object[]{ngiProperties.getOrdererKeepAliveTimeout(), TimeUnit.SECONDS});
    channel.addOrderer(client.newOrderer(ngiProperties.getOrdererHost(), ngiProperties.getOrdererGrpc(), ordererProperties));
    logger.info("Order added to the channel:" + ngiProperties.getOrdererHost()); // orderer.example.com
    Properties peerProperties = new Properties();
    peerProperties.setProperty("pemFile", ngiProperties.getPeerAServerCert());
    peerProperties.setProperty("trustServerCertificate", ngiProperties.getPeerATrustServerCertificate());
    peerProperties.setProperty("hostnameOverride", ngiProperties.getPeerAHostnameOverride());
    peerProperties.setProperty("sslProvider", ngiProperties.getPeerASslProvider());
    peerProperties.setProperty("negotiationType", ngiProperties.getPeerANegotiationType());
    channel.addPeer(client.newPeer(ngiProperties.getPeerAHost(), ngiProperties.getPeerAGrpc(), peerProperties));
    logger.info("Peer added to the channel:" + ngiProperties.getPeerAHost()); // peer0.org1.example.com
    channel.initialize();

现在我意识到,如果只是在通道中添加来自 org2 的另一个对等点,问题就会得到解决,即,只需在初始化通道之前添加下面的代码

    peerProperties = new Properties();
    peerProperties.setProperty("pemFile", ngiProperties.getPeerCServerCert());
    peerProperties.setProperty("trustServerCertificate", ngiProperties.getPeerCTrustServerCertificate());
    peerProperties.setProperty("hostnameOverride", ngiProperties.getPeerCHostnameOverride());
    peerProperties.setProperty("sslProvider", ngiProperties.getPeerCSslProvider());
    peerProperties.setProperty("negotiationType", ngiProperties.getPeerCNegotiationType());
    channel.addPeer(client.newPeer(ngiProperties.getPeerCHost(), ngiProperties.getPeerCGrpc(), peerProperties));
    logger.info("Peer added to the channel:" + ngiProperties.getPeerCHost()); // peer0.org2.example.com

有了这个,我有几个问题

  1. 如果仅通过在通道初始化中添加所需的背书节点来实现交易的有效性,那么执行背书规则的意义何在?如果 org1 以某种方式设法获取 org2 的对等详细信息,那么 org1 是否可以在未经 org2 同意的情况下提交事务?
  2. 设置向 HFClient 提交交易的用户有什么意义?在交易过程中,用户上下文及其注册在哪里以及如何由结构验证?
  3. 理想情况下,我希望如果我有AND ('Org1MSP.peer','Org2MSP.peer')背书策略并且有一个 UI 来提交交易,在 HFClient 中设置的用户上下文应该具有“Org1MSP.peer”签名,并且 org2 中具有“Org2MSP.peer”的用户应该得到通知提交的交易。仅当具有签名“Org2MSP.peer”的任何用户签名时才应提交事务。无论我使用多少对等方来初始化通道,所有这些都应该发生。我的期望有效吗?如果是这样如何用fabric JAVA SDK实现它?
4

1 回答 1

0

如果仅通过在通道初始化中添加所需的背书节点来实现交易的有效性,那么执行背书规则的意义何在?如果 org1 以某种方式设法获取 org2 的对等详细信息,那么 org1 是否可以在未经 org2 同意的情况下提交事务?

  1. 背书节点是安装链码的节点。现在,当您的客户端发送交易提案进行背书时,它首先检查结构运行时的背书策略。在您的情况下,AND('Org1MSP.peer','Org2MSP.peer')这意味着两个背书人都应该返回提案响应,但您在频道上只有一个对等方,因此它在不符合背书政策规则的第一步本身就失败了。**背书政策的执行提供了一种方法来管理一个同行篡改数据和双重支出。**这里有一个非常详细的概述。

  2. 由于网络是分布式的,我几乎没有任何组织可以访问任何其他组织的证书。

PS 交易签名是一个自动化过程,任何组织都不会让人们手动签署交易。

希望这可以帮助。

设置向 HFClient 提交交易的用户有什么意义?在交易过程中,用户上下文及其注册在哪里以及如何由结构验证?

要知道谁想要改变区块链中的数据状态。例如,当 org1 想要改变汽车的所有权时,当数据提交时,什么时候才能知道谁改变了汽车的所有权。

理想情况下,如果我有 AND ('Org1MSP.peer','Org2MSP.peer') 作为背书策略并且有一个 UI 来提交交易,那么在 HFClient 中设置的用户上下文应该有 'Org1MSP.peer' 签名和org2 中具有“Org2MSP.peer”的用户应收到有关提交交易的通知。仅当具有签名“Org2MSP.peer”的任何用户签名时才应提交事务。无论我使用多少对等方来初始化通道,所有这些都应该发生。我的期望有效吗?如果是这样如何用fabric JAVA SDK实现它?

好吧,客户只是发送交易提案,即要执行的操作和元数据,并使用其私钥对其进行签名。链码容器将处理自己的证书。实际上没有人会手动签署交易提案,它是一个由背书节点执行的自动化过程。

于 2019-07-18T05:22:29.520 回答