From 1689a50cedd18850383f8cd5f64bfec82bed0104 Mon Sep 17 00:00:00 2001 From: shaozhuguang Date: Thu, 11 Apr 2019 16:21:23 +0800 Subject: [PATCH 01/43] Add tikv-client module and modify dbconnection to auto check way! --- source/pom.xml | 1 + source/stp/pom.xml | 21 +++ source/stp/stp-communication/pom.xml | 35 +++++ .../stp/communication/MessageHandler.java | 21 +++ .../stp/communication/RemoteNode.java | 44 ++++++ .../stp/communication/RemoteSession.java | 94 +++++++++++++ .../communication/RemoteSessionManager.java | 98 +++++++++++++ .../stp/communication/inner/Receiver.java | 27 ++++ .../stp/communication/inner/Sender.java | 35 +++++ .../communication/message/LoadMessage.java | 21 +++ .../message/TransferMessage.java | 46 ++++++ .../test/java/com/jd/blockchain/StpTest.java | 131 ++++++++++++++++++ 12 files changed, 574 insertions(+) create mode 100644 source/stp/pom.xml create mode 100644 source/stp/stp-communication/pom.xml create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/MessageHandler.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteNode.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteSession.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteSessionManager.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/inner/Receiver.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/inner/Sender.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/LoadMessage.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/TransferMessage.java create mode 100644 source/stp/stp-communication/src/test/java/com/jd/blockchain/StpTest.java diff --git a/source/pom.xml b/source/pom.xml index 2e510d96..cee45061 100644 --- a/source/pom.xml +++ b/source/pom.xml @@ -36,6 +36,7 @@ tools test deployment + stp diff --git a/source/stp/pom.xml b/source/stp/pom.xml new file mode 100644 index 00000000..fd7fc35e --- /dev/null +++ b/source/stp/pom.xml @@ -0,0 +1,21 @@ + + + + + jdchain-root + com.jd.blockchain + 0.9.0-SNAPSHOT + + 4.0.0 + + stp + pom + + stp-communication + + + + UTF-8 + + diff --git a/source/stp/stp-communication/pom.xml b/source/stp/stp-communication/pom.xml new file mode 100644 index 00000000..fcf21bc1 --- /dev/null +++ b/source/stp/stp-communication/pom.xml @@ -0,0 +1,35 @@ + + + + + stp + com.jd.blockchain + 0.9.0-SNAPSHOT + + 4.0.0 + + stp-communication + + stp-communication + + + UTF-8 + 1.8 + 1.8 + + + + + junit + junit + test + + + + io.netty + netty-all + 4.1.29.Final + + + diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/MessageHandler.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/MessageHandler.java new file mode 100644 index 00000000..cae8a853 --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/MessageHandler.java @@ -0,0 +1,21 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.MessageHandler + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/11 上午10:59 + * Description: + */ +package com.jd.blockchain.stp.communication; + +/** + * + * @author shaozhuguang + * @create 2019/4/11 + * @since 1.0.0 + */ + +public interface MessageHandler { + + void receive(byte[] key, byte[] data, RemoteSession session); +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteNode.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteNode.java new file mode 100644 index 00000000..18fcafd2 --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteNode.java @@ -0,0 +1,44 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.RemoteNode + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/11 下午3:40 + * Description: + */ +package com.jd.blockchain.stp.communication; + +/** + * + * @author shaozhuguang + * @create 2019/4/11 + * @since 1.0.0 + */ + +public class RemoteNode { + + private int port; + + private String hostName; + + public RemoteNode(String hostName, int port) { + this.port = port; + this.hostName = hostName; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public String getHostName() { + return hostName; + } + + public void setHostName(String hostName) { + this.hostName = hostName; + } +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteSession.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteSession.java new file mode 100644 index 00000000..4a047e7f --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteSession.java @@ -0,0 +1,94 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.RemoteSession + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/11 上午11:15 + * Description: + */ +package com.jd.blockchain.stp.communication; + +import com.jd.blockchain.stp.communication.inner.Receiver; +import com.jd.blockchain.stp.communication.inner.Sender; +import com.jd.blockchain.stp.communication.message.LoadMessage; + +import java.net.InetAddress; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Future; +import java.util.concurrent.Semaphore; + +/** + * + * @author shaozhuguang + * @create 2019/4/11 + * @since 1.0.0 + */ + +public class RemoteSession { + + private String id; + + private RemoteNode remoteNode; + + private Sender sender; + + private Receiver receiver; + + private MessageHandler messageHandler; + + public void initHandler(MessageHandler messageHandler) { + + } + + public void connect() { + + } + + public byte[] send(LoadMessage loadMessage) { + + return null; + } + + public Future asyncSend(LoadMessage loadMessage) { + return null; + } + + public Future asyncSend(LoadMessage loadMessage, CountDownLatch countDownLatch) { + return null; + } + + public byte[] send(byte[] loadMessage) { + + return null; + } + + public Future asyncSend(byte[] loadMessage) { + + return null; + } + + public Future asyncSend(byte[] loadMessage, CountDownLatch countDownLatch) { + + return null; + } + + public void reply(byte[] key, LoadMessage loadMessage) { + + } + + public void asyncReply(byte[] key, LoadMessage loadMessage) { + + } + + public void reply(byte[] key, byte[] loadMessage) { + + } + + public void asyncReply(byte[] key, byte[] loadMessage) { + + } + + public void close() { + + } +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteSessionManager.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteSessionManager.java new file mode 100644 index 00000000..2e87cf16 --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteSessionManager.java @@ -0,0 +1,98 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.RemoteSessionManager + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/11 上午11:22 + * Description: + */ +package com.jd.blockchain.stp.communication; + +import com.jd.blockchain.stp.communication.inner.Receiver; + +import java.net.InetAddress; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * + * @author shaozhuguang + * @create 2019/4/11 + * @since 1.0.0 + */ + +public class RemoteSessionManager { + + private static Map receiverMap = new ConcurrentHashMap<>(); + + private static final Lock lock = new ReentrantLock(); + + public RemoteSessionManager(int listenPort) { + if (listenPort <= 0) { + throw new IllegalArgumentException("Illegal port, please check !!!"); + } + + if (!receiverMap.containsKey(listenPort)) { + try { + lock.lock(); + if (!receiverMap.containsKey(listenPort)) { + Receiver receiver = initReceiver(listenPort); + receiverMap.put(listenPort, receiver); + } + } finally { + lock.unlock(); + } + } + } + + public RemoteSession newSession(RemoteNode remoteNode) { + return newSession(toRemoteId(remoteNode), remoteNode); + } + + public RemoteSession newSession(String remoteId, RemoteNode remoteNode) { + return newSession(remoteId, remoteNode, null); + } + + public RemoteSession newSession(RemoteNode remoteNode, MessageHandler messageHandler) { + return newSession(toRemoteId(remoteNode), remoteNode, messageHandler); + } + + public RemoteSession newSession(String remoteId, RemoteNode remoteNode, MessageHandler messageHandler) { + + + return null; + } + + public RemoteSession[] newSessions(RemoteNode[] remoteNodes) { + + + return null; + } + + public RemoteSession[] newSessions(String[] remoteIds, RemoteNode[] remoteNodes) { + + return null; + } + + public RemoteSession[] newSessions(RemoteNode[] remoteNodes, MessageHandler messageHandler) { + + return null; + } + + public RemoteSession[] newSessions(String[] remoteIds, RemoteNode[] remoteNodes, MessageHandler messageHandler) { + + return null; + } + + public String toRemoteId(RemoteNode remoteNode) { + + return null; + } + + private Receiver initReceiver(int port) { + + return null; + } +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/inner/Receiver.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/inner/Receiver.java new file mode 100644 index 00000000..698c52b8 --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/inner/Receiver.java @@ -0,0 +1,27 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.inner.Receiver + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/11 上午10:59 + * Description: + */ +package com.jd.blockchain.stp.communication.inner; + +import com.jd.blockchain.stp.communication.MessageHandler; + +/** + * + * @author shaozhuguang + * @create 2019/4/11 + * @since 1.0.0 + */ + +public class Receiver { + + private MessageHandler messageHandler; + + public void listen() { + + } +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/inner/Sender.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/inner/Sender.java new file mode 100644 index 00000000..8072c675 --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/inner/Sender.java @@ -0,0 +1,35 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.inner.Sender + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/11 上午10:58 + * Description: + */ +package com.jd.blockchain.stp.communication.inner; + +import java.net.InetAddress; + +/** + * + * @author shaozhuguang + * @create 2019/4/11 + * @since 1.0.0 + */ + +public class Sender { + + private InetAddress inetAddress; + + public void connect() { + + } + + public void send(String message) { + + } + + public void send(byte[] message) { + + } +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/LoadMessage.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/LoadMessage.java new file mode 100644 index 00000000..acdedee2 --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/LoadMessage.java @@ -0,0 +1,21 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.message.LoadMessage + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/11 上午10:59 + * Description: + */ +package com.jd.blockchain.stp.communication.message; + +/** + * + * @author shaozhuguang + * @create 2019/4/11 + * @since 1.0.0 + */ + +public interface LoadMessage { + + byte[] toBytes(); +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/TransferMessage.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/TransferMessage.java new file mode 100644 index 00000000..eac2d2a2 --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/TransferMessage.java @@ -0,0 +1,46 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.message.TransferMessage + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/11 上午11:00 + * Description: + */ +package com.jd.blockchain.stp.communication.message; + +/** + * + * @author shaozhuguang + * @create 2019/4/11 + * @since 1.0.0 + */ + +public class TransferMessage { + + private byte[] key; + + private byte[] load; + + public byte[] getKey() { + return key; + } + + public void setKey(byte[] key) { + this.key = key; + } + + public byte[] getLoad() { + return load; + } + + public void setLoad(byte[] load) { + this.load = load; + } + + public String toBase64() { + + + + return null; + } +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/test/java/com/jd/blockchain/StpTest.java b/source/stp/stp-communication/src/test/java/com/jd/blockchain/StpTest.java new file mode 100644 index 00000000..04c7f1e4 --- /dev/null +++ b/source/stp/stp-communication/src/test/java/com/jd/blockchain/StpTest.java @@ -0,0 +1,131 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.StpTest + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/11 下午3:31 + * Description: + */ +package com.jd.blockchain; + +import com.jd.blockchain.stp.communication.MessageHandler; +import com.jd.blockchain.stp.communication.RemoteNode; +import com.jd.blockchain.stp.communication.RemoteSession; +import com.jd.blockchain.stp.communication.RemoteSessionManager; +import com.jd.blockchain.stp.communication.message.LoadMessage; +import org.junit.Before; +import org.junit.Test; + +import java.net.InetAddress; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Future; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; + +/** + * + * @author shaozhuguang + * @create 2019/4/11 + * @since 1.0.0 + */ + +public class StpTest { + + private int listenPort = 6000; + + private int maxWaitTime = 2000; + + private RemoteNode[] remoteNodes = new RemoteNode[3]; + + @Before + public void init() { + for (int i = 0; i < remoteNodes.length; i++) { + remoteNodes[i] = new RemoteNode("127.0.0.1", 6001 + i); + } + } + + + @Test + public void test() { + // 创建RemoteSessionManager对象 + RemoteSessionManager sessionManager = new RemoteSessionManager(listenPort); + + // 创建RemoteSession[]对象 + RemoteSession[] remoteSessions = sessionManager.newSessions(remoteNodes); + + // 设置MessageHandler并连接 + for (RemoteSession remoteSession : remoteSessions) { + + // 设置MessageHandler + remoteSession.initHandler(new StpMessageHandler()); + + // session连接 + remoteSession.connect(); + } + + // 生成请求对象 + LoadMessage loadMessage = new StpLoadMessage(); + + // 异步发送处理过程 + + CountDownLatch countDownLatch = new CountDownLatch(remoteSessions.length); + + // 发送请求至remotes + LinkedList> responses = new LinkedList<>(); + for (RemoteSession remoteSession : remoteSessions) { + Future response = remoteSession.asyncSend(loadMessage, countDownLatch); + responses.addLast(response); + } + + // 超时判断 + try { + if (countDownLatch.await(maxWaitTime, TimeUnit.MILLISECONDS)) { + // 汇总异步消息结果 + LinkedList receiveResponses = new LinkedList<>(); + // 通过迭代器遍历链表 + Iterator> iterator = responses.iterator(); + while (iterator.hasNext()) { + Future response = iterator.next(); + // 判断是否已完成,对于没有完成的直接放弃(因为已经超时) + if (response.isDone()) { + receiveResponses.addLast(response.get()); + } + } + + //TODO 检查汇总后的应答消息,准备开始新一轮的请求 + + + + + } + } catch (Exception e) { + + } + } + + + public static class StpMessageHandler implements MessageHandler { + + @Override + public void receive(byte[] key, byte[] data, RemoteSession session) { + // 作为Receiver接收到请求消息后需要发送应答 + // 生成应答消息 + LoadMessage replyLoadMessage = new StpLoadMessage(); + + // 发送应答消息(注意key必须保持一致) + // 异步发送应答消息可使用asyncReply + session.reply(key, replyLoadMessage); + } + } + + public static class StpLoadMessage implements LoadMessage { + + @Override + public byte[] toBytes() { + return new byte[0]; + } + } +} \ No newline at end of file From 99f8063c8740ce7d5e324b750b75048a7ceac6d9 Mon Sep 17 00:00:00 2001 From: zhangshuang Date: Thu, 11 Apr 2019 16:51:04 +0800 Subject: [PATCH 02/43] add state transfer layer frame code --- source/peer/pom.xml | 5 ++ .../statetransfer/DataSequenceReaderImpl.java | 25 ++++++ .../statetransfer/DataSequenceWriterImpl.java | 22 +++++ source/pom.xml | 1 + source/state-transfer/pom.xml | 23 +++++ .../statetransfer/DSProcessManager.java | 44 ++++++++++ .../statetransfer/DSTransferProcess.java | 84 +++++++++++++++++++ .../statetransfer/DataSequenceElement.java | 49 +++++++++++ .../statetransfer/DataSequenceInfo.java | 37 ++++++++ .../statetransfer/DataSequenceMsgHandle.java | 32 +++++++ .../statetransfer/DataSequenceReader.java | 22 +++++ .../statetransfer/DataSequenceWriter.java | 17 ++++ 12 files changed, 361 insertions(+) create mode 100644 source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceReaderImpl.java create mode 100644 source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceWriterImpl.java create mode 100644 source/state-transfer/pom.xml create mode 100644 source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DSProcessManager.java create mode 100644 source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DSTransferProcess.java create mode 100644 source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceElement.java create mode 100644 source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceInfo.java create mode 100644 source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceMsgHandle.java create mode 100644 source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceReader.java create mode 100644 source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceWriter.java diff --git a/source/peer/pom.xml b/source/peer/pom.xml index 01311d5c..51746e7d 100644 --- a/source/peer/pom.xml +++ b/source/peer/pom.xml @@ -20,6 +20,11 @@ consensus-framework ${project.version} + + com.jd.blockchain + state-transfer + ${project.version} + com.jd.blockchain ledger-rpc diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceReaderImpl.java b/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceReaderImpl.java new file mode 100644 index 00000000..cd2677ac --- /dev/null +++ b/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceReaderImpl.java @@ -0,0 +1,25 @@ +package com.jd.blockchain.peer.statetransfer; + +import com.jd.blockchain.statetransfer.DataSequenceElement; +import com.jd.blockchain.statetransfer.DataSequenceInfo; +import com.jd.blockchain.statetransfer.DataSequenceReader; + +/** + *数据序列差异的提供者需要使用的回调接口实现类 + * @author zhangshuang + * @create 2019/4/11 + * @since 1.0.0 + * + */ +public class DataSequenceReaderImpl implements DataSequenceReader { + + @Override + public DataSequenceInfo getDSInfo(String id) { + return null; + } + + @Override + public DataSequenceElement[] getDSContent(String id, long from, long to) { + return null; + } +} diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceWriterImpl.java b/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceWriterImpl.java new file mode 100644 index 00000000..e2c48601 --- /dev/null +++ b/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceWriterImpl.java @@ -0,0 +1,22 @@ +package com.jd.blockchain.peer.statetransfer; + +import com.jd.blockchain.statetransfer.DataSequenceElement; +import com.jd.blockchain.statetransfer.DataSequenceInfo; +import com.jd.blockchain.statetransfer.DataSequenceReader; +import com.jd.blockchain.statetransfer.DataSequenceWriter; + +/** + *数据序列差异的请求者需要使用的回调接口实现类 + * @author zhangshuang + * @create 2019/4/11 + * @since 1.0.0 + * + */ +public class DataSequenceWriterImpl implements DataSequenceWriter { + + + @Override + public void updateDSInfo(String id, DataSequenceElement[] diffContents) { + + } +} diff --git a/source/pom.xml b/source/pom.xml index cee45061..0a03b26c 100644 --- a/source/pom.xml +++ b/source/pom.xml @@ -32,6 +32,7 @@ storage gateway peer + state-transfer sdk tools test diff --git a/source/state-transfer/pom.xml b/source/state-transfer/pom.xml new file mode 100644 index 00000000..9c3f04be --- /dev/null +++ b/source/state-transfer/pom.xml @@ -0,0 +1,23 @@ + + 4.0.0 + + com.jd.blockchain + jdchain-root + 0.9.0-SNAPSHOT + + state-transfer + + + + com.jd.blockchain + stp-communication + ${project.version} + + + + + + + diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DSProcessManager.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DSProcessManager.java new file mode 100644 index 00000000..cc849eba --- /dev/null +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DSProcessManager.java @@ -0,0 +1,44 @@ +package com.jd.blockchain.statetransfer; + +import com.jd.blockchain.stp.communication.RemoteSession; +import com.jd.blockchain.stp.communication.RemoteSessionManager; + +import java.net.InetSocketAddress; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * + * @author zhangshuang + * @create 2019/4/11 + * @since 1.0.0 + */ +public class DSProcessManager { + + private Map dSProcessMap = new ConcurrentHashMap<>(); + private RemoteSession[] remoteSessions; + + DSTransferProcess startDSProcess(DataSequenceInfo dsInfo, InetSocketAddress listener, InetSocketAddress[] targets, DataSequenceWriter dsWriter, DataSequenceReader dsReader) { + + RemoteSessionManager remoteSessionManager = new RemoteSessionManager(listener.getPort()); + DSTransferProcess dsTransferProcess = new DSTransferProcess(dsInfo, remoteSessionManager, targets, dsWriter, dsReader); + + dsTransferProcess.start(); + remoteSessions = dsTransferProcess.getSessions(); + + for(RemoteSession session : remoteSessions) { + dsTransferProcess.send(DSTransferProcess.DataSequenceMsgType.CMD_DSINFO, session); + } + + + dSProcessMap.put(dsInfo.getId(), dsTransferProcess); + + return dsTransferProcess; + } + + void setDSReader(DataSequenceReader reader) { + + } + + +} diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DSTransferProcess.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DSTransferProcess.java new file mode 100644 index 00000000..55a1402c --- /dev/null +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DSTransferProcess.java @@ -0,0 +1,84 @@ +package com.jd.blockchain.statetransfer; + +import com.jd.blockchain.stp.communication.RemoteNode; +import com.jd.blockchain.stp.communication.RemoteSession; +import com.jd.blockchain.stp.communication.RemoteSessionManager; + +import java.net.InetSocketAddress; + +/** + * + * @author zhangshuang + * @create 2019/4/11 + * @since 1.0.0 + */ +public class DSTransferProcess { + + private InetSocketAddress[] targets; + private DataSequenceWriter dsWriter; + private DataSequenceReader dsReader; + private DataSequenceInfo dsInfo; + private RemoteSessionManager remoteSessionManager; + private RemoteSession[] remoteSessions; + private String id; + + + public DSTransferProcess(DataSequenceInfo dsInfo, RemoteSessionManager remoteSessionManager, InetSocketAddress[] targets, DataSequenceWriter dsWriter, DataSequenceReader dsReader) { + + this.dsInfo = dsInfo; + this.targets = targets; + this.dsWriter = dsWriter; + this.dsReader = dsReader; + this.remoteSessionManager = remoteSessionManager; + this.id = dsInfo.getId(); + + } + + void send(DataSequenceMsgType msgType, RemoteSession session) { + + //session.send(); + + } + + byte[] createMsg(DataSequenceMsgType msgType) { + return null; + } + + public void computeDiff() { + //todo + } + + public void getDSInfo(String id) { + //todo + } + + public RemoteSession[] getSessions() { + //todo + return remoteSessions; + } + + public void start() { + + RemoteNode[] remoteNodes = new RemoteNode[targets.length]; + + for (int i = 0; i< remoteNodes.length; i++) { + remoteNodes[i] = new RemoteNode(targets[i].getHostName(), targets[i].getPort()); + } + + remoteSessions = remoteSessionManager.newSessions(remoteNodes); + + for (int i = 0; i < remoteSessions.length; i++) { + DataSequenceMsgHandle msgHandle = new DataSequenceMsgHandle(dsReader, dsWriter); + remoteSessions[i].initHandler(msgHandle); + remoteSessions[i].connect(); + } + } + + enum DataSequenceMsgType { + + CMD_DSINFO, + CMD_GETDSDIFF + } + + +} diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceElement.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceElement.java new file mode 100644 index 00000000..e1e904ed --- /dev/null +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceElement.java @@ -0,0 +1,49 @@ +package com.jd.blockchain.statetransfer; + +/** + *数据序列复制的元素或单位 + * @author zhangshuang + * @create 2019/4/11 + * @since 1.0.0 + */ +public class DataSequenceElement { + + //数据序列的唯一标识符; + private String id; + + //数据序列的某个高度; + private long height; + + //对应某个高度的数据序列内容 + private byte[][] data; + + public DataSequenceElement(String id, long height, byte[][] data) { + this.id = id; + this.height = height; + this.data = data; + } + + public long getHeight() { + return height; + } + + public void setHeight(long height) { + this.height = height; + } + + public String getId() { + return id; + } + + public void setId(String id) { + id = id; + } + + public byte[][] getData() { + return data; + } + + public void setData(byte[][] data) { + this.data = data; + } +} diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceInfo.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceInfo.java new file mode 100644 index 00000000..8aa45566 --- /dev/null +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceInfo.java @@ -0,0 +1,37 @@ +package com.jd.blockchain.statetransfer; + +/** + *共识结点上的某个数据序列的当前状态信息,每个共识结点可以对应任意个数据序列; + * @author zhangshuang + * @create 2019/4/11 + * @since 1.0.0 + */ +public class DataSequenceInfo { + + //数据序列的唯一标识 + private String id; + + //数据序列的当前高度 + private long height; + + public DataSequenceInfo(String id, long height) { + this.id = id; + this.height = height; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public long getHeight() { + return height; + } + + public void setHeight(long height) { + this.height = height; + } +} diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceMsgHandle.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceMsgHandle.java new file mode 100644 index 00000000..878869ad --- /dev/null +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceMsgHandle.java @@ -0,0 +1,32 @@ +package com.jd.blockchain.statetransfer; + +import com.jd.blockchain.stp.communication.MessageHandler; +import com.jd.blockchain.stp.communication.RemoteSession; + +/** + * + * @author zhangshuang + * @create 2019/4/11 + * @since 1.0.0 + */ +public class DataSequenceMsgHandle implements MessageHandler { + + DataSequenceReader dsReader; + DataSequenceWriter dsWriter; + + public DataSequenceMsgHandle(DataSequenceReader dsReader, DataSequenceWriter dsWriter) { + this.dsReader = dsReader; + this.dsWriter = dsWriter; + } + + @Override + public void receive(byte[] key, byte[] data, RemoteSession session) { + + } + + /** + * + * + */ + +} diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceReader.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceReader.java new file mode 100644 index 00000000..5662c117 --- /dev/null +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceReader.java @@ -0,0 +1,22 @@ +package com.jd.blockchain.statetransfer; +/** + *数据序列差异的提供者需要使用的回调接口 + * @author zhangshuang + * @create 2019/4/11 + * @since 1.0.0 + */ +public interface DataSequenceReader { + + /** + * 差异的提供者根据输入的数据序列标识符获取当前的数据序列信息; + * + */ + DataSequenceInfo getDSInfo(String id); + + + /** + * 差异的提供者根据输入的数据序列标识符以及起始,结束高度获得数据序列的差异内容; + * + */ + DataSequenceElement[] getDSContent(String id, long from, long to); +} diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceWriter.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceWriter.java new file mode 100644 index 00000000..0c45de18 --- /dev/null +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceWriter.java @@ -0,0 +1,17 @@ +package com.jd.blockchain.statetransfer; + +/** + *数据序列差异的请求者获得差异内容后需要回调该接口,通过接口提供的方法对指定数据序列执行差异内容的重放,并更新数据序列的当前状态; + * @author zhangshuang + * @create 2019/4/11 + * @since 1.0.0 + */ +public interface DataSequenceWriter { + + /** + *更新数据序列的当前状态 + * return void + */ + void updateDSInfo(String id, DataSequenceElement[] diffContents); + +} From 562d801e3fdedb1510bae3defe83e977bbe253bf Mon Sep 17 00:00:00 2001 From: shaozhuguang Date: Wed, 17 Apr 2019 17:15:08 +0800 Subject: [PATCH 03/43] Add stp communication module --- source/pom.xml | 6 + .../statetransfer/DSProcessManager.java | 5 +- .../statetransfer/DSTransferProcess.java | 8 +- .../statetransfer/DataSequenceMsgHandle.java | 11 +- source/stp/stp-communication/pom.xml | 15 ++ .../stp/communication/MessageExecute.java | 36 +++ .../stp/communication/MessageHandler.java | 21 -- .../stp/communication/RemoteSession.java | 75 +++--- .../communication/RemoteSessionManager.java | 98 -------- .../callback/CallBackBarrier.java | 56 +++++ .../callback/CallBackDataListener.java | 70 ++++++ .../connection/AbstractAsyncExecutor.java | 51 ++++ .../connection/AsyncExecutor.java | 25 ++ .../communication/connection/Connection.java | 120 ++++++++++ .../communication/connection/Receiver.java | 132 +++++++++++ .../stp/communication/connection/Sender.java | 162 +++++++++++++ .../handler/HeartBeatReceiverHandler.java | 41 ++++ .../handler/HeartBeatReceiverTrigger.java | 40 ++++ .../handler/HeartBeatSenderHandler.java | 42 ++++ .../handler/HeartBeatSenderTrigger.java | 48 ++++ .../connection/handler/ReceiverHandler.java | 223 ++++++++++++++++++ .../connection/handler/SenderHandler.java | 46 ++++ .../connection/handler/WatchDogHandler.java | 183 ++++++++++++++ .../connection/listener/ReplyListener.java | 74 ++++++ .../stp/communication/inner/Receiver.java | 27 --- .../stp/communication/inner/Sender.java | 35 --- .../manager/ConnectionManager.java | 110 +++++++++ .../manager/RemoteSessionManager.java | 132 +++++++++++ .../message/AbstractMessage.java | 30 +++ .../message/HeartBeatMessage.java | 57 +++++ .../stp/communication/message/IMessage.java | 25 ++ .../communication/message/SessionMessage.java | 95 ++++++++ .../message/TransferMessage.java | 128 +++++++++- .../stp/communication/node/LocalNode.java | 52 ++++ .../communication/{ => node}/RemoteNode.java | 26 +- .../com/jd/blockchain/SessionMessageTest.java | 37 +++ .../test/java/com/jd/blockchain/StpTest.java | 131 ---------- source/test/pom.xml | 1 + source/test/test-stp-community/pom.xml | 36 +++ .../stp/commucation/MyMessageExecutor.java | 37 +++ .../test/java/com/jd/blockchain/StpTest.java | 185 +++++++++++++++ 41 files changed, 2355 insertions(+), 377 deletions(-) create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/MessageExecute.java delete mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/MessageHandler.java delete mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteSessionManager.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackBarrier.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackDataListener.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/AbstractAsyncExecutor.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/AsyncExecutor.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Connection.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Receiver.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Sender.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatReceiverHandler.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatReceiverTrigger.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatSenderHandler.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatSenderTrigger.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/ReceiverHandler.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/SenderHandler.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/WatchDogHandler.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/listener/ReplyListener.java delete mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/inner/Receiver.java delete mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/inner/Sender.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/ConnectionManager.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/RemoteSessionManager.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/AbstractMessage.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/HeartBeatMessage.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/IMessage.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/SessionMessage.java create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/node/LocalNode.java rename source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/{ => node}/RemoteNode.java (56%) create mode 100644 source/stp/stp-communication/src/test/java/com/jd/blockchain/SessionMessageTest.java delete mode 100644 source/stp/stp-communication/src/test/java/com/jd/blockchain/StpTest.java create mode 100644 source/test/test-stp-community/pom.xml create mode 100644 source/test/test-stp-community/src/main/java/com/jd/blockchain/stp/commucation/MyMessageExecutor.java create mode 100644 source/test/test-stp-community/src/test/java/com/jd/blockchain/StpTest.java diff --git a/source/pom.xml b/source/pom.xml index 0a03b26c..7cebfced 100644 --- a/source/pom.xml +++ b/source/pom.xml @@ -299,6 +299,12 @@ commons-collections4 4.1 + + + com.google.guava + guava + 19.0 + diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DSProcessManager.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DSProcessManager.java index cc849eba..63573700 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DSProcessManager.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DSProcessManager.java @@ -1,7 +1,7 @@ package com.jd.blockchain.statetransfer; import com.jd.blockchain.stp.communication.RemoteSession; -import com.jd.blockchain.stp.communication.RemoteSessionManager; +import com.jd.blockchain.stp.communication.manager.RemoteSessionManager; import java.net.InetSocketAddress; import java.util.Map; @@ -20,7 +20,8 @@ public class DSProcessManager { DSTransferProcess startDSProcess(DataSequenceInfo dsInfo, InetSocketAddress listener, InetSocketAddress[] targets, DataSequenceWriter dsWriter, DataSequenceReader dsReader) { - RemoteSessionManager remoteSessionManager = new RemoteSessionManager(listener.getPort()); +// RemoteSessionManager remoteSessionManager = new RemoteSessionManager(listener.getPort()); + RemoteSessionManager remoteSessionManager = null; DSTransferProcess dsTransferProcess = new DSTransferProcess(dsInfo, remoteSessionManager, targets, dsWriter, dsReader); dsTransferProcess.start(); diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DSTransferProcess.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DSTransferProcess.java index 55a1402c..1fba56ff 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DSTransferProcess.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DSTransferProcess.java @@ -1,8 +1,8 @@ package com.jd.blockchain.statetransfer; -import com.jd.blockchain.stp.communication.RemoteNode; import com.jd.blockchain.stp.communication.RemoteSession; -import com.jd.blockchain.stp.communication.RemoteSessionManager; +import com.jd.blockchain.stp.communication.manager.RemoteSessionManager; +import com.jd.blockchain.stp.communication.node.RemoteNode; import java.net.InetSocketAddress; @@ -69,8 +69,8 @@ public class DSTransferProcess { for (int i = 0; i < remoteSessions.length; i++) { DataSequenceMsgHandle msgHandle = new DataSequenceMsgHandle(dsReader, dsWriter); - remoteSessions[i].initHandler(msgHandle); - remoteSessions[i].connect(); + remoteSessions[i].initExecute(msgHandle); + remoteSessions[i].init(); } } diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceMsgHandle.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceMsgHandle.java index 878869ad..77fa0417 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceMsgHandle.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceMsgHandle.java @@ -1,6 +1,6 @@ package com.jd.blockchain.statetransfer; -import com.jd.blockchain.stp.communication.MessageHandler; +import com.jd.blockchain.stp.communication.MessageExecute; import com.jd.blockchain.stp.communication.RemoteSession; /** @@ -9,7 +9,7 @@ import com.jd.blockchain.stp.communication.RemoteSession; * @create 2019/4/11 * @since 1.0.0 */ -public class DataSequenceMsgHandle implements MessageHandler { +public class DataSequenceMsgHandle implements MessageExecute { DataSequenceReader dsReader; DataSequenceWriter dsWriter; @@ -20,8 +20,13 @@ public class DataSequenceMsgHandle implements MessageHandler { } @Override - public void receive(byte[] key, byte[] data, RemoteSession session) { + public byte[] receive(String key, byte[] data, RemoteSession session) { + return new byte[0]; + } + @Override + public REPLY replyType() { + return REPLY.AUTO; } /** diff --git a/source/stp/stp-communication/pom.xml b/source/stp/stp-communication/pom.xml index fcf21bc1..96798377 100644 --- a/source/stp/stp-communication/pom.xml +++ b/source/stp/stp-communication/pom.xml @@ -26,10 +26,25 @@ test + + commons-codec + commons-codec + + + + com.alibaba + fastjson + + io.netty netty-all 4.1.29.Final + + + com.google.guava + guava + diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/MessageExecute.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/MessageExecute.java new file mode 100644 index 00000000..7640d122 --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/MessageExecute.java @@ -0,0 +1,36 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.MessageExecute + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/11 上午10:59 + * Description: + */ +package com.jd.blockchain.stp.communication; + +/** + * + * @author shaozhuguang + * @create 2019/4/11 + * @since 1.0.0 + */ + +public interface MessageExecute { + + byte[] receive(String key, byte[] data, RemoteSession session); + + REPLY replyType(); + + // 应答方式 + enum REPLY { + // 手动应答:Receiver不会自动发送应答请求,需要调用 + // session.reply(String key, LoadMessage loadMessage) 或 + // asyncReply(String key, LoadMessage loadMessage) + MANUAL, + + // 自动应答:Receiver会根据receive方法的应答结果自动调用应答 + // 使用者不能重新调用 + AUTO, + ; + } +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/MessageHandler.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/MessageHandler.java deleted file mode 100644 index cae8a853..00000000 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/MessageHandler.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright: Copyright 2016-2020 JD.COM All Right Reserved - * FileName: com.jd.blockchain.stp.communication.MessageHandler - * Author: shaozhuguang - * Department: Y事业部 - * Date: 2019/4/11 上午10:59 - * Description: - */ -package com.jd.blockchain.stp.communication; - -/** - * - * @author shaozhuguang - * @create 2019/4/11 - * @since 1.0.0 - */ - -public interface MessageHandler { - - void receive(byte[] key, byte[] data, RemoteSession session); -} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteSession.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteSession.java index 4a047e7f..b6ad6794 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteSession.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteSession.java @@ -8,14 +8,11 @@ */ package com.jd.blockchain.stp.communication; -import com.jd.blockchain.stp.communication.inner.Receiver; -import com.jd.blockchain.stp.communication.inner.Sender; +import com.jd.blockchain.stp.communication.callback.CallBackBarrier; +import com.jd.blockchain.stp.communication.callback.CallBackDataListener; +import com.jd.blockchain.stp.communication.connection.Connection; import com.jd.blockchain.stp.communication.message.LoadMessage; -import java.net.InetAddress; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Future; -import java.util.concurrent.Semaphore; /** * @@ -28,67 +25,57 @@ public class RemoteSession { private String id; - private RemoteNode remoteNode; + private Connection connection; - private Sender sender; - - private Receiver receiver; - - private MessageHandler messageHandler; - - public void initHandler(MessageHandler messageHandler) { + private MessageExecute messageExecute; + public RemoteSession(String id, Connection connection, MessageExecute messageExecute) { + this.id = id; + this.connection = connection; + this.messageExecute = messageExecute; } - public void connect() { - + public void init() { + connection.initSession(this); } - public byte[] send(LoadMessage loadMessage) { - - return null; + public void initExecute(MessageExecute messageExecute) { + this.messageExecute = messageExecute; } - public Future asyncSend(LoadMessage loadMessage) { - return null; + public byte[] request(LoadMessage loadMessage) throws Exception { + return this.connection.request(this.id, loadMessage, null).getCallBackData(); } - public Future asyncSend(LoadMessage loadMessage, CountDownLatch countDownLatch) { - return null; + public CallBackDataListener asyncRequest(LoadMessage loadMessage) { + return asyncRequest(loadMessage, null); } - public byte[] send(byte[] loadMessage) { - - return null; + public CallBackDataListener asyncRequest(LoadMessage loadMessage, CallBackBarrier callBackBarrier) { + return this.connection.request(this.id, loadMessage, callBackBarrier); } - public Future asyncSend(byte[] loadMessage) { - - return null; + public void reply(String key, LoadMessage loadMessage) { + this.connection.reply(this.id, key, loadMessage); } - public Future asyncSend(byte[] loadMessage, CountDownLatch countDownLatch) { - - return null; + public void closeAll() { + this.connection.closeAll(); } - public void reply(byte[] key, LoadMessage loadMessage) { - + public void closeReceiver() { + this.connection.closeReceiver(); } - public void asyncReply(byte[] key, LoadMessage loadMessage) { - + public void closeSender() { + this.connection.closeSender(); } - public void reply(byte[] key, byte[] loadMessage) { - + public String sessionId() { + return id; } - public void asyncReply(byte[] key, byte[] loadMessage) { - - } - - public void close() { - + public MessageExecute messageExecute() { + return this.messageExecute; } } \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteSessionManager.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteSessionManager.java deleted file mode 100644 index 2e87cf16..00000000 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteSessionManager.java +++ /dev/null @@ -1,98 +0,0 @@ -/** - * Copyright: Copyright 2016-2020 JD.COM All Right Reserved - * FileName: com.jd.blockchain.stp.communication.RemoteSessionManager - * Author: shaozhuguang - * Department: Y事业部 - * Date: 2019/4/11 上午11:22 - * Description: - */ -package com.jd.blockchain.stp.communication; - -import com.jd.blockchain.stp.communication.inner.Receiver; - -import java.net.InetAddress; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -/** - * - * @author shaozhuguang - * @create 2019/4/11 - * @since 1.0.0 - */ - -public class RemoteSessionManager { - - private static Map receiverMap = new ConcurrentHashMap<>(); - - private static final Lock lock = new ReentrantLock(); - - public RemoteSessionManager(int listenPort) { - if (listenPort <= 0) { - throw new IllegalArgumentException("Illegal port, please check !!!"); - } - - if (!receiverMap.containsKey(listenPort)) { - try { - lock.lock(); - if (!receiverMap.containsKey(listenPort)) { - Receiver receiver = initReceiver(listenPort); - receiverMap.put(listenPort, receiver); - } - } finally { - lock.unlock(); - } - } - } - - public RemoteSession newSession(RemoteNode remoteNode) { - return newSession(toRemoteId(remoteNode), remoteNode); - } - - public RemoteSession newSession(String remoteId, RemoteNode remoteNode) { - return newSession(remoteId, remoteNode, null); - } - - public RemoteSession newSession(RemoteNode remoteNode, MessageHandler messageHandler) { - return newSession(toRemoteId(remoteNode), remoteNode, messageHandler); - } - - public RemoteSession newSession(String remoteId, RemoteNode remoteNode, MessageHandler messageHandler) { - - - return null; - } - - public RemoteSession[] newSessions(RemoteNode[] remoteNodes) { - - - return null; - } - - public RemoteSession[] newSessions(String[] remoteIds, RemoteNode[] remoteNodes) { - - return null; - } - - public RemoteSession[] newSessions(RemoteNode[] remoteNodes, MessageHandler messageHandler) { - - return null; - } - - public RemoteSession[] newSessions(String[] remoteIds, RemoteNode[] remoteNodes, MessageHandler messageHandler) { - - return null; - } - - public String toRemoteId(RemoteNode remoteNode) { - - return null; - } - - private Receiver initReceiver(int port) { - - return null; - } -} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackBarrier.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackBarrier.java new file mode 100644 index 00000000..433533a0 --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackBarrier.java @@ -0,0 +1,56 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.CallBackBarrier + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/12 上午10:22 + * Description: + */ +package com.jd.blockchain.stp.communication.callback; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/** + * + * @author shaozhuguang + * @create 2019/4/12 + * @since 1.0.0 + */ + +public class CallBackBarrier { + + private CountDownLatch countDownLatch; + + private long maxTryCallMillSeconds = 2000; + + public static final CallBackBarrier newCallBackBarrier(int barrierLength) { + return new CallBackBarrier(barrierLength); + } + + public static final CallBackBarrier newCallBackBarrier(int barrierLength, long maxTryCallMillSeconds) { + return new CallBackBarrier(barrierLength, maxTryCallMillSeconds); + } + + private CallBackBarrier(int barrierLength) { + this.countDownLatch = new CountDownLatch(barrierLength); + } + + private CallBackBarrier(int barrierLength, long maxTryCallMillSeconds) { + this.countDownLatch = new CountDownLatch(barrierLength); + this.maxTryCallMillSeconds = maxTryCallMillSeconds; + } + + public void release() { + countDownLatch.countDown(); + } + + public boolean tryCall() throws InterruptedException { + return countDownLatch.await(maxTryCallMillSeconds, TimeUnit.MILLISECONDS); + } + + public boolean tryCall(long timeout, TimeUnit unit) throws InterruptedException { + return countDownLatch.await(timeout, unit); + } +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackDataListener.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackDataListener.java new file mode 100644 index 00000000..252765f9 --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackDataListener.java @@ -0,0 +1,70 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.callback.CallBackDataListener + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/15 下午4:40 + * Description: + */ +package com.jd.blockchain.stp.communication.callback; + +import com.jd.blockchain.stp.communication.node.RemoteNode; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * + * @author shaozhuguang + * @create 2019/4/15 + * @since 1.0.0 + */ + +public class CallBackDataListener { + + private CompletableFuture future = new CompletableFuture<>(); + + private RemoteNode remoteNode; + + private boolean isFill = false; + + private Lock lock = new ReentrantLock(); + + public CallBackDataListener(RemoteNode remoteNode) { + this.remoteNode = remoteNode; + } + + public byte[] getCallBackData() throws InterruptedException, ExecutionException { + return future.get(); + } + + public byte[] getCallBackData(long time, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException { + return future.get(time, timeUnit); + } + + public void setCallBackData(byte[] data) { + if (!isFill) { + try { + lock.lock(); + if (!isFill) { + future.complete(data); + isFill = true; + } + } finally { + lock.unlock(); + } + } + } + + public RemoteNode remoteNode() { + return this.remoteNode; + } + + public boolean isDone() { + return future.isDone(); + } +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/AbstractAsyncExecutor.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/AbstractAsyncExecutor.java new file mode 100644 index 00000000..b1c07df7 --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/AbstractAsyncExecutor.java @@ -0,0 +1,51 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.connection.AbstractAsyncExecutor + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/17 上午11:16 + * Description: + */ +package com.jd.blockchain.stp.communication.connection; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; + +import java.util.concurrent.*; + +/** + * + * @author shaozhuguang + * @create 2019/4/17 + * @since 1.0.0 + */ + +public abstract class AbstractAsyncExecutor implements AsyncExecutor{ + + private static final int QUEUE_CAPACITY = 1024; + + protected final Semaphore isStarted = new Semaphore(0, true); + + protected boolean isStartSuccess = false; + + @Override + public ThreadPoolExecutor initRunThread() { + ThreadFactory timerFactory = new ThreadFactoryBuilder() + .setNameFormat(threadNameFormat()).build(); + + ThreadPoolExecutor runThread = new ThreadPoolExecutor(1, 1, + 0, TimeUnit.MILLISECONDS, + new LinkedBlockingQueue<>(QUEUE_CAPACITY), + timerFactory, + new ThreadPoolExecutor.AbortPolicy()); + + return runThread; + } + + @Override + public boolean waitStarted() throws InterruptedException { + this.isStarted.acquire(); + return this.isStartSuccess; + } + + public abstract String threadNameFormat(); +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/AsyncExecutor.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/AsyncExecutor.java new file mode 100644 index 00000000..170b1ea5 --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/AsyncExecutor.java @@ -0,0 +1,25 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.connection.AsyncExecutor + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/17 上午11:14 + * Description: + */ +package com.jd.blockchain.stp.communication.connection; + +import java.util.concurrent.ThreadPoolExecutor; + +/** + * + * @author shaozhuguang + * @create 2019/4/17 + * @since 1.0.0 + */ + +public interface AsyncExecutor { + + ThreadPoolExecutor initRunThread(); + + boolean waitStarted() throws InterruptedException; +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Connection.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Connection.java new file mode 100644 index 00000000..1cb673f7 --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Connection.java @@ -0,0 +1,120 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.connection.Connection + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/11 下午5:39 + * Description: + */ +package com.jd.blockchain.stp.communication.connection; + +import com.jd.blockchain.stp.communication.RemoteSession; +import com.jd.blockchain.stp.communication.callback.CallBackBarrier; +import com.jd.blockchain.stp.communication.callback.CallBackDataListener; +import com.jd.blockchain.stp.communication.connection.listener.ReplyListener; +import com.jd.blockchain.stp.communication.message.LoadMessage; +import com.jd.blockchain.stp.communication.message.SessionMessage; +import com.jd.blockchain.stp.communication.message.TransferMessage; +import com.jd.blockchain.stp.communication.node.LocalNode; +import com.jd.blockchain.stp.communication.node.RemoteNode; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.digest.DigestUtils; + +/** + * + * @author shaozhuguang + * @create 2019/4/11 + * @since 1.0.0 + */ + +public class Connection { + + private RemoteNode remoteNode; + + private Receiver receiver; + + private Sender sender; + + public Connection(Receiver receiver) { + this.receiver = receiver; + } + + public void initSession(RemoteSession remoteSession) { + this.receiver.initRemoteSession(remoteSession.sessionId(), remoteSession); + } + + public boolean connect(RemoteNode remoteNode, String messageExecuteClass) throws InterruptedException { + this.remoteNode = remoteNode; + this.sender = new Sender(this.remoteNode, sessionMessage(messageExecuteClass)); + this.sender.connect(); + return this.sender.waitStarted(); + } + + public CallBackDataListener request(String sessionId, LoadMessage loadMessage, CallBackBarrier callBackBarrier) { + + TransferMessage transferMessage = transferMessage(sessionId, null, loadMessage, TransferMessage.MESSAGE_TYPE.TYPE_REQUEST); + + // 监听器的Key + String listenKey = transferMessage.toListenKey(); + + // 创建监听器 + ReplyListener replyListener = new ReplyListener(listenKey, this.remoteNode, callBackBarrier); + + // 添加监听器至Receiver + this.receiver.addListener(replyListener); + + // 发送请求 + this.sender.send(transferMessage); + + return replyListener.callBackDataListener(); + } + + public void reply(String sessionId, String key, LoadMessage loadMessage) { + TransferMessage transferMessage = transferMessage(sessionId, key, loadMessage, TransferMessage.MESSAGE_TYPE.TYPE_RESPONSE); + + // 通过Sender发送数据 + this.sender.send(transferMessage); + } + + private String loadKey(LoadMessage loadMessage) { + // 使用Sha256求Hash + byte[] sha256Bytes = DigestUtils.sha256(loadMessage.toBytes()); + // 使用base64作为Key + return Base64.encodeBase64String(sha256Bytes); + } + + private TransferMessage transferMessage(String sessionId, String key, LoadMessage loadMessage, TransferMessage.MESSAGE_TYPE messageType) { + + if (key == null || key.length() == 0) { + key = loadKey(loadMessage); + } + + TransferMessage transferMessage = new TransferMessage( + sessionId, messageType.code(), key, loadMessage.toBytes()); + + return transferMessage; + } + + private SessionMessage sessionMessage(String messageExecuteClass) { + + LocalNode localNode = this.receiver.localNode(); + + SessionMessage sessionMessage = new SessionMessage( + localNode.getHostName(), localNode.getPort(), messageExecuteClass); + + return sessionMessage; + } + + public void closeAll() { + closeReceiver(); + closeSender(); + } + + public void closeReceiver() { + this.receiver.close(); + } + + public void closeSender() { + this.sender.close(); + } +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Receiver.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Receiver.java new file mode 100644 index 00000000..3adee11d --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Receiver.java @@ -0,0 +1,132 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.inner.Receiver + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/11 上午10:59 + * Description: + */ +package com.jd.blockchain.stp.communication.connection; + +import com.jd.blockchain.stp.communication.RemoteSession; +import com.jd.blockchain.stp.communication.connection.handler.HeartBeatReceiverHandler; +import com.jd.blockchain.stp.communication.connection.handler.HeartBeatReceiverTrigger; +import com.jd.blockchain.stp.communication.connection.handler.ReceiverHandler; +import com.jd.blockchain.stp.communication.connection.listener.ReplyListener; +import com.jd.blockchain.stp.communication.manager.ConnectionManager; +import com.jd.blockchain.stp.communication.manager.RemoteSessionManager; +import com.jd.blockchain.stp.communication.node.LocalNode; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.LineBasedFrameDecoder; +import io.netty.handler.codec.string.StringDecoder; +import io.netty.handler.codec.string.StringEncoder; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import io.netty.handler.timeout.IdleStateHandler; + +import java.io.Closeable; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.util.Map; +import java.util.concurrent.*; + +/** + * + * @author shaozhuguang + * @create 2019/4/11 + * @since 1.0.0 + */ + +public class Receiver extends AbstractAsyncExecutor implements Closeable { + + private final EventLoopGroup bossGroup = new NioEventLoopGroup(); + + private final EventLoopGroup workerGroup = new NioEventLoopGroup(); + + private LocalNode localNode; + + private ReceiverHandler receiverHandler; + + public Receiver(LocalNode localNode) { + this.localNode = localNode; + } + + public void startListen() { + ServerBootstrap bootstrap = new ServerBootstrap(); + + bootstrap.group(bossGroup, workerGroup) + .channel(NioServerSocketChannel.class) + .option(ChannelOption.SO_BACKLOG, 1024) + .childOption(ChannelOption.SO_KEEPALIVE, true) + .localAddress(new InetSocketAddress(this.localNode.getPort())) + .childHandler(new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel socketChannel) throws Exception { + socketChannel.pipeline() +// .addLast(new LoggingHandler(LogLevel.ERROR)) + .addLast(new IdleStateHandler(8, 0, 0, TimeUnit.SECONDS)) + .addLast(new LineBasedFrameDecoder(1024)) + .addLast(new StringDecoder()) + .addLast(new HeartBeatReceiverTrigger()) + .addLast(new HeartBeatReceiverHandler()) + .addLast(receiverHandler); + } + }); + + // 由单独的线程启动 + ThreadPoolExecutor runThread = initRunThread(); + runThread.execute(() -> { + try { + ChannelFuture f = bootstrap.bind().sync(); + super.isStartSuccess = f.isSuccess(); + super.isStarted.release(); + if (super.isStartSuccess) { + // 启动成功 + f.channel().closeFuture().sync(); + } else { + // 启动失败 + throw new Exception("Receiver start fail :" + f.cause().getMessage() + " !!!"); + } + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + close(); + } + }); + } + + @Override + public String threadNameFormat() { + return "receiver-pool-%d"; + } + + public void initReceiverHandler(ConnectionManager connectionManager, String messageExecuteClass) { + receiverHandler = new ReceiverHandler(connectionManager, messageExecuteClass); + } + + public void initRemoteSession(String sessionId, RemoteSession remoteSession) { + receiverHandler.putRemoteSession(sessionId, remoteSession); + } + + public void addListener(ReplyListener replyListener) { + receiverHandler.addListener(replyListener); + } + + @Override + public void close() { + receiverHandler.close(); + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully(); + } + + public LocalNode localNode() { + return this.localNode; + } +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Sender.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Sender.java new file mode 100644 index 00000000..6e9dde46 --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Sender.java @@ -0,0 +1,162 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.inner.Sender + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/11 上午10:58 + * Description: + */ +package com.jd.blockchain.stp.communication.connection; + +import com.jd.blockchain.stp.communication.connection.handler.*; +import com.jd.blockchain.stp.communication.message.IMessage; +import com.jd.blockchain.stp.communication.message.SessionMessage; +import com.jd.blockchain.stp.communication.node.RemoteNode; +import io.netty.bootstrap.Bootstrap; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.*; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.codec.LineBasedFrameDecoder; +import io.netty.handler.codec.string.StringDecoder; +import io.netty.handler.codec.string.StringEncoder; +import io.netty.handler.timeout.IdleStateHandler; + +import java.io.Closeable; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.*; + +/** + * + * @author shaozhuguang + * @create 2019/4/11 + * @since 1.0.0 + */ + +public class Sender extends AbstractAsyncExecutor implements Closeable { + + private final EventLoopGroup loopGroup = new NioEventLoopGroup(); + + private Bootstrap bootstrap; + + private ChannelFuture channelFuture; + + private SessionMessage sessionMessage; + + private String remoteHost; + + private int remotePort; + + private WatchDogHandler watchDogHandler; + + public Sender(RemoteNode remoteNode, SessionMessage sessionMessage) { + init(remoteNode, sessionMessage); + } + + public Sender(String remoteHost, int remotePort, SessionMessage sessionMessage) { + init(remoteHost, remotePort, sessionMessage); + } + + public void connect() { + watchDogHandler = new WatchDogHandler(this.remoteHost, this.remotePort, bootstrap); + + ChannelHandlers frontChannelHandlers = new ChannelHandlers() + .addHandler(watchDogHandler); + + ChannelHandlers afterChannelHandlers = new ChannelHandlers() + .addHandler(new StringDecoder()) + .addHandler(new HeartBeatSenderTrigger()) + .addHandler(new HeartBeatSenderHandler()) + .addHandler(new SenderHandler(this.sessionMessage)); + + // 初始化watchDogHandler + watchDogHandler.init(frontChannelHandlers.toArray(), afterChannelHandlers.toArray()); + + bootstrap.handler(new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel ch) throws Exception { + ch.pipeline() + .addLast(frontChannelHandlers.toArray()) + .addLast(new IdleStateHandler(10, 4, 0, TimeUnit.SECONDS)) + .addLast(new LineBasedFrameDecoder(1024)) + .addLast(afterChannelHandlers.toArray()); + } + }); + + ThreadPoolExecutor runThread = initRunThread(); + + runThread.execute(() -> { + try { + // 发起连接请求 + channelFuture = bootstrap.connect(this.remoteHost, this.remotePort).sync(); + + isStartSuccess = channelFuture.isSuccess(); + isStarted.release(); + if (isStartSuccess) { + // 启动成功 + // 设置ChannelFuture对象,以便于发送的连接状态处理 + watchDogHandler.initChannelFuture(channelFuture); + // 等待客户端关闭连接 + channelFuture.channel().closeFuture().sync(); + } else { + // 启动失败 + throw new Exception("Sender start fail :" + channelFuture.cause().getMessage() + " !!!"); + } + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + close(); + } + }); + } + + private void init(RemoteNode remoteNode, SessionMessage sessionMessage) { + init(remoteNode.getHostName(), remoteNode.getPort(), sessionMessage); + } + + private void init(String remoteHost, int remotePort, SessionMessage sessionMessage) { + this.remoteHost = remoteHost; + this.remotePort = remotePort; + + this.sessionMessage = sessionMessage; + + this.bootstrap = new Bootstrap().group(loopGroup) + .channel(NioSocketChannel.class) + .option(ChannelOption.SO_KEEPALIVE, true) + .option(ChannelOption.TCP_NODELAY, true); + } + + @Override + public String threadNameFormat() { + return "sender-pool-%d"; + } + + public void send(IMessage message) { + watchDogHandler.channelFuture().channel().writeAndFlush(message.toTransferByteBuf()); + } + + @Override + public void close() { + // 因为要重连,需要仍然需要使用该LoopGroup,因此不能关闭 +// loopGroup.shutdownGracefully(); + } + + public static class ChannelHandlers { + + private List channelHandlers = new ArrayList<>(); + + public ChannelHandlers addHandler(ChannelHandler channelHandler) { + channelHandlers.add(channelHandler); + return this; + } + + public ChannelHandler[] toArray() { + ChannelHandler[] channelHandlerArray = new ChannelHandler[channelHandlers.size()]; + return channelHandlers.toArray(channelHandlerArray); + } + } +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatReceiverHandler.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatReceiverHandler.java new file mode 100644 index 00000000..a67920e9 --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatReceiverHandler.java @@ -0,0 +1,41 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.connection.handler.HeartBeatSenderHandler + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/15 上午10:10 + * Description: + */ +package com.jd.blockchain.stp.communication.connection.handler; + +import com.jd.blockchain.stp.communication.message.HeartBeatMessage; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; + +/** + * + * @author shaozhuguang + * @create 2019/4/15 + * @since 1.0.0 + */ +@ChannelHandler.Sharable +public class HeartBeatReceiverHandler extends ChannelInboundHandlerAdapter { + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + if (HeartBeatMessage.isHeartBeat(msg)) { + // 收到的消息是心跳消息,此时需要回复一个心跳消息 + HeartBeatMessage.write(ctx); + System.out.println("Receive HeartBeat Request Message -> " + msg.toString()); + } else { + super.channelRead(ctx, msg); + } + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + // 出现异常直接关闭连接 + ctx.close(); + } +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatReceiverTrigger.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatReceiverTrigger.java new file mode 100644 index 00000000..575895be --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatReceiverTrigger.java @@ -0,0 +1,40 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.connection.handler.HeartBeatSenderTrigger + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/15 上午10:11 + * Description: + */ +package com.jd.blockchain.stp.communication.connection.handler; + +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.handler.timeout.IdleState; +import io.netty.handler.timeout.IdleStateEvent; + +/** + * + * @author shaozhuguang + * @create 2019/4/15 + * @since 1.0.0 + */ +@ChannelHandler.Sharable +public class HeartBeatReceiverTrigger extends ChannelInboundHandlerAdapter { + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + // 服务端只会接收心跳数据后应答,而不会主动应答 + if (evt instanceof IdleStateEvent) { + IdleState idleState = ((IdleStateEvent) evt).state(); + if (idleState.equals(IdleState.READER_IDLE)) { + // 长时间未收到客户端请求,则关闭连接 + System.out.println("Long Time UnReceive HeartBeat Request, Close Connection !!!"); + ctx.close(); + } + } else { + super.userEventTriggered(ctx, evt); + } + } +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatSenderHandler.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatSenderHandler.java new file mode 100644 index 00000000..da471003 --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatSenderHandler.java @@ -0,0 +1,42 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.connection.handler.HeartBeatSenderHandler + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/15 上午10:10 + * Description: + */ +package com.jd.blockchain.stp.communication.connection.handler; + +import com.jd.blockchain.stp.communication.message.HeartBeatMessage; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; + +/** + * + * @author shaozhuguang + * @create 2019/4/15 + * @since 1.0.0 + */ +@ChannelHandler.Sharable +public class HeartBeatSenderHandler extends ChannelInboundHandlerAdapter { + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // 判断收到的消息 + if (HeartBeatMessage.isHeartBeat(msg)) { + // 假设收到的消息是字符串,并且是心跳消息,说明由服务端发送了心跳信息 + // TODO 此处不需要进行消息反馈,只需要打印日志即可 + System.out.println("Receive HeartBeat Response Message -> " + msg.toString()); + } else { + super.channelRead(ctx, msg); + } + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + // 出现异常直接关闭连接 + ctx.close(); + } +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatSenderTrigger.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatSenderTrigger.java new file mode 100644 index 00000000..496dc348 --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatSenderTrigger.java @@ -0,0 +1,48 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.connection.handler.HeartBeatSenderTrigger + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/15 上午10:11 + * Description: + */ +package com.jd.blockchain.stp.communication.connection.handler; + +import com.jd.blockchain.stp.communication.message.HeartBeatMessage; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.handler.timeout.IdleState; +import io.netty.handler.timeout.IdleStateEvent; + +/** + * + * @author shaozhuguang + * @create 2019/4/15 + * @since 1.0.0 + */ +@ChannelHandler.Sharable +public class HeartBeatSenderTrigger extends ChannelInboundHandlerAdapter { + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + + // 心跳事件 + if (evt instanceof IdleStateEvent) { + IdleState idleState = ((IdleStateEvent) evt).state(); + if (idleState.equals(IdleState.READER_IDLE)) { + // Sender读超时,表示在指定时间内未收到Receiver的应答 + // 此时关闭连接,自动调用重连机制,进行重连操作 + System.out.println("Long Time UnReceive HeartBeat Response, Close Connection !!!"); + ctx.close(); + } else if (idleState == IdleState.WRITER_IDLE) { + // Sender写超时,表示很长时间没有发送消息了,需要发送消息至Receiver + System.out.println("Read TimeOut Trigger, Send HeartBeat Request !!!"); + HeartBeatMessage.write(ctx); + } + // 还有一种情况是读写超时,该情况暂不处理 + } else { + super.userEventTriggered(ctx, evt); + } + } +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/ReceiverHandler.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/ReceiverHandler.java new file mode 100644 index 00000000..179ff0da --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/ReceiverHandler.java @@ -0,0 +1,223 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.connection.handler.ReceiverHandler + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/12 上午11:14 + * Description: + */ +package com.jd.blockchain.stp.communication.connection.handler; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import com.jd.blockchain.stp.communication.MessageExecute; +import com.jd.blockchain.stp.communication.RemoteSession; +import com.jd.blockchain.stp.communication.connection.Connection; +import com.jd.blockchain.stp.communication.connection.listener.ReplyListener; +import com.jd.blockchain.stp.communication.manager.ConnectionManager; +import com.jd.blockchain.stp.communication.message.SessionMessage; +import com.jd.blockchain.stp.communication.message.TransferMessage; +import com.jd.blockchain.stp.communication.node.RemoteNode; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; + +import java.io.Closeable; +import java.util.Map; +import java.util.concurrent.*; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * + * @author shaozhuguang + * @create 2019/4/12 + * @since 1.0.0 + */ +@ChannelHandler.Sharable +public class ReceiverHandler extends ChannelInboundHandlerAdapter implements Closeable { + + // 队列的最大容量为256K(防止队列溢出) + private static final int QUEUE_CAPACITY = 256 * 1024; + + private final Map remoteSessions = new ConcurrentHashMap<>(); + + private final Map allReplyListeners = new ConcurrentHashMap<>(); + + private final Lock lock = new ReentrantLock(); + + private String messageExecuteClass; + + private ConnectionManager connectionManager; + + private ExecutorService msgExecutePool; + + public ReceiverHandler(ConnectionManager connectionManager, String messageExecuteClass) { + this.connectionManager = connectionManager; + this.messageExecuteClass = messageExecuteClass; + init(); + } + + public void putRemoteSession(String sessionId, RemoteSession remoteSession) { + remoteSessions.put(sessionId, remoteSession); + } + + public void addListener(ReplyListener replyListener) { + allReplyListeners.put(replyListener.listenKey(), replyListener); + } + + public void removeListener(String key) { + this.allReplyListeners.remove(key); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + + System.out.println("Receive Biz Message -> " + msg.toString()); + // 有数据接入 + // 首先判断数据是否TransferMessage,当前Handler不处理非TransferMessage + TransferMessage tm = TransferMessage.toTransferMessageObj(msg); + if (tm == null) { + // 判断是否是SessionMessage + SessionMessage sm = SessionMessage.toNodeSessionMessage(msg); + if (sm != null) { + executeSessionMessage(sm); + } else { + super.channelRead(ctx, msg); + } + } else { + TransferMessage.MESSAGE_TYPE messageType = TransferMessage.MESSAGE_TYPE.valueOf(tm.getType()); + // 对于请求和应答处理方式不同 + if (messageType.equals(TransferMessage.MESSAGE_TYPE.TYPE_REQUEST)) { + // 假设是请求消息 + executeRequest(tm); + } else if (messageType.equals(TransferMessage.MESSAGE_TYPE.TYPE_RESPONSE)) { + // 假设是应答消息 + executeResponse(tm); + } else { + // todo 其他消息只需要打印日志即可 + + + } + } + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + ctx.close(); + } + + // 防止消息的处理过程阻塞主进程 + private void executeRequest(final TransferMessage transferMessage) { + msgExecutePool.execute(() -> { + RemoteSession remoteSession = remoteSessions.get(transferMessage.getSessionId()); + if (remoteSession != null) { + MessageExecute messageExecute = remoteSession.messageExecute(); + if (messageExecute != null) { + MessageExecute.REPLY replyType = messageExecute.replyType(); + if (replyType != null) { + switch (messageExecute.replyType()) { + case MANUAL: + messageExecute.receive(transferMessage.loadKey(), transferMessage.load(), remoteSession); + break; + case AUTO: + String requestKey = transferMessage.loadKey(); + byte[] replyMsg = messageExecute.receive(requestKey, transferMessage.load(), remoteSession); + // 应答 + remoteSession.reply(requestKey, () -> replyMsg); + break; + default: + break; + } + } + } + } + }); + } + + private void executeResponse(final TransferMessage transferMessage) { + msgExecutePool.execute(() -> { + // listenKey和msgKey是不一致的 + // msgKey是对消息本身设置key,listenKey是对整个消息(包括session信息) + String listenKey = transferMessage.toListenKey(); + + ReplyListener replyListener = allReplyListeners.get(listenKey); + + if (replyListener != null) { + // 填充对应的结果 + replyListener.replyData(transferMessage.load()); + + ReplyListener.MANAGE_TYPE manageType = replyListener.manageType(); + + if (manageType != null) { + switch (manageType) { + case REMOVE: + // 将对象从Map中移除 + removeListener(listenKey); + break; + case HOLD: + default: + // todo 打印日志 + + break; + } + } + } + }); + } + + private void executeSessionMessage(SessionMessage sessionMessage) { + // 处理SessionMessage + String sessionId = sessionMessage.sessionId(); + if (sessionId != null && !remoteSessions.containsKey(sessionId)) { + + try { + lock.lock(); + // 生成对应的MessageExecute对象 + String messageExecuteClass = sessionMessage.getMessageExecute(); + MessageExecute messageExecute = null; + if (messageExecuteClass != null && messageExecuteClass.length() > 0) { + try { + Class clazz = Class.forName(messageExecuteClass); + messageExecute = (MessageExecute) clazz.newInstance(); + } catch (Exception e) { + // TODO 打印日志 + e.printStackTrace(); + } + } + + // 必须保证该对象不为空 + if (messageExecute != null) { + // 说明尚未和请求来的客户端建立连接,需要建立连接 + Connection remoteConnection = this.connectionManager.connect(new RemoteNode( + sessionMessage.getLocalHost(), sessionMessage.getListenPort()), + this.messageExecuteClass); + RemoteSession remoteSession = new RemoteSession(sessionId, remoteConnection, messageExecute); + + // Double check !!! + if (!remoteSessions.containsKey(sessionId)) { + remoteSessions.put(sessionId, remoteSession); + } + } + } finally { + lock.unlock(); + } + } + } + + private void init() { + + ThreadFactory msgExecuteThreadFactory = new ThreadFactoryBuilder() + .setNameFormat("msg-execute-pool-%d").build(); + + //Common Thread Pool + msgExecutePool = new ThreadPoolExecutor(5, 10, + 60, TimeUnit.SECONDS, + new LinkedBlockingQueue<>(QUEUE_CAPACITY), + msgExecuteThreadFactory, new ThreadPoolExecutor.AbortPolicy()); + } + + @Override + public void close() { + msgExecutePool.shutdown(); + } +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/SenderHandler.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/SenderHandler.java new file mode 100644 index 00000000..d1590318 --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/SenderHandler.java @@ -0,0 +1,46 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.connection.handler.SenderHandler + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/16 下午2:00 + * Description: + */ +package com.jd.blockchain.stp.communication.connection.handler; + +import com.jd.blockchain.stp.communication.message.SessionMessage; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; + +import java.util.concurrent.Executors; + +/** + * + * @author shaozhuguang + * @create 2019/4/16 + * @since 1.0.0 + */ +@ChannelHandler.Sharable +public class SenderHandler extends ChannelInboundHandlerAdapter { + + private SessionMessage sessionMessage; + + public SenderHandler(SessionMessage sessionMessage) { + this.sessionMessage = sessionMessage; + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + // 发送本机信息(包括IP、端口等)至对端 + System.out.println("Connection Receiver Success, Send Local Node Information !!!"); + ctx.writeAndFlush(sessionMessage.toTransferByteBuf()); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + ctx.close(); + } +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/WatchDogHandler.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/WatchDogHandler.java new file mode 100644 index 00000000..dac7b823 --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/WatchDogHandler.java @@ -0,0 +1,183 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.connection.SenderWatchDog + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/12 下午4:56 + * Description: + */ +package com.jd.blockchain.stp.communication.connection.handler; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import com.jd.blockchain.stp.communication.message.HeartBeatMessage; +import com.jd.blockchain.stp.communication.node.RemoteNode; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.*; +import io.netty.handler.codec.LineBasedFrameDecoder; +import io.netty.handler.timeout.IdleStateHandler; + +import java.io.Closeable; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * + * @author shaozhuguang + * @create 2019/4/12 + * @since 1.0.0 + */ +@ChannelHandler.Sharable +public class WatchDogHandler extends ChannelInboundHandlerAdapter implements Runnable, Closeable { + + private final AtomicBoolean currentActive = new AtomicBoolean(false); + + private final Lock reconnectLock = new ReentrantLock(); + + // 默认的最多重连次数 + private final int maxReconnectSize = 16; + + // 默认重连的时间 + private final int defaultReconnectSeconds = 2; + + // 标识是否正常工作中,假设不再工作则不再重连 + private boolean isWorking = true; + + private ScheduledExecutorService reconnectTimer; + + private String hostName; + + private int port; + + private Bootstrap bootstrap; + + private ChannelHandler[] frontHandlers; + + private ChannelHandler[] afterHandlers; + + private ChannelFuture channelFuture; + + public WatchDogHandler(String hostName, int port, Bootstrap bootstrap) { + this.hostName = hostName; + this.port = port; + this.bootstrap = bootstrap; + } + + public WatchDogHandler(RemoteNode remoteNode, Bootstrap bootstrap) { + this(remoteNode.getHostName(), remoteNode.getPort(), bootstrap); + } + + public void init(ChannelHandler[] frontHandlers, ChannelHandler[] afterHandlers) { + this.frontHandlers = frontHandlers; + this.afterHandlers = afterHandlers; + initTimer(); + } + + public void initChannelFuture(ChannelFuture channelFuture) { + this.channelFuture = channelFuture; + } + + public ChannelFuture channelFuture() { + try { + reconnectLock.lock(); + return this.channelFuture; + } finally { + reconnectLock.unlock(); + } + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + // 调用该方法表示连接成功 + connectSuccess(); + + // 连接成功后发送心跳消息至服务端 + HeartBeatMessage.write(ctx); + + ctx.fireChannelActive(); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + + System.err.println("Connection Exception, Close And Reconnect !!!"); + // 调用该方法时表示连接关闭了(无论是什么原因) + // 连接关闭的情况下需要重新连接 + + connectFail(); + + ctx.close(); + + for (int i = 0; i < maxReconnectSize; i++) { + reconnectTimer.schedule(this, defaultReconnectSeconds << i, TimeUnit.SECONDS); + } + + ctx.fireChannelInactive(); + } + + @Override + public void run() { + if (isNeedReconnect()) { + // 重连 + try { + reconnectLock.lock(); + if (isNeedReconnect()) { + + bootstrap.handler(new ChannelInitializer() { + @Override + protected void initChannel(Channel ch) throws Exception { + ch.pipeline() + .addLast(frontHandlers) + .addLast(new IdleStateHandler(10, 4, 0, TimeUnit.SECONDS)) + .addLast(new LineBasedFrameDecoder(1024)) + .addLast(afterHandlers) + ; + } + }); + + channelFuture = bootstrap.connect(hostName, port); + + // 增加监听器用于判断本次重连是否成功 + channelFuture.addListener((ChannelFutureListener) future -> { + boolean isReconnectSuccess = future.isSuccess(); + if (isReconnectSuccess) { + // 连接成功 + connectSuccess(); + } else { + connectFail(); + } + }); + + } + } finally { + reconnectLock.unlock(); + } + } + } + + private boolean isNeedReconnect() { + return isWorking && !currentActive.get(); + } + + private void connectSuccess() { + this.currentActive.set(true); + } + + private void connectFail() { + this.currentActive.set(false); + } + + @Override + public void close() { + this.isWorking = false; + this.reconnectTimer.shutdown(); + } + + private void initTimer() { + ThreadFactory timerFactory = new ThreadFactoryBuilder() + .setNameFormat("reconnect-pool-%d").build(); + + reconnectTimer = new ScheduledThreadPoolExecutor(1, timerFactory, new ThreadPoolExecutor.AbortPolicy()); + } +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/listener/ReplyListener.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/listener/ReplyListener.java new file mode 100644 index 00000000..842e6e8e --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/listener/ReplyListener.java @@ -0,0 +1,74 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.connection.listener.ReplyListener + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/12 上午10:36 + * Description: + */ +package com.jd.blockchain.stp.communication.connection.listener; + +import com.jd.blockchain.stp.communication.callback.CallBackBarrier; +import com.jd.blockchain.stp.communication.callback.CallBackDataListener; +import com.jd.blockchain.stp.communication.node.RemoteNode; + + +/** + * + * @author shaozhuguang + * @create 2019/4/12 + * @since 1.0.0 + */ + +public class ReplyListener { + + private String listenKey; + + private MANAGE_TYPE manageType = MANAGE_TYPE.REMOVE; + + private CallBackDataListener callBackDataListener; + + private CallBackBarrier callBackBarrier; + + public ReplyListener(String listenKey, RemoteNode remoteNode) { + this.listenKey = listenKey; + this.callBackDataListener = new CallBackDataListener(remoteNode); + } + + public ReplyListener(String listenKey, RemoteNode remoteNode, CallBackBarrier callBackBarrier) { + this.listenKey = listenKey; + this.callBackDataListener = new CallBackDataListener(remoteNode); + this.callBackBarrier = callBackBarrier; + } + + public void setManageType(MANAGE_TYPE manageType) { + this.manageType = manageType; + } + + public String listenKey() { + return listenKey; + } + + public CallBackDataListener callBackDataListener() { + return this.callBackDataListener; + } + + public void replyData(byte[] reply) { + // 设置数据 + this.callBackDataListener.setCallBackData(reply); + if (this.callBackBarrier != null) { + // 同步释放对应的栅栏 + this.callBackBarrier.release(); + } + } + + public MANAGE_TYPE manageType() { + return this.manageType; + } + + public enum MANAGE_TYPE { + HOLD, + REMOVE, + ; + } +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/inner/Receiver.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/inner/Receiver.java deleted file mode 100644 index 698c52b8..00000000 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/inner/Receiver.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright: Copyright 2016-2020 JD.COM All Right Reserved - * FileName: com.jd.blockchain.stp.communication.inner.Receiver - * Author: shaozhuguang - * Department: Y事业部 - * Date: 2019/4/11 上午10:59 - * Description: - */ -package com.jd.blockchain.stp.communication.inner; - -import com.jd.blockchain.stp.communication.MessageHandler; - -/** - * - * @author shaozhuguang - * @create 2019/4/11 - * @since 1.0.0 - */ - -public class Receiver { - - private MessageHandler messageHandler; - - public void listen() { - - } -} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/inner/Sender.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/inner/Sender.java deleted file mode 100644 index 8072c675..00000000 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/inner/Sender.java +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright: Copyright 2016-2020 JD.COM All Right Reserved - * FileName: com.jd.blockchain.stp.communication.inner.Sender - * Author: shaozhuguang - * Department: Y事业部 - * Date: 2019/4/11 上午10:58 - * Description: - */ -package com.jd.blockchain.stp.communication.inner; - -import java.net.InetAddress; - -/** - * - * @author shaozhuguang - * @create 2019/4/11 - * @since 1.0.0 - */ - -public class Sender { - - private InetAddress inetAddress; - - public void connect() { - - } - - public void send(String message) { - - } - - public void send(byte[] message) { - - } -} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/ConnectionManager.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/ConnectionManager.java new file mode 100644 index 00000000..e4aef871 --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/ConnectionManager.java @@ -0,0 +1,110 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.ConnectionManager + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/11 下午6:11 + * Description: + */ +package com.jd.blockchain.stp.communication.manager; + +import com.jd.blockchain.stp.communication.MessageExecute; +import com.jd.blockchain.stp.communication.connection.Receiver; +import com.jd.blockchain.stp.communication.connection.Connection; +import com.jd.blockchain.stp.communication.node.LocalNode; +import com.jd.blockchain.stp.communication.node.RemoteNode; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * + * @author shaozhuguang + * @create 2019/4/11 + * @since 1.0.0 + */ + +public class ConnectionManager { + + private static final Map connectionMap = new ConcurrentHashMap<>(); + + private static final Map connectionManagerMap = new ConcurrentHashMap<>(); + + private static final Lock managerLock = new ReentrantLock(); + + private static final Lock connectionLock = new ReentrantLock(); + + private Receiver receiver; + + public static final ConnectionManager newConnectionManager(LocalNode localNode) { + int listenPort = localNode.getPort(); + if (!connectionManagerMap.containsKey(listenPort)) { + try { + managerLock.lock(); + if (!connectionManagerMap.containsKey(listenPort)) { + ConnectionManager connectionManager = newInstance(localNode); + connectionManagerMap.put(listenPort, connectionManager); + return connectionManager; + } + } finally { + managerLock.unlock(); + } + } + return connectionManagerMap.get(listenPort); + } + + private static final ConnectionManager newInstance(LocalNode localNode) { + return new ConnectionManager(new Receiver(localNode)); + } + + public final boolean start(String messageExecuteClass) throws InterruptedException { + receiver.initReceiverHandler(this, messageExecuteClass); + receiver.startListen(); + // 判断是否启动完成,启动完成后再返回 + return receiver.waitStarted(); + } + + private ConnectionManager(Receiver receiver) { + this.receiver = receiver; + } + + public Connection connect(RemoteNode remoteNode, MessageExecute messageExecute) { + return connect(remoteNode, messageExecute.getClass().toString()); + } + + public Connection connect(RemoteNode remoteNode, String messageExecuteClass) { + if (!connectionMap.containsKey(remoteNode)) { + try { + connectionLock.lock(); + if (!connectionMap.containsKey(remoteNode)) { + Connection connection = init(remoteNode, messageExecuteClass); + connectionMap.put(remoteNode, connection); + } + } finally { + connectionLock.unlock(); + } + } + return connectionMap.get(remoteNode); + } + + private Connection init(RemoteNode remoteNode, String messageExecuteClass) { + + // 初始化Connection + Connection remoteConnection = new Connection(this.receiver); + + try { + // 连接远端 + boolean isSuccess = remoteConnection.connect(remoteNode, messageExecuteClass); + if (!isSuccess) { + throw new RuntimeException(String.format("RemoteNode {%s} Connect Fail !!!", remoteNode.toString())); + } + } catch (InterruptedException e) { + throw new RuntimeException(e); + } catch (RuntimeException e) { + throw e; + } + return remoteConnection; + } +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/RemoteSessionManager.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/RemoteSessionManager.java new file mode 100644 index 00000000..bdcfc085 --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/RemoteSessionManager.java @@ -0,0 +1,132 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.RemoteSessionManager + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/11 上午11:22 + * Description: + */ +package com.jd.blockchain.stp.communication.manager; + + +import com.jd.blockchain.stp.communication.MessageExecute; +import com.jd.blockchain.stp.communication.RemoteSession; +import com.jd.blockchain.stp.communication.connection.Connection; +import com.jd.blockchain.stp.communication.node.LocalNode; +import com.jd.blockchain.stp.communication.node.RemoteNode; +import org.apache.commons.codec.binary.Hex; + + +/** + * + * @author shaozhuguang + * @create 2019/4/11 + * @since 1.0.0 + */ + +public class RemoteSessionManager { + + private ConnectionManager connectionManager; + + private LocalNode localNode; + + public RemoteSessionManager(LocalNode localNode) { + this.localNode = localNode; + check(); + this.connectionManager = ConnectionManager.newConnectionManager(this.localNode); + try { + boolean isStartedSuccess = start(this.localNode.messageExecuteClass()); + if (!isStartedSuccess) { + throw new RuntimeException(String.format("LocalNode {%s} Start Receiver Fail !!!", this.localNode.toString())); + } + } catch (InterruptedException e) { + throw new RuntimeException(e); + } catch (RuntimeException e) { + throw e; + } + + } + + private void check() { + // 要求端口范围:1~65535,messageExecuteClass不能为null + int listenPort = this.localNode.getPort(); + if (listenPort <= 0 || listenPort > 65535) { + throw new IllegalArgumentException("Illegal Local Listen Port, Please Check !!!"); + } + + String messageExecuteClass = this.localNode.messageExecuteClass(); + if (messageExecuteClass == null) { + throw new IllegalArgumentException("Illegal MessageExecute Class, Please Check !!!"); + } + } + + private boolean start(String messageExecuteClass) throws InterruptedException { + return this.connectionManager.start(messageExecuteClass); + } + + public RemoteSession newSession(RemoteNode remoteNode) { + return newSession(null, remoteNode); + } + + public RemoteSession newSession(String sessionId, RemoteNode remoteNode) { + return newSession(sessionId, remoteNode, null); + } + + public RemoteSession newSession(RemoteNode remoteNode, MessageExecute messageExecute) { + return newSession(null, remoteNode, messageExecute); + } + + public RemoteSession newSession(String sessionId, RemoteNode remoteNode, MessageExecute messageExecute) { + if (sessionId == null) { + sessionId = toSessionId(localNode); + } + Connection remoteConnection = this.connectionManager.connect(remoteNode, localNode.messageExecuteClass()); + + RemoteSession remoteSession = new RemoteSession(sessionId, remoteConnection, messageExecute); + + remoteSession.init(); + + return remoteSession; + } + + public RemoteSession[] newSessions(RemoteNode[] remoteNodes) { + return newSessions(null, remoteNodes); + } + + public RemoteSession[] newSessions(String[] sessionIds, RemoteNode[] remoteNodes) { + + return newSessions(sessionIds, remoteNodes, null); + } + + public RemoteSession[] newSessions(RemoteNode[] remoteNodes, MessageExecute messageExecute) { + + return newSessions(null, remoteNodes, messageExecute); + } + + public RemoteSession[] newSessions(String[] sessionIds, RemoteNode[] remoteNodes, MessageExecute messageExecute) { + if (remoteNodes == null || remoteNodes.length <= 0) { + throw new IllegalArgumentException("RemoteNodes is empty !!!"); + } + + if (sessionIds != null) { + if (sessionIds.length != remoteNodes.length) { + throw new IllegalArgumentException("RemoteNodes and sessionIds are different in length !!!"); + } + } + + RemoteSession[] remoteSessions = new RemoteSession[remoteNodes.length]; + + for (int i = 0; i < remoteNodes.length; i++) { + if (sessionIds == null) { + remoteSessions[i] = newSession(remoteNodes[i], messageExecute); + } else { + remoteSessions[i] = newSession(sessionIds[i], remoteNodes[i], messageExecute); + } + } + return remoteSessions; + } + + public String toSessionId(RemoteNode remoteNode) { + return Hex.encodeHexString(remoteNode.toString().getBytes()); + } +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/AbstractMessage.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/AbstractMessage.java new file mode 100644 index 00000000..b872fbfb --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/AbstractMessage.java @@ -0,0 +1,30 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.message.AbstractMessage + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/17 下午4:00 + * Description: + */ +package com.jd.blockchain.stp.communication.message; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; + +/** + * + * @author shaozhuguang + * @create 2019/4/17 + * @since 1.0.0 + */ + +public abstract class AbstractMessage implements IMessage { + + @Override + public ByteBuf toTransferByteBuf() { + byte[] message = (toTransfer() + "\r\n").getBytes(); + ByteBuf byteBuf = Unpooled.buffer(message.length); + byteBuf.writeBytes(message); + return byteBuf; + } +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/HeartBeatMessage.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/HeartBeatMessage.java new file mode 100644 index 00000000..6395d030 --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/HeartBeatMessage.java @@ -0,0 +1,57 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.message.HeartBeatMessage + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/12 下午4:55 + * Description: + */ +package com.jd.blockchain.stp.communication.message; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; +import io.netty.util.CharsetUtil; + +/** + * 心跳消息 + * @author shaozhuguang + * @create 2019/4/12 + * @since 1.0.0 + */ + +public class HeartBeatMessage implements IMessage { + + private static final String HEARTBEAT_STRING = "JDChainHeartBeat"; + + private static final ByteBuf HEARTBEAT_MESSAGE = Unpooled.unreleasableBuffer(Unpooled.copiedBuffer(HEARTBEAT_STRING + "\r\n", + CharsetUtil.UTF_8)); + + public static final void write(ChannelHandlerContext ctx) { + ctx.writeAndFlush(HEARTBEAT_MESSAGE.duplicate()); + } + + public static final boolean isHeartBeat(Object msg) { + if (msg instanceof String) { + return isHeartBeat((String) msg); + } + return false; + } + + public static final boolean isHeartBeat(String msg) { + if (HEARTBEAT_STRING.equals(msg)) { + return true; + } + return false; + } + + @Override + public String toTransfer() { + return HEARTBEAT_STRING; + } + + @Override + public ByteBuf toTransferByteBuf() { + return HEARTBEAT_MESSAGE; + } +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/IMessage.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/IMessage.java new file mode 100644 index 00000000..0e3ed5df --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/IMessage.java @@ -0,0 +1,25 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.message.IMessage + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/16 下午1:58 + * Description: + */ +package com.jd.blockchain.stp.communication.message; + +import io.netty.buffer.ByteBuf; + +/** + * + * @author shaozhuguang + * @create 2019/4/16 + * @since 1.0.0 + */ + +public interface IMessage { + + String toTransfer(); + + ByteBuf toTransferByteBuf(); +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/SessionMessage.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/SessionMessage.java new file mode 100644 index 00000000..10a121a3 --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/SessionMessage.java @@ -0,0 +1,95 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.message.SessionMessage + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/16 上午10:40 + * Description: + */ +package com.jd.blockchain.stp.communication.message; + +import com.alibaba.fastjson.JSON; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import org.apache.commons.codec.binary.Hex; + +/** + * + * @author shaozhuguang + * @create 2019/4/16 + * @since 1.0.0 + */ + +public class SessionMessage extends AbstractMessage implements IMessage { + + private String localHost; + + private int listenPort; + + private String messageExecute; + + public SessionMessage() { + } + + public SessionMessage(String localHost, int listenPort, String messageExecute) { + this.localHost = localHost; + this.listenPort = listenPort; + this.messageExecute = messageExecute; + } + + public String getLocalHost() { + return localHost; + } + + public void setLocalHost(String localHost) { + this.localHost = localHost; + } + + public void setListenPort(int listenPort) { + this.listenPort = listenPort; + } + + + public int getListenPort() { + return listenPort; + } + + public String getMessageExecute() { + return messageExecute; + } + + public void setMessageExecute(String messageExecute) { + this.messageExecute = messageExecute; + } + + public String sessionId() { + return Hex.encodeHexString((this.localHost + ":" + this.listenPort).getBytes()); + } + + public static SessionMessage toNodeSessionMessage(Object msg) { + String msgString = msg.toString(); + try { + String[] msgArray = msgString.split("\\|"); + if (msgArray.length == 2 || msgArray.length == 3) { + String host = msgArray[0]; + int port = Integer.parseInt(msgArray[1]); + String msgExecuteClass = null; + if (msgArray.length == 3) { + msgExecuteClass = msgArray[2]; + } + return new SessionMessage(host, port, msgExecuteClass); + } + return null; + } catch (Exception e) { + return null; + } + } + + @Override + public String toTransfer() { + // 为区别于TransferMessage的JSON格式,该处使用字符串连接处理 + // 格式:localHost|port|class + String transferMsg = this.localHost + "|" + this.listenPort + "|" + this.messageExecute; + return transferMsg; + } +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/TransferMessage.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/TransferMessage.java index eac2d2a2..7f0659fa 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/TransferMessage.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/TransferMessage.java @@ -8,6 +8,9 @@ */ package com.jd.blockchain.stp.communication.message; +import com.alibaba.fastjson.JSON; +import org.apache.commons.codec.binary.Base64; + /** * * @author shaozhuguang @@ -15,32 +18,135 @@ package com.jd.blockchain.stp.communication.message; * @since 1.0.0 */ -public class TransferMessage { +public class TransferMessage extends AbstractMessage implements IMessage{ - private byte[] key; + private String sessionId; - private byte[] load; + private int type; - public byte[] getKey() { - return key; + private String key; + + private transient byte[] load; + + private String loadBase64; + + public TransferMessage() { } - public void setKey(byte[] key) { + public TransferMessage(String sessionId, int type, String key, byte[] load) { + this.sessionId = sessionId; + this.type = type; this.key = key; + this.load = load; } - public byte[] getLoad() { + public static TransferMessage toTransferMessageObj(Object msg) { + if (msg == null) { + return null; + } + TransferMessage tm; + try { + tm = JSON.parseObject(msg.toString(), TransferMessage.class); + tm.initLoad(); + } catch (Exception e) { + return null; + } + return tm; + } + + public byte[] load() { return load; } - public void setLoad(byte[] load) { - this.load = load; + public void initLoad() { + if (loadBase64 != null && loadBase64.length() > 0) { + load = Base64.decodeBase64(loadBase64); + } + } + + public void initLoadBase64() { + if (load != null && load.length > 0) { + loadBase64 = Base64.encodeBase64String(load); + } + } + + @Override + public String toTransfer() { + // 使用JSON的方式发送 + // 初始化load的base64转换 + initLoadBase64(); + + // 将字符串转换为JSON + return JSON.toJSONString(this); + } + + public String toListenKey() { + // 格式:sessionId:key + return sessionId + ":" + key; + } + + public String getSessionId() { + return sessionId; + } + + public void setSessionId(String sessionId) { + this.sessionId = sessionId; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public String loadKey() { + return key; } - public String toBase64() { + public void setKey(String key) { + this.key = key; + } + + public String getKey() { + return key; + } + + public String getLoadBase64() { + return loadBase64; + } + + public void setLoadBase64(String loadBase64) { + this.loadBase64 = loadBase64; + } + + public enum MESSAGE_TYPE { + + TYPE_REQUEST(0), + + TYPE_RESPONSE(1); + + private int code; + + MESSAGE_TYPE(int code) { + this.code = code; + } + + public int code() { + return code; + } + public static MESSAGE_TYPE valueOf(int code) { + switch (code) { + case 0: + return TYPE_REQUEST; + case 1: + return TYPE_RESPONSE; + } + return null; + } - return null; } } \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/node/LocalNode.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/node/LocalNode.java new file mode 100644 index 00000000..f58bd034 --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/node/LocalNode.java @@ -0,0 +1,52 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.node.LocalNode + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/16 下午3:12 + * Description: + */ +package com.jd.blockchain.stp.communication.node; + +import com.jd.blockchain.stp.communication.MessageExecute; + +/** + * + * @author shaozhuguang + * @create 2019/4/16 + * @since 1.0.0 + */ + +public class LocalNode extends RemoteNode { + + private Class messageExecute; + + public LocalNode(String hostName, int port) { + super(hostName, port); + } + + public LocalNode(String hostName, int port, MessageExecute messageExecute) { + super(hostName, port); + this.messageExecute = messageExecute.getClass(); + } + + public LocalNode(String hostName, int port, Class messageExecute) { + super(hostName, port); + this.messageExecute = messageExecute; + } + + public String messageExecuteClass() { + if (this.messageExecute == null) { + return null; + } + return this.messageExecute.getName(); + } + + public void setMessageExecute(MessageExecute messageExecute) { + this.messageExecute = messageExecute.getClass(); + } + + public void setMessageExecute(Class messageExecute) { + this.messageExecute = messageExecute; + } +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteNode.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/node/RemoteNode.java similarity index 56% rename from source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteNode.java rename to source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/node/RemoteNode.java index 18fcafd2..dceb9115 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteNode.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/node/RemoteNode.java @@ -6,7 +6,7 @@ * Date: 2019/4/11 下午3:40 * Description: */ -package com.jd.blockchain.stp.communication; +package com.jd.blockchain.stp.communication.node; /** * @@ -41,4 +41,28 @@ public class RemoteNode { public void setHostName(String hostName) { this.hostName = hostName; } + + @Override + public int hashCode() { + return (hostName + ":" + port).hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (obj instanceof RemoteNode) { + RemoteNode other = (RemoteNode) obj; + if (this.hashCode() == other.hashCode()) { + return true; + } + } + return false; + } + + @Override + public String toString() { + return this.hostName + ":" + this.port; + } } \ No newline at end of file diff --git a/source/stp/stp-communication/src/test/java/com/jd/blockchain/SessionMessageTest.java b/source/stp/stp-communication/src/test/java/com/jd/blockchain/SessionMessageTest.java new file mode 100644 index 00000000..4a9211b6 --- /dev/null +++ b/source/stp/stp-communication/src/test/java/com/jd/blockchain/SessionMessageTest.java @@ -0,0 +1,37 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.SessionMessageTest + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/17 下午3:24 + * Description: + */ +package com.jd.blockchain; + +import com.jd.blockchain.stp.communication.message.SessionMessage; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * + * @author shaozhuguang + * @create 2019/4/17 + * @since 1.0.0 + */ + +public class SessionMessageTest { + + + @Test + public void test() { + SessionMessage message = new SessionMessage("127.0.0.1", 9001, "com.jd.blockchain.StpTest.StpMessageExecute"); + + String transMsg = message.toTransfer(); + System.out.println(transMsg); + + SessionMessage sm = SessionMessage.toNodeSessionMessage(transMsg); + + assertEquals(transMsg, sm.toTransfer()); + } +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/test/java/com/jd/blockchain/StpTest.java b/source/stp/stp-communication/src/test/java/com/jd/blockchain/StpTest.java deleted file mode 100644 index 04c7f1e4..00000000 --- a/source/stp/stp-communication/src/test/java/com/jd/blockchain/StpTest.java +++ /dev/null @@ -1,131 +0,0 @@ -/** - * Copyright: Copyright 2016-2020 JD.COM All Right Reserved - * FileName: com.jd.blockchain.StpTest - * Author: shaozhuguang - * Department: Y事业部 - * Date: 2019/4/11 下午3:31 - * Description: - */ -package com.jd.blockchain; - -import com.jd.blockchain.stp.communication.MessageHandler; -import com.jd.blockchain.stp.communication.RemoteNode; -import com.jd.blockchain.stp.communication.RemoteSession; -import com.jd.blockchain.stp.communication.RemoteSessionManager; -import com.jd.blockchain.stp.communication.message.LoadMessage; -import org.junit.Before; -import org.junit.Test; - -import java.net.InetAddress; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Future; -import java.util.concurrent.Semaphore; -import java.util.concurrent.TimeUnit; - -/** - * - * @author shaozhuguang - * @create 2019/4/11 - * @since 1.0.0 - */ - -public class StpTest { - - private int listenPort = 6000; - - private int maxWaitTime = 2000; - - private RemoteNode[] remoteNodes = new RemoteNode[3]; - - @Before - public void init() { - for (int i = 0; i < remoteNodes.length; i++) { - remoteNodes[i] = new RemoteNode("127.0.0.1", 6001 + i); - } - } - - - @Test - public void test() { - // 创建RemoteSessionManager对象 - RemoteSessionManager sessionManager = new RemoteSessionManager(listenPort); - - // 创建RemoteSession[]对象 - RemoteSession[] remoteSessions = sessionManager.newSessions(remoteNodes); - - // 设置MessageHandler并连接 - for (RemoteSession remoteSession : remoteSessions) { - - // 设置MessageHandler - remoteSession.initHandler(new StpMessageHandler()); - - // session连接 - remoteSession.connect(); - } - - // 生成请求对象 - LoadMessage loadMessage = new StpLoadMessage(); - - // 异步发送处理过程 - - CountDownLatch countDownLatch = new CountDownLatch(remoteSessions.length); - - // 发送请求至remotes - LinkedList> responses = new LinkedList<>(); - for (RemoteSession remoteSession : remoteSessions) { - Future response = remoteSession.asyncSend(loadMessage, countDownLatch); - responses.addLast(response); - } - - // 超时判断 - try { - if (countDownLatch.await(maxWaitTime, TimeUnit.MILLISECONDS)) { - // 汇总异步消息结果 - LinkedList receiveResponses = new LinkedList<>(); - // 通过迭代器遍历链表 - Iterator> iterator = responses.iterator(); - while (iterator.hasNext()) { - Future response = iterator.next(); - // 判断是否已完成,对于没有完成的直接放弃(因为已经超时) - if (response.isDone()) { - receiveResponses.addLast(response.get()); - } - } - - //TODO 检查汇总后的应答消息,准备开始新一轮的请求 - - - - - } - } catch (Exception e) { - - } - } - - - public static class StpMessageHandler implements MessageHandler { - - @Override - public void receive(byte[] key, byte[] data, RemoteSession session) { - // 作为Receiver接收到请求消息后需要发送应答 - // 生成应答消息 - LoadMessage replyLoadMessage = new StpLoadMessage(); - - // 发送应答消息(注意key必须保持一致) - // 异步发送应答消息可使用asyncReply - session.reply(key, replyLoadMessage); - } - } - - public static class StpLoadMessage implements LoadMessage { - - @Override - public byte[] toBytes() { - return new byte[0]; - } - } -} \ No newline at end of file diff --git a/source/test/pom.xml b/source/test/pom.xml index 4df214ad..ac3b0562 100644 --- a/source/test/pom.xml +++ b/source/test/pom.xml @@ -15,6 +15,7 @@ test-consensus-node test-ledger-core test-integration + test-stp-community diff --git a/source/test/test-stp-community/pom.xml b/source/test/test-stp-community/pom.xml new file mode 100644 index 00000000..12d031b1 --- /dev/null +++ b/source/test/test-stp-community/pom.xml @@ -0,0 +1,36 @@ + + + + + test + com.jd.blockchain + 0.9.0-SNAPSHOT + + 4.0.0 + + test-stp-community + + test-stp-community + + + UTF-8 + 1.8 + 1.8 + + + + + + com.jd.blockchain + stp-communication + ${project.version} + + + + junit + junit + test + + + diff --git a/source/test/test-stp-community/src/main/java/com/jd/blockchain/stp/commucation/MyMessageExecutor.java b/source/test/test-stp-community/src/main/java/com/jd/blockchain/stp/commucation/MyMessageExecutor.java new file mode 100644 index 00000000..aa8f6014 --- /dev/null +++ b/source/test/test-stp-community/src/main/java/com/jd/blockchain/stp/commucation/MyMessageExecutor.java @@ -0,0 +1,37 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.commucation.MyMessageExecutor + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/17 下午3:38 + * Description: + */ +package com.jd.blockchain.stp.commucation; + +import com.jd.blockchain.stp.communication.MessageExecute; +import com.jd.blockchain.stp.communication.RemoteSession; + +import java.nio.charset.Charset; + +/** + * + * @author shaozhuguang + * @create 2019/4/17 + * @since 1.0.0 + */ + +public class MyMessageExecutor implements MessageExecute { + + @Override + public byte[] receive(String key, byte[] data, RemoteSession session) { + String receiveMsg = new String(data, Charset.defaultCharset()); + System.out.printf("receive client {%s} request {%s} \r\n", session.sessionId(), receiveMsg); + String msg = session.sessionId() + " -> received !!!"; + return msg.getBytes(Charset.defaultCharset()); + } + + @Override + public REPLY replyType() { + return REPLY.AUTO; + } +} \ No newline at end of file diff --git a/source/test/test-stp-community/src/test/java/com/jd/blockchain/StpTest.java b/source/test/test-stp-community/src/test/java/com/jd/blockchain/StpTest.java new file mode 100644 index 00000000..422fb9a4 --- /dev/null +++ b/source/test/test-stp-community/src/test/java/com/jd/blockchain/StpTest.java @@ -0,0 +1,185 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.StpTest + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/11 下午3:31 + * Description: + */ +package com.jd.blockchain; + +import com.jd.blockchain.stp.commucation.MyMessageExecutor; +import com.jd.blockchain.stp.communication.MessageExecute; +import com.jd.blockchain.stp.communication.RemoteSession; +import com.jd.blockchain.stp.communication.callback.CallBackBarrier; +import com.jd.blockchain.stp.communication.callback.CallBackDataListener; +import com.jd.blockchain.stp.communication.manager.RemoteSessionManager; +import com.jd.blockchain.stp.communication.message.LoadMessage; +import com.jd.blockchain.stp.communication.node.LocalNode; +import com.jd.blockchain.stp.communication.node.RemoteNode; +import org.junit.Before; +import org.junit.Test; + +import java.nio.charset.Charset; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * + * @author shaozhuguang + * @create 2019/4/11 + * @since 1.0.0 + */ + +public class StpTest { + + private int maxWaitTime = 2000; + + private final String remoteHost = "127.0.0.1"; + + private final int localPort = 9001; + + private final int[] listenPorts = new int[]{9001, 9002, 9003, 9004}; + + private final RemoteSessionManager[] sessionManagers = new RemoteSessionManager[listenPorts.length]; + + private final ExecutorService threadPool = Executors.newFixedThreadPool(6); + + private RemoteSession[] remoteSessions; + + @Before + public void init() { + + System.out.println("---------- listenStart -----------"); + listenStart(); + System.out.println("---------- listenComplete -----------"); + System.out.println("---------- ConnectionStart ----------"); + connectAllOthers(); + System.out.println("---------- ConnectionComplete ----------"); + } + + private void listenStart() { + CountDownLatch countDownLatch = new CountDownLatch(listenPorts.length); + + for (int i = 0; i < listenPorts.length; i++) { + final int port = listenPorts[i], index = i; + threadPool.execute(() -> { + // 创建本地节点 + final LocalNode localNode = new LocalNode(remoteHost, port, MyMessageExecutor.class); + // 启动当前节点 + RemoteSessionManager sessionManager = new RemoteSessionManager(localNode); + sessionManagers[index] = sessionManager; + countDownLatch.countDown(); + System.out.printf("Current Node {%s} start success !!! \r\n", localNode.toString()); + }); + } + + // 等待所有节点启动完成 + try { + countDownLatch.await(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void connectAllOthers() { + // 所有节点完成之后,需要启动 + // 启动一个节点 + RemoteSessionManager starter = sessionManagers[0]; + + // 当前节点需要连接到其他3个节点 + RemoteNode[] remoteNodes = new RemoteNode[listenPorts.length - 1]; + int index = 0; + for (int port : listenPorts) { + if (port != localPort) { + remoteNodes[index++] = new RemoteNode(remoteHost, port); + } + } + + remoteSessions = starter.newSessions(remoteNodes, new MyMessageExecutor()); + } + + private void connectOneOther() { + // 所有节点完成之后,需要启动 + // 启动一个节点 + RemoteSessionManager starter = sessionManagers[0]; + + // 当前节点需要连接到其他3个节点 + RemoteNode[] remoteNodes = new RemoteNode[1]; + int index = 0; + for (int port : listenPorts) { + if (port != localPort && index < 1) { + remoteNodes[index++] = new RemoteNode(remoteHost, port); + } + } + + remoteSessions = starter.newSessions(remoteNodes, new MyMessageExecutor()); + } + + + @Test + public void test() { + + try { + Thread.sleep(3000); + + } catch (Exception e) { + e.printStackTrace(); + } + + // 生成请求对象 + LoadMessage loadMessage = new StpLoadMessage(remoteHost + ":" + localPort); + + // 异步发送处理过程 + CallBackBarrier callBackBarrier = CallBackBarrier.newCallBackBarrier(remoteSessions.length, 10000); + + // 发送请求至remotes + LinkedList responses = new LinkedList<>(); + for (RemoteSession remoteSession : remoteSessions) { + CallBackDataListener response = remoteSession.asyncRequest(loadMessage, callBackBarrier); + responses.addLast(response); + } + + // 超时判断 + try { + if (callBackBarrier.tryCall()) { + + // 说明结果已经全部返回 + // 打印出所有的结果 + // 通过迭代器遍历链表 + Iterator iterator = responses.iterator(); + while (iterator.hasNext()) { + CallBackDataListener response = iterator.next(); + // 判断是否已完成,对于没有完成的直接放弃(因为已经超时) + if (response.isDone()) { + System.out.printf("Receive Response {%s} {%s} \r\n", + response.remoteNode().toString(), new String(response.getCallBackData())); + } + } + } + Thread.sleep(Integer.MAX_VALUE); + } catch (Exception e) { + e.printStackTrace(); + } + + + } + + public static class StpLoadMessage implements LoadMessage { + + private String localInfo; + + public StpLoadMessage(String localInfo) { + this.localInfo = localInfo; + } + + @Override + public byte[] toBytes() { + String msg = localInfo + " -> Send !!!"; + return msg.getBytes(Charset.defaultCharset()); + } + } +} \ No newline at end of file From a4ae5ab97be2373bac10a05f721a5b5ec3223c90 Mon Sep 17 00:00:00 2001 From: shaozhuguang Date: Thu, 18 Apr 2019 15:41:17 +0800 Subject: [PATCH 04/43] Add Explanatory Notes for SFP-Communication Module. --- .../statetransfer/DSTransferProcess.java | 2 +- .../statetransfer/DataSequenceMsgHandle.java | 4 +- ...ssageExecute.java => MessageExecutor.java} | 6 +- .../stp/communication/RemoteSession.java | 103 +++++++- .../callback/CallBackBarrier.java | 22 +- .../callback/CallBackDataListener.java | 45 +++- .../callback/CallBackLauncher.java | 79 +++++++ .../connection/AbstractAsyncExecutor.java | 36 ++- .../connection/AsyncExecutor.java | 15 +- .../communication/connection/Connection.java | 101 +++++++- .../communication/connection/Receiver.java | 57 +++-- .../stp/communication/connection/Sender.java | 34 ++- .../handler/HeartBeatReceiverHandler.java | 4 +- .../handler/HeartBeatReceiverTrigger.java | 4 +- .../handler/HeartBeatSenderHandler.java | 2 +- .../handler/HeartBeatSenderTrigger.java | 6 +- .../connection/handler/ReceiverHandler.java | 220 +++++++++++++----- .../connection/handler/SenderHandler.java | 5 +- .../connection/handler/WatchDogHandler.java | 64 ++++- .../connection/listener/ReplyListener.java | 19 +- .../manager/ConnectionManager.java | 94 ++++++-- .../manager/RemoteSessionManager.java | 173 ++++++++++---- .../message/AbstractMessage.java | 2 +- .../message/HeartBeatMessage.java | 27 ++- .../stp/communication/message/IMessage.java | 10 +- .../communication/message/LoadMessage.java | 7 +- .../communication/message/SessionMessage.java | 51 ++-- .../message/TransferMessage.java | 33 ++- .../stp/communication/node/LocalNode.java | 75 ++++-- .../stp/communication/node/RemoteNode.java | 12 +- .../com/jd/blockchain/SessionMessageTest.java | 2 +- .../stp/commucation/MyMessageExecutor.java | 4 +- .../test/java/com/jd/blockchain/StpTest.java | 41 +++- 33 files changed, 1100 insertions(+), 259 deletions(-) rename source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/{MessageExecute.java => MessageExecutor.java} (87%) create mode 100644 source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackLauncher.java diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DSTransferProcess.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DSTransferProcess.java index 1fba56ff..6d5b699f 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DSTransferProcess.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DSTransferProcess.java @@ -69,7 +69,7 @@ public class DSTransferProcess { for (int i = 0; i < remoteSessions.length; i++) { DataSequenceMsgHandle msgHandle = new DataSequenceMsgHandle(dsReader, dsWriter); - remoteSessions[i].initExecute(msgHandle); + remoteSessions[i].initExecutor(msgHandle); remoteSessions[i].init(); } } diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceMsgHandle.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceMsgHandle.java index 77fa0417..d396ff3e 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceMsgHandle.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceMsgHandle.java @@ -1,6 +1,6 @@ package com.jd.blockchain.statetransfer; -import com.jd.blockchain.stp.communication.MessageExecute; +import com.jd.blockchain.stp.communication.MessageExecutor; import com.jd.blockchain.stp.communication.RemoteSession; /** @@ -9,7 +9,7 @@ import com.jd.blockchain.stp.communication.RemoteSession; * @create 2019/4/11 * @since 1.0.0 */ -public class DataSequenceMsgHandle implements MessageExecute { +public class DataSequenceMsgHandle implements MessageExecutor { DataSequenceReader dsReader; DataSequenceWriter dsWriter; diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/MessageExecute.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/MessageExecutor.java similarity index 87% rename from source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/MessageExecute.java rename to source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/MessageExecutor.java index 7640d122..ca85b0c8 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/MessageExecute.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/MessageExecutor.java @@ -9,13 +9,15 @@ package com.jd.blockchain.stp.communication; /** - * + * 消息执行器 + * 该执行器由其他应用实现 * @author shaozhuguang * @create 2019/4/11 * @since 1.0.0 + * @date 2019-04-18 15:29 */ -public interface MessageExecute { +public interface MessageExecutor { byte[] receive(String key, byte[] data, RemoteSession session); diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteSession.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteSession.java index b6ad6794..cc4dd167 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteSession.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteSession.java @@ -13,6 +13,8 @@ import com.jd.blockchain.stp.communication.callback.CallBackDataListener; import com.jd.blockchain.stp.communication.connection.Connection; import com.jd.blockchain.stp.communication.message.LoadMessage; +import java.util.concurrent.TimeUnit; + /** * @@ -23,38 +25,125 @@ import com.jd.blockchain.stp.communication.message.LoadMessage; public class RemoteSession { + /** + * 远端节点ID + */ private String id; + /** + * 远端连接 + */ private Connection connection; - private MessageExecute messageExecute; + /** + * 对应远端节点消息的处理器 + * 该处理器若为NULL,则使用当前节点默认处理器 + */ + private MessageExecutor messageExecutor; + + + /** + * 构造器 + * @param id + * 远端节点ID + * @param connection + * 对应连接 + */ + public RemoteSession(String id, Connection connection) { + this(id, connection, null); + } - public RemoteSession(String id, Connection connection, MessageExecute messageExecute) { + /** + * 构造器 + * @param id + * 远端ID + * @param connection + * 对应连接 + * @param messageExecutor + * 对应远端消息处理器 + */ + public RemoteSession(String id, Connection connection, MessageExecutor messageExecutor) { this.id = id; this.connection = connection; - this.messageExecute = messageExecute; + this.messageExecutor = messageExecutor; } public void init() { connection.initSession(this); } - public void initExecute(MessageExecute messageExecute) { - this.messageExecute = messageExecute; + public void initExecutor(MessageExecutor messageExecutor) { + this.messageExecutor = messageExecutor; } + /** + * 同步请求 + * 该请求会阻塞原线程 + * + * @param loadMessage + * 要请求的负载消息 + * @return + * 应答,直到有消息应答或出现异常 + * @throws Exception + */ public byte[] request(LoadMessage loadMessage) throws Exception { return this.connection.request(this.id, loadMessage, null).getCallBackData(); } + /** + * 同步请求 + * 该请求会阻塞原线程 + * + * @param loadMessage + * 要请求的负载消息 + * @param time + * 请求的最长等待时间 + * @param timeUnit + * 请求的最长等待单位 + * @return + * 应答,直到有消息或时间截止或出现异常 + * @throws Exception + */ + public byte[] request(LoadMessage loadMessage, long time, TimeUnit timeUnit) throws Exception { + return this.connection.request(this.id, loadMessage, null).getCallBackData(time, timeUnit); + } + + /** + * 异步请求 + * 不会阻塞调用线程 + * + * @param loadMessage + * 要发送的负载消息 + * @return + * 应答,需要调用者从Listener中获取结果 + */ public CallBackDataListener asyncRequest(LoadMessage loadMessage) { return asyncRequest(loadMessage, null); } + /** + * 异步请求 + * 不会阻塞调用线程 + * + * @param loadMessage + * 要请求的负载消息 + * @param callBackBarrier + * 回调栅栏(用于多个请求时进行统一阻拦) + * @return + * 应答,需要调用者从Listener中获取结果 + */ public CallBackDataListener asyncRequest(LoadMessage loadMessage, CallBackBarrier callBackBarrier) { return this.connection.request(this.id, loadMessage, callBackBarrier); } + /** + * 应答 + * + * @param key + * 请求消息的Key + * @param loadMessage + * 需要应答的负载消息 + */ public void reply(String key, LoadMessage loadMessage) { this.connection.reply(this.id, key, loadMessage); } @@ -75,7 +164,7 @@ public class RemoteSession { return id; } - public MessageExecute messageExecute() { - return this.messageExecute; + public MessageExecutor messageExecutor() { + return this.messageExecutor; } } \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackBarrier.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackBarrier.java index 433533a0..c9580e10 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackBarrier.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackBarrier.java @@ -8,12 +8,12 @@ */ package com.jd.blockchain.stp.communication.callback; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** - * + * 回调栅栏 + * 用于对批量请求的应答回调处理 * @author shaozhuguang * @create 2019/4/12 * @since 1.0.0 @@ -23,12 +23,30 @@ public class CallBackBarrier { private CountDownLatch countDownLatch; + /** + * 默认最大尝试调用时间(单位:毫秒) + */ private long maxTryCallMillSeconds = 2000; + + /** + * 静态构造器 + * @param barrierLength + * 请求的远端数量 + * @return + */ public static final CallBackBarrier newCallBackBarrier(int barrierLength) { return new CallBackBarrier(barrierLength); } + /** + * 静态构造器 + * @param barrierLength + * 请求的远端数量 + * @param maxTryCallMillSeconds + * 最大尝试的时间,单位:毫秒 + * @return + */ public static final CallBackBarrier newCallBackBarrier(int barrierLength, long maxTryCallMillSeconds) { return new CallBackBarrier(barrierLength, maxTryCallMillSeconds); } diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackDataListener.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackDataListener.java index 252765f9..e9aa4417 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackDataListener.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackDataListener.java @@ -18,7 +18,7 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** - * + * 数据回调监听器 * @author shaozhuguang * @create 2019/4/15 * @since 1.0.0 @@ -26,30 +26,69 @@ import java.util.concurrent.locks.ReentrantLock; public class CallBackDataListener { + /** + * Future + */ private CompletableFuture future = new CompletableFuture<>(); + /** + * 远端节点 + */ private RemoteNode remoteNode; private boolean isFill = false; private Lock lock = new ReentrantLock(); + + /** + * 构造器 + * @param remoteNode + * 远端节点信息 + */ public CallBackDataListener(RemoteNode remoteNode) { this.remoteNode = remoteNode; } + /** + * 获取返回的数据 + * 调用该方法会阻塞当前线程,直到有数据返回或出现异常 + * @return + * 应答结果 + * @throws InterruptedException + * @throws ExecutionException + */ public byte[] getCallBackData() throws InterruptedException, ExecutionException { return future.get(); } + /** + * 指定时间内获取返回的数据 + * 调用该方法会阻塞当前线程,直到时间到达或有数据返回或出现异常 + * @param time + * 超时时间 + * @param timeUnit + * 超时单位 + * @return + * 应答结果,若指定时间内没有数据,则返回null + * @throws InterruptedException + * @throws ExecutionException + * @throws TimeoutException + */ public byte[] getCallBackData(long time, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException { return future.get(time, timeUnit); } + /** + * 设置返回的数据 + * @param data + */ public void setCallBackData(byte[] data) { + // 防止数据多次设置 if (!isFill) { try { lock.lock(); + // Double Check if (!isFill) { future.complete(data); isFill = true; @@ -64,6 +103,10 @@ public class CallBackDataListener { return this.remoteNode; } + /** + * 判断是否异步操作完成 + * @return + */ public boolean isDone() { return future.isDone(); } diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackLauncher.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackLauncher.java new file mode 100644 index 00000000..bef91db4 --- /dev/null +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackLauncher.java @@ -0,0 +1,79 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.stp.communication.callback.CallBackLauncher + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/17 下午6:27 + * Description: + */ +package com.jd.blockchain.stp.communication.callback; + +import java.util.concurrent.Semaphore; + +/** + * 启动器回调 + * @author shaozhuguang + * @create 2019/4/17 + * @since 1.0.0 + */ + +public class CallBackLauncher { + + /** + * 是否启动成功 + */ + private boolean isBootSuccess = false; + + /** + * 信号量 + */ + private Semaphore isBooted = new Semaphore(0, true); + + /** + * 异常 + */ + private Exception exception; + + /** + * 标识当前启动成功 + */ + public void bootSuccess() { + isBootSuccess = true; + release(); + } + + /** + * 标识当前启动失败 + * @param e + * 导致失败的异常信息 + */ + public void bootFail(Exception e) { + this.exception = e; + isBootSuccess = false; + release(); + } + + /** + * 等待启动完成 + * 调用该方法会阻塞当前线程,知道启动完成或发生异常 + * @return + * 当前对象 + * @throws InterruptedException + */ + public CallBackLauncher waitingBooted() throws InterruptedException { + this.isBooted.acquire(); + return this; + } + + public boolean isBootSuccess() { + return isBootSuccess; + } + + public Exception exception() { + return exception; + } + + private void release() { + this.isBooted.release(); + } +} \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/AbstractAsyncExecutor.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/AbstractAsyncExecutor.java index b1c07df7..273fcbc0 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/AbstractAsyncExecutor.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/AbstractAsyncExecutor.java @@ -9,11 +9,12 @@ package com.jd.blockchain.stp.communication.connection; import com.google.common.util.concurrent.ThreadFactoryBuilder; +import com.jd.blockchain.stp.communication.callback.CallBackLauncher; import java.util.concurrent.*; /** - * + * 抽象异步执行器 * @author shaozhuguang * @create 2019/4/17 * @since 1.0.0 @@ -21,19 +22,27 @@ import java.util.concurrent.*; public abstract class AbstractAsyncExecutor implements AsyncExecutor{ + /** + * 线程池可处理队列的容量 + */ private static final int QUEUE_CAPACITY = 1024; - protected final Semaphore isStarted = new Semaphore(0, true); - - protected boolean isStartSuccess = false; + /** + * 回调执行器 + */ + protected final CallBackLauncher callBackLauncher = new CallBackLauncher(); + /** + * 默认提供的初始化活跃线程调度器 + * @return + */ @Override public ThreadPoolExecutor initRunThread() { ThreadFactory timerFactory = new ThreadFactoryBuilder() .setNameFormat(threadNameFormat()).build(); ThreadPoolExecutor runThread = new ThreadPoolExecutor(1, 1, - 0, TimeUnit.MILLISECONDS, + 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(QUEUE_CAPACITY), timerFactory, new ThreadPoolExecutor.AbortPolicy()); @@ -41,11 +50,22 @@ public abstract class AbstractAsyncExecutor implements AsyncExecutor{ return runThread; } + /** + * 启动完成后回调 + * 该调用会阻塞当前线程,直到启动完成,无论是成功或失败 + * @return + * 回调执行器 + * 成功或失败会在回调执行器中有所体现 + * @throws InterruptedException + */ @Override - public boolean waitStarted() throws InterruptedException { - this.isStarted.acquire(); - return this.isStartSuccess; + public CallBackLauncher waitBooted() throws InterruptedException { + return callBackLauncher.waitingBooted(); } + /** + * 线程池中的线程命名格式 + * @return + */ public abstract String threadNameFormat(); } \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/AsyncExecutor.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/AsyncExecutor.java index 170b1ea5..22c0c28a 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/AsyncExecutor.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/AsyncExecutor.java @@ -8,10 +8,12 @@ */ package com.jd.blockchain.stp.communication.connection; +import com.jd.blockchain.stp.communication.callback.CallBackLauncher; + import java.util.concurrent.ThreadPoolExecutor; /** - * + * 异步执行器接口 * @author shaozhuguang * @create 2019/4/17 * @since 1.0.0 @@ -19,7 +21,16 @@ import java.util.concurrent.ThreadPoolExecutor; public interface AsyncExecutor { + /** + * 初始化运行线程 + * @return + */ ThreadPoolExecutor initRunThread(); - boolean waitStarted() throws InterruptedException; + /** + * 启动完成后返回调度执行器 + * @return + * @throws InterruptedException + */ + CallBackLauncher waitBooted() throws InterruptedException; } \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Connection.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Connection.java index 1cb673f7..7ceedf77 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Connection.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Connection.java @@ -11,6 +11,7 @@ package com.jd.blockchain.stp.communication.connection; import com.jd.blockchain.stp.communication.RemoteSession; import com.jd.blockchain.stp.communication.callback.CallBackBarrier; import com.jd.blockchain.stp.communication.callback.CallBackDataListener; +import com.jd.blockchain.stp.communication.callback.CallBackLauncher; import com.jd.blockchain.stp.communication.connection.listener.ReplyListener; import com.jd.blockchain.stp.communication.message.LoadMessage; import com.jd.blockchain.stp.communication.message.SessionMessage; @@ -21,35 +22,85 @@ import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.digest.DigestUtils; /** - * + * 统一连接对象 + * 该对象中有两个对象Receiver和Sender + * Receiver为复用对象(每个端口监听产生的Receiver只有一个) * @author shaozhuguang * @create 2019/4/11 * @since 1.0.0 + * @date 2019-04-18 14:49 */ - public class Connection { + /** + * 远端节点 + */ private RemoteNode remoteNode; + /** + * 接收器 + */ private Receiver receiver; + /** + * 发送器 + */ private Sender sender; + /** + * 构造器 + * + * @param receiver + */ public Connection(Receiver receiver) { this.receiver = receiver; } + /** + * 初始化RemoteSession + * + * @param remoteSession + */ public void initSession(RemoteSession remoteSession) { this.receiver.initRemoteSession(remoteSession.sessionId(), remoteSession); } - public boolean connect(RemoteNode remoteNode, String messageExecuteClass) throws InterruptedException { + /** + * 连接远端 + * + * @param remoteNode + * 远端节点 + * @param messageExecutorClass + * 希望远端节点处理本地节点消息时的消息处理器 + * @return + * 回调执行器 + * @throws InterruptedException + */ + public CallBackLauncher connect(RemoteNode remoteNode, String messageExecutorClass) throws InterruptedException { this.remoteNode = remoteNode; - this.sender = new Sender(this.remoteNode, sessionMessage(messageExecuteClass)); + this.sender = new Sender(this.remoteNode, sessionMessage(messageExecutorClass)); this.sender.connect(); - return this.sender.waitStarted(); + return this.sender.waitBooted(); } + /** + * 发送请求 + * + * 处理过程简述如下: + * 1、生成底层消息(TransferMessage),其中消息类型为请求,用于描述本次发送的消息是用于请求应答; + * 2、根据消息的唯一Key,生成listenKey,并生成应答监听器 + * 3、将应答监听器添加到Receiver中(Receiver中是以Map存储) + * 4、调用Sender发送消息至对端节点 + * 5、返回应答监听器的回调数据监听对象 + * + * @param sessionId + * 当前SessionId + * @param loadMessage + * 载体消息 + * @param callBackBarrier + * 回调栅栏 + * @return + */ public CallBackDataListener request(String sessionId, LoadMessage loadMessage, CallBackBarrier callBackBarrier) { TransferMessage transferMessage = transferMessage(sessionId, null, loadMessage, TransferMessage.MESSAGE_TYPE.TYPE_REQUEST); @@ -69,6 +120,16 @@ public class Connection { return replyListener.callBackDataListener(); } + /** + * 发送应答 + * + * @param sessionId + * 当前SessionID + * @param key + * 请求消息的Key,用于描述对应的请求 + * @param loadMessage + * 应答的载体消息 + */ public void reply(String sessionId, String key, LoadMessage loadMessage) { TransferMessage transferMessage = transferMessage(sessionId, key, loadMessage, TransferMessage.MESSAGE_TYPE.TYPE_RESPONSE); @@ -76,6 +137,12 @@ public class Connection { this.sender.send(transferMessage); } + /** + * 生成载体消息的Key + * + * @param loadMessage + * @return + */ private String loadKey(LoadMessage loadMessage) { // 使用Sha256求Hash byte[] sha256Bytes = DigestUtils.sha256(loadMessage.toBytes()); @@ -83,6 +150,19 @@ public class Connection { return Base64.encodeBase64String(sha256Bytes); } + /** + * 生成TransferMessage + * + * @param sessionId + * 节点ID + * @param key + * 消息Key + * @param loadMessage + * 载体消息 + * @param messageType + * 消息类型 + * @return + */ private TransferMessage transferMessage(String sessionId, String key, LoadMessage loadMessage, TransferMessage.MESSAGE_TYPE messageType) { if (key == null || key.length() == 0) { @@ -95,12 +175,19 @@ public class Connection { return transferMessage; } - private SessionMessage sessionMessage(String messageExecuteClass) { + /** + * 生成SessionMessage + * + * @param messageExecutorClass + * + * @return + */ + private SessionMessage sessionMessage(String messageExecutorClass) { LocalNode localNode = this.receiver.localNode(); SessionMessage sessionMessage = new SessionMessage( - localNode.getHostName(), localNode.getPort(), messageExecuteClass); + localNode.getHostName(), localNode.getPort(), messageExecutorClass); return sessionMessage; } diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Receiver.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Receiver.java index 3adee11d..c9dae7fa 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Receiver.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Receiver.java @@ -14,7 +14,6 @@ import com.jd.blockchain.stp.communication.connection.handler.HeartBeatReceiverT import com.jd.blockchain.stp.communication.connection.handler.ReceiverHandler; import com.jd.blockchain.stp.communication.connection.listener.ReplyListener; import com.jd.blockchain.stp.communication.manager.ConnectionManager; -import com.jd.blockchain.stp.communication.manager.RemoteSessionManager; import com.jd.blockchain.stp.communication.node.LocalNode; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; @@ -26,19 +25,14 @@ import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.LineBasedFrameDecoder; import io.netty.handler.codec.string.StringDecoder; -import io.netty.handler.codec.string.StringEncoder; -import io.netty.handler.logging.LogLevel; -import io.netty.handler.logging.LoggingHandler; import io.netty.handler.timeout.IdleStateHandler; import java.io.Closeable; -import java.io.IOException; import java.net.InetSocketAddress; -import java.util.Map; import java.util.concurrent.*; /** - * + * 接收器 * @author shaozhuguang * @create 2019/4/11 * @since 1.0.0 @@ -46,18 +40,33 @@ import java.util.concurrent.*; public class Receiver extends AbstractAsyncExecutor implements Closeable { + /** + * Netty中的BOSS线程 + */ private final EventLoopGroup bossGroup = new NioEventLoopGroup(); + /** + * Netty中的Worker线程 + */ private final EventLoopGroup workerGroup = new NioEventLoopGroup(); + /** + * 本地节点 + */ private LocalNode localNode; + /** + * 消息接收Handler + */ private ReceiverHandler receiverHandler; public Receiver(LocalNode localNode) { this.localNode = localNode; } + /** + * 启动监听 + */ public void startListen() { ServerBootstrap bootstrap = new ServerBootstrap(); @@ -80,14 +89,14 @@ public class Receiver extends AbstractAsyncExecutor implements Closeable { } }); - // 由单独的线程启动 + // 由单独的线程启动,防止外部调用线程阻塞 ThreadPoolExecutor runThread = initRunThread(); runThread.execute(() -> { try { ChannelFuture f = bootstrap.bind().sync(); - super.isStartSuccess = f.isSuccess(); - super.isStarted.release(); - if (super.isStartSuccess) { + boolean isStartSuccess = f.isSuccess(); + if (isStartSuccess) { + super.callBackLauncher.bootSuccess(); // 启动成功 f.channel().closeFuture().sync(); } else { @@ -95,7 +104,7 @@ public class Receiver extends AbstractAsyncExecutor implements Closeable { throw new Exception("Receiver start fail :" + f.cause().getMessage() + " !!!"); } } catch (Exception e) { - throw new RuntimeException(e); + super.callBackLauncher.bootFail(e); } finally { close(); } @@ -107,14 +116,34 @@ public class Receiver extends AbstractAsyncExecutor implements Closeable { return "receiver-pool-%d"; } - public void initReceiverHandler(ConnectionManager connectionManager, String messageExecuteClass) { - receiverHandler = new ReceiverHandler(connectionManager, messageExecuteClass); + /** + * 初始化ReceiverHandler + * + * @param connectionManager + * 连接管理器 + * @param messageExecutorClass + * 当前节点的消息处理Class + */ + public void initReceiverHandler(ConnectionManager connectionManager, String messageExecutorClass) { + receiverHandler = new ReceiverHandler(connectionManager, messageExecutorClass, this.localNode.defaultMessageExecutor()); } + /** + * 初始化远端Session + * + * @param sessionId + * + * @param remoteSession + */ public void initRemoteSession(String sessionId, RemoteSession remoteSession) { receiverHandler.putRemoteSession(sessionId, remoteSession); } + /** + * 添加监听器 + * + * @param replyListener + */ public void addListener(ReplyListener replyListener) { receiverHandler.addListener(replyListener); } diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Sender.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Sender.java index 6e9dde46..cbc57467 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Sender.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Sender.java @@ -13,30 +13,27 @@ import com.jd.blockchain.stp.communication.message.IMessage; import com.jd.blockchain.stp.communication.message.SessionMessage; import com.jd.blockchain.stp.communication.node.RemoteNode; import io.netty.bootstrap.Bootstrap; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.LineBasedFrameDecoder; import io.netty.handler.codec.string.StringDecoder; -import io.netty.handler.codec.string.StringEncoder; import io.netty.handler.timeout.IdleStateHandler; import java.io.Closeable; -import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; import java.util.concurrent.*; /** + * 发送器 * * @author shaozhuguang * @create 2019/4/11 * @since 1.0.0 + * @date 2019-04-18 15:08 */ - public class Sender extends AbstractAsyncExecutor implements Closeable { private final EventLoopGroup loopGroup = new NioEventLoopGroup(); @@ -45,12 +42,24 @@ public class Sender extends AbstractAsyncExecutor implements Closeable { private ChannelFuture channelFuture; + /** + * 当前节点的SessionMessage + */ private SessionMessage sessionMessage; + /** + * 远端HOST + */ private String remoteHost; + /** + * 远端端口 + */ private int remotePort; + /** + * 监听Handler(重连Handler) + */ private WatchDogHandler watchDogHandler; public Sender(RemoteNode remoteNode, SessionMessage sessionMessage) { @@ -61,6 +70,9 @@ public class Sender extends AbstractAsyncExecutor implements Closeable { init(remoteHost, remotePort, sessionMessage); } + /** + * 连接 + */ public void connect() { watchDogHandler = new WatchDogHandler(this.remoteHost, this.remotePort, bootstrap); @@ -93,13 +105,13 @@ public class Sender extends AbstractAsyncExecutor implements Closeable { try { // 发起连接请求 channelFuture = bootstrap.connect(this.remoteHost, this.remotePort).sync(); - - isStartSuccess = channelFuture.isSuccess(); - isStarted.release(); + boolean isStartSuccess = channelFuture.isSuccess(); if (isStartSuccess) { // 启动成功 // 设置ChannelFuture对象,以便于发送的连接状态处理 watchDogHandler.initChannelFuture(channelFuture); + // 释放等待 + super.callBackLauncher.bootSuccess(); // 等待客户端关闭连接 channelFuture.channel().closeFuture().sync(); } else { @@ -107,7 +119,7 @@ public class Sender extends AbstractAsyncExecutor implements Closeable { throw new Exception("Sender start fail :" + channelFuture.cause().getMessage() + " !!!"); } } catch (Exception e) { - throw new RuntimeException(e); + super.callBackLauncher.bootFail(e); } finally { close(); } @@ -135,6 +147,10 @@ public class Sender extends AbstractAsyncExecutor implements Closeable { return "sender-pool-%d"; } + /** + * 发送消息 + * @param message + */ public void send(IMessage message) { watchDogHandler.channelFuture().channel().writeAndFlush(message.toTransferByteBuf()); } diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatReceiverHandler.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatReceiverHandler.java index a67920e9..47d65176 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatReceiverHandler.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatReceiverHandler.java @@ -14,7 +14,7 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; /** - * + * 心跳接收Handler * @author shaozhuguang * @create 2019/4/15 * @since 1.0.0 @@ -24,11 +24,13 @@ public class HeartBeatReceiverHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // 判断当前收到的信息是否为心跳信息 if (HeartBeatMessage.isHeartBeat(msg)) { // 收到的消息是心跳消息,此时需要回复一个心跳消息 HeartBeatMessage.write(ctx); System.out.println("Receive HeartBeat Request Message -> " + msg.toString()); } else { + // 非心跳信息的情况下交由其他Handler继续处理 super.channelRead(ctx, msg); } } diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatReceiverTrigger.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatReceiverTrigger.java index 575895be..588b6de3 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatReceiverTrigger.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatReceiverTrigger.java @@ -15,7 +15,7 @@ import io.netty.handler.timeout.IdleState; import io.netty.handler.timeout.IdleStateEvent; /** - * + * 心跳接收触发器 * @author shaozhuguang * @create 2019/4/15 * @since 1.0.0 @@ -28,12 +28,14 @@ public class HeartBeatReceiverTrigger extends ChannelInboundHandlerAdapter { // 服务端只会接收心跳数据后应答,而不会主动应答 if (evt instanceof IdleStateEvent) { IdleState idleState = ((IdleStateEvent) evt).state(); + // 读请求超时表示很久没有收到客户端请求 if (idleState.equals(IdleState.READER_IDLE)) { // 长时间未收到客户端请求,则关闭连接 System.out.println("Long Time UnReceive HeartBeat Request, Close Connection !!!"); ctx.close(); } } else { + // 非空闲状态事件,由其他Handler处理 super.userEventTriggered(ctx, evt); } } diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatSenderHandler.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatSenderHandler.java index da471003..a477c42c 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatSenderHandler.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatSenderHandler.java @@ -14,7 +14,7 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; /** - * + * 心跳发送Handler * @author shaozhuguang * @create 2019/4/15 * @since 1.0.0 diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatSenderTrigger.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatSenderTrigger.java index 496dc348..fc059d54 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatSenderTrigger.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatSenderTrigger.java @@ -16,7 +16,7 @@ import io.netty.handler.timeout.IdleState; import io.netty.handler.timeout.IdleStateEvent; /** - * + * 心跳发送触发器 * @author shaozhuguang * @create 2019/4/15 * @since 1.0.0 @@ -27,7 +27,7 @@ public class HeartBeatSenderTrigger extends ChannelInboundHandlerAdapter { @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { - // 心跳事件 + // 心跳事件(状态空闲事件) if (evt instanceof IdleStateEvent) { IdleState idleState = ((IdleStateEvent) evt).state(); if (idleState.equals(IdleState.READER_IDLE)) { @@ -40,7 +40,7 @@ public class HeartBeatSenderTrigger extends ChannelInboundHandlerAdapter { System.out.println("Read TimeOut Trigger, Send HeartBeat Request !!!"); HeartBeatMessage.write(ctx); } - // 还有一种情况是读写超时,该情况暂不处理 + // TODO 还有一种情况是读写超时,该情况暂不处理 } else { super.userEventTriggered(ctx, evt); } diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/ReceiverHandler.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/ReceiverHandler.java index 179ff0da..1bcb5ef3 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/ReceiverHandler.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/ReceiverHandler.java @@ -9,7 +9,7 @@ package com.jd.blockchain.stp.communication.connection.handler; import com.google.common.util.concurrent.ThreadFactoryBuilder; -import com.jd.blockchain.stp.communication.MessageExecute; +import com.jd.blockchain.stp.communication.MessageExecutor; import com.jd.blockchain.stp.communication.RemoteSession; import com.jd.blockchain.stp.communication.connection.Connection; import com.jd.blockchain.stp.communication.connection.listener.ReplyListener; @@ -28,7 +28,7 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** - * + * 接收者消息处理Handler * @author shaozhuguang * @create 2019/4/12 * @since 1.0.0 @@ -36,25 +36,62 @@ import java.util.concurrent.locks.ReentrantLock; @ChannelHandler.Sharable public class ReceiverHandler extends ChannelInboundHandlerAdapter implements Closeable { - // 队列的最大容量为256K(防止队列溢出) + /** + * 队列的最大容量设置,默认为256K(防止队列溢出) + */ private static final int QUEUE_CAPACITY = 256 * 1024; + /** + * 远端RemoteSession信息集合 + * Key为SessionId + * Sender发送的消息中会携带SessionId + * ReceiverHandler会根据不同的SessionId采用不同的MessageExecutor处理策略 + */ private final Map remoteSessions = new ConcurrentHashMap<>(); + /** + * 监听器集合 + * 对应Sender在发送请求之前会设置ReplyListener + * Key为每个请求消息的Hash,用于描述消息的唯一性 + * 应答一方会在应答中加入对应的key,用于消息的映射 + */ private final Map allReplyListeners = new ConcurrentHashMap<>(); - private final Lock lock = new ReentrantLock(); - - private String messageExecuteClass; - + /** + * session控制锁 + * 用于防止对统一RemoteSession对象进行重复设置 + */ + private final Lock sessionLock = new ReentrantLock(); + + /** + * 当前节点(本地节点)的消息处理器对应Class + * 该信息用于发送至其他节点,向其他节点通知遇到本节点请求时该如何处理 + */ + private String localMsgExecutorClass; + + /** + * 连接控制器,用于与远端节点连接 + */ private ConnectionManager connectionManager; - private ExecutorService msgExecutePool; + /** + * 消息处理执行线程池 + * 防止执行内容过长,导致阻塞 + */ + private ExecutorService msgExecutorPool; - public ReceiverHandler(ConnectionManager connectionManager, String messageExecuteClass) { + /** + * 默认消息处理器 + * 当对应session获取到的RemoteSession中没有获取到指定MessageExecutor时,短时间内由其进行处理 + */ + private MessageExecutor defaultMessageExecutor; + + public ReceiverHandler(ConnectionManager connectionManager, String localMsgExecutorClass, + MessageExecutor defaultMessageExecutor) { this.connectionManager = connectionManager; - this.messageExecuteClass = messageExecuteClass; - init(); + this.localMsgExecutorClass = localMsgExecutorClass; + this.defaultMessageExecutor = defaultMessageExecutor; + initMsgExecutorPool(); } public void putRemoteSession(String sessionId, RemoteSession remoteSession) { @@ -75,10 +112,10 @@ public class ReceiverHandler extends ChannelInboundHandlerAdapter implements Clo System.out.println("Receive Biz Message -> " + msg.toString()); // 有数据接入 // 首先判断数据是否TransferMessage,当前Handler不处理非TransferMessage - TransferMessage tm = TransferMessage.toTransferMessageObj(msg); + TransferMessage tm = TransferMessage.toTransferMessage(msg); if (tm == null) { // 判断是否是SessionMessage - SessionMessage sm = SessionMessage.toNodeSessionMessage(msg); + SessionMessage sm = SessionMessage.toSessionMessage(msg); if (sm != null) { executeSessionMessage(sm); } else { @@ -106,36 +143,48 @@ public class ReceiverHandler extends ChannelInboundHandlerAdapter implements Clo ctx.close(); } - // 防止消息的处理过程阻塞主进程 + /** + * 处理请求消息 + * + * @param transferMessage + * 接收到的请求消息 + */ private void executeRequest(final TransferMessage transferMessage) { - msgExecutePool.execute(() -> { + msgExecutorPool.execute(() -> { RemoteSession remoteSession = remoteSessions.get(transferMessage.getSessionId()); if (remoteSession != null) { - MessageExecute messageExecute = remoteSession.messageExecute(); - if (messageExecute != null) { - MessageExecute.REPLY replyType = messageExecute.replyType(); - if (replyType != null) { - switch (messageExecute.replyType()) { - case MANUAL: - messageExecute.receive(transferMessage.loadKey(), transferMessage.load(), remoteSession); - break; - case AUTO: - String requestKey = transferMessage.loadKey(); - byte[] replyMsg = messageExecute.receive(requestKey, transferMessage.load(), remoteSession); - // 应答 - remoteSession.reply(requestKey, () -> replyMsg); - break; - default: - break; - } + MessageExecutor messageExecutor = remoteSession.messageExecutor(); + if (messageExecutor == null) { + // 采用默认处理器进行处理 + messageExecutor = defaultMessageExecutor; + } + MessageExecutor.REPLY replyType = messageExecutor.replyType(); + if (replyType != null) { + switch (replyType) { + case MANUAL: + messageExecutor.receive(transferMessage.loadKey(), transferMessage.load(), remoteSession); + break; + case AUTO: + String requestKey = transferMessage.loadKey(); + byte[] replyMsg = messageExecutor.receive(requestKey, transferMessage.load(), remoteSession); + // 应答 + remoteSession.reply(requestKey, () -> replyMsg); + break; + default: + break; } } } }); } + /** + * 处理应答消息 + * @param transferMessage + * 接收到的应答消息 + */ private void executeResponse(final TransferMessage transferMessage) { - msgExecutePool.execute(() -> { + msgExecutorPool.execute(() -> { // listenKey和msgKey是不一致的 // msgKey是对消息本身设置key,listenKey是对整个消息(包括session信息) String listenKey = transferMessage.toListenKey(); @@ -165,52 +214,99 @@ public class ReceiverHandler extends ChannelInboundHandlerAdapter implements Clo }); } + /** + * 处理SessionMessage + * @param sessionMessage + * 描述Session的消息对象 + */ private void executeSessionMessage(SessionMessage sessionMessage) { // 处理SessionMessage String sessionId = sessionMessage.sessionId(); - if (sessionId != null && !remoteSessions.containsKey(sessionId)) { - - try { - lock.lock(); - // 生成对应的MessageExecute对象 - String messageExecuteClass = sessionMessage.getMessageExecute(); - MessageExecute messageExecute = null; - if (messageExecuteClass != null && messageExecuteClass.length() > 0) { - try { - Class clazz = Class.forName(messageExecuteClass); - messageExecute = (MessageExecute) clazz.newInstance(); - } catch (Exception e) { - // TODO 打印日志 - e.printStackTrace(); - } - } + if (sessionId != null) { + // 对于含有的RemoteSession的Map,需要判断其MessageExecutor是否为NULL + RemoteSession remoteSession = remoteSessions.get(sessionId); + if (remoteSession == null) { + try { + sessionLock.lock(); + // 生成对应的MessageExecute对象 + String meClass = sessionMessage.getMessageExecutor(); + MessageExecutor messageExecutor = initMessageExecutor(meClass); - // 必须保证该对象不为空 - if (messageExecute != null) { // 说明尚未和请求来的客户端建立连接,需要建立连接 Connection remoteConnection = this.connectionManager.connect(new RemoteNode( sessionMessage.getLocalHost(), sessionMessage.getListenPort()), - this.messageExecuteClass); - RemoteSession remoteSession = new RemoteSession(sessionId, remoteConnection, messageExecute); + this.localMsgExecutorClass); + // 假设连接失败的话,返回的Connection对象为null,此时不放入Map,等后续再处理 + if (remoteConnection != null) { + + remoteSession = new RemoteSession(sessionId, remoteConnection, messageExecutor); - // Double check !!! - if (!remoteSessions.containsKey(sessionId)) { - remoteSessions.put(sessionId, remoteSession); + // Double check !!! + if (!remoteSessions.containsKey(sessionId)) { + remoteSessions.put(sessionId, remoteSession); + } } + } finally { + sessionLock.unlock(); } - } finally { - lock.unlock(); + } else { + // 需要判断MessageExecutor + MessageExecutor me = remoteSession.messageExecutor(); + if (me == null) { + try { + sessionLock.lock(); + // Double Check !!! + if (remoteSession.messageExecutor() == null) { + // 表明上次存储的MessageExecutor未创建成功,本次进行更新 + String meClass = sessionMessage.getMessageExecutor(); + MessageExecutor messageExecutor = initMessageExecutor(meClass); + + // 防止NULL将其他的进行覆盖 + if (messageExecutor != null) { + remoteSession.initExecutor(messageExecutor); + } + } + } finally { + sessionLock.unlock(); + } + } + } + } + } + + /** + * 初始化消息执行器 + * 根据消息执行器的Class字符串生成对应的消息处理对象 + * @param messageExecutorClass + * 消息执行器的Class字符串 + * @return + * 对应的消息处理对象,产生任何异常都返回NULL + */ + private MessageExecutor initMessageExecutor(String messageExecutorClass) { + // 生成对应的MessageExecute对象 + MessageExecutor messageExecutor = null; + if (messageExecutorClass != null && messageExecutorClass.length() > 0) { + try { + Class clazz = Class.forName(messageExecutorClass); + messageExecutor = (MessageExecutor) clazz.newInstance(); + } catch (Exception e) { + e.printStackTrace(); + return null; } } + return messageExecutor; } - private void init() { + /** + * 初始化消息处理线程池 + */ + private void initMsgExecutorPool() { ThreadFactory msgExecuteThreadFactory = new ThreadFactoryBuilder() - .setNameFormat("msg-execute-pool-%d").build(); + .setNameFormat("msg-executor-pool-%d").build(); //Common Thread Pool - msgExecutePool = new ThreadPoolExecutor(5, 10, + msgExecutorPool = new ThreadPoolExecutor(5, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(QUEUE_CAPACITY), msgExecuteThreadFactory, new ThreadPoolExecutor.AbortPolicy()); @@ -218,6 +314,6 @@ public class ReceiverHandler extends ChannelInboundHandlerAdapter implements Clo @Override public void close() { - msgExecutePool.shutdown(); + msgExecutorPool.shutdown(); } } \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/SenderHandler.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/SenderHandler.java index d1590318..ac86ea54 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/SenderHandler.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/SenderHandler.java @@ -9,16 +9,13 @@ package com.jd.blockchain.stp.communication.connection.handler; import com.jd.blockchain.stp.communication.message.SessionMessage; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; -import java.util.concurrent.Executors; /** - * + * Sender对应Handler * @author shaozhuguang * @create 2019/4/16 * @since 1.0.0 diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/WatchDogHandler.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/WatchDogHandler.java index dac7b823..ca41fc9a 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/WatchDogHandler.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/WatchDogHandler.java @@ -23,7 +23,7 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** - * + * 连接监听器 * @author shaozhuguang * @create 2019/4/12 * @since 1.0.0 @@ -31,8 +31,15 @@ import java.util.concurrent.locks.ReentrantLock; @ChannelHandler.Sharable public class WatchDogHandler extends ChannelInboundHandlerAdapter implements Runnable, Closeable { + /** + * 当前连接活跃状态 + */ private final AtomicBoolean currentActive = new AtomicBoolean(false); + /** + * 重连的控制锁 + * 防止重连过程中重复多次调用 + */ private final Lock reconnectLock = new ReentrantLock(); // 默认的最多重连次数 @@ -44,30 +51,70 @@ public class WatchDogHandler extends ChannelInboundHandlerAdapter implements Run // 标识是否正常工作中,假设不再工作则不再重连 private boolean isWorking = true; + /** + * 重连调度器 + */ private ScheduledExecutorService reconnectTimer; + /** + * 远端的IP(域名)信息 + */ private String hostName; + /** + * 远端的端口 + */ private int port; private Bootstrap bootstrap; + /** + * 第一组Handler数组 + */ private ChannelHandler[] frontHandlers; + /** + * 后一组Handler数组 + */ private ChannelHandler[] afterHandlers; + /** + * 用于重连时对象重置 + */ private ChannelFuture channelFuture; + /** + * 构造器 + * @param hostName + * 远端Host + * @param port + * 远端端口 + * @param bootstrap + * Netty工作启动器 + */ public WatchDogHandler(String hostName, int port, Bootstrap bootstrap) { this.hostName = hostName; this.port = port; this.bootstrap = bootstrap; } + /** + * 构造器 + * @param remoteNode + * 远端节点 + * @param bootstrap + * Netty工作启动器 + */ public WatchDogHandler(RemoteNode remoteNode, Bootstrap bootstrap) { this(remoteNode.getHostName(), remoteNode.getPort(), bootstrap); } + /** + * 配置重连需要的Handler + * 主要是为了对象的复用,同时有些Handler无法复用,对于每次连接请求必须要new新的对象 + * @param frontHandlers + * @param afterHandlers + */ public void init(ChannelHandler[] frontHandlers, ChannelHandler[] afterHandlers) { this.frontHandlers = frontHandlers; this.afterHandlers = afterHandlers; @@ -87,6 +134,12 @@ public class WatchDogHandler extends ChannelInboundHandlerAdapter implements Run } } + /** + * 连接成功调用 + * 该连接成功表示完全连接成功,对于TCP而言就是三次握手成功 + * @param ctx + * @throws Exception + */ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { // 调用该方法表示连接成功 @@ -98,6 +151,12 @@ public class WatchDogHandler extends ChannelInboundHandlerAdapter implements Run ctx.fireChannelActive(); } + /** + * 连接失败时调用 + * 此处是触发重连的入口 + * @param ctx + * @throws Exception + */ @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { @@ -174,6 +233,9 @@ public class WatchDogHandler extends ChannelInboundHandlerAdapter implements Run this.reconnectTimer.shutdown(); } + /** + * 设置调度器 + */ private void initTimer() { ThreadFactory timerFactory = new ThreadFactoryBuilder() .setNameFormat("reconnect-pool-%d").build(); diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/listener/ReplyListener.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/listener/ReplyListener.java index 842e6e8e..47d11883 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/listener/ReplyListener.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/listener/ReplyListener.java @@ -14,7 +14,7 @@ import com.jd.blockchain.stp.communication.node.RemoteNode; /** - * + * 应答监听器 * @author shaozhuguang * @create 2019/4/12 * @since 1.0.0 @@ -22,17 +22,30 @@ import com.jd.blockchain.stp.communication.node.RemoteNode; public class ReplyListener { + /** + * 监听的Key,通常用于描述唯一的请求 + */ private String listenKey; + /** + * 消息处理类型 + * REMOVE:表示处理完该对象之后从缓存中清除 + * HOLD:表示处理完该对象之后仍在缓存中保存 + */ private MANAGE_TYPE manageType = MANAGE_TYPE.REMOVE; + /** + * 数据回调监听器 + */ private CallBackDataListener callBackDataListener; + /** + * 回调栅栏 + */ private CallBackBarrier callBackBarrier; public ReplyListener(String listenKey, RemoteNode remoteNode) { - this.listenKey = listenKey; - this.callBackDataListener = new CallBackDataListener(remoteNode); + this(listenKey, remoteNode, null); } public ReplyListener(String listenKey, RemoteNode remoteNode, CallBackBarrier callBackBarrier) { diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/ConnectionManager.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/ConnectionManager.java index e4aef871..3f322e97 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/ConnectionManager.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/ConnectionManager.java @@ -8,7 +8,8 @@ */ package com.jd.blockchain.stp.communication.manager; -import com.jd.blockchain.stp.communication.MessageExecute; +import com.jd.blockchain.stp.communication.MessageExecutor; +import com.jd.blockchain.stp.communication.callback.CallBackLauncher; import com.jd.blockchain.stp.communication.connection.Receiver; import com.jd.blockchain.stp.communication.connection.Connection; import com.jd.blockchain.stp.communication.node.LocalNode; @@ -20,24 +21,50 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** - * + * 连接管理器 * @author shaozhuguang * @create 2019/4/11 * @since 1.0.0 + * @date 2019-04-18 15:11 */ public class ConnectionManager { + /** + * Connection对应Map + * RemoteNode唯一性:IP(HOST)+PORT + */ private static final Map connectionMap = new ConcurrentHashMap<>(); + /** + * 连接管理器对应MAP + * 以监听端口(int)作为Key,进行唯一性约束 + */ private static final Map connectionManagerMap = new ConcurrentHashMap<>(); + /** + * connectionManagerMap控制锁 + */ private static final Lock managerLock = new ReentrantLock(); + /** + * connectionMap控制锁 + */ private static final Lock connectionLock = new ReentrantLock(); + /** + * 当前ConnectionManager对应的Receiver + */ private Receiver receiver; + /** + * 静态ConnectionManager构造器 + * + * @param localNode + * 本地节点 + * @return + * 优先返回Map中的对象 + */ public static final ConnectionManager newConnectionManager(LocalNode localNode) { int listenPort = localNode.getPort(); if (!connectionManagerMap.containsKey(listenPort)) { @@ -55,32 +82,61 @@ public class ConnectionManager { return connectionManagerMap.get(listenPort); } + /** + * 内部调用的静态构造器 + * + * @param localNode + * 本地节点 + * @return + */ private static final ConnectionManager newInstance(LocalNode localNode) { return new ConnectionManager(new Receiver(localNode)); } - public final boolean start(String messageExecuteClass) throws InterruptedException { - receiver.initReceiverHandler(this, messageExecuteClass); + /** + * 启动 + * 该启动是启动Receiver,返回启动的状态 + * + * @param messageExecutorClass + * 当前节点希望其他节点收到该节点信息时的处理Handler + * @return + * 回调执行器 + * @throws InterruptedException + */ + public final CallBackLauncher start(String messageExecutorClass) throws InterruptedException { + receiver.initReceiverHandler(this, messageExecutorClass); receiver.startListen(); // 判断是否启动完成,启动完成后再返回 - return receiver.waitStarted(); + return receiver.waitBooted(); } private ConnectionManager(Receiver receiver) { this.receiver = receiver; } - public Connection connect(RemoteNode remoteNode, MessageExecute messageExecute) { - return connect(remoteNode, messageExecute.getClass().toString()); - } - - public Connection connect(RemoteNode remoteNode, String messageExecuteClass) { + /** + * 连接远端节点 + * + * @param remoteNode + * 远端节点信息 + * @param messageExecutorClass + * 希望远端节点接收到本节点消息时的处理Handler + * @return + */ + public Connection connect(RemoteNode remoteNode, String messageExecutorClass) { if (!connectionMap.containsKey(remoteNode)) { try { connectionLock.lock(); if (!connectionMap.containsKey(remoteNode)) { - Connection connection = init(remoteNode, messageExecuteClass); - connectionMap.put(remoteNode, connection); + Connection connection = init(remoteNode, messageExecutorClass); + if (connection != null) { + // 保证都是连接成功的 + connectionMap.put(remoteNode, connection); + return connection; + } else { + // 连接失败返回null + return null; + } } } finally { connectionLock.unlock(); @@ -89,22 +145,24 @@ public class ConnectionManager { return connectionMap.get(remoteNode); } - private Connection init(RemoteNode remoteNode, String messageExecuteClass) { + private Connection init(RemoteNode remoteNode, String messageExecutorClass) { // 初始化Connection Connection remoteConnection = new Connection(this.receiver); try { - // 连接远端 - boolean isSuccess = remoteConnection.connect(remoteNode, messageExecuteClass); - if (!isSuccess) { - throw new RuntimeException(String.format("RemoteNode {%s} Connect Fail !!!", remoteNode.toString())); + // 连接远端,需要发送当前节点处理的MessageExecuteClass + CallBackLauncher callBackLauncher = remoteConnection.connect(remoteNode, messageExecutorClass); + if (!callBackLauncher.isBootSuccess()) { + // TODO 打印错误日志 + callBackLauncher.exception().printStackTrace(); + return null; } + return remoteConnection; } catch (InterruptedException e) { throw new RuntimeException(e); } catch (RuntimeException e) { throw e; } - return remoteConnection; } } \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/RemoteSessionManager.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/RemoteSessionManager.java index bdcfc085..3403d2a0 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/RemoteSessionManager.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/RemoteSessionManager.java @@ -9,16 +9,24 @@ package com.jd.blockchain.stp.communication.manager; -import com.jd.blockchain.stp.communication.MessageExecute; +import com.jd.blockchain.stp.communication.MessageExecutor; import com.jd.blockchain.stp.communication.RemoteSession; +import com.jd.blockchain.stp.communication.callback.CallBackLauncher; import com.jd.blockchain.stp.communication.connection.Connection; import com.jd.blockchain.stp.communication.node.LocalNode; import com.jd.blockchain.stp.communication.node.RemoteNode; import org.apache.commons.codec.binary.Hex; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + /** - * + * 远端Session管理器 * @author shaozhuguang * @create 2019/4/11 * @since 1.0.0 @@ -26,84 +34,158 @@ import org.apache.commons.codec.binary.Hex; public class RemoteSessionManager { + /** + * 可监听的最大端口 + */ + private static final int MAX_PORT = 65535; + + /** + * 节点Session的集合信息 + */ + private Map nodeRemoteSessionMap = new ConcurrentHashMap<>(); + + /** + * nodeRemoteSessionMap的控制锁 + */ + private Lock lock = new ReentrantLock(); + + /** + * 连接管理器 + * 用于管理底层的通信连接 + */ private ConnectionManager connectionManager; + /** + * 本地节点信息 + */ private LocalNode localNode; + /** + * 构造器 + * @param localNode + * 本地节点信息 + */ public RemoteSessionManager(LocalNode localNode) { this.localNode = localNode; + // 校验本地节点的配置,防止异常 check(); this.connectionManager = ConnectionManager.newConnectionManager(this.localNode); try { - boolean isStartedSuccess = start(this.localNode.messageExecuteClass()); - if (!isStartedSuccess) { - throw new RuntimeException(String.format("LocalNode {%s} Start Receiver Fail !!!", this.localNode.toString())); + CallBackLauncher callBackLauncher = start(); + if (!callBackLauncher.isBootSuccess()) { + // 启动当前端口连接必须要成功,否则则退出,交由应用程序处理 + throw new RuntimeException(callBackLauncher.exception()); } } catch (InterruptedException e) { throw new RuntimeException(e); } catch (RuntimeException e) { throw e; } - - } - - private void check() { - // 要求端口范围:1~65535,messageExecuteClass不能为null - int listenPort = this.localNode.getPort(); - if (listenPort <= 0 || listenPort > 65535) { - throw new IllegalArgumentException("Illegal Local Listen Port, Please Check !!!"); - } - - String messageExecuteClass = this.localNode.messageExecuteClass(); - if (messageExecuteClass == null) { - throw new IllegalArgumentException("Illegal MessageExecute Class, Please Check !!!"); - } - } - - private boolean start(String messageExecuteClass) throws InterruptedException { - return this.connectionManager.start(messageExecuteClass); } + /** + * 生成新的Session + * @param remoteNode + * @return + */ public RemoteSession newSession(RemoteNode remoteNode) { return newSession(null, remoteNode); } + /** + * RemoteSession对象生成器 + * @param sessionId + * RemoteSession的Key + * @param remoteNode + * 远端节点信息 + * @return + */ public RemoteSession newSession(String sessionId, RemoteNode remoteNode) { - return newSession(sessionId, remoteNode, null); - } - public RemoteSession newSession(RemoteNode remoteNode, MessageExecute messageExecute) { - return newSession(null, remoteNode, messageExecute); - } + RemoteSession remoteSession = nodeRemoteSessionMap.get(remoteNode); - public RemoteSession newSession(String sessionId, RemoteNode remoteNode, MessageExecute messageExecute) { - if (sessionId == null) { - sessionId = toSessionId(localNode); - } - Connection remoteConnection = this.connectionManager.connect(remoteNode, localNode.messageExecuteClass()); + if (remoteSession != null) { + return remoteSession; + } else { + try { + lock.lock(); + + // Double Check !!! + if (!nodeRemoteSessionMap.containsKey(remoteNode)) { + if (sessionId == null) { + sessionId = sessionId(localNode); + } + Connection remoteConnection = this.connectionManager.connect(remoteNode, localNode.messageExecutorClass()); + + if (remoteConnection == null) { + return null; + } - RemoteSession remoteSession = new RemoteSession(sessionId, remoteConnection, messageExecute); + remoteSession = new RemoteSession(sessionId, remoteConnection); - remoteSession.init(); + remoteSession.init(); + nodeRemoteSessionMap.put(remoteNode, remoteSession); + + return remoteSession; + } + } finally { + lock.unlock(); + } + } return remoteSession; } public RemoteSession[] newSessions(RemoteNode[] remoteNodes) { + return newSessions(null, remoteNodes); } public RemoteSession[] newSessions(String[] sessionIds, RemoteNode[] remoteNodes) { + checkSessions(sessionIds, remoteNodes); + + List remoteSessionList = new ArrayList<>(); + + for (int i = 0; i < remoteNodes.length; i++) { + RemoteSession remoteSession; + if (sessionIds == null) { + remoteSession = newSession(remoteNodes[i]); + } else { + remoteSession = newSession(sessionIds[i], remoteNodes[i]); + } + if (remoteSession != null) { + remoteSessionList.add(remoteSession); + } + } - return newSessions(sessionIds, remoteNodes, null); + if (remoteSessionList.isEmpty()) { + return null; + } + + RemoteSession[] remoteSessions = new RemoteSession[remoteSessionList.size()]; + + return remoteSessionList.toArray(remoteSessions); } - public RemoteSession[] newSessions(RemoteNode[] remoteNodes, MessageExecute messageExecute) { + private void check() { + // 要求端口范围:1~65535,messageExecuteClass不能为null + int listenPort = this.localNode.getPort(); + if (listenPort <= 0 || listenPort > MAX_PORT) { + throw new IllegalArgumentException("Illegal Local Listen Port, Please Check !!!"); + } + + // 默认处理器必须包含,可不包含本机需要对端知晓的处理器 + MessageExecutor defaultMessageExecutor = this.localNode.defaultMessageExecutor(); + if (defaultMessageExecutor == null) { + throw new IllegalArgumentException("Illegal Default MessageExecutor, Please Check !!!"); + } + } - return newSessions(null, remoteNodes, messageExecute); + private CallBackLauncher start() throws InterruptedException { + return this.connectionManager.start(this.localNode.messageExecutorClass()); } - public RemoteSession[] newSessions(String[] sessionIds, RemoteNode[] remoteNodes, MessageExecute messageExecute) { + private void checkSessions(String[] sessionIds, RemoteNode[] remoteNodes) { if (remoteNodes == null || remoteNodes.length <= 0) { throw new IllegalArgumentException("RemoteNodes is empty !!!"); } @@ -113,20 +195,9 @@ public class RemoteSessionManager { throw new IllegalArgumentException("RemoteNodes and sessionIds are different in length !!!"); } } - - RemoteSession[] remoteSessions = new RemoteSession[remoteNodes.length]; - - for (int i = 0; i < remoteNodes.length; i++) { - if (sessionIds == null) { - remoteSessions[i] = newSession(remoteNodes[i], messageExecute); - } else { - remoteSessions[i] = newSession(sessionIds[i], remoteNodes[i], messageExecute); - } - } - return remoteSessions; } - public String toSessionId(RemoteNode remoteNode) { + private String sessionId(RemoteNode remoteNode) { return Hex.encodeHexString(remoteNode.toString().getBytes()); } } \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/AbstractMessage.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/AbstractMessage.java index b872fbfb..8cd0a3e9 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/AbstractMessage.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/AbstractMessage.java @@ -12,7 +12,7 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; /** - * + * 抽象消息 * @author shaozhuguang * @create 2019/4/17 * @since 1.0.0 diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/HeartBeatMessage.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/HeartBeatMessage.java index 6395d030..a0f5974c 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/HeartBeatMessage.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/HeartBeatMessage.java @@ -22,22 +22,41 @@ import io.netty.util.CharsetUtil; public class HeartBeatMessage implements IMessage { + /** + * 统一的心跳信息字符串 + */ private static final String HEARTBEAT_STRING = "JDChainHeartBeat"; + /** + * 统一的心跳消息字符串对一个的ByteBuf + */ private static final ByteBuf HEARTBEAT_MESSAGE = Unpooled.unreleasableBuffer(Unpooled.copiedBuffer(HEARTBEAT_STRING + "\r\n", CharsetUtil.UTF_8)); + /** + * 将心跳消息写入Ctx + * @param ctx + */ public static final void write(ChannelHandlerContext ctx) { ctx.writeAndFlush(HEARTBEAT_MESSAGE.duplicate()); } + /** + * 判断接收的消息是否为心跳消息 + * + * @param msg + * @return + */ public static final boolean isHeartBeat(Object msg) { - if (msg instanceof String) { - return isHeartBeat((String) msg); - } - return false; + return isHeartBeat(msg.toString()); } + /** + * 判断接收的消息是否为心跳消息 + * + * @param msg + * @return + */ public static final boolean isHeartBeat(String msg) { if (HEARTBEAT_STRING.equals(msg)) { return true; diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/IMessage.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/IMessage.java index 0e3ed5df..6cb0a0a4 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/IMessage.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/IMessage.java @@ -11,7 +11,7 @@ package com.jd.blockchain.stp.communication.message; import io.netty.buffer.ByteBuf; /** - * + * 消息接口 * @author shaozhuguang * @create 2019/4/16 * @since 1.0.0 @@ -19,7 +19,15 @@ import io.netty.buffer.ByteBuf; public interface IMessage { + /** + * 消息转换为字符串 + * @return + */ String toTransfer(); + /** + * 消息转换为ByteBuf + * @return + */ ByteBuf toTransferByteBuf(); } \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/LoadMessage.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/LoadMessage.java index acdedee2..795fa8c1 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/LoadMessage.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/LoadMessage.java @@ -9,7 +9,8 @@ package com.jd.blockchain.stp.communication.message; /** - * + * 负载消息 + * 该接口用于应用实现 * @author shaozhuguang * @create 2019/4/11 * @since 1.0.0 @@ -17,5 +18,9 @@ package com.jd.blockchain.stp.communication.message; public interface LoadMessage { + /** + * 将负载消息转换为字节数组 + * @return + */ byte[] toBytes(); } \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/SessionMessage.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/SessionMessage.java index 10a121a3..c685b77c 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/SessionMessage.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/SessionMessage.java @@ -8,13 +8,11 @@ */ package com.jd.blockchain.stp.communication.message; -import com.alibaba.fastjson.JSON; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; import org.apache.commons.codec.binary.Hex; /** - * + * Session消息 + * 该消息用于发送至远端节点,告诉远端节点本地的信息 * @author shaozhuguang * @create 2019/4/16 * @since 1.0.0 @@ -22,19 +20,28 @@ import org.apache.commons.codec.binary.Hex; public class SessionMessage extends AbstractMessage implements IMessage { + /** + * 本地节点HOST + */ private String localHost; + /** + * 本地节点监听端口 + */ private int listenPort; - private String messageExecute; + /** + * 远端接收到本地节点信息时处理的Class + */ + private String messageExecutor; public SessionMessage() { } - public SessionMessage(String localHost, int listenPort, String messageExecute) { + public SessionMessage(String localHost, int listenPort, String messageExecutor) { this.localHost = localHost; this.listenPort = listenPort; - this.messageExecute = messageExecute; + this.messageExecutor = messageExecutor; } public String getLocalHost() { @@ -54,30 +61,37 @@ public class SessionMessage extends AbstractMessage implements IMessage { return listenPort; } - public String getMessageExecute() { - return messageExecute; + public String getMessageExecutor() { + return messageExecutor; } - public void setMessageExecute(String messageExecute) { - this.messageExecute = messageExecute; + public void setMessageExecutor(String messageExecutor) { + this.messageExecutor = messageExecutor; } public String sessionId() { return Hex.encodeHexString((this.localHost + ":" + this.listenPort).getBytes()); } - public static SessionMessage toNodeSessionMessage(Object msg) { + /** + * 将对象(或者说接收到的消息)转换为SessionMessage + * @param msg + * 接收到的消息对象 + * @return + * 可正确解析则返回,否则返回NULL + */ + public static SessionMessage toSessionMessage(Object msg) { String msgString = msg.toString(); try { String[] msgArray = msgString.split("\\|"); if (msgArray.length == 2 || msgArray.length == 3) { String host = msgArray[0]; int port = Integer.parseInt(msgArray[1]); - String msgExecuteClass = null; + String msgExecutorClass = null; if (msgArray.length == 3) { - msgExecuteClass = msgArray[2]; + msgExecutorClass = msgArray[2]; } - return new SessionMessage(host, port, msgExecuteClass); + return new SessionMessage(host, port, msgExecutorClass); } return null; } catch (Exception e) { @@ -89,7 +103,10 @@ public class SessionMessage extends AbstractMessage implements IMessage { public String toTransfer() { // 为区别于TransferMessage的JSON格式,该处使用字符串连接处理 // 格式:localHost|port|class - String transferMsg = this.localHost + "|" + this.listenPort + "|" + this.messageExecute; - return transferMsg; + if (this.messageExecutor == null) { + return this.localHost + "|" + this.listenPort; + } else { + return this.localHost + "|" + this.listenPort + "|" + this.messageExecutor; + } } } \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/TransferMessage.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/TransferMessage.java index 7f0659fa..8bc9a448 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/TransferMessage.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/TransferMessage.java @@ -12,6 +12,7 @@ import com.alibaba.fastjson.JSON; import org.apache.commons.codec.binary.Base64; /** + * 底层传输协议 * * @author shaozhuguang * @create 2019/4/11 @@ -20,14 +21,32 @@ import org.apache.commons.codec.binary.Base64; public class TransferMessage extends AbstractMessage implements IMessage{ + /** + * sessionId(描述节点信息) + */ private String sessionId; + /** + * 本次消息的类型 + * 0:请求; + * 1:应答; + */ private int type; + /** + * 消息的Key + */ private String key; + /** + * 消息载体的内容 + * 本内容不可被序列化 + */ private transient byte[] load; + /** + * 消息载体的内容->Base64转换 + */ private String loadBase64; public TransferMessage() { @@ -40,7 +59,13 @@ public class TransferMessage extends AbstractMessage implements IMessage{ this.load = load; } - public static TransferMessage toTransferMessageObj(Object msg) { + /** + * 转换为TransferMessage对象 + * + * @param msg + * @return + */ + public static TransferMessage toTransferMessage(Object msg) { if (msg == null) { return null; } @@ -80,6 +105,12 @@ public class TransferMessage extends AbstractMessage implements IMessage{ return JSON.toJSONString(this); } + /** + * 转换为监听的Key + * 该Key可描述为从远端发送来消息及其内容的唯一性 + * + * @return + */ public String toListenKey() { // 格式:sessionId:key return sessionId + ":" + key; diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/node/LocalNode.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/node/LocalNode.java index f58bd034..64c203bd 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/node/LocalNode.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/node/LocalNode.java @@ -8,10 +8,10 @@ */ package com.jd.blockchain.stp.communication.node; -import com.jd.blockchain.stp.communication.MessageExecute; +import com.jd.blockchain.stp.communication.MessageExecutor; /** - * + * 本地节点 * @author shaozhuguang * @create 2019/4/16 * @since 1.0.0 @@ -19,34 +19,69 @@ import com.jd.blockchain.stp.communication.MessageExecute; public class LocalNode extends RemoteNode { - private Class messageExecute; + /** + * 当前节点消息处理器 + * 该消息处理器用于描述远端节点收到当前节点的消息该如何处理 + * 通常该消息处理器会以字符串的形式发送至远端节点 + */ + private Class messageExecutorClass; - public LocalNode(String hostName, int port) { - super(hostName, port); - } + /** + * 当前节点接收消息默认处理器 + * 与messageExecutor不同,该字段描述的是当前节点接收到其他节点信息时的默认处理器 + * 该参数硬性要求必须不能为空 + */ + private MessageExecutor defaultMessageExecutor; - public LocalNode(String hostName, int port, MessageExecute messageExecute) { - super(hostName, port); - this.messageExecute = messageExecute.getClass(); + /** + * 构造器 + * @param hostName + * 当前节点Host,该Host必须是一种远端节点可访问的形式 + * @param port + * 当前节点监听端口 + * @param defaultMessageExecutor + * 当前节点接收到远端消息无法处理时的消息处理器 + * + */ + public LocalNode(String hostName, int port, MessageExecutor defaultMessageExecutor) { + this(hostName, port, null, defaultMessageExecutor); } - public LocalNode(String hostName, int port, Class messageExecute) { + /** + * 构造器 + * @param hostName + * 当前节点Host,该Host必须是一种远端节点可访问的形式 + * @param port + * 当前节点监听端口 + * @param messageExecutorClass + * 当前节点期望远端节点接收到消息后的处理器 + * @param defaultMessageExecutor + * 当前节点接收到远端消息无法处理时的消息处理器 + * + */ + public LocalNode(String hostName, int port, Class messageExecutorClass, MessageExecutor defaultMessageExecutor) { super(hostName, port); - this.messageExecute = messageExecute; + this.messageExecutorClass = messageExecutorClass; + this.defaultMessageExecutor = defaultMessageExecutor; } - public String messageExecuteClass() { - if (this.messageExecute == null) { + /** + * 返回消息执行器的类对应的字符串 + * 该返回值通常用于消息传递 + * @return + */ + public String messageExecutorClass() { + if (this.messageExecutorClass == null) { return null; } - return this.messageExecute.getName(); - } - - public void setMessageExecute(MessageExecute messageExecute) { - this.messageExecute = messageExecute.getClass(); + return this.messageExecutorClass.getName(); } - public void setMessageExecute(Class messageExecute) { - this.messageExecute = messageExecute; + /** + * 返回默认的消息处理器 + * @return + */ + public MessageExecutor defaultMessageExecutor() { + return this.defaultMessageExecutor; } } \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/node/RemoteNode.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/node/RemoteNode.java index dceb9115..7e2004c8 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/node/RemoteNode.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/node/RemoteNode.java @@ -9,7 +9,7 @@ package com.jd.blockchain.stp.communication.node; /** - * + * 节点信息 * @author shaozhuguang * @create 2019/4/11 * @since 1.0.0 @@ -17,8 +17,14 @@ package com.jd.blockchain.stp.communication.node; public class RemoteNode { + /** + * 监听端口 + */ private int port; + /** + * 当前节点域名 + */ private String hostName; public RemoteNode(String hostName, int port) { @@ -42,6 +48,10 @@ public class RemoteNode { this.hostName = hostName; } + /** + * 通过hostName+port形式作为判断节点的唯一标识 + * @return + */ @Override public int hashCode() { return (hostName + ":" + port).hashCode(); diff --git a/source/stp/stp-communication/src/test/java/com/jd/blockchain/SessionMessageTest.java b/source/stp/stp-communication/src/test/java/com/jd/blockchain/SessionMessageTest.java index 4a9211b6..b3cee4ab 100644 --- a/source/stp/stp-communication/src/test/java/com/jd/blockchain/SessionMessageTest.java +++ b/source/stp/stp-communication/src/test/java/com/jd/blockchain/SessionMessageTest.java @@ -30,7 +30,7 @@ public class SessionMessageTest { String transMsg = message.toTransfer(); System.out.println(transMsg); - SessionMessage sm = SessionMessage.toNodeSessionMessage(transMsg); + SessionMessage sm = SessionMessage.toSessionMessage(transMsg); assertEquals(transMsg, sm.toTransfer()); } diff --git a/source/test/test-stp-community/src/main/java/com/jd/blockchain/stp/commucation/MyMessageExecutor.java b/source/test/test-stp-community/src/main/java/com/jd/blockchain/stp/commucation/MyMessageExecutor.java index aa8f6014..e1223981 100644 --- a/source/test/test-stp-community/src/main/java/com/jd/blockchain/stp/commucation/MyMessageExecutor.java +++ b/source/test/test-stp-community/src/main/java/com/jd/blockchain/stp/commucation/MyMessageExecutor.java @@ -8,7 +8,7 @@ */ package com.jd.blockchain.stp.commucation; -import com.jd.blockchain.stp.communication.MessageExecute; +import com.jd.blockchain.stp.communication.MessageExecutor; import com.jd.blockchain.stp.communication.RemoteSession; import java.nio.charset.Charset; @@ -20,7 +20,7 @@ import java.nio.charset.Charset; * @since 1.0.0 */ -public class MyMessageExecutor implements MessageExecute { +public class MyMessageExecutor implements MessageExecutor { @Override public byte[] receive(String key, byte[] data, RemoteSession session) { diff --git a/source/test/test-stp-community/src/test/java/com/jd/blockchain/StpTest.java b/source/test/test-stp-community/src/test/java/com/jd/blockchain/StpTest.java index 422fb9a4..2e66c8e1 100644 --- a/source/test/test-stp-community/src/test/java/com/jd/blockchain/StpTest.java +++ b/source/test/test-stp-community/src/test/java/com/jd/blockchain/StpTest.java @@ -9,7 +9,6 @@ package com.jd.blockchain; import com.jd.blockchain.stp.commucation.MyMessageExecutor; -import com.jd.blockchain.stp.communication.MessageExecute; import com.jd.blockchain.stp.communication.RemoteSession; import com.jd.blockchain.stp.communication.callback.CallBackBarrier; import com.jd.blockchain.stp.communication.callback.CallBackDataListener; @@ -27,6 +26,8 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import static org.junit.Assert.assertNull; + /** * * @author shaozhuguang @@ -57,7 +58,7 @@ public class StpTest { listenStart(); System.out.println("---------- listenComplete -----------"); System.out.println("---------- ConnectionStart ----------"); - connectAllOthers(); + connectOneOther(); System.out.println("---------- ConnectionComplete ----------"); } @@ -68,12 +69,17 @@ public class StpTest { final int port = listenPorts[i], index = i; threadPool.execute(() -> { // 创建本地节点 - final LocalNode localNode = new LocalNode(remoteHost, port, MyMessageExecutor.class); - // 启动当前节点 - RemoteSessionManager sessionManager = new RemoteSessionManager(localNode); - sessionManagers[index] = sessionManager; - countDownLatch.countDown(); - System.out.printf("Current Node {%s} start success !!! \r\n", localNode.toString()); + final LocalNode localNode = new LocalNode(remoteHost, port, new MyMessageExecutor()); + try { + // 启动当前节点 + RemoteSessionManager sessionManager = new RemoteSessionManager(localNode); + sessionManagers[index] = sessionManager; + System.out.printf("Current Node {%s} start success !!! \r\n", localNode.toString()); + } catch (Exception e) { + e.printStackTrace(); + } finally { + countDownLatch.countDown(); + } }); } @@ -99,7 +105,7 @@ public class StpTest { } } - remoteSessions = starter.newSessions(remoteNodes, new MyMessageExecutor()); + remoteSessions = starter.newSessions(remoteNodes); } private void connectOneOther() { @@ -116,7 +122,22 @@ public class StpTest { } } - remoteSessions = starter.newSessions(remoteNodes, new MyMessageExecutor()); + remoteSessions = starter.newSessions(remoteNodes); + } + + private void connectOneErrorNode() { + // 所有节点完成之后,需要启动 + // 启动一个节点 + RemoteSessionManager starter = sessionManagers[0]; + + // 当前节点需要连接到其他3个节点 + RemoteNode[] remoteNodes = new RemoteNode[1]; + + remoteNodes[0] = new RemoteNode(remoteHost, 10001); + + remoteSessions = starter.newSessions(remoteNodes); + + assertNull(remoteSessions); } From a0a68fe933a996d220ffb03642aab246d6a44f51 Mon Sep 17 00:00:00 2001 From: shaozhuguang Date: Thu, 18 Apr 2019 17:48:53 +0800 Subject: [PATCH 05/43] Add Close receiver function --- .../manager/ConnectionManager.java | 9 +- .../manager/RemoteSessionManager.java | 9 ++ .../stp/commucation/StpReceiversBoot.java | 75 +++++++++++++++ .../jd/blockchain/StpReceiversBootTest.java | 43 +++++++++ .../java/com/jd/blockchain/StpSenderTest.java | 96 +++++++++++++++++++ 5 files changed, 231 insertions(+), 1 deletion(-) create mode 100644 source/test/test-stp-community/src/main/java/com/jd/blockchain/stp/commucation/StpReceiversBoot.java create mode 100644 source/test/test-stp-community/src/test/java/com/jd/blockchain/StpReceiversBootTest.java create mode 100644 source/test/test-stp-community/src/test/java/com/jd/blockchain/StpSenderTest.java diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/ConnectionManager.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/ConnectionManager.java index 3f322e97..0db2cdfe 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/ConnectionManager.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/ConnectionManager.java @@ -8,7 +8,6 @@ */ package com.jd.blockchain.stp.communication.manager; -import com.jd.blockchain.stp.communication.MessageExecutor; import com.jd.blockchain.stp.communication.callback.CallBackLauncher; import com.jd.blockchain.stp.communication.connection.Receiver; import com.jd.blockchain.stp.communication.connection.Connection; @@ -145,6 +144,14 @@ public class ConnectionManager { return connectionMap.get(remoteNode); } + /** + * 关闭Receiver + * + */ + public void closeReceiver() { + this.receiver.close(); + } + private Connection init(RemoteNode remoteNode, String messageExecutorClass) { // 初始化Connection diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/RemoteSessionManager.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/RemoteSessionManager.java index 3403d2a0..50adda54 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/RemoteSessionManager.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/RemoteSessionManager.java @@ -167,6 +167,15 @@ public class RemoteSessionManager { return remoteSessionList.toArray(remoteSessions); } + /** + * 返回底层通信管理器 + * + * @return + */ + public ConnectionManager connectionManager() { + return this.connectionManager; + } + private void check() { // 要求端口范围:1~65535,messageExecuteClass不能为null int listenPort = this.localNode.getPort(); diff --git a/source/test/test-stp-community/src/main/java/com/jd/blockchain/stp/commucation/StpReceiversBoot.java b/source/test/test-stp-community/src/main/java/com/jd/blockchain/stp/commucation/StpReceiversBoot.java new file mode 100644 index 00000000..e725d77b --- /dev/null +++ b/source/test/test-stp-community/src/main/java/com/jd/blockchain/stp/commucation/StpReceiversBoot.java @@ -0,0 +1,75 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.StpReceiversBoot + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/18 下午3:44 + * Description: + */ +package com.jd.blockchain.stp.commucation; + +import com.jd.blockchain.stp.communication.MessageExecutor; +import com.jd.blockchain.stp.communication.manager.RemoteSessionManager; +import com.jd.blockchain.stp.communication.node.LocalNode; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * + * @author shaozhuguang + * @create 2019/4/18 + * @since 1.0.0 + */ + +public class StpReceiversBoot { + + private int[] listenPorts; + + private final String remoteHost = "127.0.0.1"; + + private ExecutorService threadPool; + + public StpReceiversBoot(int... ports) { + listenPorts = ports; + threadPool = Executors.newFixedThreadPool(ports.length + 2); + } + + public RemoteSessionManager[] start(MessageExecutor messageExecutor) { + + final int totalSessionSize = listenPorts.length; + + CountDownLatch countDownLatch = new CountDownLatch(totalSessionSize); + + RemoteSessionManager[] sessionManagers = new RemoteSessionManager[totalSessionSize]; + for (int i = 0; i < totalSessionSize; i++) { + final int port = listenPorts[i], index = i; + threadPool.execute(() -> { + // 创建本地节点 + final LocalNode localNode = new LocalNode(remoteHost, port, messageExecutor); + try { + // 启动当前节点 + RemoteSessionManager sessionManager = new RemoteSessionManager(localNode); + sessionManagers[index] = sessionManager; + System.out.printf("Current Node {%s} start success !!! \r\n", localNode.toString()); + } catch (Exception e) { + e.printStackTrace(); + } finally { + countDownLatch.countDown(); + } + }); + } + + // 等待所有节点启动完成 + try { + countDownLatch.await(); + } catch (Exception e) { + e.printStackTrace(); + } + + return sessionManagers; + } + + +} \ No newline at end of file diff --git a/source/test/test-stp-community/src/test/java/com/jd/blockchain/StpReceiversBootTest.java b/source/test/test-stp-community/src/test/java/com/jd/blockchain/StpReceiversBootTest.java new file mode 100644 index 00000000..1cd6e985 --- /dev/null +++ b/source/test/test-stp-community/src/test/java/com/jd/blockchain/StpReceiversBootTest.java @@ -0,0 +1,43 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.StpReceiversBootTest + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/18 下午3:53 + * Description: + */ +package com.jd.blockchain; + +import com.jd.blockchain.stp.commucation.MyMessageExecutor; +import com.jd.blockchain.stp.commucation.StpReceiversBoot; +import com.jd.blockchain.stp.communication.manager.RemoteSessionManager; +import org.junit.Test; + +/** + * + * @author shaozhuguang + * @create 2019/4/18 + * @since 1.0.0 + */ + +public class StpReceiversBootTest { + + public static final int[] localPorts = new int[]{9900, 9901}; + + @Test + public void test() { + StpReceiversBoot stpReceiversBoot = new StpReceiversBoot(9900, 9901); + RemoteSessionManager[] sessionManagers = stpReceiversBoot.start(new MyMessageExecutor()); + + try { + Thread.sleep(10000); + + // 关闭所有的监听器 + for (RemoteSessionManager sessionManager : sessionManagers) { + sessionManager.connectionManager().closeReceiver(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/source/test/test-stp-community/src/test/java/com/jd/blockchain/StpSenderTest.java b/source/test/test-stp-community/src/test/java/com/jd/blockchain/StpSenderTest.java new file mode 100644 index 00000000..29741ae0 --- /dev/null +++ b/source/test/test-stp-community/src/test/java/com/jd/blockchain/StpSenderTest.java @@ -0,0 +1,96 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.StpSenderTest + * Author: shaozhuguang + * Department: Y事业部 + * Date: 2019/4/18 下午3:56 + * Description: + */ +package com.jd.blockchain; + +import com.jd.blockchain.stp.commucation.MyMessageExecutor; +import com.jd.blockchain.stp.commucation.StpReceiversBoot; +import com.jd.blockchain.stp.communication.RemoteSession; +import com.jd.blockchain.stp.communication.callback.CallBackBarrier; +import com.jd.blockchain.stp.communication.callback.CallBackDataListener; +import com.jd.blockchain.stp.communication.manager.RemoteSessionManager; +import com.jd.blockchain.stp.communication.message.LoadMessage; +import com.jd.blockchain.stp.communication.node.RemoteNode; +import org.junit.Test; + +import java.util.Iterator; +import java.util.LinkedList; + +/** + * + * @author shaozhuguang + * @create 2019/4/18 + * @since 1.0.0 + */ + +public class StpSenderTest { + + // 本地的端口 + private static final int localPort = 9800; + + // 连接的远端端口集合 + private static final int[] remotePorts = StpReceiversBootTest.localPorts; + + // 本地节点信息 + private static final String localHost = "127.0.0.1"; + + @Test + public void test() { + // 首先启动本地节点 + StpReceiversBoot stpReceiversBoot = new StpReceiversBoot(localPort); + RemoteSessionManager[] sessionManagers = stpReceiversBoot.start(new MyMessageExecutor()); + + // 本地节点启动完成后 + if (sessionManagers != null && sessionManagers.length > 0) { + RemoteSessionManager localSessionManager = sessionManagers[0]; + + // 连接远端的两个节点 + RemoteNode[] remoteNodes = new RemoteNode[]{ + new RemoteNode(localHost, remotePorts[0]), + new RemoteNode(localHost, remotePorts[1]) + }; + + RemoteSession[] remoteSessions = localSessionManager.newSessions(remoteNodes); + + // 生成请求对象 + LoadMessage loadMessage = new StpTest.StpLoadMessage(localHost + ":" + localPort); + + // 异步发送处理过程 + CallBackBarrier callBackBarrier = CallBackBarrier.newCallBackBarrier(remoteSessions.length, 10000); + + // 发送请求至remotes + LinkedList responses = new LinkedList<>(); + for (RemoteSession remoteSession : remoteSessions) { + CallBackDataListener response = remoteSession.asyncRequest(loadMessage, callBackBarrier); + responses.addLast(response); + } + + // 超时判断 + try { + if (callBackBarrier.tryCall()) { + + // 说明结果已经全部返回 + // 打印出所有的结果 + // 通过迭代器遍历链表 + Iterator iterator = responses.iterator(); + while (iterator.hasNext()) { + CallBackDataListener response = iterator.next(); + // 判断是否已完成,对于没有完成的直接放弃(因为已经超时) + if (response.isDone()) { + System.out.printf("Receive Response {%s} {%s} \r\n", + response.remoteNode().toString(), new String(response.getCallBackData())); + } + } + } + Thread.sleep(Integer.MAX_VALUE); + } catch (Exception e) { + e.printStackTrace(); + } + } + } +} \ No newline at end of file From 469c23fef86baee82fa0c2e767523db45fbd31e2 Mon Sep 17 00:00:00 2001 From: shaozhuguang Date: Fri, 19 Apr 2019 09:56:49 +0800 Subject: [PATCH 06/43] Modify Class Note...... --- .../stp/communication/MessageExecutor.java | 22 ++++++++++- .../stp/communication/RemoteSession.java | 2 +- .../callback/CallBackBarrier.java | 2 +- .../callback/CallBackDataListener.java | 2 +- .../callback/CallBackLauncher.java | 3 +- .../connection/AbstractAsyncExecutor.java | 2 +- .../connection/AsyncExecutor.java | 2 +- .../communication/connection/Connection.java | 2 +- .../communication/connection/Receiver.java | 2 +- .../stp/communication/connection/Sender.java | 38 ++++++++++++++++++- .../handler/HeartBeatReceiverHandler.java | 2 +- .../handler/HeartBeatReceiverTrigger.java | 2 +- .../handler/HeartBeatSenderHandler.java | 2 +- .../handler/HeartBeatSenderTrigger.java | 2 +- .../connection/handler/ReceiverHandler.java | 2 +- .../connection/handler/SenderHandler.java | 2 +- .../connection/handler/WatchDogHandler.java | 30 +++++++++++++-- .../connection/listener/ReplyListener.java | 2 +- .../manager/ConnectionManager.java | 2 +- .../manager/RemoteSessionManager.java | 2 +- .../message/AbstractMessage.java | 2 +- .../message/HeartBeatMessage.java | 2 +- .../stp/communication/message/IMessage.java | 2 +- .../communication/message/LoadMessage.java | 2 +- .../communication/message/SessionMessage.java | 2 +- .../message/TransferMessage.java | 2 +- .../stp/communication/node/LocalNode.java | 3 +- .../stp/communication/node/RemoteNode.java | 3 +- 28 files changed, 111 insertions(+), 32 deletions(-) diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/MessageExecutor.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/MessageExecutor.java index ca85b0c8..dba7e0d0 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/MessageExecutor.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/MessageExecutor.java @@ -1,8 +1,8 @@ /** * Copyright: Copyright 2016-2020 JD.COM All Right Reserved - * FileName: com.jd.blockchain.stp.communication.MessageExecute + * FileName: com.jd.blockchain.stp.communication.MessageExecutor * Author: shaozhuguang - * Department: Y事业部 + * Department: Jingdong Digits Technology * Date: 2019/4/11 上午10:59 * Description: */ @@ -19,8 +19,26 @@ package com.jd.blockchain.stp.communication; public interface MessageExecutor { + /** + * 接收到receive消息如何处理 + * + * @param key + * 请求消息的Key,调用者需要在应答时通过该Key应答远端 + * @param data + * 请求消息的内容 + * @param session + * 远端Session,描述该消息是从哪发送来的 + * @return + * 应答结果 + */ byte[] receive(String key, byte[] data, RemoteSession session); + /** + * 应答方式 + * + * @return + * 参考:{@link REPLY} + */ REPLY replyType(); // 应答方式 diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteSession.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteSession.java index cc4dd167..f72a071c 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteSession.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteSession.java @@ -2,7 +2,7 @@ * Copyright: Copyright 2016-2020 JD.COM All Right Reserved * FileName: com.jd.blockchain.stp.communication.RemoteSession * Author: shaozhuguang - * Department: Y事业部 + * Department: Jingdong Digits Technology * Date: 2019/4/11 上午11:15 * Description: */ diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackBarrier.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackBarrier.java index c9580e10..41da6b66 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackBarrier.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackBarrier.java @@ -2,7 +2,7 @@ * Copyright: Copyright 2016-2020 JD.COM All Right Reserved * FileName: com.jd.blockchain.stp.communication.CallBackBarrier * Author: shaozhuguang - * Department: Y事业部 + * Department: Jingdong Digits Technology * Date: 2019/4/12 上午10:22 * Description: */ diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackDataListener.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackDataListener.java index e9aa4417..9de7aa32 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackDataListener.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackDataListener.java @@ -2,7 +2,7 @@ * Copyright: Copyright 2016-2020 JD.COM All Right Reserved * FileName: com.jd.blockchain.stp.communication.callback.CallBackDataListener * Author: shaozhuguang - * Department: Y事业部 + * Department: Jingdong Digits Technology * Date: 2019/4/15 下午4:40 * Description: */ diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackLauncher.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackLauncher.java index bef91db4..e1f9473a 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackLauncher.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/callback/CallBackLauncher.java @@ -2,7 +2,7 @@ * Copyright: Copyright 2016-2020 JD.COM All Right Reserved * FileName: com.jd.blockchain.stp.communication.callback.CallBackLauncher * Author: shaozhuguang - * Department: Y事业部 + * Department: Jingdong Digits Technology * Date: 2019/4/17 下午6:27 * Description: */ @@ -15,6 +15,7 @@ import java.util.concurrent.Semaphore; * @author shaozhuguang * @create 2019/4/17 * @since 1.0.0 + * @date 2019-04-19 09:53 */ public class CallBackLauncher { diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/AbstractAsyncExecutor.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/AbstractAsyncExecutor.java index 273fcbc0..fc99cb05 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/AbstractAsyncExecutor.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/AbstractAsyncExecutor.java @@ -2,7 +2,7 @@ * Copyright: Copyright 2016-2020 JD.COM All Right Reserved * FileName: com.jd.blockchain.stp.communication.connection.AbstractAsyncExecutor * Author: shaozhuguang - * Department: Y事业部 + * Department: Jingdong Digits Technology * Date: 2019/4/17 上午11:16 * Description: */ diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/AsyncExecutor.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/AsyncExecutor.java index 22c0c28a..5bfdd682 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/AsyncExecutor.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/AsyncExecutor.java @@ -2,7 +2,7 @@ * Copyright: Copyright 2016-2020 JD.COM All Right Reserved * FileName: com.jd.blockchain.stp.communication.connection.AsyncExecutor * Author: shaozhuguang - * Department: Y事业部 + * Department: Jingdong Digits Technology * Date: 2019/4/17 上午11:14 * Description: */ diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Connection.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Connection.java index 7ceedf77..1c6d2dc6 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Connection.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Connection.java @@ -2,7 +2,7 @@ * Copyright: Copyright 2016-2020 JD.COM All Right Reserved * FileName: com.jd.blockchain.stp.communication.connection.Connection * Author: shaozhuguang - * Department: Y事业部 + * Department: Jingdong Digits Technology * Date: 2019/4/11 下午5:39 * Description: */ diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Receiver.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Receiver.java index c9dae7fa..50eab985 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Receiver.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Receiver.java @@ -2,7 +2,7 @@ * Copyright: Copyright 2016-2020 JD.COM All Right Reserved * FileName: com.jd.blockchain.stp.communication.inner.Receiver * Author: shaozhuguang - * Department: Y事业部 + * Department: Jingdong Digits Technology * Date: 2019/4/11 上午10:59 * Description: */ diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Sender.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Sender.java index cbc57467..dcef4009 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Sender.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Sender.java @@ -2,7 +2,7 @@ * Copyright: Copyright 2016-2020 JD.COM All Right Reserved * FileName: com.jd.blockchain.stp.communication.inner.Sender * Author: shaozhuguang - * Department: Y事业部 + * Department: Jingdong Digits Technology * Date: 2019/4/11 上午10:58 * Description: */ @@ -101,6 +101,7 @@ public class Sender extends AbstractAsyncExecutor implements Closeable { ThreadPoolExecutor runThread = initRunThread(); + // 单独线程进行连接,防止当前调用线程阻塞 runThread.execute(() -> { try { // 发起连接请求 @@ -126,10 +127,28 @@ public class Sender extends AbstractAsyncExecutor implements Closeable { }); } + /** + * 初始化相关配置 + * + * @param remoteNode + * 远端节点 + * @param sessionMessage + * 本地节点连接到远端节点后发送的SessionMessage + */ private void init(RemoteNode remoteNode, SessionMessage sessionMessage) { init(remoteNode.getHostName(), remoteNode.getPort(), sessionMessage); } + /** + * 初始化相关配置 + * + * @param remoteHost + * 远端HOST + * @param remotePort + * 远端端口 + * @param sessionMessage + * 本地节点连接到远端节点后发送的SessionMessage + */ private void init(String remoteHost, int remotePort, SessionMessage sessionMessage) { this.remoteHost = remoteHost; this.remotePort = remotePort; @@ -149,7 +168,9 @@ public class Sender extends AbstractAsyncExecutor implements Closeable { /** * 发送消息 + * * @param message + * 消息统一接口 */ public void send(IMessage message) { watchDogHandler.channelFuture().channel().writeAndFlush(message.toTransferByteBuf()); @@ -161,15 +182,30 @@ public class Sender extends AbstractAsyncExecutor implements Closeable { // loopGroup.shutdownGracefully(); } + /** + * ChannelHandler集合管理类 + */ public static class ChannelHandlers { private List channelHandlers = new ArrayList<>(); + /** + * 添加指定的ChannelHandler + * + * @param channelHandler + * 需要加入的ChannelHandler + * @return + */ public ChannelHandlers addHandler(ChannelHandler channelHandler) { channelHandlers.add(channelHandler); return this; } + /** + * List集合转换为数组 + * + * @return + */ public ChannelHandler[] toArray() { ChannelHandler[] channelHandlerArray = new ChannelHandler[channelHandlers.size()]; return channelHandlers.toArray(channelHandlerArray); diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatReceiverHandler.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatReceiverHandler.java index 47d65176..ab3595e9 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatReceiverHandler.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatReceiverHandler.java @@ -2,7 +2,7 @@ * Copyright: Copyright 2016-2020 JD.COM All Right Reserved * FileName: com.jd.blockchain.stp.communication.connection.handler.HeartBeatSenderHandler * Author: shaozhuguang - * Department: Y事业部 + * Department: Jingdong Digits Technology * Date: 2019/4/15 上午10:10 * Description: */ diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatReceiverTrigger.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatReceiverTrigger.java index 588b6de3..48288dc6 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatReceiverTrigger.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatReceiverTrigger.java @@ -2,7 +2,7 @@ * Copyright: Copyright 2016-2020 JD.COM All Right Reserved * FileName: com.jd.blockchain.stp.communication.connection.handler.HeartBeatSenderTrigger * Author: shaozhuguang - * Department: Y事业部 + * Department: Jingdong Digits Technology * Date: 2019/4/15 上午10:11 * Description: */ diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatSenderHandler.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatSenderHandler.java index a477c42c..be1c187b 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatSenderHandler.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatSenderHandler.java @@ -2,7 +2,7 @@ * Copyright: Copyright 2016-2020 JD.COM All Right Reserved * FileName: com.jd.blockchain.stp.communication.connection.handler.HeartBeatSenderHandler * Author: shaozhuguang - * Department: Y事业部 + * Department: Jingdong Digits Technology * Date: 2019/4/15 上午10:10 * Description: */ diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatSenderTrigger.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatSenderTrigger.java index fc059d54..9a61f31a 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatSenderTrigger.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/HeartBeatSenderTrigger.java @@ -2,7 +2,7 @@ * Copyright: Copyright 2016-2020 JD.COM All Right Reserved * FileName: com.jd.blockchain.stp.communication.connection.handler.HeartBeatSenderTrigger * Author: shaozhuguang - * Department: Y事业部 + * Department: Jingdong Digits Technology * Date: 2019/4/15 上午10:11 * Description: */ diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/ReceiverHandler.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/ReceiverHandler.java index 1bcb5ef3..8a13db4e 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/ReceiverHandler.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/ReceiverHandler.java @@ -2,7 +2,7 @@ * Copyright: Copyright 2016-2020 JD.COM All Right Reserved * FileName: com.jd.blockchain.stp.communication.connection.handler.ReceiverHandler * Author: shaozhuguang - * Department: Y事业部 + * Department: Jingdong Digits Technology * Date: 2019/4/12 上午11:14 * Description: */ diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/SenderHandler.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/SenderHandler.java index ac86ea54..b3d194cb 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/SenderHandler.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/SenderHandler.java @@ -2,7 +2,7 @@ * Copyright: Copyright 2016-2020 JD.COM All Right Reserved * FileName: com.jd.blockchain.stp.communication.connection.handler.SenderHandler * Author: shaozhuguang - * Department: Y事业部 + * Department: Jingdong Digits Technology * Date: 2019/4/16 下午2:00 * Description: */ diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/WatchDogHandler.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/WatchDogHandler.java index ca41fc9a..bdcb82de 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/WatchDogHandler.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/WatchDogHandler.java @@ -2,7 +2,7 @@ * Copyright: Copyright 2016-2020 JD.COM All Right Reserved * FileName: com.jd.blockchain.stp.communication.connection.SenderWatchDog * Author: shaozhuguang - * Department: Y事业部 + * Department: Jingdong Digits Technology * Date: 2019/4/12 下午4:56 * Description: */ @@ -27,6 +27,7 @@ import java.util.concurrent.locks.ReentrantLock; * @author shaozhuguang * @create 2019/4/12 * @since 1.0.0 + * @date 2019-04-19 09:21 */ @ChannelHandler.Sharable public class WatchDogHandler extends ChannelInboundHandlerAdapter implements Runnable, Closeable { @@ -42,13 +43,19 @@ public class WatchDogHandler extends ChannelInboundHandlerAdapter implements Run */ private final Lock reconnectLock = new ReentrantLock(); - // 默认的最多重连次数 + /** + * 默认的最多重连次数 + */ private final int maxReconnectSize = 16; - // 默认重连的时间 + /** + * 默认重连的时间,下次重连时间会变长 + */ private final int defaultReconnectSeconds = 2; - // 标识是否正常工作中,假设不再工作则不再重连 + /** + * 标识是否正常工作中,假设不再工作则不再重连 + */ private boolean isWorking = true; /** @@ -121,12 +128,27 @@ public class WatchDogHandler extends ChannelInboundHandlerAdapter implements Run initTimer(); } + /** + * 初始化ChannelFuture + * + * @param channelFuture + */ public void initChannelFuture(ChannelFuture channelFuture) { this.channelFuture = channelFuture; } + /** + * 返回ChannelFuture + * + * @return + * 该返回对象目前未处理是否连接成功的情况 + * 调用者可直接使用,但假设发送不成功的话会存在异常抛出 + * 调用者可手动处理异常 + */ public ChannelFuture channelFuture() { try { + // 使用锁防止在重连进行过程中互相竞争 + // 一定是等待本次重连完成才返回 reconnectLock.lock(); return this.channelFuture; } finally { diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/listener/ReplyListener.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/listener/ReplyListener.java index 47d11883..ac9221d0 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/listener/ReplyListener.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/listener/ReplyListener.java @@ -2,7 +2,7 @@ * Copyright: Copyright 2016-2020 JD.COM All Right Reserved * FileName: com.jd.blockchain.stp.communication.connection.listener.ReplyListener * Author: shaozhuguang - * Department: Y事业部 + * Department: Jingdong Digits Technology * Date: 2019/4/12 上午10:36 * Description: */ diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/ConnectionManager.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/ConnectionManager.java index 0db2cdfe..c4f8097f 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/ConnectionManager.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/ConnectionManager.java @@ -2,7 +2,7 @@ * Copyright: Copyright 2016-2020 JD.COM All Right Reserved * FileName: com.jd.blockchain.stp.communication.ConnectionManager * Author: shaozhuguang - * Department: Y事业部 + * Department: Jingdong Digits Technology * Date: 2019/4/11 下午6:11 * Description: */ diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/RemoteSessionManager.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/RemoteSessionManager.java index 50adda54..8025252a 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/RemoteSessionManager.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/RemoteSessionManager.java @@ -2,7 +2,7 @@ * Copyright: Copyright 2016-2020 JD.COM All Right Reserved * FileName: com.jd.blockchain.stp.communication.RemoteSessionManager * Author: shaozhuguang - * Department: Y事业部 + * Department: Jingdong Digits Technology * Date: 2019/4/11 上午11:22 * Description: */ diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/AbstractMessage.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/AbstractMessage.java index 8cd0a3e9..a20ef623 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/AbstractMessage.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/AbstractMessage.java @@ -2,7 +2,7 @@ * Copyright: Copyright 2016-2020 JD.COM All Right Reserved * FileName: com.jd.blockchain.stp.communication.message.AbstractMessage * Author: shaozhuguang - * Department: Y事业部 + * Department: Jingdong Digits Technology * Date: 2019/4/17 下午4:00 * Description: */ diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/HeartBeatMessage.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/HeartBeatMessage.java index a0f5974c..eba5e4b6 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/HeartBeatMessage.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/HeartBeatMessage.java @@ -2,7 +2,7 @@ * Copyright: Copyright 2016-2020 JD.COM All Right Reserved * FileName: com.jd.blockchain.stp.communication.message.HeartBeatMessage * Author: shaozhuguang - * Department: Y事业部 + * Department: Jingdong Digits Technology * Date: 2019/4/12 下午4:55 * Description: */ diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/IMessage.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/IMessage.java index 6cb0a0a4..c43e8d84 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/IMessage.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/IMessage.java @@ -2,7 +2,7 @@ * Copyright: Copyright 2016-2020 JD.COM All Right Reserved * FileName: com.jd.blockchain.stp.communication.message.IMessage * Author: shaozhuguang - * Department: Y事业部 + * Department: Jingdong Digits Technology * Date: 2019/4/16 下午1:58 * Description: */ diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/LoadMessage.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/LoadMessage.java index 795fa8c1..b8971293 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/LoadMessage.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/LoadMessage.java @@ -2,7 +2,7 @@ * Copyright: Copyright 2016-2020 JD.COM All Right Reserved * FileName: com.jd.blockchain.stp.communication.message.LoadMessage * Author: shaozhuguang - * Department: Y事业部 + * Department: Jingdong Digits Technology * Date: 2019/4/11 上午10:59 * Description: */ diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/SessionMessage.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/SessionMessage.java index c685b77c..b3ce460b 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/SessionMessage.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/SessionMessage.java @@ -2,7 +2,7 @@ * Copyright: Copyright 2016-2020 JD.COM All Right Reserved * FileName: com.jd.blockchain.stp.communication.message.SessionMessage * Author: shaozhuguang - * Department: Y事业部 + * Department: Jingdong Digits Technology * Date: 2019/4/16 上午10:40 * Description: */ diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/TransferMessage.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/TransferMessage.java index 8bc9a448..b6000866 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/TransferMessage.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/TransferMessage.java @@ -2,7 +2,7 @@ * Copyright: Copyright 2016-2020 JD.COM All Right Reserved * FileName: com.jd.blockchain.stp.communication.message.TransferMessage * Author: shaozhuguang - * Department: Y事业部 + * Department: Jingdong Digits Technology * Date: 2019/4/11 上午11:00 * Description: */ diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/node/LocalNode.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/node/LocalNode.java index 64c203bd..60b9b11b 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/node/LocalNode.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/node/LocalNode.java @@ -2,7 +2,7 @@ * Copyright: Copyright 2016-2020 JD.COM All Right Reserved * FileName: com.jd.blockchain.stp.communication.node.LocalNode * Author: shaozhuguang - * Department: Y事业部 + * Department: Jingdong Digits Technology * Date: 2019/4/16 下午3:12 * Description: */ @@ -15,6 +15,7 @@ import com.jd.blockchain.stp.communication.MessageExecutor; * @author shaozhuguang * @create 2019/4/16 * @since 1.0.0 + * @date 2019-04-19 09:28 */ public class LocalNode extends RemoteNode { diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/node/RemoteNode.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/node/RemoteNode.java index 7e2004c8..89287380 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/node/RemoteNode.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/node/RemoteNode.java @@ -2,7 +2,7 @@ * Copyright: Copyright 2016-2020 JD.COM All Right Reserved * FileName: com.jd.blockchain.stp.communication.RemoteNode * Author: shaozhuguang - * Department: Y事业部 + * Department: Jingdong Digits Technology * Date: 2019/4/11 下午3:40 * Description: */ @@ -13,6 +13,7 @@ package com.jd.blockchain.stp.communication.node; * @author shaozhuguang * @create 2019/4/11 * @since 1.0.0 + * @date 2019-04-19 09:28 */ public class RemoteNode { From 6e8130c30a6c7b8e3cfaccfc04bb6a73943c6519 Mon Sep 17 00:00:00 2001 From: shaozhuguang Date: Fri, 19 Apr 2019 15:00:34 +0800 Subject: [PATCH 07/43] Fix BftsmartMessageService throw Exception... --- .../consensus/bftsmart/client/BftsmartMessageService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartMessageService.java b/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartMessageService.java index 53a5f0a8..5ecf6596 100644 --- a/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartMessageService.java +++ b/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartMessageService.java @@ -40,7 +40,7 @@ public class BftsmartMessageService implements MessageService { asyncFuture.complete(result); } catch (Exception e) { - throw new RuntimeException(); + throw new RuntimeException(e); } finally { asyncPeerProxyPool.returnObject(asynchServiceProxy); From 9b2fa94463012c24747ea906a0af70aff775aebb Mon Sep 17 00:00:00 2001 From: zhangshuang Date: Fri, 19 Apr 2019 18:45:27 +0800 Subject: [PATCH 08/43] add state transfer layer code --- source/state-transfer/pom.xml | 11 + .../statetransfer/DSProcessManager.java | 45 ---- .../statetransfer/DSTransferProcess.java | 84 -------- .../statetransfer/DataSequenceElement.java | 6 +- .../statetransfer/DataSequenceMsgHandle.java | 37 ---- .../statetransfer/DataSequenceReader.java | 22 -- .../statetransfer/DataSequenceWriter.java | 17 -- .../callback/DataSequenceReader.java | 33 +++ .../callback/DataSequenceWriter.java | 25 +++ .../message/DSDefaultMessageExecutor.java | 75 +++++++ .../message/DSMsgResolverFactory.java | 15 ++ .../message/DataSequenceLoadMessage.java | 24 +++ .../message/DataSequenceMsgDecoder.java | 95 +++++++++ .../message/DataSequenceMsgEncoder.java | 116 +++++++++++ .../process/DSProcessManager.java | 155 ++++++++++++++ .../process/DSTransferProcess.java | 192 ++++++++++++++++++ .../result/DSDiffRequestResult.java | 39 ++++ .../result/DSInfoResponseResult.java | 37 ++++ 18 files changed, 822 insertions(+), 206 deletions(-) delete mode 100644 source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DSProcessManager.java delete mode 100644 source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DSTransferProcess.java delete mode 100644 source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceMsgHandle.java delete mode 100644 source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceReader.java delete mode 100644 source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceWriter.java create mode 100644 source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceReader.java create mode 100644 source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriter.java create mode 100644 source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DSDefaultMessageExecutor.java create mode 100644 source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DSMsgResolverFactory.java create mode 100644 source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceLoadMessage.java create mode 100644 source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceMsgDecoder.java create mode 100644 source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceMsgEncoder.java create mode 100644 source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSProcessManager.java create mode 100644 source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSTransferProcess.java create mode 100644 source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/result/DSDiffRequestResult.java create mode 100644 source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/result/DSInfoResponseResult.java diff --git a/source/state-transfer/pom.xml b/source/state-transfer/pom.xml index 9c3f04be..d17c8e03 100644 --- a/source/state-transfer/pom.xml +++ b/source/state-transfer/pom.xml @@ -15,6 +15,17 @@ stp-communication ${project.version} + + com.jd.blockchain + utils-common + ${project.version} + + + + com.jd.blockchain + utils-serialize + ${project.version} + diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DSProcessManager.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DSProcessManager.java deleted file mode 100644 index 63573700..00000000 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DSProcessManager.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.jd.blockchain.statetransfer; - -import com.jd.blockchain.stp.communication.RemoteSession; -import com.jd.blockchain.stp.communication.manager.RemoteSessionManager; - -import java.net.InetSocketAddress; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * - * @author zhangshuang - * @create 2019/4/11 - * @since 1.0.0 - */ -public class DSProcessManager { - - private Map dSProcessMap = new ConcurrentHashMap<>(); - private RemoteSession[] remoteSessions; - - DSTransferProcess startDSProcess(DataSequenceInfo dsInfo, InetSocketAddress listener, InetSocketAddress[] targets, DataSequenceWriter dsWriter, DataSequenceReader dsReader) { - -// RemoteSessionManager remoteSessionManager = new RemoteSessionManager(listener.getPort()); - RemoteSessionManager remoteSessionManager = null; - DSTransferProcess dsTransferProcess = new DSTransferProcess(dsInfo, remoteSessionManager, targets, dsWriter, dsReader); - - dsTransferProcess.start(); - remoteSessions = dsTransferProcess.getSessions(); - - for(RemoteSession session : remoteSessions) { - dsTransferProcess.send(DSTransferProcess.DataSequenceMsgType.CMD_DSINFO, session); - } - - - dSProcessMap.put(dsInfo.getId(), dsTransferProcess); - - return dsTransferProcess; - } - - void setDSReader(DataSequenceReader reader) { - - } - - -} diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DSTransferProcess.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DSTransferProcess.java deleted file mode 100644 index 6d5b699f..00000000 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DSTransferProcess.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.jd.blockchain.statetransfer; - -import com.jd.blockchain.stp.communication.RemoteSession; -import com.jd.blockchain.stp.communication.manager.RemoteSessionManager; -import com.jd.blockchain.stp.communication.node.RemoteNode; - -import java.net.InetSocketAddress; - -/** - * - * @author zhangshuang - * @create 2019/4/11 - * @since 1.0.0 - */ -public class DSTransferProcess { - - private InetSocketAddress[] targets; - private DataSequenceWriter dsWriter; - private DataSequenceReader dsReader; - private DataSequenceInfo dsInfo; - private RemoteSessionManager remoteSessionManager; - private RemoteSession[] remoteSessions; - private String id; - - - public DSTransferProcess(DataSequenceInfo dsInfo, RemoteSessionManager remoteSessionManager, InetSocketAddress[] targets, DataSequenceWriter dsWriter, DataSequenceReader dsReader) { - - this.dsInfo = dsInfo; - this.targets = targets; - this.dsWriter = dsWriter; - this.dsReader = dsReader; - this.remoteSessionManager = remoteSessionManager; - this.id = dsInfo.getId(); - - } - - void send(DataSequenceMsgType msgType, RemoteSession session) { - - //session.send(); - - } - - byte[] createMsg(DataSequenceMsgType msgType) { - return null; - } - - public void computeDiff() { - //todo - } - - public void getDSInfo(String id) { - //todo - } - - public RemoteSession[] getSessions() { - //todo - return remoteSessions; - } - - public void start() { - - RemoteNode[] remoteNodes = new RemoteNode[targets.length]; - - for (int i = 0; i< remoteNodes.length; i++) { - remoteNodes[i] = new RemoteNode(targets[i].getHostName(), targets[i].getPort()); - } - - remoteSessions = remoteSessionManager.newSessions(remoteNodes); - - for (int i = 0; i < remoteSessions.length; i++) { - DataSequenceMsgHandle msgHandle = new DataSequenceMsgHandle(dsReader, dsWriter); - remoteSessions[i].initExecutor(msgHandle); - remoteSessions[i].init(); - } - } - - enum DataSequenceMsgType { - - CMD_DSINFO, - CMD_GETDSDIFF - } - - -} diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceElement.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceElement.java index e1e904ed..b64bd963 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceElement.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceElement.java @@ -1,12 +1,16 @@ package com.jd.blockchain.statetransfer; +import java.io.Serializable; + /** *数据序列复制的元素或单位 * @author zhangshuang * @create 2019/4/11 * @since 1.0.0 */ -public class DataSequenceElement { +public class DataSequenceElement implements Serializable { + + private static final long serialVersionUID = -719578198150380571L; //数据序列的唯一标识符; private String id; diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceMsgHandle.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceMsgHandle.java deleted file mode 100644 index d396ff3e..00000000 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceMsgHandle.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.jd.blockchain.statetransfer; - -import com.jd.blockchain.stp.communication.MessageExecutor; -import com.jd.blockchain.stp.communication.RemoteSession; - -/** - * - * @author zhangshuang - * @create 2019/4/11 - * @since 1.0.0 - */ -public class DataSequenceMsgHandle implements MessageExecutor { - - DataSequenceReader dsReader; - DataSequenceWriter dsWriter; - - public DataSequenceMsgHandle(DataSequenceReader dsReader, DataSequenceWriter dsWriter) { - this.dsReader = dsReader; - this.dsWriter = dsWriter; - } - - @Override - public byte[] receive(String key, byte[] data, RemoteSession session) { - return new byte[0]; - } - - @Override - public REPLY replyType() { - return REPLY.AUTO; - } - - /** - * - * - */ - -} diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceReader.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceReader.java deleted file mode 100644 index 5662c117..00000000 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceReader.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.jd.blockchain.statetransfer; -/** - *数据序列差异的提供者需要使用的回调接口 - * @author zhangshuang - * @create 2019/4/11 - * @since 1.0.0 - */ -public interface DataSequenceReader { - - /** - * 差异的提供者根据输入的数据序列标识符获取当前的数据序列信息; - * - */ - DataSequenceInfo getDSInfo(String id); - - - /** - * 差异的提供者根据输入的数据序列标识符以及起始,结束高度获得数据序列的差异内容; - * - */ - DataSequenceElement[] getDSContent(String id, long from, long to); -} diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceWriter.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceWriter.java deleted file mode 100644 index 0c45de18..00000000 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceWriter.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.jd.blockchain.statetransfer; - -/** - *数据序列差异的请求者获得差异内容后需要回调该接口,通过接口提供的方法对指定数据序列执行差异内容的重放,并更新数据序列的当前状态; - * @author zhangshuang - * @create 2019/4/11 - * @since 1.0.0 - */ -public interface DataSequenceWriter { - - /** - *更新数据序列的当前状态 - * return void - */ - void updateDSInfo(String id, DataSequenceElement[] diffContents); - -} diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceReader.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceReader.java new file mode 100644 index 00000000..8e0dda19 --- /dev/null +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceReader.java @@ -0,0 +1,33 @@ +package com.jd.blockchain.statetransfer.callback; + +import com.jd.blockchain.statetransfer.DataSequenceElement; +import com.jd.blockchain.statetransfer.DataSequenceInfo; + +/** + *数据序列差异的提供者需要使用的回调接口 + * @author zhangshuang + * @create 2019/4/11 + * @since 1.0.0 + */ +public interface DataSequenceReader { + + /** + * 差异的提供者根据输入的数据序列标识符获取当前的数据序列信息; + * + */ + DataSequenceInfo getDSInfo(String id); + + + /** + * 差异的提供者根据输入的数据序列标识符以及起始,结束高度提供数据序列的差异内容; + * + */ + DataSequenceElement[] getDSDiffContent(String id, long from, long to); + + + /** + * 差异的提供者根据输入的数据序列标识符以及高度提供数据序列的差异内容; + * + */ + DataSequenceElement getDSDiffContent(String id, long height); +} diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriter.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriter.java new file mode 100644 index 00000000..3e7d060f --- /dev/null +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriter.java @@ -0,0 +1,25 @@ +package com.jd.blockchain.statetransfer.callback; + +import com.jd.blockchain.statetransfer.DataSequenceElement; + +/** + *数据序列差异的请求者获得差异内容后需要回调该接口,通过接口提供的方法对指定数据序列执行差异内容的重放,并更新数据序列的当前状态; + * @author zhangshuang + * @create 2019/4/11 + * @since 1.0.0 + */ +public interface DataSequenceWriter { + + /** + *更新数据序列的当前状态,一次更新多个高度的差异 + * return void + */ + int updateDSInfo(String id, DataSequenceElement[] diffContents); + + /** + *更新数据序列的当前状态,一次更新一个高度的差异 + * return void + */ + int updateDSInfo(String id, DataSequenceElement diffContents); + +} diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DSDefaultMessageExecutor.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DSDefaultMessageExecutor.java new file mode 100644 index 00000000..258c5fdb --- /dev/null +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DSDefaultMessageExecutor.java @@ -0,0 +1,75 @@ +package com.jd.blockchain.statetransfer.message; + +import com.jd.blockchain.statetransfer.callback.DataSequenceReader; +import com.jd.blockchain.statetransfer.callback.DataSequenceWriter; +import com.jd.blockchain.statetransfer.process.DSTransferProcess; +import com.jd.blockchain.statetransfer.result.DSDiffRequestResult; +import com.jd.blockchain.stp.communication.MessageExecutor; +import com.jd.blockchain.stp.communication.RemoteSession; + +/** + * + * @author zhangshuang + * @create 2019/4/11 + * @since 1.0.0 + */ +public class DSDefaultMessageExecutor implements MessageExecutor { + + DataSequenceReader dsReader; + DataSequenceWriter dsWriter; + + public DSDefaultMessageExecutor(DataSequenceReader dsReader, DataSequenceWriter dsWriter) { + this.dsReader = dsReader; + this.dsWriter = dsWriter; + } + + /** + * 对状态机复制的请求进行响应 + * + */ + + @Override + public byte[] receive(String key, byte[] data, RemoteSession session) { + + try { + Object object = DSMsgResolverFactory.getDecoder(dsWriter, dsReader).decode(data); + + if (object instanceof String) { + + String id = (String)object; + byte[] respLoadMsg = DSMsgResolverFactory.getEncoder(dsWriter, dsReader).encode(DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_RESPONSE, id, 0, 0); + session.reply(key, new DataSequenceLoadMessage(respLoadMsg)); + } + else if (object instanceof DSDiffRequestResult) { + + DSDiffRequestResult requestResult = (DSDiffRequestResult)object; + String id = requestResult.getId(); + long fromHeight = requestResult.getFromHeight(); + long toHeight = requestResult.getToHeight(); + for (long i = fromHeight; i < toHeight + 1; i++) { + byte[] respLoadMsg = DSMsgResolverFactory.getEncoder(dsWriter, dsReader).encode(DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_RESPONSE, id, i, i); + session.reply(key, new DataSequenceLoadMessage(respLoadMsg)); + } + } + else { + throw new IllegalArgumentException("Receive data exception, unknown message type!"); + } + + } catch (Exception e) { + e.printStackTrace(); + } + + return null; + } + + @Override + public REPLY replyType() { + return REPLY.MANUAL; + } + + /** + * + * + */ + +} diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DSMsgResolverFactory.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DSMsgResolverFactory.java new file mode 100644 index 00000000..874ef367 --- /dev/null +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DSMsgResolverFactory.java @@ -0,0 +1,15 @@ +package com.jd.blockchain.statetransfer.message; + +import com.jd.blockchain.statetransfer.callback.DataSequenceReader; +import com.jd.blockchain.statetransfer.callback.DataSequenceWriter; + +public class DSMsgResolverFactory { + + public static DataSequenceMsgEncoder getEncoder(DataSequenceWriter dsWriter, DataSequenceReader dsReader) { + return new DataSequenceMsgEncoder(dsWriter, dsReader); + } + + public static DataSequenceMsgDecoder getDecoder(DataSequenceWriter dsWriter, DataSequenceReader dsReader) { + return new DataSequenceMsgDecoder(dsWriter, dsReader); + } +} diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceLoadMessage.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceLoadMessage.java new file mode 100644 index 00000000..ee38f880 --- /dev/null +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceLoadMessage.java @@ -0,0 +1,24 @@ +package com.jd.blockchain.statetransfer.message; + +import com.jd.blockchain.stp.communication.message.LoadMessage; + +/** + * + * + */ +public class DataSequenceLoadMessage implements LoadMessage { + byte[] bytes; + + public DataSequenceLoadMessage(byte[] bytes) { + this.bytes = bytes; + } + + public void setBytes(byte[] bytes) { + this.bytes = bytes; + } + + @Override + public byte[] toBytes() { + return bytes; + } +} diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceMsgDecoder.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceMsgDecoder.java new file mode 100644 index 00000000..81df552f --- /dev/null +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceMsgDecoder.java @@ -0,0 +1,95 @@ +package com.jd.blockchain.statetransfer.message; + +import com.jd.blockchain.statetransfer.DataSequenceElement; +import com.jd.blockchain.statetransfer.DataSequenceInfo; +import com.jd.blockchain.statetransfer.callback.DataSequenceReader; +import com.jd.blockchain.statetransfer.callback.DataSequenceWriter; +import com.jd.blockchain.statetransfer.process.DSTransferProcess; +import com.jd.blockchain.statetransfer.result.DSDiffRequestResult; +import com.jd.blockchain.utils.io.BytesUtils; +import com.jd.blockchain.utils.serialize.binary.BinarySerializeUtils; + +public class DataSequenceMsgDecoder { + + private int heightSize = 8; + private int msgTypeSize = 1; + + private long respHeight; + private long fromHeight; + private long toHeight; + private int idSize; + private byte[] idBytes; + private String id; + private int diffElemSize; + private byte[] diffElem; + DataSequenceElement dsElement; + + private DataSequenceWriter dsWriter; + private DataSequenceReader dsReader; + + public DataSequenceMsgDecoder(DataSequenceWriter dsWriter, DataSequenceReader dsReader) { + this.dsWriter = dsWriter; + this.dsReader = dsReader; + } + + + /** + * + * + */ + public Object decode(byte[] loadMessage) { + + try { + if (loadMessage.length <= 5) { + System.out.println("LoadMessage size is less than 5!"); + throw new IllegalArgumentException(); + } + + int dataLength = BytesUtils.toInt(loadMessage, 0, 4); + byte msgCode = loadMessage[4]; + + if (msgCode == DSTransferProcess.DataSequenceMsgType.CMD_DSINFO_RESPONSE.CODE) { + respHeight = BytesUtils.toLong(loadMessage, 4 + msgTypeSize); + idSize = BytesUtils.toInt(loadMessage, 4 + msgTypeSize + heightSize, 4); + idBytes = new byte[idSize]; + System.arraycopy(loadMessage, 4 + msgTypeSize + heightSize + 4, idBytes, 0, idSize); + id = new String(idBytes); + return new DataSequenceInfo(id, respHeight); + } else if (msgCode == DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_RESPONSE.CODE) { + diffElemSize = BytesUtils.toInt(loadMessage, 4 + msgTypeSize, 4); + diffElem = new byte[diffElemSize]; + System.arraycopy(loadMessage, 4 + msgTypeSize + 4, diffElem, 0, diffElemSize); + dsElement = BinarySerializeUtils.deserialize(diffElem); + return dsElement; + } else if (msgCode == DSTransferProcess.DataSequenceMsgType.CMD_DSINFO_REQUEST.CODE) { + idSize = BytesUtils.toInt(loadMessage, 4 + msgTypeSize, 4); + idBytes = new byte[idSize]; + System.arraycopy(loadMessage, 4 + msgTypeSize + 4, idBytes, 0, idSize); + id = new String(idBytes); + return id; + } else if (msgCode == DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_REQUEST.CODE) { + fromHeight = BytesUtils.toLong(loadMessage, 4 + msgTypeSize); + toHeight = BytesUtils.toLong(loadMessage, 4 + msgTypeSize + heightSize); + idSize = BytesUtils.toInt(loadMessage, 4 + msgTypeSize + heightSize + heightSize, 4); + idBytes = new byte[idSize]; + System.arraycopy(loadMessage, 4 + msgTypeSize + heightSize + heightSize + 4, idBytes, 0, idSize); + id = new String(idBytes); + return new DSDiffRequestResult(id, fromHeight, toHeight); + } + else { + System.out.println("Unknown message type!"); + throw new IllegalArgumentException(); + } + + } catch (Exception e) { + System.out.println("Error to decode message: " + e.getMessage() + "!"); + e.printStackTrace(); + + } + + return null; + } + + + +} diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceMsgEncoder.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceMsgEncoder.java new file mode 100644 index 00000000..9b1adad0 --- /dev/null +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceMsgEncoder.java @@ -0,0 +1,116 @@ +package com.jd.blockchain.statetransfer.message; + +import com.jd.blockchain.statetransfer.DataSequenceElement; +import com.jd.blockchain.statetransfer.callback.DataSequenceReader; +import com.jd.blockchain.statetransfer.callback.DataSequenceWriter; +import com.jd.blockchain.statetransfer.process.DSTransferProcess; +import com.jd.blockchain.utils.io.BytesUtils; +import com.jd.blockchain.utils.serialize.binary.BinarySerializeUtils; + +public class DataSequenceMsgEncoder { + + private int heightSize = 8; + private int msgTypeSize = 1; + + private DataSequenceWriter dsWriter; + private DataSequenceReader dsReader; + + public DataSequenceMsgEncoder(DataSequenceWriter dsWriter, DataSequenceReader dsReader) { + this.dsWriter = dsWriter; + this.dsReader = dsReader; + } + + /** + * 目前暂时考虑fromHeight与toHeight相同的情况,即每次只对一个高度的差异编码并响应 + * + */ + public byte[] encode(DSTransferProcess.DataSequenceMsgType msgType, String id, long fromHeight, long toHeight) { + + try { + + int dataLength; + int idSize = id.getBytes().length; + byte[] loadMessage = null; + + // different encoding methods for different message types + if (msgType == DSTransferProcess.DataSequenceMsgType.CMD_DSINFO_REQUEST) { + + // CMD_DSINFO_REQUEST Message parts : 4 bytes total message size, 1 byte message type coe, + // 4 bytes id length, id content size bytes + + dataLength = 4 + msgTypeSize + 4 + idSize; + + loadMessage = new byte[dataLength]; + + System.arraycopy(BytesUtils.toBytes(dataLength), 0, loadMessage, 0, 4); + System.arraycopy(msgType.CODE, 0, loadMessage, 4, msgTypeSize); + System.arraycopy(BytesUtils.toBytes(idSize), 0, loadMessage, 4 + msgTypeSize, 4); + System.arraycopy(id.getBytes(), 0, loadMessage, 4 + msgTypeSize + 4, idSize); + } else if (msgType == DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_REQUEST) { + + // CMD_GETDSDIFF_REQUEST Message parts : 4 bytes total message size, 1 byte message type coe, 8 bytes from height, + // 8 bytes to height, 4 bytes id length, id content size bytes + + dataLength = 4 + msgTypeSize + heightSize + heightSize + 4 + idSize; + + loadMessage = new byte[dataLength]; + + System.arraycopy(BytesUtils.toBytes(dataLength), 0, loadMessage, 0, 4); + System.arraycopy(msgType.CODE, 0, loadMessage, 4, msgTypeSize); + System.arraycopy(BytesUtils.toBytes(fromHeight), 0, loadMessage, 4 + msgTypeSize, heightSize); + System.arraycopy(BytesUtils.toBytes(toHeight), 0, loadMessage, 4 + msgTypeSize + heightSize, heightSize); + System.arraycopy(BytesUtils.toBytes(idSize), 0, loadMessage, 4 + msgTypeSize + heightSize + heightSize, 4); + System.arraycopy(id.getBytes(), 0, loadMessage, 4 + msgTypeSize + heightSize + heightSize + 4, idSize); + } else if (msgType == DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_RESPONSE) { + + // CMD_DSINFO_RESPONSE Message parts : 4 bytes total message size, 1 byte message type coe, 8 bytes data sequence local height, + // 4 bytes id length, id content size bytes + + dataLength = 4 + msgTypeSize + heightSize + 4 + idSize; + + loadMessage = new byte[dataLength]; + + System.arraycopy(BytesUtils.toBytes(dataLength), 0, loadMessage, 0, 4); + System.arraycopy(msgType.CODE, 0, loadMessage, 4, msgTypeSize); + System.arraycopy(BytesUtils.toBytes(dsReader.getDSInfo(id).getHeight()), 0, loadMessage, 4 + msgTypeSize, heightSize); + + System.arraycopy(BytesUtils.toBytes(idSize), 0, loadMessage, 4 + msgTypeSize + heightSize, 4); + System.arraycopy(id.getBytes(), 0, loadMessage, 4 + msgTypeSize + heightSize + 4, idSize); + + } else if (msgType == DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_RESPONSE) { + if (fromHeight != toHeight) { + throw new IllegalArgumentException("Height parameter error!"); + } + + // CMD_DSINFO_RESPONSE Message parts : 4 bytes total message size, 1 byte message type coe, + // 4 bytes diffElem size, diff content size; + + // 回调reader,获得这个高度上的所有差异的数据序列内容,并组织成DataSequenceElement结构 + DataSequenceElement element = dsReader.getDSDiffContent(id, fromHeight); + + byte[] diffElem = BinarySerializeUtils.serialize(element); + + dataLength = 4 + msgTypeSize + 4 + diffElem.length; + loadMessage = new byte[dataLength]; + + System.arraycopy(BytesUtils.toBytes(dataLength), 0, loadMessage, 0, 4); //total size + System.arraycopy(msgType.CODE, 0, loadMessage, 4, msgTypeSize); //msgType size + System.arraycopy(BytesUtils.toBytes(diffElem.length), 0, loadMessage, 4 + msgTypeSize, 4); // diffElem size + System.arraycopy(diffElem, 0, loadMessage, 4 + msgTypeSize + 4, diffElem.length); // diffElem bytes + } + else { + System.out.println("Unknown message type!"); + throw new IllegalArgumentException(); + } + + return loadMessage; + + } catch (Exception e) { + System.out.println("Error to encode message type : " + msgType + "!"); + e.printStackTrace(); + } + + return null; + } + +} diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSProcessManager.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSProcessManager.java new file mode 100644 index 00000000..af40d6f2 --- /dev/null +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSProcessManager.java @@ -0,0 +1,155 @@ +package com.jd.blockchain.statetransfer.process; + +import com.jd.blockchain.statetransfer.DataSequenceElement; +import com.jd.blockchain.statetransfer.DataSequenceInfo; +import com.jd.blockchain.statetransfer.callback.DataSequenceReader; +import com.jd.blockchain.statetransfer.callback.DataSequenceWriter; +import com.jd.blockchain.statetransfer.message.DSDefaultMessageExecutor; +import com.jd.blockchain.statetransfer.result.DSInfoResponseResult; +import com.jd.blockchain.stp.communication.RemoteSession; +import com.jd.blockchain.stp.communication.callback.CallBackBarrier; +import com.jd.blockchain.stp.communication.callback.CallBackDataListener; +import com.jd.blockchain.stp.communication.manager.RemoteSessionManager; +import com.jd.blockchain.stp.communication.node.LocalNode; +import com.jd.blockchain.utils.concurrent.CompletableAsyncFuture; + +import java.net.InetSocketAddress; +import java.util.LinkedList; +import java.util.Map; +import java.util.concurrent.*; + +/** + * + * @author zhangshuang + * @create 2019/4/11 + * @since 1.0.0 + */ +public class DSProcessManager { + + private static Map dSProcessMap = new ConcurrentHashMap<>(); + private RemoteSession[] remoteSessions; + private long dsInfoResponseTimeout = 2000; + private ExecutorService writeExecutors = Executors.newFixedThreadPool(5); + private int returnCode = 0; + /** + * + * + */ + public int startDSProcess(DataSequenceInfo dsInfo, InetSocketAddress listener, InetSocketAddress[] targets, DataSequenceWriter dsWriter, DataSequenceReader dsReader) { + + // create remote sessions manager, add listener + + LocalNode listenNode = new LocalNode(listener.getHostName(), listener.getPort(), new DSDefaultMessageExecutor(dsReader, dsWriter)); + + RemoteSessionManager remoteSessionManager = new RemoteSessionManager(listenNode); + + // data sequence transfer process life cycle start + DSTransferProcess dsTransferProcess = new DSTransferProcess(dsInfo, targets); + dsTransferProcess.setDSReader(dsReader); + dsTransferProcess.setDSWriter(dsWriter); + dsTransferProcess.setRemoteSessionManager(remoteSessionManager); + + dSProcessMap.put(dsInfo.getId(), dsTransferProcess); + + try { + // start network connections with targets + dsTransferProcess.start(); + + //get all target sessions + remoteSessions = dsTransferProcess.getSessions(); + + // async message send process + CallBackBarrier callBackBarrier = CallBackBarrier.newCallBackBarrier(remoteSessions.length, dsInfoResponseTimeout); + + // response message manage map + Map dsInfoResponses = new ConcurrentHashMap<>(); + + // step1: send get dsInfo request, then hold + for (RemoteSession remoteSession : remoteSessions) { + + CallBackDataListener dsInfoResponse = dsTransferProcess.send(DSTransferProcess.DataSequenceMsgType.CMD_DSINFO_REQUEST, remoteSession, 0, 0, callBackBarrier); + + dsInfoResponses.put(remoteSession, dsInfoResponse); + } + + // step2: collect get dsInfo response + Map receiveResponses = new ConcurrentHashMap<>(); + if (callBackBarrier.tryCall()) { + for (RemoteSession remoteSession : dsInfoResponses.keySet()) { + CallBackDataListener asyncFuture = dsInfoResponses.get(remoteSession); + // if really done + if (asyncFuture.isDone()) { + receiveResponses.put(remoteSession, asyncFuture.getCallBackData()); + } + } + } + + // step3: process received responses + DSInfoResponseResult diffResult = dsTransferProcess.computeDiffInfo(receiveResponses); + + // height diff + long diff = dsInfo.getHeight() - diffResult.getMaxHeight(); + + if (diff == 0 || diff > 0) { + // no duplication is required, life cycle ends + dsTransferProcess.close(); + dSProcessMap.remove(dsInfo.getId()); + return returnCode; + + } + else { + + // step4: async send get data sequence diff request + // single step get diff + // async message send process + CallBackBarrier callBackBarrierDiff = CallBackBarrier.newCallBackBarrier((int)(diffResult.getMaxHeight() - dsInfo.getHeight()), dsInfoResponseTimeout); + LinkedList dsDiffResponses = new LinkedList<>(); + + // step5: collect get data sequence diff response + for (long height = dsInfo.getHeight() + 1; height < diffResult.getMaxHeight() + 1; height++) { + CallBackDataListener dsDiffResponse = dsTransferProcess.send(DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_REQUEST, diffResult.getMaxHeightSession(), height, height, callBackBarrierDiff); + dsDiffResponses.addLast(dsDiffResponse); + } + + // 考虑性能 +// writeExecutors.execute(() -> { +// +// }); + + LinkedList receiveDiffResponses = new LinkedList<>(); + if (callBackBarrierDiff.tryCall()) { + for (int i = 0; i < dsDiffResponses.size(); i++) { + CallBackDataListener asyncFutureDiff = dsDiffResponses.get(i); + if (asyncFutureDiff.isDone()) { + receiveDiffResponses.addLast(asyncFutureDiff.getCallBackData()); + } + } + } + // step6: process data sequence diff response, update local data sequence state + DataSequenceElement[] dataSequenceElements = dsTransferProcess.computeDiffElement(receiveDiffResponses.toArray(new byte[receiveDiffResponses.size()][])); + returnCode = dsWriter.updateDSInfo(dsInfo.getId(), dataSequenceElements); + + // data sequence transfer complete, close all sessions, end process life cycle + + dsTransferProcess.close(); + dSProcessMap.remove(dsInfo.getId()); + } + + + } catch (Exception e) { + e.printStackTrace(); + } + return returnCode; + } + + + /** + * + * + */ + void setDSReader(DataSequenceReader reader) { + + } + + +} diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSTransferProcess.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSTransferProcess.java new file mode 100644 index 00000000..90003712 --- /dev/null +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSTransferProcess.java @@ -0,0 +1,192 @@ +package com.jd.blockchain.statetransfer.process; + +import com.jd.blockchain.statetransfer.DataSequenceElement; +import com.jd.blockchain.statetransfer.DataSequenceInfo; +import com.jd.blockchain.statetransfer.callback.DataSequenceReader; +import com.jd.blockchain.statetransfer.callback.DataSequenceWriter; +import com.jd.blockchain.statetransfer.message.DSMsgResolverFactory; +import com.jd.blockchain.statetransfer.message.DataSequenceLoadMessage; +import com.jd.blockchain.statetransfer.result.DSInfoResponseResult; +import com.jd.blockchain.stp.communication.RemoteSession; +import com.jd.blockchain.stp.communication.callback.CallBackBarrier; +import com.jd.blockchain.stp.communication.callback.CallBackDataListener; +import com.jd.blockchain.stp.communication.manager.RemoteSessionManager; +import com.jd.blockchain.stp.communication.node.RemoteNode; +import com.jd.blockchain.utils.IllegalDataException; + +import java.net.InetSocketAddress; +import java.util.Map; + +/** + * + * @author zhangshuang + * @create 2019/4/11 + * @since 1.0.0 + */ +public class DSTransferProcess { + + private InetSocketAddress[] targets; + private DataSequenceWriter dsWriter; + private DataSequenceReader dsReader; + private DataSequenceInfo dsInfo; + private RemoteSessionManager remoteSessionManager; + private RemoteSession[] remoteSessions; + private String id; + + /** + * + * + */ + public DSTransferProcess(DataSequenceInfo dsInfo, InetSocketAddress[] targets) { + this.dsInfo = dsInfo; + this.targets = targets; + this.id = dsInfo.getId(); + } + + public void setDSWriter(DataSequenceWriter dsWriter) { + this.dsWriter = dsWriter; + } + + public void setDSReader(DataSequenceReader dsReader) { + this.dsReader = dsReader; + } + + public void setRemoteSessionManager(RemoteSessionManager remoteSessionManager) { + this.remoteSessionManager = remoteSessionManager; + } + + + /** + * get unique id from data sequence transfer process + * + */ + public String getId() { + return id; + } + + /** + * + * + */ + CallBackDataListener send(DataSequenceMsgType msgType, RemoteSession remoteSession, long fromHeight, long toHeight, CallBackBarrier callBackBarrier) { + + byte[] loadMessage = DSMsgResolverFactory.getEncoder(dsWriter, dsReader).encode(msgType, id, fromHeight, toHeight); + + return remoteSession.asyncRequest(new DataSequenceLoadMessage(loadMessage), callBackBarrier); + } + /** + * + * + */ + public DataSequenceElement[] computeDiffElement(byte[][] diffArray) { + DataSequenceElement[] dataSequenceElements = new DataSequenceElement[diffArray.length]; + for (int i = 0 ; i < dataSequenceElements.length; i++) { + Object object = DSMsgResolverFactory.getDecoder(dsWriter, dsReader).decode(diffArray[i]); + if (object instanceof DataSequenceElement) { + dataSequenceElements[i] = (DataSequenceElement) object; + } + else { + throw new IllegalDataException("Unknown instance object!"); + } + } + + return dataSequenceElements; + } + + /** + * + * + */ + public DSInfoResponseResult computeDiffInfo(Map responseMap) { + long maxHeight = 0; + RemoteSession maxHeightSession = null; + + for (RemoteSession remoteSession : responseMap.keySet()) { + Object object = DSMsgResolverFactory.getDecoder(dsWriter, dsReader).decode(responseMap.get(remoteSession)); + if (object instanceof DataSequenceInfo) { + DataSequenceInfo dsInfo = (DataSequenceInfo) object; + long height = dsInfo.getHeight(); + if (maxHeight < height) { + maxHeight = height; + maxHeightSession = remoteSession; + } + } + else { + throw new IllegalDataException("Unknown instance object!"); + } + + } + + return new DSInfoResponseResult(maxHeight, maxHeightSession); + } + + /** + * + * + */ + public void getDSInfo(String id) { + + } + + /** + * + * + */ + public RemoteSession[] getSessions() { + return remoteSessions; + } + + /** + * close all sessions + * + */ + public void close() { + for (RemoteSession session : remoteSessions) { + session.closeAll(); + } + } + + /** + * establish connections with target remote nodes + * + */ + public void start() { + + RemoteNode[] remoteNodes = new RemoteNode[targets.length]; + + for (int i = 0; i < remoteNodes.length; i++) { + remoteNodes[i] = new RemoteNode(targets[i].getHostName(), targets[i].getPort()); + } + + remoteSessions = remoteSessionManager.newSessions(remoteNodes); + } + + + /** + * data sequence transfer message type + * + */ + public enum DataSequenceMsgType { + CMD_DSINFO_REQUEST((byte) 0x1), + CMD_DSINFO_RESPONSE((byte) 0x2), + CMD_GETDSDIFF_REQUEST((byte) 0x3), + CMD_GETDSDIFF_RESPONSE((byte) 0x4), + ; + public final byte CODE; + + private DataSequenceMsgType(byte code) { + this.CODE = code; + } + + public static DataSequenceMsgType valueOf(byte code) { + for (DataSequenceMsgType msgType : DataSequenceMsgType.values()) { + if (msgType.CODE == code) { + return msgType; + } + } + throw new IllegalArgumentException("Unsupported code[" + code + "] of msgType!"); + } + } + + +} diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/result/DSDiffRequestResult.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/result/DSDiffRequestResult.java new file mode 100644 index 00000000..f71ebbfb --- /dev/null +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/result/DSDiffRequestResult.java @@ -0,0 +1,39 @@ +package com.jd.blockchain.statetransfer.result; + +public class DSDiffRequestResult { + + String id; + long fromHeight; + long toHeight; + + public DSDiffRequestResult(String id ,long fromHeight, long toHeight) { + this.id = id; + this.fromHeight = fromHeight; + this.toHeight = toHeight; + } + + public String getId() { + return id; + } + + public long getFromHeight() { + return fromHeight; + } + + public long getToHeight() { + return toHeight; + } + + public void setId(String id) { + this.id = id; + } + + public void setFromHeight(long fromHeight) { + this.fromHeight = fromHeight; + } + + public void setToHeight(long toHeight) { + this.toHeight = toHeight; + } + +} diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/result/DSInfoResponseResult.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/result/DSInfoResponseResult.java new file mode 100644 index 00000000..d0a57b26 --- /dev/null +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/result/DSInfoResponseResult.java @@ -0,0 +1,37 @@ +package com.jd.blockchain.statetransfer.result; + +import com.jd.blockchain.stp.communication.RemoteSession; + +/** + * + * + * + * + */ +public class DSInfoResponseResult { + + long maxHeight; + RemoteSession maxHeightSession; + + public DSInfoResponseResult(long maxHeight, RemoteSession maxHeightSession) { + this.maxHeight = maxHeight; + this.maxHeightSession = maxHeightSession; + } + + public long getMaxHeight() { + return maxHeight; + } + + public RemoteSession getMaxHeightSession() { + return maxHeightSession; + } + + public void setMaxHeight(long maxHeight) { + this.maxHeight = maxHeight; + } + + public void setMaxHeightSession(RemoteSession maxHeightSession) { + this.maxHeightSession = maxHeightSession; + } + +} From 0b3b7f8109f4634efd3f517039d90cefdaa1362f Mon Sep 17 00:00:00 2001 From: zhangshuang Date: Mon, 22 Apr 2019 09:21:18 +0800 Subject: [PATCH 09/43] add state transfer layer code --- .../blockchain/ledger/TransactionState.java | 5 + .../statetransfer/DataSequenceReaderImpl.java | 80 +++++++++- .../statetransfer/DataSequenceWriterImpl.java | 148 +++++++++++++++++- .../callback/DataSequenceWriter.java | 5 +- .../comparator/DataSequenceComparator.java | 24 +++ .../exception/DataSequenceException.java | 15 ++ .../process/DSProcessManager.java | 2 +- 7 files changed, 269 insertions(+), 10 deletions(-) create mode 100644 source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/comparator/DataSequenceComparator.java create mode 100644 source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/exception/DataSequenceException.java diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionState.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionState.java index d19bcff2..f78df593 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionState.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionState.java @@ -29,6 +29,11 @@ public enum TransactionState { */ LEDGER_ERROR((byte) 2), + /** + * 数据序列更新错误; + */ + DATA_SEQUENCE_UPDATE_ERROR((byte) 3), + /** * 系统错误; */ diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceReaderImpl.java b/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceReaderImpl.java index cd2677ac..f41bfe9e 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceReaderImpl.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceReaderImpl.java @@ -1,8 +1,19 @@ package com.jd.blockchain.peer.statetransfer; +import com.jd.blockchain.crypto.hash.HashDigest; +import com.jd.blockchain.ledger.LedgerBlock; +import com.jd.blockchain.ledger.core.LedgerManage; +import com.jd.blockchain.ledger.core.LedgerRepository; +import com.jd.blockchain.ledger.core.TransactionSet; import com.jd.blockchain.statetransfer.DataSequenceElement; import com.jd.blockchain.statetransfer.DataSequenceInfo; -import com.jd.blockchain.statetransfer.DataSequenceReader; +import com.jd.blockchain.statetransfer.callback.DataSequenceReader; +import com.jd.blockchain.storage.service.DbConnection; +import com.jd.blockchain.storage.service.DbConnectionFactory; +import com.jd.blockchain.tools.initializer.LedgerBindingConfig; +import com.jd.blockchain.utils.codec.Base58Utils; +import com.jd.blockchain.utils.codec.HexUtils; +import org.springframework.beans.factory.annotation.Autowired; /** *数据序列差异的提供者需要使用的回调接口实现类 @@ -13,13 +24,74 @@ import com.jd.blockchain.statetransfer.DataSequenceReader; */ public class DataSequenceReaderImpl implements DataSequenceReader { + private LedgerManage ledgerManager; + + private DbConnectionFactory connFactory; + + private LedgerBindingConfig config; + + public DataSequenceReaderImpl(LedgerBindingConfig config, LedgerManage ledgerManager, DbConnectionFactory connFactory) { + this.config = config; + this.ledgerManager = ledgerManager; + this.connFactory = connFactory; + } + + + /** + * + * + */ @Override public DataSequenceInfo getDSInfo(String id) { - return null; + + byte[] hashBytes = Base58Utils.decode(id); + + HashDigest ledgerHash = new HashDigest(hashBytes); + + LedgerBindingConfig.BindingConfig bindingConfig = config.getLedger(ledgerHash); + DbConnection dbConnNew = connFactory.connect(bindingConfig.getDbConnection().getUri(), + bindingConfig.getDbConnection().getPassword()); + LedgerRepository ledgerRepository = ledgerManager.register(ledgerHash, dbConnNew.getStorageService()); + + return new DataSequenceInfo(id, ledgerRepository.getLatestBlockHeight()); } + /** + * + * + */ @Override - public DataSequenceElement[] getDSContent(String id, long from, long to) { - return null; + public DataSequenceElement[] getDSDiffContent(String id, long from, long to) { + + DataSequenceElement[] dataSequenceElements = new DataSequenceElement[(int)(to - from + 1)]; + for (long i = from; i < to + 1; i++) { + dataSequenceElements[(int)(i - from)] = getDSDiffContent(id, i); + } + + return dataSequenceElements; + } + + /** + * + * + */ + @Override + public DataSequenceElement getDSDiffContent(String id, long height) { + + byte[] hashBytes = Base58Utils.decode(id); + + HashDigest ledgerHash = new HashDigest(hashBytes); + + LedgerBindingConfig.BindingConfig bindingConfig = config.getLedger(ledgerHash); + DbConnection dbConnNew = connFactory.connect(bindingConfig.getDbConnection().getUri(), + bindingConfig.getDbConnection().getPassword()); + LedgerRepository ledgerRepository = ledgerManager.register(ledgerHash, dbConnNew.getStorageService()); + + LedgerBlock ledgerBlock = ledgerRepository.getBlock(height); + TransactionSet transactionSet = ledgerRepository.getTransactionSet(ledgerBlock); + //todo + + + return null; } } diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceWriterImpl.java b/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceWriterImpl.java index e2c48601..589c7d88 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceWriterImpl.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceWriterImpl.java @@ -1,9 +1,14 @@ package com.jd.blockchain.peer.statetransfer; +import com.jd.blockchain.consensus.service.MessageHandle; +import com.jd.blockchain.ledger.TransactionState; import com.jd.blockchain.statetransfer.DataSequenceElement; import com.jd.blockchain.statetransfer.DataSequenceInfo; -import com.jd.blockchain.statetransfer.DataSequenceReader; -import com.jd.blockchain.statetransfer.DataSequenceWriter; +import com.jd.blockchain.statetransfer.callback.DataSequenceWriter; +import com.jd.blockchain.statetransfer.comparator.DataSequenceComparator; + +import java.util.ArrayList; +import java.util.Collections; /** *数据序列差异的请求者需要使用的回调接口实现类 @@ -14,9 +19,146 @@ import com.jd.blockchain.statetransfer.DataSequenceWriter; */ public class DataSequenceWriterImpl implements DataSequenceWriter { + private long currHeight; + private ArrayList deceidedElements = new ArrayList(); + + private MessageHandle batchMessageHandle; + + + public DataSequenceWriterImpl(MessageHandle batchMessageHandle) { + this.batchMessageHandle = batchMessageHandle; + } + + /** + * check height to data sequence diff elements + * + */ + private int checkElementsHeight(long currHeight, ArrayList dsUpdateElements) { + boolean lossMiddleElements = false; + + // lose first element + if (currHeight + 1 < dsUpdateElements.get(0).getHeight()){ + System.out.println("Diff response loss first element error!"); + return DataSequenceErrorType.DATA_SEQUENCE_LOSS_FIRST_ELEMENT.CODE; + } + else { + for (int i = 0; i < dsUpdateElements.size(); i++) { + if (dsUpdateElements.get(i).getHeight() == currHeight + 1 + i) { + deceidedElements.add(dsUpdateElements.get(i)); + } + // lose middle elements + else { + lossMiddleElements = true; + break; + } + } + + if (lossMiddleElements) { + System.out.println("Diff response loss middle elements error!"); + return DataSequenceErrorType.DATA_SEQUENCE_LOSS_MIDDLE_ELEMENT.CODE; + } + + System.out.println("Diff response elements height normal!"); + return DataSequenceErrorType.DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL.CODE; + } + + } + + /** + * + * + */ + private void exeUpdate(String realmName) { + for (int i = 0; i < deceidedElements.size(); i++) { + byte[][] element = deceidedElements.get(i).getData(); + + String batchId = batchMessageHandle.beginBatch(realmName); + try { + int msgId = 0; + for (byte[] txContent : element) { + batchMessageHandle.processOrdered(msgId++, txContent, realmName, batchId); + } + batchMessageHandle.completeBatch(realmName, batchId); + batchMessageHandle.commitBatch(realmName, batchId); + } catch (Exception e) { + // todo 需要处理应答码 404 + batchMessageHandle.rollbackBatch(realmName, batchId, TransactionState.DATA_SEQUENCE_UPDATE_ERROR.CODE); + } + } + + } + /** + * + * + */ @Override - public void updateDSInfo(String id, DataSequenceElement[] diffContents) { + public int updateDSInfo(DataSequenceInfo id, DataSequenceElement[] diffContents) { + int result = 0; + try { + ArrayList dsUpdateElements = new ArrayList(); + //remove unexpected elements + for (int i = 0 ; i < diffContents.length; i++) { + if (diffContents[i].getId().equals(id.getId())) { + dsUpdateElements.add(diffContents[i]); + } + } + + // sort elements by height + Collections.sort(dsUpdateElements, new DataSequenceComparator()); + + currHeight = id.getHeight(); + + // check element's height + result = checkElementsHeight(currHeight, dsUpdateElements); + + // cann't exe update + if (result == DataSequenceErrorType.DATA_SEQUENCE_LOSS_FIRST_ELEMENT.CODE) { + return result; + } + // exe elements update + else { + exeUpdate(id.getId()); + return result; + } + } catch (Exception e) { + System.out.println(e.getMessage()); + e.printStackTrace(); + } + + return result; + } + + @Override + public int updateDSInfo(DataSequenceInfo id, DataSequenceElement diffContents) { + return 0; } + + + /** + * data sequence transfer error type + * + */ + public enum DataSequenceErrorType { + DATA_SEQUENCE_LOSS_FIRST_ELEMENT((byte) 0x1), + DATA_SEQUENCE_LOSS_MIDDLE_ELEMENT((byte) 0x2), + DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL((byte) 0x3), + ; + public final int CODE; + + private DataSequenceErrorType(byte code) { + this.CODE = code; + } + + public static DataSequenceErrorType valueOf(byte code) { + for (DataSequenceErrorType errorType : DataSequenceErrorType.values()) { + if (errorType.CODE == code) { + return errorType; + } + } + throw new IllegalArgumentException("Unsupported code[" + code + "] of errorType!"); + } + } + } diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriter.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriter.java index 3e7d060f..ee9a959b 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriter.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriter.java @@ -1,6 +1,7 @@ package com.jd.blockchain.statetransfer.callback; import com.jd.blockchain.statetransfer.DataSequenceElement; +import com.jd.blockchain.statetransfer.DataSequenceInfo; /** *数据序列差异的请求者获得差异内容后需要回调该接口,通过接口提供的方法对指定数据序列执行差异内容的重放,并更新数据序列的当前状态; @@ -14,12 +15,12 @@ public interface DataSequenceWriter { *更新数据序列的当前状态,一次更新多个高度的差异 * return void */ - int updateDSInfo(String id, DataSequenceElement[] diffContents); + int updateDSInfo(DataSequenceInfo id, DataSequenceElement[] diffContents); /** *更新数据序列的当前状态,一次更新一个高度的差异 * return void */ - int updateDSInfo(String id, DataSequenceElement diffContents); + int updateDSInfo(DataSequenceInfo id, DataSequenceElement diffContents); } diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/comparator/DataSequenceComparator.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/comparator/DataSequenceComparator.java new file mode 100644 index 00000000..53ad5a15 --- /dev/null +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/comparator/DataSequenceComparator.java @@ -0,0 +1,24 @@ +package com.jd.blockchain.statetransfer.comparator; + +import com.jd.blockchain.statetransfer.DataSequenceElement; + +import java.util.Comparator; + +/** + * + * + */ +public class DataSequenceComparator implements Comparator { + + // sort by data sequence height + @Override + public int compare(DataSequenceElement o1, DataSequenceElement o2) { + long height1; + long height2; + + height1 = o1.getHeight(); + height2 = o2.getHeight(); + + return (int) (height1 - height2); + } +} diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/exception/DataSequenceException.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/exception/DataSequenceException.java new file mode 100644 index 00000000..95718487 --- /dev/null +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/exception/DataSequenceException.java @@ -0,0 +1,15 @@ +package com.jd.blockchain.statetransfer.exception; + +public class DataSequenceException extends RuntimeException { + + private static final long serialVersionUID = -4090881296855827889L; + + + public DataSequenceException(String message) { + super(message); + } + public DataSequenceException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSProcessManager.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSProcessManager.java index af40d6f2..fecfa5c3 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSProcessManager.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSProcessManager.java @@ -127,7 +127,7 @@ public class DSProcessManager { } // step6: process data sequence diff response, update local data sequence state DataSequenceElement[] dataSequenceElements = dsTransferProcess.computeDiffElement(receiveDiffResponses.toArray(new byte[receiveDiffResponses.size()][])); - returnCode = dsWriter.updateDSInfo(dsInfo.getId(), dataSequenceElements); + returnCode = dsWriter.updateDSInfo(dsInfo, dataSequenceElements); // data sequence transfer complete, close all sessions, end process life cycle From efedca1a08ff2b10262b973554661937ae104765 Mon Sep 17 00:00:00 2001 From: zhangshuang Date: Tue, 23 Apr 2019 09:31:01 +0800 Subject: [PATCH 10/43] add test examples for state transfer layer --- .../statetransfer/DataSequenceReaderImpl.java | 50 +++++- .../statetransfer/DataSequenceWriterImpl.java | 33 ++-- .../callback/DataSequenceWriter.java | 4 +- .../statetransfer/DataSequence.java | 70 ++++++++ .../statetransfer/DataSequenceReaderImpl.java | 60 +++++++ .../statetransfer/DataSequenceWriterImpl.java | 58 +++++++ .../statetransfer/StateTransferLayerTest.java | 155 ++++++++++++++++++ 7 files changed, 408 insertions(+), 22 deletions(-) create mode 100644 source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequence.java create mode 100644 source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceReaderImpl.java create mode 100644 source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceWriterImpl.java create mode 100644 source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/StateTransferLayerTest.java diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceReaderImpl.java b/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceReaderImpl.java index f41bfe9e..eeb1819e 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceReaderImpl.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceReaderImpl.java @@ -1,7 +1,9 @@ package com.jd.blockchain.peer.statetransfer; +import com.jd.blockchain.binaryproto.BinaryEncodingUtils; import com.jd.blockchain.crypto.hash.HashDigest; import com.jd.blockchain.ledger.LedgerBlock; +import com.jd.blockchain.ledger.LedgerTransaction; import com.jd.blockchain.ledger.core.LedgerManage; import com.jd.blockchain.ledger.core.LedgerRepository; import com.jd.blockchain.ledger.core.TransactionSet; @@ -38,8 +40,8 @@ public class DataSequenceReaderImpl implements DataSequenceReader { /** - * - * + * @param id 账本哈希的Base58编码 + * @return DataSequenceInfo 数据序列信息 */ @Override public DataSequenceInfo getDSInfo(String id) { @@ -58,7 +60,10 @@ public class DataSequenceReaderImpl implements DataSequenceReader { /** * - * + * @param id 账本哈希的Base58编码 + * @param from 数据序列复制的起始高度 + * @param to 数据序列复制的结束高度 + * @return DataSequenceElement【】数据序列差异数据元素的数组 */ @Override public DataSequenceElement[] getDSDiffContent(String id, long from, long to) { @@ -72,12 +77,27 @@ public class DataSequenceReaderImpl implements DataSequenceReader { } /** - * - * + * 账本交易序列化 + * @param transaction 账本交易 + * @return byte[] 对账本交易进行序列化的结果 + */ + private byte[] serialize(LedgerTransaction transaction) { + return BinaryEncodingUtils.encode(transaction, LedgerTransaction.class); + } + + /** + * 获得账本某一高度区块上的所有交易 + * @param id 账本哈希的Base58编码 + * @param height 账本的某个区块高度 + * @return DataSequenceElement 数据序列差异数据元素 */ @Override public DataSequenceElement getDSDiffContent(String id, long height) { + int lastHeightTxTotalNums = 0; + + byte[][] transacionDatas = null; + byte[] hashBytes = Base58Utils.decode(id); HashDigest ledgerHash = new HashDigest(hashBytes); @@ -89,9 +109,25 @@ public class DataSequenceReaderImpl implements DataSequenceReader { LedgerBlock ledgerBlock = ledgerRepository.getBlock(height); TransactionSet transactionSet = ledgerRepository.getTransactionSet(ledgerBlock); - //todo + if (height > 0) { + lastHeightTxTotalNums = (int) ledgerRepository.getTransactionSet(ledgerRepository.getBlock(height - 1)).getTotalCount(); + } + + int currentHeightTxTotalNums = (int)ledgerRepository.getTransactionSet(ledgerRepository.getBlock(height)).getTotalCount(); + + // get all transactions from current height block + int currentHeightTxNums = currentHeightTxTotalNums - lastHeightTxTotalNums; + + LedgerTransaction[] transactions = transactionSet.getTxs(lastHeightTxTotalNums , currentHeightTxNums); - return null; + for (int i = 0; i < transactions.length; i++) { + byte[] transactionData = serialize(transactions[i]); + transacionDatas[i] = transactionData; + } + + return new DataSequenceElement(id, height, transacionDatas); } + + } diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceWriterImpl.java b/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceWriterImpl.java index 589c7d88..56a67358 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceWriterImpl.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceWriterImpl.java @@ -30,8 +30,10 @@ public class DataSequenceWriterImpl implements DataSequenceWriter { } /** - * check height to data sequence diff elements - * + * 检查数据序列差异元素中的高度是否合理; + * @param currHeight 当前结点的账本高度 + * @param dsUpdateElements 需要更新到本地结点的数据序列元素List + * @return */ private int checkElementsHeight(long currHeight, ArrayList dsUpdateElements) { boolean lossMiddleElements = false; @@ -65,10 +67,12 @@ public class DataSequenceWriterImpl implements DataSequenceWriter { } /** - * - * + * 对本地结点执行账本更新 + * @param realmName 账本哈希的Base58编码 + * @return void */ private void exeUpdate(String realmName) { + for (int i = 0; i < deceidedElements.size(); i++) { byte[][] element = deceidedElements.get(i).getData(); @@ -78,6 +82,7 @@ public class DataSequenceWriterImpl implements DataSequenceWriter { for (byte[] txContent : element) { batchMessageHandle.processOrdered(msgId++, txContent, realmName, batchId); } + // 结块 batchMessageHandle.completeBatch(realmName, batchId); batchMessageHandle.commitBatch(realmName, batchId); } catch (Exception e) { @@ -89,18 +94,19 @@ public class DataSequenceWriterImpl implements DataSequenceWriter { } /** - * - * + * @param dsInfo 当前结点的数据序列信息 + * @param diffContents 数据序列差异的数据元素数组 + * @return int 更新结果码 */ @Override - public int updateDSInfo(DataSequenceInfo id, DataSequenceElement[] diffContents) { + public int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement[] diffContents) { int result = 0; try { ArrayList dsUpdateElements = new ArrayList(); //remove unexpected elements for (int i = 0 ; i < diffContents.length; i++) { - if (diffContents[i].getId().equals(id.getId())) { + if (diffContents[i].getId().equals(dsInfo.getId())) { dsUpdateElements.add(diffContents[i]); } } @@ -108,7 +114,7 @@ public class DataSequenceWriterImpl implements DataSequenceWriter { // sort elements by height Collections.sort(dsUpdateElements, new DataSequenceComparator()); - currHeight = id.getHeight(); + currHeight = dsInfo.getHeight(); // check element's height result = checkElementsHeight(currHeight, dsUpdateElements); @@ -119,7 +125,7 @@ public class DataSequenceWriterImpl implements DataSequenceWriter { } // exe elements update else { - exeUpdate(id.getId()); + exeUpdate(dsInfo.getId()); return result; } } catch (Exception e) { @@ -131,14 +137,15 @@ public class DataSequenceWriterImpl implements DataSequenceWriter { } @Override - public int updateDSInfo(DataSequenceInfo id, DataSequenceElement diffContents) { + public int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement diffContents) { return 0; } /** - * data sequence transfer error type - * + * 数据序列更新错误码 + * @param + * @return */ public enum DataSequenceErrorType { DATA_SEQUENCE_LOSS_FIRST_ELEMENT((byte) 0x1), diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriter.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriter.java index ee9a959b..73f5d45d 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriter.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriter.java @@ -15,12 +15,12 @@ public interface DataSequenceWriter { *更新数据序列的当前状态,一次更新多个高度的差异 * return void */ - int updateDSInfo(DataSequenceInfo id, DataSequenceElement[] diffContents); + int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement[] diffContents); /** *更新数据序列的当前状态,一次更新一个高度的差异 * return void */ - int updateDSInfo(DataSequenceInfo id, DataSequenceElement diffContents); + int updateDSInfo(DataSequenceInfo id, DataSequenceElement diffContent); } diff --git a/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequence.java b/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequence.java new file mode 100644 index 00000000..4d138d04 --- /dev/null +++ b/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequence.java @@ -0,0 +1,70 @@ +package test.com.jd.blockchain.statetransfer; + +import com.jd.blockchain.statetransfer.DataSequenceElement; +import com.jd.blockchain.statetransfer.DataSequenceInfo; + +import java.net.InetSocketAddress; +import java.util.LinkedList; + +public class DataSequence { + + private InetSocketAddress address; + private String id; + + private static LinkedList dataSequenceElements = new LinkedList<>(); + + + public DataSequence(InetSocketAddress address, String id) { + this.address = address; + this.id = id; + } + + public String getId() { + return id; + } + + public InetSocketAddress getAddress() { + return address; + } + + public void addElements(DataSequenceElement[] elements) { + for (DataSequenceElement element : elements) { + addElement(element); + } + } + + public void addElement(DataSequenceElement element) { + try { + if (dataSequenceElements.size() == 0) { + if (element.getHeight() != 0) { + throw new IllegalArgumentException("Data sequence add element height error!"); + } + dataSequenceElements.addLast(element); + } + else { + if (dataSequenceElements.getLast().getHeight() != element.getHeight() - 1) { + throw new IllegalArgumentException("Data sequence add element height error!"); + } + dataSequenceElements.addLast(element); + } + + } catch (Exception e) { + System.out.println(e.getMessage()); + e.printStackTrace(); + } + } + + public LinkedList getDataSequenceElements() { + return dataSequenceElements; + } + + public DataSequenceInfo getDSInfo() { + if (dataSequenceElements.size() == 0) { + return new DataSequenceInfo(id, -1); + } + else { + return new DataSequenceInfo(id, dataSequenceElements.getLast().getHeight()); + } + } + +} diff --git a/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceReaderImpl.java b/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceReaderImpl.java new file mode 100644 index 00000000..cbb97172 --- /dev/null +++ b/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceReaderImpl.java @@ -0,0 +1,60 @@ +package test.com.jd.blockchain.statetransfer; + +import com.jd.blockchain.statetransfer.DataSequenceElement; +import com.jd.blockchain.statetransfer.DataSequenceInfo; +import com.jd.blockchain.statetransfer.callback.DataSequenceReader; + +import java.net.InetSocketAddress; +import java.util.LinkedList; + +/** + *数据序列差异的提供者需要使用的回调接口实现类 + * @author zhangshuang + * @create 2019/4/22 + * @since 1.0.0 + * + */ + +public class DataSequenceReaderImpl implements DataSequenceReader { + + DataSequence currDataSequence; + + public DataSequenceReaderImpl(DataSequence currDataSequence) { + this.currDataSequence = currDataSequence; + } + + @Override + public DataSequenceInfo getDSInfo(String id) { + return currDataSequence.getDSInfo(); + } + + @Override + public DataSequenceElement[] getDSDiffContent(String id, long from, long to) { + DataSequenceElement[] elements = new DataSequenceElement[(int)(to - from + 1)]; + + int i = 0; + LinkedList dataSequenceElements = currDataSequence.getDataSequenceElements(); + for (DataSequenceElement element : dataSequenceElements) { + if (element.getHeight() < from || element.getHeight() > to) { + continue; + } + else { + elements[i++] = element; + } + } + + return elements; + + } + + @Override + public DataSequenceElement getDSDiffContent(String id, long height) { + for(DataSequenceElement dataSequenceElement : currDataSequence.getDataSequenceElements()) { + if (dataSequenceElement.getHeight() == height) { + return dataSequenceElement; + + } + } + return null; + } +} diff --git a/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceWriterImpl.java b/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceWriterImpl.java new file mode 100644 index 00000000..59ce5bbc --- /dev/null +++ b/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceWriterImpl.java @@ -0,0 +1,58 @@ +package test.com.jd.blockchain.statetransfer; + +import com.jd.blockchain.statetransfer.DataSequenceElement; +import com.jd.blockchain.statetransfer.DataSequenceInfo; +import com.jd.blockchain.statetransfer.callback.DataSequenceWriter; + +/** + *数据序列差异的请求者需要使用的回调接口实现类 + * @author zhangshuang + * @create 2019/4/22 + * @since 1.0.0 + * + */ +public class DataSequenceWriterImpl implements DataSequenceWriter { + + DataSequence currDataSequence; + + public DataSequenceWriterImpl(DataSequence currDataSequence) { + this.currDataSequence = currDataSequence; + } + + @Override + public int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement[] diffContents) { + + currDataSequence.addElements(diffContents); + + return DataSequenceErrorType.DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL.CODE; + + } + + @Override + public int updateDSInfo(DataSequenceInfo id, DataSequenceElement diffContent) { + currDataSequence.addElement(diffContent); + return DataSequenceErrorType.DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL.CODE; + } + + public enum DataSequenceErrorType { + DATA_SEQUENCE_LOSS_FIRST_ELEMENT((byte) 0x1), + DATA_SEQUENCE_LOSS_MIDDLE_ELEMENT((byte) 0x2), + DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL((byte) 0x3), + ; + public final int CODE; + + private DataSequenceErrorType(byte code) { + this.CODE = code; + } + + public static DataSequenceErrorType valueOf(byte code) { + for (DataSequenceErrorType errorType : DataSequenceErrorType.values()) { + if (errorType.CODE == code) { + return errorType; + } + } + throw new IllegalArgumentException("Unsupported code[" + code + "] of errorType!"); + } + } + +} diff --git a/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/StateTransferLayerTest.java b/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/StateTransferLayerTest.java new file mode 100644 index 00000000..efcaa060 --- /dev/null +++ b/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/StateTransferLayerTest.java @@ -0,0 +1,155 @@ +package test.com.jd.blockchain.statetransfer; + +import com.jd.blockchain.statetransfer.DataSequenceElement; +import com.jd.blockchain.statetransfer.DataSequenceInfo; +import com.jd.blockchain.statetransfer.callback.DataSequenceReader; +import com.jd.blockchain.statetransfer.callback.DataSequenceWriter; +import com.jd.blockchain.statetransfer.process.DSProcessManager; +import com.jd.blockchain.utils.codec.Base58Utils; +import org.junit.Before; +import org.junit.Test; + +import java.net.InetSocketAddress; +import java.util.LinkedList; +import java.util.Random; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class StateTransferLayerTest { + + private final int[] listenPorts = new int[]{9000, 9010, 9020, 9030}; + + private String localIp = "127.0.0.1"; + + private int DataSequenceNum = 1; + + private int nodesNum = 4; + + private byte[] idBytes = new byte[20]; + + private Random rand = new Random(); + + private String[] dataSequenceIds; + + private DSProcessManager dsProcessManager; + + private DataSequenceReader dataSequenceReader; + + private DataSequenceWriter dataSequenceWriter; + + private InetSocketAddress[] remoteNodeIps = new InetSocketAddress[nodesNum]; + + private final ExecutorService threadPool = Executors.newFixedThreadPool(8); + + private static LinkedList dataSequencesPerNode = new LinkedList<>(); + + // 假定每个数据序列元素里有四条记录数据 + private byte[][] dsElementDatas = new byte[4][]; + + + @Before + public void init() { + + // 产生两个唯一的数据序列Id标识 + for (int i = 0; i < DataSequenceNum; i++) { + + dataSequenceIds[i] = new String(); + rand.nextBytes(idBytes); + dataSequenceIds[i] = Base58Utils.encode(idBytes); + } + + // 创建数据序列处理管理者实例 + dsProcessManager = new DSProcessManager(); + + + // 准备好所有的远端结点,包括监听者 + for (int i = 0; i < nodesNum; i++) { + remoteNodeIps[i] = new InetSocketAddress(localIp, listenPorts[i]); + } + + // 为数据序列的每个高度准备好内容,为了方便测试,每个高度的内容设置为一致 + for (int i = 0; i < dsElementDatas.length; i++) { + rand.nextBytes(idBytes); + dsElementDatas[i] = idBytes; + } + + // 为结点准备数据序列 + for (String id : dataSequenceIds) { + for (int i = 0; i < remoteNodeIps.length; i++) { + DataSequence dataSequence = new DataSequence(remoteNodeIps[i], id); + + // 为数据序列的0,1,2高度添加内容 + for (int j = 0; j < 3; i++) { + dataSequence.addElement(new DataSequenceElement(id, i, dsElementDatas)); + } + dataSequencesPerNode.addLast(dataSequence); + } + + // 把其中一个结点的数据序列与其他结点区别开来 + for (int i = 0; i < dataSequencesPerNode.size(); i++) { + DataSequence dataSequence = dataSequencesPerNode.get(i); + if (dataSequence.getAddress().getPort() != listenPorts[0]) { + // 为数据序列的3,4高度添加内容 + for (int j = 3; j < 5; i++) { + dataSequence.addElement(new DataSequenceElement(id, j, dsElementDatas)); + } + } + } + } + } + + // 获得除监听结点之外的其他远端结点 + InetSocketAddress[] getTargetNodesIp(InetSocketAddress listenIp, InetSocketAddress[] remoteNodeIps) { + + InetSocketAddress[] targets = new InetSocketAddress[remoteNodeIps.length - 1]; + int j = 0; + + for (int i = 0; i < remoteNodeIps.length; i++) { + if ((remoteNodeIps[i].getHostName().equals(listenIp.getHostName())) && (remoteNodeIps[i].getPort() == listenIp.getPort())) { + continue; + } + targets[j++] = new InetSocketAddress(remoteNodeIps[i].getHostName(), remoteNodeIps[i].getPort()); + } + + return targets; + + } + + DataSequence findDataSequence(String id, InetSocketAddress listenNodeAddr) { + for (DataSequence dataSequence : dataSequencesPerNode) { + if ((dataSequence.getAddress().getPort() == listenNodeAddr.getPort() && (dataSequence.getAddress().getHostName().equals(listenNodeAddr.getHostName())) + && (dataSequence.getId().equals(id)))) { + return dataSequence; + } + } + return null; + } + + + @Test + public void test() { + + CountDownLatch countDownLatch = new CountDownLatch(nodesNum); + + for (String id : dataSequenceIds) { + for (int i = 0; i < nodesNum; i++) { + InetSocketAddress listenNode = remoteNodeIps[i]; + threadPool.execute(() -> { + DataSequence currDataSequence = findDataSequence(id, listenNode); + DataSequenceInfo dsInfo = currDataSequence.getDSInfo(); + InetSocketAddress[] targets = getTargetNodesIp(listenNode, remoteNodeIps); + dsProcessManager.startDSProcess(dsInfo, listenNode, targets, new DataSequenceWriterImpl(currDataSequence), new DataSequenceReaderImpl(currDataSequence)); + countDownLatch.countDown(); + }); + } + } + + // 等待数据序列更新完成 + try { + countDownLatch.await(); + } catch (Exception e) { + e.printStackTrace(); + } + } +} From e681e8edc8e247d0283255e044deec4108b04359 Mon Sep 17 00:00:00 2001 From: zhangshuang Date: Tue, 23 Apr 2019 16:22:12 +0800 Subject: [PATCH 11/43] modify node communication protocol code --- .../stp/communication/connection/Connection.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Connection.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Connection.java index 1c6d2dc6..4c676ca4 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Connection.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Connection.java @@ -21,6 +21,8 @@ import com.jd.blockchain.stp.communication.node.RemoteNode; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.digest.DigestUtils; +import java.util.Random; + /** * 统一连接对象 * 该对象中有两个对象Receiver和Sender @@ -144,8 +146,15 @@ public class Connection { * @return */ private String loadKey(LoadMessage loadMessage) { + // key每次不能一致,因此增加随机数 + byte[] randomBytes = new byte[8]; + new Random().nextBytes(randomBytes); + byte[] loadBytes = loadMessage.toBytes(); + byte[] keyBytes = new byte[loadBytes.length + randomBytes.length]; + System.arraycopy(randomBytes, 0, keyBytes, 0, randomBytes.length); + System.arraycopy(loadBytes, 0, keyBytes, randomBytes.length, loadBytes.length); // 使用Sha256求Hash - byte[] sha256Bytes = DigestUtils.sha256(loadMessage.toBytes()); + byte[] sha256Bytes = DigestUtils.sha256(keyBytes); // 使用base64作为Key return Base64.encodeBase64String(sha256Bytes); } From c65896df102547baf426f15f84f8d947fe93301b Mon Sep 17 00:00:00 2001 From: shaozhuguang Date: Tue, 23 Apr 2019 18:10:36 +0800 Subject: [PATCH 12/43] =?UTF-8?q?=E4=BF=AE=E6=94=B9STP=E5=BA=95=E5=B1=82?= =?UTF-8?q?=E9=80=9A=E4=BF=A1=E5=A4=84=E7=90=86=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../stp/communication/RemoteSession.java | 70 ++++++++++++++----- .../communication/connection/Connection.java | 8 ++- .../communication/connection/Receiver.java | 2 +- .../stp/communication/connection/Sender.java | 59 +++++++--------- .../connection/handler/ReceiverHandler.java | 34 +++++++-- .../connection/handler/SenderHandler.java | 28 +++++++- .../manager/RemoteSessionManager.java | 56 ++++----------- .../stp/commucation/MyMessageExecutor.java | 4 +- 8 files changed, 156 insertions(+), 105 deletions(-) diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteSession.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteSession.java index f72a071c..0ce9fceb 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteSession.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/RemoteSession.java @@ -12,11 +12,14 @@ import com.jd.blockchain.stp.communication.callback.CallBackBarrier; import com.jd.blockchain.stp.communication.callback.CallBackDataListener; import com.jd.blockchain.stp.communication.connection.Connection; import com.jd.blockchain.stp.communication.message.LoadMessage; +import com.jd.blockchain.stp.communication.node.RemoteNode; +import org.apache.commons.codec.binary.Hex; import java.util.concurrent.TimeUnit; /** + * 远端Session * * @author shaozhuguang * @create 2019/4/11 @@ -26,9 +29,14 @@ import java.util.concurrent.TimeUnit; public class RemoteSession { /** - * 远端节点ID + * 本地节点ID */ - private String id; + private String localId; + + /** + * 远端节点 + */ + private RemoteNode remoteNode; /** * 远端连接 @@ -41,31 +49,31 @@ public class RemoteSession { */ private MessageExecutor messageExecutor; - /** * 构造器 - * @param id - * 远端节点ID + * @param localId + * 本地节点ID * @param connection * 对应连接 */ - public RemoteSession(String id, Connection connection) { - this(id, connection, null); + public RemoteSession(String localId, Connection connection) { + this(localId, connection, null); } /** * 构造器 - * @param id - * 远端ID + * @param localId + * 本地节点ID * @param connection * 对应连接 * @param messageExecutor * 对应远端消息处理器 */ - public RemoteSession(String id, Connection connection, MessageExecutor messageExecutor) { - this.id = id; + public RemoteSession(String localId, Connection connection, MessageExecutor messageExecutor) { + this.localId = localId; this.connection = connection; this.messageExecutor = messageExecutor; + this.remoteNode = connection.remoteNode(); } public void init() { @@ -87,7 +95,7 @@ public class RemoteSession { * @throws Exception */ public byte[] request(LoadMessage loadMessage) throws Exception { - return this.connection.request(this.id, loadMessage, null).getCallBackData(); + return this.connection.request(this.localId, loadMessage, null).getCallBackData(); } /** @@ -105,7 +113,7 @@ public class RemoteSession { * @throws Exception */ public byte[] request(LoadMessage loadMessage, long time, TimeUnit timeUnit) throws Exception { - return this.connection.request(this.id, loadMessage, null).getCallBackData(time, timeUnit); + return this.connection.request(this.localId, loadMessage, null).getCallBackData(time, timeUnit); } /** @@ -133,7 +141,7 @@ public class RemoteSession { * 应答,需要调用者从Listener中获取结果 */ public CallBackDataListener asyncRequest(LoadMessage loadMessage, CallBackBarrier callBackBarrier) { - return this.connection.request(this.id, loadMessage, callBackBarrier); + return this.connection.request(this.localId, loadMessage, callBackBarrier); } /** @@ -145,7 +153,7 @@ public class RemoteSession { * 需要应答的负载消息 */ public void reply(String key, LoadMessage loadMessage) { - this.connection.reply(this.id, key, loadMessage); + this.connection.reply(this.localId, key, loadMessage); } public void closeAll() { @@ -160,11 +168,39 @@ public class RemoteSession { this.connection.closeSender(); } - public String sessionId() { - return id; + /** + * 返回本地节点ID + * + * @return + */ + public String localId() { + return localId; + } + + /** + * 返回远端对应的SessionID + * + * @return + */ + public String remoteSessionId() { + return Hex.encodeHexString(remoteNode.toString().getBytes()); } + /** + * 返回远端对应执行器 + * + * @return + */ public MessageExecutor messageExecutor() { return this.messageExecutor; } + + /** + * 返回对应远端节点 + * + * @return + */ + public RemoteNode remoteNode() { + return remoteNode; + } } \ No newline at end of file diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Connection.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Connection.java index 4c676ca4..5d534686 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Connection.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Connection.java @@ -64,7 +64,7 @@ public class Connection { * @param remoteSession */ public void initSession(RemoteSession remoteSession) { - this.receiver.initRemoteSession(remoteSession.sessionId(), remoteSession); + this.receiver.initRemoteSession(remoteSession.remoteSessionId(), remoteSession); } /** @@ -80,7 +80,7 @@ public class Connection { */ public CallBackLauncher connect(RemoteNode remoteNode, String messageExecutorClass) throws InterruptedException { this.remoteNode = remoteNode; - this.sender = new Sender(this.remoteNode, sessionMessage(messageExecutorClass)); + this.sender = new Sender(this.receiver.localNode(), this.remoteNode, sessionMessage(messageExecutorClass)); this.sender.connect(); return this.sender.waitBooted(); } @@ -206,6 +206,10 @@ public class Connection { closeSender(); } + public RemoteNode remoteNode() { + return remoteNode; + } + public void closeReceiver() { this.receiver.close(); } diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Receiver.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Receiver.java index 50eab985..fdbb0df6 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Receiver.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Receiver.java @@ -125,7 +125,7 @@ public class Receiver extends AbstractAsyncExecutor implements Closeable { * 当前节点的消息处理Class */ public void initReceiverHandler(ConnectionManager connectionManager, String messageExecutorClass) { - receiverHandler = new ReceiverHandler(connectionManager, messageExecutorClass, this.localNode.defaultMessageExecutor()); + receiverHandler = new ReceiverHandler(connectionManager, messageExecutorClass, this.localNode); } /** diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Sender.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Sender.java index dcef4009..7c17f18f 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Sender.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/Sender.java @@ -11,6 +11,7 @@ package com.jd.blockchain.stp.communication.connection; import com.jd.blockchain.stp.communication.connection.handler.*; import com.jd.blockchain.stp.communication.message.IMessage; import com.jd.blockchain.stp.communication.message.SessionMessage; +import com.jd.blockchain.stp.communication.node.LocalNode; import com.jd.blockchain.stp.communication.node.RemoteNode; import io.netty.bootstrap.Bootstrap; import io.netty.channel.*; @@ -47,34 +48,38 @@ public class Sender extends AbstractAsyncExecutor implements Closeable { */ private SessionMessage sessionMessage; - /** - * 远端HOST - */ - private String remoteHost; + private LocalNode localNode; - /** - * 远端端口 - */ - private int remotePort; + private RemoteNode remoteNode; + +// /** +// * 远端HOST +// */ +// private String remoteHost; +// +// /** +// * 远端端口 +// */ +// private int remotePort; /** * 监听Handler(重连Handler) */ private WatchDogHandler watchDogHandler; - public Sender(RemoteNode remoteNode, SessionMessage sessionMessage) { - init(remoteNode, sessionMessage); + public Sender(LocalNode localNode, RemoteNode remoteNode, SessionMessage sessionMessage) { + init(localNode, remoteNode, sessionMessage); } - public Sender(String remoteHost, int remotePort, SessionMessage sessionMessage) { - init(remoteHost, remotePort, sessionMessage); - } +// public Sender(String remoteHost, int remotePort, SessionMessage sessionMessage) { +// init(remoteHost, remotePort, sessionMessage); +// } /** * 连接 */ public void connect() { - watchDogHandler = new WatchDogHandler(this.remoteHost, this.remotePort, bootstrap); + watchDogHandler = new WatchDogHandler(this.remoteNode.getHostName(), this.remoteNode.getPort(), bootstrap); ChannelHandlers frontChannelHandlers = new ChannelHandlers() .addHandler(watchDogHandler); @@ -83,7 +88,7 @@ public class Sender extends AbstractAsyncExecutor implements Closeable { .addHandler(new StringDecoder()) .addHandler(new HeartBeatSenderTrigger()) .addHandler(new HeartBeatSenderHandler()) - .addHandler(new SenderHandler(this.sessionMessage)); + .addHandler(new SenderHandler(this.localNode, this.remoteNode, this.sessionMessage)); // 初始化watchDogHandler watchDogHandler.init(frontChannelHandlers.toArray(), afterChannelHandlers.toArray()); @@ -105,7 +110,7 @@ public class Sender extends AbstractAsyncExecutor implements Closeable { runThread.execute(() -> { try { // 发起连接请求 - channelFuture = bootstrap.connect(this.remoteHost, this.remotePort).sync(); + channelFuture = bootstrap.connect(this.remoteNode.getHostName(), this.remoteNode.getPort()).sync(); boolean isStartSuccess = channelFuture.isSuccess(); if (isStartSuccess) { // 启动成功 @@ -130,28 +135,16 @@ public class Sender extends AbstractAsyncExecutor implements Closeable { /** * 初始化相关配置 * + * @param localNode + * 本地节点 * @param remoteNode * 远端节点 * @param sessionMessage * 本地节点连接到远端节点后发送的SessionMessage */ - private void init(RemoteNode remoteNode, SessionMessage sessionMessage) { - init(remoteNode.getHostName(), remoteNode.getPort(), sessionMessage); - } - - /** - * 初始化相关配置 - * - * @param remoteHost - * 远端HOST - * @param remotePort - * 远端端口 - * @param sessionMessage - * 本地节点连接到远端节点后发送的SessionMessage - */ - private void init(String remoteHost, int remotePort, SessionMessage sessionMessage) { - this.remoteHost = remoteHost; - this.remotePort = remotePort; + private void init(LocalNode localNode, RemoteNode remoteNode, SessionMessage sessionMessage) { + this.localNode = localNode; + this.remoteNode = remoteNode; this.sessionMessage = sessionMessage; diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/ReceiverHandler.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/ReceiverHandler.java index 8a13db4e..3459a804 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/ReceiverHandler.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/ReceiverHandler.java @@ -16,10 +16,12 @@ import com.jd.blockchain.stp.communication.connection.listener.ReplyListener; import com.jd.blockchain.stp.communication.manager.ConnectionManager; import com.jd.blockchain.stp.communication.message.SessionMessage; import com.jd.blockchain.stp.communication.message.TransferMessage; +import com.jd.blockchain.stp.communication.node.LocalNode; import com.jd.blockchain.stp.communication.node.RemoteNode; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; +import org.apache.commons.codec.binary.Hex; import java.io.Closeable; import java.util.Map; @@ -86,11 +88,17 @@ public class ReceiverHandler extends ChannelInboundHandlerAdapter implements Clo */ private MessageExecutor defaultMessageExecutor; + /** + * 本地节点 + */ + private LocalNode localNode; + public ReceiverHandler(ConnectionManager connectionManager, String localMsgExecutorClass, - MessageExecutor defaultMessageExecutor) { + LocalNode localNode) { this.connectionManager = connectionManager; this.localMsgExecutorClass = localMsgExecutorClass; - this.defaultMessageExecutor = defaultMessageExecutor; + this.defaultMessageExecutor = localNode.defaultMessageExecutor(); + this.localNode = localNode; initMsgExecutorPool(); } @@ -109,7 +117,7 @@ public class ReceiverHandler extends ChannelInboundHandlerAdapter implements Clo @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - System.out.println("Receive Biz Message -> " + msg.toString()); + System.out.printf("%s Receive Biz Message -> %s \r\n", this.localNode.toString(), msg.toString()); // 有数据接入 // 首先判断数据是否TransferMessage,当前Handler不处理非TransferMessage TransferMessage tm = TransferMessage.toTransferMessage(msg); @@ -239,7 +247,7 @@ public class ReceiverHandler extends ChannelInboundHandlerAdapter implements Clo // 假设连接失败的话,返回的Connection对象为null,此时不放入Map,等后续再处理 if (remoteConnection != null) { - remoteSession = new RemoteSession(sessionId, remoteConnection, messageExecutor); + remoteSession = new RemoteSession(this.localId(), remoteConnection, messageExecutor); // Double check !!! if (!remoteSessions.containsKey(sessionId)) { @@ -312,6 +320,24 @@ public class ReceiverHandler extends ChannelInboundHandlerAdapter implements Clo msgExecuteThreadFactory, new ThreadPoolExecutor.AbortPolicy()); } + /** + * 返回本地节点 + * + * @return + */ + public LocalNode localNode() { + return localNode; + } + + /** + * 返回本地节点ID + * + * @return + */ + private String localId() { + return Hex.encodeHexString(localNode.toString().getBytes()); + } + @Override public void close() { msgExecutorPool.shutdown(); diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/SenderHandler.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/SenderHandler.java index b3d194cb..ed763434 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/SenderHandler.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/SenderHandler.java @@ -9,6 +9,8 @@ package com.jd.blockchain.stp.communication.connection.handler; import com.jd.blockchain.stp.communication.message.SessionMessage; +import com.jd.blockchain.stp.communication.node.LocalNode; +import com.jd.blockchain.stp.communication.node.RemoteNode; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; @@ -23,16 +25,38 @@ import io.netty.channel.ChannelInboundHandlerAdapter; @ChannelHandler.Sharable public class SenderHandler extends ChannelInboundHandlerAdapter { + /** + * 本地session信息 + */ private SessionMessage sessionMessage; - public SenderHandler(SessionMessage sessionMessage) { + /** + * 本地节点 + */ + private LocalNode localNode; + + /** + * 远端节点 + */ + private RemoteNode remoteNode; + + public SenderHandler(LocalNode localNode, RemoteNode remoteNode, SessionMessage sessionMessage) { + this.localNode = localNode; + this.remoteNode = remoteNode; this.sessionMessage = sessionMessage; } + /** + * 连接远端节点成功时触发 + * + * @param ctx + * @throws Exception + */ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { + // 发送本机信息(包括IP、端口等)至对端 - System.out.println("Connection Receiver Success, Send Local Node Information !!!"); + System.out.printf("%s Connect %s Success, Send Local Node Information !!! \r\n", this.localNode, this.remoteNode); ctx.writeAndFlush(sessionMessage.toTransferByteBuf()); } diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/RemoteSessionManager.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/RemoteSessionManager.java index 8025252a..1086fb33 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/RemoteSessionManager.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/RemoteSessionManager.java @@ -60,6 +60,11 @@ public class RemoteSessionManager { */ private LocalNode localNode; + /** + * 本地节点ID + */ + private String localId; + /** * 构造器 * @param localNode @@ -67,6 +72,7 @@ public class RemoteSessionManager { */ public RemoteSessionManager(LocalNode localNode) { this.localNode = localNode; + this.localId = localId(); // 校验本地节点的配置,防止异常 check(); this.connectionManager = ConnectionManager.newConnectionManager(this.localNode); @@ -83,24 +89,13 @@ public class RemoteSessionManager { } } - /** - * 生成新的Session - * @param remoteNode - * @return - */ - public RemoteSession newSession(RemoteNode remoteNode) { - return newSession(null, remoteNode); - } - /** * RemoteSession对象生成器 - * @param sessionId - * RemoteSession的Key * @param remoteNode * 远端节点信息 * @return */ - public RemoteSession newSession(String sessionId, RemoteNode remoteNode) { + public RemoteSession newSession(RemoteNode remoteNode) { RemoteSession remoteSession = nodeRemoteSessionMap.get(remoteNode); @@ -112,16 +107,13 @@ public class RemoteSessionManager { // Double Check !!! if (!nodeRemoteSessionMap.containsKey(remoteNode)) { - if (sessionId == null) { - sessionId = sessionId(localNode); - } Connection remoteConnection = this.connectionManager.connect(remoteNode, localNode.messageExecutorClass()); if (remoteConnection == null) { return null; } - remoteSession = new RemoteSession(sessionId, remoteConnection); + remoteSession = new RemoteSession(localId, remoteConnection); remoteSession.init(); @@ -133,26 +125,14 @@ public class RemoteSessionManager { lock.unlock(); } } - return remoteSession; + return null; } public RemoteSession[] newSessions(RemoteNode[] remoteNodes) { - - return newSessions(null, remoteNodes); - } - - public RemoteSession[] newSessions(String[] sessionIds, RemoteNode[] remoteNodes) { - checkSessions(sessionIds, remoteNodes); - List remoteSessionList = new ArrayList<>(); for (int i = 0; i < remoteNodes.length; i++) { - RemoteSession remoteSession; - if (sessionIds == null) { - remoteSession = newSession(remoteNodes[i]); - } else { - remoteSession = newSession(sessionIds[i], remoteNodes[i]); - } + RemoteSession remoteSession = newSession(remoteNodes[i]); if (remoteSession != null) { remoteSessionList.add(remoteSession); } @@ -194,19 +174,7 @@ public class RemoteSessionManager { return this.connectionManager.start(this.localNode.messageExecutorClass()); } - private void checkSessions(String[] sessionIds, RemoteNode[] remoteNodes) { - if (remoteNodes == null || remoteNodes.length <= 0) { - throw new IllegalArgumentException("RemoteNodes is empty !!!"); - } - - if (sessionIds != null) { - if (sessionIds.length != remoteNodes.length) { - throw new IllegalArgumentException("RemoteNodes and sessionIds are different in length !!!"); - } - } - } - - private String sessionId(RemoteNode remoteNode) { - return Hex.encodeHexString(remoteNode.toString().getBytes()); + private String localId() { + return Hex.encodeHexString(localNode.toString().getBytes()); } } \ No newline at end of file diff --git a/source/test/test-stp-community/src/main/java/com/jd/blockchain/stp/commucation/MyMessageExecutor.java b/source/test/test-stp-community/src/main/java/com/jd/blockchain/stp/commucation/MyMessageExecutor.java index e1223981..26656a8b 100644 --- a/source/test/test-stp-community/src/main/java/com/jd/blockchain/stp/commucation/MyMessageExecutor.java +++ b/source/test/test-stp-community/src/main/java/com/jd/blockchain/stp/commucation/MyMessageExecutor.java @@ -25,8 +25,8 @@ public class MyMessageExecutor implements MessageExecutor { @Override public byte[] receive(String key, byte[] data, RemoteSession session) { String receiveMsg = new String(data, Charset.defaultCharset()); - System.out.printf("receive client {%s} request {%s} \r\n", session.sessionId(), receiveMsg); - String msg = session.sessionId() + " -> received !!!"; + System.out.printf("receive client {%s} request {%s} \r\n", session.remoteNode().toString(), receiveMsg); + String msg = session.localId() + " -> received !!!"; return msg.getBytes(Charset.defaultCharset()); } From 20ed2db6c7dc7d780d2897cdda731010f66a3fc9 Mon Sep 17 00:00:00 2001 From: shaozhuguang Date: Tue, 23 Apr 2019 18:18:13 +0800 Subject: [PATCH 13/43] =?UTF-8?q?=E4=BF=AE=E6=94=B9STP=E5=BA=95=E5=B1=82?= =?UTF-8?q?=E9=80=9A=E4=BF=A1=E5=8C=85=E8=A3=85=E6=B6=88=E6=81=AF=E7=9A=84?= =?UTF-8?q?Key?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blockchain/stp/communication/message/TransferMessage.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/TransferMessage.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/TransferMessage.java index b6000866..fb918295 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/TransferMessage.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/message/TransferMessage.java @@ -112,8 +112,7 @@ public class TransferMessage extends AbstractMessage implements IMessage{ * @return */ public String toListenKey() { - // 格式:sessionId:key - return sessionId + ":" + key; + return key; } public String getSessionId() { From 27591f0fe93134e083583ca447e78aa6e7cdc942 Mon Sep 17 00:00:00 2001 From: zhangshuang Date: Wed, 24 Apr 2019 14:50:54 +0800 Subject: [PATCH 14/43] stp code debug --- .../message/DSDefaultMessageExecutor.java | 3 +- .../message/DataSequenceMsgEncoder.java | 10 +-- .../process/DSProcessManager.java | 66 +++++++++++++------ .../process/DSTransferProcess.java | 55 ++++++++++------ .../result/DSInfoResponseResult.java | 15 +++-- .../statetransfer/DataSequence.java | 2 +- .../statetransfer/DataSequenceWriterImpl.java | 11 ++++ .../statetransfer/StateTransferLayerTest.java | 23 ++----- 8 files changed, 112 insertions(+), 73 deletions(-) diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DSDefaultMessageExecutor.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DSDefaultMessageExecutor.java index 258c5fdb..08464db2 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DSDefaultMessageExecutor.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DSDefaultMessageExecutor.java @@ -35,9 +35,8 @@ public class DSDefaultMessageExecutor implements MessageExecutor { Object object = DSMsgResolverFactory.getDecoder(dsWriter, dsReader).decode(data); if (object instanceof String) { - String id = (String)object; - byte[] respLoadMsg = DSMsgResolverFactory.getEncoder(dsWriter, dsReader).encode(DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_RESPONSE, id, 0, 0); + byte[] respLoadMsg = DSMsgResolverFactory.getEncoder(dsWriter, dsReader).encode(DSTransferProcess.DataSequenceMsgType.CMD_DSINFO_RESPONSE, id, 0, 0); session.reply(key, new DataSequenceLoadMessage(respLoadMsg)); } else if (object instanceof DSDiffRequestResult) { diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceMsgEncoder.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceMsgEncoder.java index 9b1adad0..0de98605 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceMsgEncoder.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceMsgEncoder.java @@ -43,7 +43,7 @@ public class DataSequenceMsgEncoder { loadMessage = new byte[dataLength]; System.arraycopy(BytesUtils.toBytes(dataLength), 0, loadMessage, 0, 4); - System.arraycopy(msgType.CODE, 0, loadMessage, 4, msgTypeSize); + loadMessage[4] = msgType.CODE; System.arraycopy(BytesUtils.toBytes(idSize), 0, loadMessage, 4 + msgTypeSize, 4); System.arraycopy(id.getBytes(), 0, loadMessage, 4 + msgTypeSize + 4, idSize); } else if (msgType == DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_REQUEST) { @@ -56,12 +56,12 @@ public class DataSequenceMsgEncoder { loadMessage = new byte[dataLength]; System.arraycopy(BytesUtils.toBytes(dataLength), 0, loadMessage, 0, 4); - System.arraycopy(msgType.CODE, 0, loadMessage, 4, msgTypeSize); + loadMessage[4] = msgType.CODE; System.arraycopy(BytesUtils.toBytes(fromHeight), 0, loadMessage, 4 + msgTypeSize, heightSize); System.arraycopy(BytesUtils.toBytes(toHeight), 0, loadMessage, 4 + msgTypeSize + heightSize, heightSize); System.arraycopy(BytesUtils.toBytes(idSize), 0, loadMessage, 4 + msgTypeSize + heightSize + heightSize, 4); System.arraycopy(id.getBytes(), 0, loadMessage, 4 + msgTypeSize + heightSize + heightSize + 4, idSize); - } else if (msgType == DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_RESPONSE) { + } else if (msgType == DSTransferProcess.DataSequenceMsgType.CMD_DSINFO_RESPONSE) { // CMD_DSINFO_RESPONSE Message parts : 4 bytes total message size, 1 byte message type coe, 8 bytes data sequence local height, // 4 bytes id length, id content size bytes @@ -71,7 +71,7 @@ public class DataSequenceMsgEncoder { loadMessage = new byte[dataLength]; System.arraycopy(BytesUtils.toBytes(dataLength), 0, loadMessage, 0, 4); - System.arraycopy(msgType.CODE, 0, loadMessage, 4, msgTypeSize); + loadMessage[4] = msgType.CODE; System.arraycopy(BytesUtils.toBytes(dsReader.getDSInfo(id).getHeight()), 0, loadMessage, 4 + msgTypeSize, heightSize); System.arraycopy(BytesUtils.toBytes(idSize), 0, loadMessage, 4 + msgTypeSize + heightSize, 4); @@ -94,7 +94,7 @@ public class DataSequenceMsgEncoder { loadMessage = new byte[dataLength]; System.arraycopy(BytesUtils.toBytes(dataLength), 0, loadMessage, 0, 4); //total size - System.arraycopy(msgType.CODE, 0, loadMessage, 4, msgTypeSize); //msgType size + loadMessage[4] = msgType.CODE; //msgType size System.arraycopy(BytesUtils.toBytes(diffElem.length), 0, loadMessage, 4 + msgTypeSize, 4); // diffElem size System.arraycopy(diffElem, 0, loadMessage, 4 + msgTypeSize + 4, diffElem.length); // diffElem bytes } diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSProcessManager.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSProcessManager.java index fecfa5c3..6440a842 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSProcessManager.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSProcessManager.java @@ -4,6 +4,7 @@ import com.jd.blockchain.statetransfer.DataSequenceElement; import com.jd.blockchain.statetransfer.DataSequenceInfo; import com.jd.blockchain.statetransfer.callback.DataSequenceReader; import com.jd.blockchain.statetransfer.callback.DataSequenceWriter; +import com.jd.blockchain.statetransfer.comparator.DataSequenceComparator; import com.jd.blockchain.statetransfer.message.DSDefaultMessageExecutor; import com.jd.blockchain.statetransfer.result.DSInfoResponseResult; import com.jd.blockchain.stp.communication.RemoteSession; @@ -11,11 +12,11 @@ import com.jd.blockchain.stp.communication.callback.CallBackBarrier; import com.jd.blockchain.stp.communication.callback.CallBackDataListener; import com.jd.blockchain.stp.communication.manager.RemoteSessionManager; import com.jd.blockchain.stp.communication.node.LocalNode; +import com.jd.blockchain.stp.communication.node.RemoteNode; import com.jd.blockchain.utils.concurrent.CompletableAsyncFuture; import java.net.InetSocketAddress; -import java.util.LinkedList; -import java.util.Map; +import java.util.*; import java.util.concurrent.*; /** @@ -28,7 +29,7 @@ public class DSProcessManager { private static Map dSProcessMap = new ConcurrentHashMap<>(); private RemoteSession[] remoteSessions; - private long dsInfoResponseTimeout = 2000; + private long dsInfoResponseTimeout = 20000; private ExecutorService writeExecutors = Executors.newFixedThreadPool(5); private int returnCode = 0; /** @@ -52,6 +53,10 @@ public class DSProcessManager { dSProcessMap.put(dsInfo.getId(), dsTransferProcess); try { + + //wait all listener nodes start + Thread.sleep(10000); + // start network connections with targets dsTransferProcess.start(); @@ -62,52 +67,58 @@ public class DSProcessManager { CallBackBarrier callBackBarrier = CallBackBarrier.newCallBackBarrier(remoteSessions.length, dsInfoResponseTimeout); // response message manage map - Map dsInfoResponses = new ConcurrentHashMap<>(); + LinkedList dsInfoResponses = new LinkedList<>(); + System.out.println("Async send CMD_DSINFO_REQUEST msg to targets will start!"); // step1: send get dsInfo request, then hold for (RemoteSession remoteSession : remoteSessions) { - CallBackDataListener dsInfoResponse = dsTransferProcess.send(DSTransferProcess.DataSequenceMsgType.CMD_DSINFO_REQUEST, remoteSession, 0, 0, callBackBarrier); - - dsInfoResponses.put(remoteSession, dsInfoResponse); + dsInfoResponses.addLast(dsInfoResponse); } + System.out.println("Wait CMD_DSINFO_RESPONSE msg from targets!"); // step2: collect get dsInfo response - Map receiveResponses = new ConcurrentHashMap<>(); + LinkedList receiveResponses = new LinkedList<>(); if (callBackBarrier.tryCall()) { - for (RemoteSession remoteSession : dsInfoResponses.keySet()) { - CallBackDataListener asyncFuture = dsInfoResponses.get(remoteSession); - // if really done - if (asyncFuture.isDone()) { - receiveResponses.put(remoteSession, asyncFuture.getCallBackData()); + Iterator iterator = dsInfoResponses.iterator(); + while (iterator.hasNext()) { + CallBackDataListener receiveResponse = iterator.next(); + if (receiveResponse.isDone()) { + receiveResponses.addLast(receiveResponse); } } } + System.out.println("Compute diff info!"); // step3: process received responses DSInfoResponseResult diffResult = dsTransferProcess.computeDiffInfo(receiveResponses); + System.out.println("Diff info result height = " + diffResult.getMaxHeight() + "!"); + // height diff long diff = dsInfo.getHeight() - diffResult.getMaxHeight(); if (diff == 0 || diff > 0) { + System.out.println("No duplication is required!"); // no duplication is required, life cycle ends - dsTransferProcess.close(); +// dsTransferProcess.close(); dSProcessMap.remove(dsInfo.getId()); return returnCode; } else { - + System.out.println("Duplication is required!"); // step4: async send get data sequence diff request // single step get diff // async message send process CallBackBarrier callBackBarrierDiff = CallBackBarrier.newCallBackBarrier((int)(diffResult.getMaxHeight() - dsInfo.getHeight()), dsInfoResponseTimeout); LinkedList dsDiffResponses = new LinkedList<>(); + RemoteSession responseSession = findResponseSession(diffResult.getMaxHeightRemoteNode(), remoteSessions); + System.out.println("Async send CMD_GETDSDIFF_REQUEST msg to targets will start!"); // step5: collect get data sequence diff response for (long height = dsInfo.getHeight() + 1; height < diffResult.getMaxHeight() + 1; height++) { - CallBackDataListener dsDiffResponse = dsTransferProcess.send(DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_REQUEST, diffResult.getMaxHeightSession(), height, height, callBackBarrierDiff); + CallBackDataListener dsDiffResponse = dsTransferProcess.send(DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_REQUEST, responseSession, height, height, callBackBarrierDiff); dsDiffResponses.addLast(dsDiffResponse); } @@ -116,6 +127,7 @@ public class DSProcessManager { // // }); + System.out.println("Wait CMD_GETDSDIFF_RESPONSE msg from targets!"); LinkedList receiveDiffResponses = new LinkedList<>(); if (callBackBarrierDiff.tryCall()) { for (int i = 0; i < dsDiffResponses.size(); i++) { @@ -125,13 +137,18 @@ public class DSProcessManager { } } } + + System.out.println("ReceiveDiffResponses size = "+ receiveDiffResponses.size()); // step6: process data sequence diff response, update local data sequence state - DataSequenceElement[] dataSequenceElements = dsTransferProcess.computeDiffElement(receiveDiffResponses.toArray(new byte[receiveDiffResponses.size()][])); - returnCode = dsWriter.updateDSInfo(dsInfo, dataSequenceElements); + System.out.println("Compute diff elements!"); + ArrayList dataSequenceElements = dsTransferProcess.computeDiffElement(receiveDiffResponses.toArray(new byte[receiveDiffResponses.size()][])); + System.out.println("Update local data sequence!"); + Collections.sort(dataSequenceElements, new DataSequenceComparator()); + returnCode = dsWriter.updateDSInfo(dsInfo, dataSequenceElements.toArray(new DataSequenceElement[dataSequenceElements.size()])); // data sequence transfer complete, close all sessions, end process life cycle - - dsTransferProcess.close(); + System.out.println("Close all sessions"); +// dsTransferProcess.close(); dSProcessMap.remove(dsInfo.getId()); } @@ -142,7 +159,14 @@ public class DSProcessManager { return returnCode; } - + RemoteSession findResponseSession(RemoteNode remoteNode, RemoteSession[] remoteSessions) { + for (RemoteSession remoteSession : remoteSessions) { + if (remoteSession.remoteNode().equals(remoteNode)) { + return remoteSession; + } + } + return null; + } /** * * diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSTransferProcess.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSTransferProcess.java index 90003712..b1e6b817 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSTransferProcess.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSTransferProcess.java @@ -15,6 +15,8 @@ import com.jd.blockchain.stp.communication.node.RemoteNode; import com.jd.blockchain.utils.IllegalDataException; import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.LinkedList; import java.util.Map; /** @@ -78,12 +80,14 @@ public class DSTransferProcess { * * */ - public DataSequenceElement[] computeDiffElement(byte[][] diffArray) { - DataSequenceElement[] dataSequenceElements = new DataSequenceElement[diffArray.length]; - for (int i = 0 ; i < dataSequenceElements.length; i++) { + public ArrayList computeDiffElement(byte[][] diffArray) { + + ArrayList dataSequenceElements = new ArrayList<>(); + + for (int i = 0 ; i < diffArray.length; i++) { Object object = DSMsgResolverFactory.getDecoder(dsWriter, dsReader).decode(diffArray[i]); if (object instanceof DataSequenceElement) { - dataSequenceElements[i] = (DataSequenceElement) object; + dataSequenceElements.add((DataSequenceElement) object); } else { throw new IllegalDataException("Unknown instance object!"); @@ -97,27 +101,36 @@ public class DSTransferProcess { * * */ - public DSInfoResponseResult computeDiffInfo(Map responseMap) { + public DSInfoResponseResult computeDiffInfo(LinkedList receiveResponses) { long maxHeight = 0; - RemoteSession maxHeightSession = null; - - for (RemoteSession remoteSession : responseMap.keySet()) { - Object object = DSMsgResolverFactory.getDecoder(dsWriter, dsReader).decode(responseMap.get(remoteSession)); - if (object instanceof DataSequenceInfo) { - DataSequenceInfo dsInfo = (DataSequenceInfo) object; - long height = dsInfo.getHeight(); - if (maxHeight < height) { - maxHeight = height; - maxHeightSession = remoteSession; - } - } - else { - throw new IllegalDataException("Unknown instance object!"); - } + RemoteNode maxHeightRemoteNode = null; + + System.out.println("ComputeDiffInfo receiveResponses size = "+ receiveResponses.size()); + + try { + for (CallBackDataListener receiveResponse : receiveResponses) { + Object object = DSMsgResolverFactory.getDecoder(dsWriter, dsReader).decode(receiveResponse.getCallBackData()); +// System.out.println("ComputeDiffInfo object = "+object); + if (object instanceof DataSequenceInfo) { + DataSequenceInfo dsInfo = (DataSequenceInfo) object; + long height = dsInfo.getHeight(); +// System.out.println("ComputeDiffInfo height = " +height); + if (maxHeight < height) { + maxHeight = height; + maxHeightRemoteNode = receiveResponse.remoteNode(); + } + } + else { + throw new IllegalDataException("Unknown instance object!"); + } + } + } catch (Exception e) { + System.out.println(e.getMessage()); + e.printStackTrace(); } - return new DSInfoResponseResult(maxHeight, maxHeightSession); + return new DSInfoResponseResult(maxHeight, maxHeightRemoteNode); } /** diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/result/DSInfoResponseResult.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/result/DSInfoResponseResult.java index d0a57b26..9a7ea126 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/result/DSInfoResponseResult.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/result/DSInfoResponseResult.java @@ -1,6 +1,7 @@ package com.jd.blockchain.statetransfer.result; import com.jd.blockchain.stp.communication.RemoteSession; +import com.jd.blockchain.stp.communication.node.RemoteNode; /** * @@ -11,27 +12,27 @@ import com.jd.blockchain.stp.communication.RemoteSession; public class DSInfoResponseResult { long maxHeight; - RemoteSession maxHeightSession; + RemoteNode maxHeightRemoteNode; - public DSInfoResponseResult(long maxHeight, RemoteSession maxHeightSession) { + public DSInfoResponseResult(long maxHeight, RemoteNode maxHeightRemoteNode) { this.maxHeight = maxHeight; - this.maxHeightSession = maxHeightSession; + this.maxHeightRemoteNode = maxHeightRemoteNode; } public long getMaxHeight() { return maxHeight; } - public RemoteSession getMaxHeightSession() { - return maxHeightSession; + public RemoteNode getMaxHeightRemoteNode() { + return maxHeightRemoteNode; } public void setMaxHeight(long maxHeight) { this.maxHeight = maxHeight; } - public void setMaxHeightSession(RemoteSession maxHeightSession) { - this.maxHeightSession = maxHeightSession; + public void setMaxHeightRemoteNode(RemoteNode maxHeightRemoteNode) { + this.maxHeightRemoteNode = maxHeightRemoteNode; } } diff --git a/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequence.java b/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequence.java index 4d138d04..ed41757b 100644 --- a/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequence.java +++ b/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequence.java @@ -11,7 +11,7 @@ public class DataSequence { private InetSocketAddress address; private String id; - private static LinkedList dataSequenceElements = new LinkedList<>(); + private LinkedList dataSequenceElements = new LinkedList<>(); public DataSequence(InetSocketAddress address, String id) { diff --git a/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceWriterImpl.java b/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceWriterImpl.java index 59ce5bbc..9da566c2 100644 --- a/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceWriterImpl.java +++ b/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceWriterImpl.java @@ -22,8 +22,19 @@ public class DataSequenceWriterImpl implements DataSequenceWriter { @Override public int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement[] diffContents) { + if (diffContents == null) { + throw new IllegalArgumentException("Update diffContents is null!"); + } + + System.out.println("Old data sequence state: "); + System.out.println(" Current height = " + currDataSequence.getDataSequenceElements().getLast().getHeight()); currDataSequence.addElements(diffContents); + System.out.println("Update diffContents is completed!"); + System.out.println("New data sequence state: "); + System.out.println(" Current height = " + currDataSequence.getDataSequenceElements().getLast().getHeight()); + + return DataSequenceErrorType.DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL.CODE; } diff --git a/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/StateTransferLayerTest.java b/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/StateTransferLayerTest.java index efcaa060..9a185d95 100644 --- a/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/StateTransferLayerTest.java +++ b/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/StateTransferLayerTest.java @@ -2,8 +2,6 @@ package test.com.jd.blockchain.statetransfer; import com.jd.blockchain.statetransfer.DataSequenceElement; import com.jd.blockchain.statetransfer.DataSequenceInfo; -import com.jd.blockchain.statetransfer.callback.DataSequenceReader; -import com.jd.blockchain.statetransfer.callback.DataSequenceWriter; import com.jd.blockchain.statetransfer.process.DSProcessManager; import com.jd.blockchain.utils.codec.Base58Utils; import org.junit.Before; @@ -30,13 +28,7 @@ public class StateTransferLayerTest { private Random rand = new Random(); - private String[] dataSequenceIds; - - private DSProcessManager dsProcessManager; - - private DataSequenceReader dataSequenceReader; - - private DataSequenceWriter dataSequenceWriter; + private String[] dataSequenceIds = new String[DataSequenceNum]; private InetSocketAddress[] remoteNodeIps = new InetSocketAddress[nodesNum]; @@ -59,10 +51,6 @@ public class StateTransferLayerTest { dataSequenceIds[i] = Base58Utils.encode(idBytes); } - // 创建数据序列处理管理者实例 - dsProcessManager = new DSProcessManager(); - - // 准备好所有的远端结点,包括监听者 for (int i = 0; i < nodesNum; i++) { remoteNodeIps[i] = new InetSocketAddress(localIp, listenPorts[i]); @@ -80,8 +68,8 @@ public class StateTransferLayerTest { DataSequence dataSequence = new DataSequence(remoteNodeIps[i], id); // 为数据序列的0,1,2高度添加内容 - for (int j = 0; j < 3; i++) { - dataSequence.addElement(new DataSequenceElement(id, i, dsElementDatas)); + for (int j = 0; j < 3; j++) { + dataSequence.addElement(new DataSequenceElement(id, j, dsElementDatas)); } dataSequencesPerNode.addLast(dataSequence); } @@ -91,7 +79,7 @@ public class StateTransferLayerTest { DataSequence dataSequence = dataSequencesPerNode.get(i); if (dataSequence.getAddress().getPort() != listenPorts[0]) { // 为数据序列的3,4高度添加内容 - for (int j = 3; j < 5; i++) { + for (int j = 3; j < 5; j++) { dataSequence.addElement(new DataSequenceElement(id, j, dsElementDatas)); } } @@ -136,6 +124,8 @@ public class StateTransferLayerTest { for (int i = 0; i < nodesNum; i++) { InetSocketAddress listenNode = remoteNodeIps[i]; threadPool.execute(() -> { + // 创建数据序列处理管理者实例 + DSProcessManager dsProcessManager = new DSProcessManager(); DataSequence currDataSequence = findDataSequence(id, listenNode); DataSequenceInfo dsInfo = currDataSequence.getDSInfo(); InetSocketAddress[] targets = getTargetNodesIp(listenNode, remoteNodeIps); @@ -147,6 +137,7 @@ public class StateTransferLayerTest { // 等待数据序列更新完成 try { + Thread.sleep(60000); countDownLatch.await(); } catch (Exception e) { e.printStackTrace(); From 0a0dffc99e5e24a1d33231eab6ce4d5b367b9bb6 Mon Sep 17 00:00:00 2001 From: zhangshuang Date: Wed, 24 Apr 2019 16:20:53 +0800 Subject: [PATCH 15/43] solve ncp layer code bug --- .../statetransfer/process/DSProcessManager.java | 12 ++++++------ .../connection/handler/ReceiverHandler.java | 2 +- .../stp/communication/manager/ConnectionManager.java | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSProcessManager.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSProcessManager.java index 6440a842..cab88add 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSProcessManager.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSProcessManager.java @@ -55,7 +55,7 @@ public class DSProcessManager { try { //wait all listener nodes start - Thread.sleep(10000); + Thread.sleep(2000); // start network connections with targets dsTransferProcess.start(); @@ -89,17 +89,17 @@ public class DSProcessManager { } } - System.out.println("Compute diff info!"); + System.out.printf("%s:%d Compute diff info!\r\n", listener.getHostName(), listener.getPort()); // step3: process received responses DSInfoResponseResult diffResult = dsTransferProcess.computeDiffInfo(receiveResponses); - System.out.println("Diff info result height = " + diffResult.getMaxHeight() + "!"); + System.out.printf("%s:%d Diff info result height = %x!\r\n", listener.getHostName(), listener.getPort(), diffResult.getMaxHeight()); // height diff long diff = dsInfo.getHeight() - diffResult.getMaxHeight(); if (diff == 0 || diff > 0) { - System.out.println("No duplication is required!"); + System.out.printf("%s:%d No duplication is required!\r\n", listener.getHostName(), listener.getPort()); // no duplication is required, life cycle ends // dsTransferProcess.close(); dSProcessMap.remove(dsInfo.getId()); @@ -107,7 +107,7 @@ public class DSProcessManager { } else { - System.out.println("Duplication is required!"); + System.out.printf("%s:%d Duplication is required!\r\n", listener.getHostName(), listener.getPort()); // step4: async send get data sequence diff request // single step get diff // async message send process @@ -138,7 +138,7 @@ public class DSProcessManager { } } - System.out.println("ReceiveDiffResponses size = "+ receiveDiffResponses.size()); + System.out.printf("%s:%d ReceiveDiffResponses size = %d !\r\n", listener.getHostName(), listener.getPort(), receiveDiffResponses.size()); // step6: process data sequence diff response, update local data sequence state System.out.println("Compute diff elements!"); ArrayList dataSequenceElements = dsTransferProcess.computeDiffElement(receiveDiffResponses.toArray(new byte[receiveDiffResponses.size()][])); diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/ReceiverHandler.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/ReceiverHandler.java index 3459a804..0dcf6753 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/ReceiverHandler.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/connection/handler/ReceiverHandler.java @@ -251,7 +251,7 @@ public class ReceiverHandler extends ChannelInboundHandlerAdapter implements Clo // Double check !!! if (!remoteSessions.containsKey(sessionId)) { - remoteSessions.put(sessionId, remoteSession); + this.putRemoteSession(sessionId, remoteSession); } } } finally { diff --git a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/ConnectionManager.java b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/ConnectionManager.java index c4f8097f..c8336284 100644 --- a/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/ConnectionManager.java +++ b/source/stp/stp-communication/src/main/java/com/jd/blockchain/stp/communication/manager/ConnectionManager.java @@ -33,7 +33,7 @@ public class ConnectionManager { * Connection对应Map * RemoteNode唯一性:IP(HOST)+PORT */ - private static final Map connectionMap = new ConcurrentHashMap<>(); + private final Map connectionMap = new ConcurrentHashMap<>(); /** * 连接管理器对应MAP From 46c1e2b20b6f4a26e9cc7cc3dbba42438f189432 Mon Sep 17 00:00:00 2001 From: zhangshuang Date: Thu, 25 Apr 2019 11:07:35 +0800 Subject: [PATCH 16/43] add notes for code --- .../statetransfer/DataSequenceReaderImpl.java | 1 - .../statetransfer/DataSequenceWriterImpl.java | 1 - .../statetransfer/DataSequenceElement.java | 2 +- .../statetransfer/DataSequenceInfo.java | 2 +- .../callback/DataSequenceReader.java | 20 ++++-- .../callback/DataSequenceWriter.java | 16 +++-- .../comparator/DataSequenceComparator.java | 12 +++- .../exception/DataSequenceException.java | 6 ++ .../message/DSDefaultMessageExecutor.java | 22 ++++--- .../message/DSMsgResolverFactory.java | 19 ++++++ .../message/DataSequenceLoadMessage.java | 6 +- .../message/DataSequenceMsgDecoder.java | 26 ++++++-- .../message/DataSequenceMsgEncoder.java | 27 ++++++-- .../process/DSProcessManager.java | 35 ++++++---- .../process/DSTransferProcess.java | 65 +++++++++++-------- .../result/DSDiffRequestResult.java | 6 ++ .../result/DSInfoResponseResult.java | 9 ++- .../statetransfer/DataSequence.java | 8 +++ .../statetransfer/DataSequenceReaderImpl.java | 3 +- .../statetransfer/DataSequenceWriterImpl.java | 3 +- .../statetransfer/StateTransferLayerTest.java | 8 ++- 21 files changed, 206 insertions(+), 91 deletions(-) diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceReaderImpl.java b/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceReaderImpl.java index eeb1819e..620efcc5 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceReaderImpl.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceReaderImpl.java @@ -22,7 +22,6 @@ import org.springframework.beans.factory.annotation.Autowired; * @author zhangshuang * @create 2019/4/11 * @since 1.0.0 - * */ public class DataSequenceReaderImpl implements DataSequenceReader { diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceWriterImpl.java b/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceWriterImpl.java index 56a67358..61cfde0f 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceWriterImpl.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceWriterImpl.java @@ -15,7 +15,6 @@ import java.util.Collections; * @author zhangshuang * @create 2019/4/11 * @since 1.0.0 - * */ public class DataSequenceWriterImpl implements DataSequenceWriter { diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceElement.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceElement.java index b64bd963..aaf6e7f5 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceElement.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceElement.java @@ -3,7 +3,7 @@ package com.jd.blockchain.statetransfer; import java.io.Serializable; /** - *数据序列复制的元素或单位 + * 数据序列需要复制内容的元素或单位 * @author zhangshuang * @create 2019/4/11 * @since 1.0.0 diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceInfo.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceInfo.java index 8aa45566..6f0f2e10 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceInfo.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequenceInfo.java @@ -1,7 +1,7 @@ package com.jd.blockchain.statetransfer; /** - *共识结点上的某个数据序列的当前状态信息,每个共识结点可以对应任意个数据序列; + * 共识结点上的某个数据序列的当前状态信息,每个共识结点可以对应任意个数据序列; * @author zhangshuang * @create 2019/4/11 * @since 1.0.0 diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceReader.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceReader.java index 8e0dda19..e137b929 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceReader.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceReader.java @@ -4,7 +4,7 @@ import com.jd.blockchain.statetransfer.DataSequenceElement; import com.jd.blockchain.statetransfer.DataSequenceInfo; /** - *数据序列差异的提供者需要使用的回调接口 + * 数据序列差异提供者需要使用的回调接口 * @author zhangshuang * @create 2019/4/11 * @since 1.0.0 @@ -12,22 +12,28 @@ import com.jd.blockchain.statetransfer.DataSequenceInfo; public interface DataSequenceReader { /** - * 差异的提供者根据输入的数据序列标识符获取当前的数据序列信息; - * + * 差异提供者根据数据序列标识符获取数据序列当前状态; + * @param id 数据序列标识符 + * @return 数据序列当前状态信息 */ DataSequenceInfo getDSInfo(String id); /** - * 差异的提供者根据输入的数据序列标识符以及起始,结束高度提供数据序列的差异内容; - * + * 差异提供者根据数据序列标识符以及起始,结束高度提供数据序列该范围的差异内容; + * @param id 数据序列标识符 + * @param from 差异的起始高度 + * @param to 差异的结束高度 + * @return 差异元素组成的数组 */ DataSequenceElement[] getDSDiffContent(String id, long from, long to); /** - * 差异的提供者根据输入的数据序列标识符以及高度提供数据序列的差异内容; - * + * 差异提供者根据数据序列标识符以及高度提供数据序列的差异内容; + * @param id 数据序列标识符 + * @param height 要获得哪个高度的差异元素 + * @return 差异元素 */ DataSequenceElement getDSDiffContent(String id, long height); } diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriter.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriter.java index 73f5d45d..a38362c7 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriter.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriter.java @@ -4,7 +4,7 @@ import com.jd.blockchain.statetransfer.DataSequenceElement; import com.jd.blockchain.statetransfer.DataSequenceInfo; /** - *数据序列差异的请求者获得差异内容后需要回调该接口,通过接口提供的方法对指定数据序列执行差异内容的重放,并更新数据序列的当前状态; + * 数据序列差异请求者获得差异内容后需要回调该接口 * @author zhangshuang * @create 2019/4/11 * @since 1.0.0 @@ -12,15 +12,19 @@ import com.jd.blockchain.statetransfer.DataSequenceInfo; public interface DataSequenceWriter { /** - *更新数据序列的当前状态,一次更新多个高度的差异 - * return void + * 差异请求者更新本地数据序列的状态,一次可以更新多个差异元素 + * @param dsInfo 数据序列当前状态信息 + * @param diffContents 需要更新的差异元素数组 + * @return 更新结果编码 */ int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement[] diffContents); /** - *更新数据序列的当前状态,一次更新一个高度的差异 - * return void + * 差异请求者更新本地数据序列的状态,一次只更新一个差异元素 + * @param dsInfo 数据序列当前状态信息 + * @param diffContent 需要更新的差异元素 + * @return 更新结果编码 */ - int updateDSInfo(DataSequenceInfo id, DataSequenceElement diffContent); + int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement diffContent); } diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/comparator/DataSequenceComparator.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/comparator/DataSequenceComparator.java index 53ad5a15..9e0afbe5 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/comparator/DataSequenceComparator.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/comparator/DataSequenceComparator.java @@ -5,12 +5,20 @@ import com.jd.blockchain.statetransfer.DataSequenceElement; import java.util.Comparator; /** - * - * + * 数据序列差异元素的高度比较器 + * @author zhangshuang + * @create 2019/4/18 + * @since 1.0.0 */ public class DataSequenceComparator implements Comparator { // sort by data sequence height + /** + * 对差异元素根据高度大小排序 + * @param o1 差异元素1 + * @param o2 差异元素2 + * @return >0 or <0 + */ @Override public int compare(DataSequenceElement o1, DataSequenceElement o2) { long height1; diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/exception/DataSequenceException.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/exception/DataSequenceException.java index 95718487..5e6248c0 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/exception/DataSequenceException.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/exception/DataSequenceException.java @@ -1,5 +1,11 @@ package com.jd.blockchain.statetransfer.exception; +/** + * 数据序列异常处理 + * @author zhangshuang + * @create 2019/4/18 + * @since 1.0.0 + */ public class DataSequenceException extends RuntimeException { private static final long serialVersionUID = -4090881296855827889L; diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DSDefaultMessageExecutor.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DSDefaultMessageExecutor.java index 08464db2..6c67e8c8 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DSDefaultMessageExecutor.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DSDefaultMessageExecutor.java @@ -8,7 +8,7 @@ import com.jd.blockchain.stp.communication.MessageExecutor; import com.jd.blockchain.stp.communication.RemoteSession; /** - * + * 数据序列差异提供者使用,解析收到的差异请求消息并产生响应 * @author zhangshuang * @create 2019/4/11 * @since 1.0.0 @@ -24,8 +24,11 @@ public class DSDefaultMessageExecutor implements MessageExecutor { } /** - * 对状态机复制的请求进行响应 - * + * 对状态机复制的差异请求进行响应 + * @param key 请求消息的Key + * @param data 需要解码的字节数组 + * @param session 指定响应需要使用的目标结点会话 + * @return 配置为自动响应时,返回值为响应的字节数组,配置为手动响应时,不需要关注返回值 */ @Override @@ -34,21 +37,25 @@ public class DSDefaultMessageExecutor implements MessageExecutor { try { Object object = DSMsgResolverFactory.getDecoder(dsWriter, dsReader).decode(data); + // 解析CMD_DSINFO_REQUEST 请求的情况 if (object instanceof String) { String id = (String)object; byte[] respLoadMsg = DSMsgResolverFactory.getEncoder(dsWriter, dsReader).encode(DSTransferProcess.DataSequenceMsgType.CMD_DSINFO_RESPONSE, id, 0, 0); session.reply(key, new DataSequenceLoadMessage(respLoadMsg)); } + // 解析CMD_GETDSDIFF_REQUEST 请求的情况 else if (object instanceof DSDiffRequestResult) { DSDiffRequestResult requestResult = (DSDiffRequestResult)object; String id = requestResult.getId(); long fromHeight = requestResult.getFromHeight(); long toHeight = requestResult.getToHeight(); + //每个高度的数据序列差异元素进行一次响应的情况 for (long i = fromHeight; i < toHeight + 1; i++) { byte[] respLoadMsg = DSMsgResolverFactory.getEncoder(dsWriter, dsReader).encode(DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_RESPONSE, id, i, i); session.reply(key, new DataSequenceLoadMessage(respLoadMsg)); } + //所有差异进行一次响应的情况 } else { throw new IllegalArgumentException("Receive data exception, unknown message type!"); @@ -61,14 +68,13 @@ public class DSDefaultMessageExecutor implements MessageExecutor { return null; } + /** + * 响应类型设置 + * 分手动响应,自动响应两种类型 + */ @Override public REPLY replyType() { return REPLY.MANUAL; } - /** - * - * - */ - } diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DSMsgResolverFactory.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DSMsgResolverFactory.java index 874ef367..c0dfae8d 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DSMsgResolverFactory.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DSMsgResolverFactory.java @@ -3,12 +3,31 @@ package com.jd.blockchain.statetransfer.message; import com.jd.blockchain.statetransfer.callback.DataSequenceReader; import com.jd.blockchain.statetransfer.callback.DataSequenceWriter; +/** + * 数据序列消息解析器工厂 + * @author zhangshuang + * @create 2019/4/18 + * @since 1.0.0 + * + */ public class DSMsgResolverFactory { + /** + * 获得数据序列消息编码器实例 + * @param dsWriter 差异请求者执行数据序列更新的执行器 + * @param dsReader 差异响应者执行数据序列读取的执行器 + * @return 消息编码器实例 + */ public static DataSequenceMsgEncoder getEncoder(DataSequenceWriter dsWriter, DataSequenceReader dsReader) { return new DataSequenceMsgEncoder(dsWriter, dsReader); } + /** + * 获得数据序列消息解码器实例 + * @param dsWriter 差异请求者执行数据序列更新的执行器 + * @param dsReader 差异响应者执行数据序列读取的执行器 + * @return 消息解码器实例 + */ public static DataSequenceMsgDecoder getDecoder(DataSequenceWriter dsWriter, DataSequenceReader dsReader) { return new DataSequenceMsgDecoder(dsWriter, dsReader); } diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceLoadMessage.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceLoadMessage.java index ee38f880..a4131e61 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceLoadMessage.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceLoadMessage.java @@ -3,10 +3,14 @@ package com.jd.blockchain.statetransfer.message; import com.jd.blockchain.stp.communication.message.LoadMessage; /** - * + * 数据序列复制的负载消息 + * @author zhangshuang + * @create 2019/4/18 + * @since 1.0.0 * */ public class DataSequenceLoadMessage implements LoadMessage { + byte[] bytes; public DataSequenceLoadMessage(byte[] bytes) { diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceMsgDecoder.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceMsgDecoder.java index 81df552f..6bfa4c97 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceMsgDecoder.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceMsgDecoder.java @@ -9,6 +9,12 @@ import com.jd.blockchain.statetransfer.result.DSDiffRequestResult; import com.jd.blockchain.utils.io.BytesUtils; import com.jd.blockchain.utils.serialize.binary.BinarySerializeUtils; +/** + * 数据序列消息解码器 + * @author zhangshuang + * @create 2019/4/18 + * @since 1.0.0 + */ public class DataSequenceMsgDecoder { private int heightSize = 8; @@ -34,8 +40,9 @@ public class DataSequenceMsgDecoder { /** - * - * + * 对编过码的字节数组解码,还原成对象实例 + * @param loadMessage 字节序列 + * @return 解码后的对象 */ public Object decode(byte[] loadMessage) { @@ -48,6 +55,7 @@ public class DataSequenceMsgDecoder { int dataLength = BytesUtils.toInt(loadMessage, 0, 4); byte msgCode = loadMessage[4]; + // send by diff provider, diff requester decode if (msgCode == DSTransferProcess.DataSequenceMsgType.CMD_DSINFO_RESPONSE.CODE) { respHeight = BytesUtils.toLong(loadMessage, 4 + msgTypeSize); idSize = BytesUtils.toInt(loadMessage, 4 + msgTypeSize + heightSize, 4); @@ -55,19 +63,25 @@ public class DataSequenceMsgDecoder { System.arraycopy(loadMessage, 4 + msgTypeSize + heightSize + 4, idBytes, 0, idSize); id = new String(idBytes); return new DataSequenceInfo(id, respHeight); - } else if (msgCode == DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_RESPONSE.CODE) { + } + // send by diff provider, diff requester decode + else if (msgCode == DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_RESPONSE.CODE) { diffElemSize = BytesUtils.toInt(loadMessage, 4 + msgTypeSize, 4); diffElem = new byte[diffElemSize]; System.arraycopy(loadMessage, 4 + msgTypeSize + 4, diffElem, 0, diffElemSize); dsElement = BinarySerializeUtils.deserialize(diffElem); return dsElement; - } else if (msgCode == DSTransferProcess.DataSequenceMsgType.CMD_DSINFO_REQUEST.CODE) { + } + // send by diff requester, diff provider decode + else if (msgCode == DSTransferProcess.DataSequenceMsgType.CMD_DSINFO_REQUEST.CODE) { idSize = BytesUtils.toInt(loadMessage, 4 + msgTypeSize, 4); idBytes = new byte[idSize]; System.arraycopy(loadMessage, 4 + msgTypeSize + 4, idBytes, 0, idSize); id = new String(idBytes); return id; - } else if (msgCode == DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_REQUEST.CODE) { + } + // send by diff requester, diff provider decode + else if (msgCode == DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_REQUEST.CODE) { fromHeight = BytesUtils.toLong(loadMessage, 4 + msgTypeSize); toHeight = BytesUtils.toLong(loadMessage, 4 + msgTypeSize + heightSize); idSize = BytesUtils.toInt(loadMessage, 4 + msgTypeSize + heightSize + heightSize, 4); @@ -90,6 +104,4 @@ public class DataSequenceMsgDecoder { return null; } - - } diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceMsgEncoder.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceMsgEncoder.java index 0de98605..71b3ef4c 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceMsgEncoder.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/message/DataSequenceMsgEncoder.java @@ -7,6 +7,12 @@ import com.jd.blockchain.statetransfer.process.DSTransferProcess; import com.jd.blockchain.utils.io.BytesUtils; import com.jd.blockchain.utils.serialize.binary.BinarySerializeUtils; +/** + * 数据序列消息编码器 + * @author zhangshuang + * @create 2019/4/18 + * @since 1.0.0 + */ public class DataSequenceMsgEncoder { private int heightSize = 8; @@ -21,8 +27,12 @@ public class DataSequenceMsgEncoder { } /** - * 目前暂时考虑fromHeight与toHeight相同的情况,即每次只对一个高度的差异编码并响应 - * + * 目前暂时考虑fromHeight与toHeight相同的情况,即每次只对一个高度的差异内容进行编码并响应 + * 把消息编码成字节数组,再交给通信层传输 + * @param msgType 数据序列状态复制消息类型 + * @param id 数据序列唯一标识符 + * @param fromHeight 差异元素起始高度 + * @param toHeight 差异元素结束高度 */ public byte[] encode(DSTransferProcess.DataSequenceMsgType msgType, String id, long fromHeight, long toHeight) { @@ -33,6 +43,7 @@ public class DataSequenceMsgEncoder { byte[] loadMessage = null; // different encoding methods for different message types + // send by diff requester, diff requester encode if (msgType == DSTransferProcess.DataSequenceMsgType.CMD_DSINFO_REQUEST) { // CMD_DSINFO_REQUEST Message parts : 4 bytes total message size, 1 byte message type coe, @@ -46,7 +57,9 @@ public class DataSequenceMsgEncoder { loadMessage[4] = msgType.CODE; System.arraycopy(BytesUtils.toBytes(idSize), 0, loadMessage, 4 + msgTypeSize, 4); System.arraycopy(id.getBytes(), 0, loadMessage, 4 + msgTypeSize + 4, idSize); - } else if (msgType == DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_REQUEST) { + } + // send by diff requester, diff requester encode + else if (msgType == DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_REQUEST) { // CMD_GETDSDIFF_REQUEST Message parts : 4 bytes total message size, 1 byte message type coe, 8 bytes from height, // 8 bytes to height, 4 bytes id length, id content size bytes @@ -61,7 +74,9 @@ public class DataSequenceMsgEncoder { System.arraycopy(BytesUtils.toBytes(toHeight), 0, loadMessage, 4 + msgTypeSize + heightSize, heightSize); System.arraycopy(BytesUtils.toBytes(idSize), 0, loadMessage, 4 + msgTypeSize + heightSize + heightSize, 4); System.arraycopy(id.getBytes(), 0, loadMessage, 4 + msgTypeSize + heightSize + heightSize + 4, idSize); - } else if (msgType == DSTransferProcess.DataSequenceMsgType.CMD_DSINFO_RESPONSE) { + } + // send by diff provider, diff provider encode + else if (msgType == DSTransferProcess.DataSequenceMsgType.CMD_DSINFO_RESPONSE) { // CMD_DSINFO_RESPONSE Message parts : 4 bytes total message size, 1 byte message type coe, 8 bytes data sequence local height, // 4 bytes id length, id content size bytes @@ -77,7 +92,9 @@ public class DataSequenceMsgEncoder { System.arraycopy(BytesUtils.toBytes(idSize), 0, loadMessage, 4 + msgTypeSize + heightSize, 4); System.arraycopy(id.getBytes(), 0, loadMessage, 4 + msgTypeSize + heightSize + 4, idSize); - } else if (msgType == DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_RESPONSE) { + } + // send by diff provider, diff provider encode + else if (msgType == DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_RESPONSE) { if (fromHeight != toHeight) { throw new IllegalArgumentException("Height parameter error!"); } diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSProcessManager.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSProcessManager.java index cab88add..97b14602 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSProcessManager.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSProcessManager.java @@ -13,17 +13,17 @@ import com.jd.blockchain.stp.communication.callback.CallBackDataListener; import com.jd.blockchain.stp.communication.manager.RemoteSessionManager; import com.jd.blockchain.stp.communication.node.LocalNode; import com.jd.blockchain.stp.communication.node.RemoteNode; -import com.jd.blockchain.utils.concurrent.CompletableAsyncFuture; import java.net.InetSocketAddress; import java.util.*; import java.util.concurrent.*; /** - * + * 数据序列状态复制过程管理器 * @author zhangshuang * @create 2019/4/11 * @since 1.0.0 + * */ public class DSProcessManager { @@ -32,14 +32,19 @@ public class DSProcessManager { private long dsInfoResponseTimeout = 20000; private ExecutorService writeExecutors = Executors.newFixedThreadPool(5); private int returnCode = 0; + /** - * - * + * 启动一个指定数据序列的状态复制过程 + * @param dsInfo 数据序列当前状态信息 + * @param listener 本地监听者 + * @param targets 目标结点 + * @param dsWriter 差异请求者执行数据序列更新的执行器 + * @param dsReader 差异响应者执行数据序列读取的执行器 + * @return returnCode 执行结果码 */ public int startDSProcess(DataSequenceInfo dsInfo, InetSocketAddress listener, InetSocketAddress[] targets, DataSequenceWriter dsWriter, DataSequenceReader dsReader) { // create remote sessions manager, add listener - LocalNode listenNode = new LocalNode(listener.getHostName(), listener.getPort(), new DSDefaultMessageExecutor(dsReader, dsWriter)); RemoteSessionManager remoteSessionManager = new RemoteSessionManager(listenNode); @@ -116,17 +121,13 @@ public class DSProcessManager { RemoteSession responseSession = findResponseSession(diffResult.getMaxHeightRemoteNode(), remoteSessions); System.out.println("Async send CMD_GETDSDIFF_REQUEST msg to targets will start!"); + // step5: collect get data sequence diff response for (long height = dsInfo.getHeight() + 1; height < diffResult.getMaxHeight() + 1; height++) { CallBackDataListener dsDiffResponse = dsTransferProcess.send(DSTransferProcess.DataSequenceMsgType.CMD_GETDSDIFF_REQUEST, responseSession, height, height, callBackBarrierDiff); dsDiffResponses.addLast(dsDiffResponse); } - - // 考虑性能 -// writeExecutors.execute(() -> { -// -// }); - + // 上述发送不合理,考虑一次性发送请求 System.out.println("Wait CMD_GETDSDIFF_RESPONSE msg from targets!"); LinkedList receiveDiffResponses = new LinkedList<>(); if (callBackBarrierDiff.tryCall()) { @@ -159,6 +160,12 @@ public class DSProcessManager { return returnCode; } + /** + * 根据远端结点找与远端结点建立的会话 + * @param remoteNode 远端结点 + * @param remoteSessions 本地维护的远端结点会话表 + * @return 与远端结点对应的会话 + */ RemoteSession findResponseSession(RemoteNode remoteNode, RemoteSession[] remoteSessions) { for (RemoteSession remoteSession : remoteSessions) { if (remoteSession.remoteNode().equals(remoteNode)) { @@ -171,9 +178,9 @@ public class DSProcessManager { * * */ - void setDSReader(DataSequenceReader reader) { - - } +// void setDSReader(DataSequenceReader reader) { +// +// } } diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSTransferProcess.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSTransferProcess.java index b1e6b817..45fc89fb 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSTransferProcess.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/process/DSTransferProcess.java @@ -20,7 +20,7 @@ import java.util.LinkedList; import java.util.Map; /** - * + * 数据序列状态复制过程 * @author zhangshuang * @create 2019/4/11 * @since 1.0.0 @@ -36,8 +36,8 @@ public class DSTransferProcess { private String id; /** - * - * + * @param dsInfo 数据序列当前状态信息 + * @param targets 目标结点 */ public DSTransferProcess(DataSequenceInfo dsInfo, InetSocketAddress[] targets) { this.dsInfo = dsInfo; @@ -45,30 +45,46 @@ public class DSTransferProcess { this.id = dsInfo.getId(); } + /** + * @param dsWriter 差异请求者执行数据序列更新的执行器 + * @return void + */ public void setDSWriter(DataSequenceWriter dsWriter) { this.dsWriter = dsWriter; } + /** + * @param dsReader 差异响应者执行数据序列读取的执行器 + * @return void + */ public void setDSReader(DataSequenceReader dsReader) { this.dsReader = dsReader; } + /** + * @param remoteSessionManager 远端会话管理器 + * @return void + */ public void setRemoteSessionManager(RemoteSessionManager remoteSessionManager) { this.remoteSessionManager = remoteSessionManager; } /** - * get unique id from data sequence transfer process * + * @return 数据序列标识符 */ public String getId() { return id; } /** - * - * + * @param msgType 数据序列差异请求消息类型 + * @param remoteSession 目标结点对应的会话 + * @param fromHeight 差异起始高度 + * @param toHeight 差异结束高度 + * @param callBackBarrier 异步回调 + * @return 异步回调 */ CallBackDataListener send(DataSequenceMsgType msgType, RemoteSession remoteSession, long fromHeight, long toHeight, CallBackBarrier callBackBarrier) { @@ -76,9 +92,11 @@ public class DSTransferProcess { return remoteSession.asyncRequest(new DataSequenceLoadMessage(loadMessage), callBackBarrier); } + /** - * - * + * 计算数据序列差异元素数组 + * @param diffArray 差异的字节数组 + * @return 对差异字节数组的解码结果 */ public ArrayList computeDiffElement(byte[][] diffArray) { @@ -98,8 +116,9 @@ public class DSTransferProcess { } /** - * - * + * 根据差异提供者响应的数据序列状态信息找到拥有最大数据序列高度的远端结点 + * @param receiveResponses 数据序列差异请求者收到的远端结点状态的响应信息 + * @return 得到远端数据序列的最大高度以及拥有者结点 */ public DSInfoResponseResult computeDiffInfo(LinkedList receiveResponses) { long maxHeight = 0; @@ -110,11 +129,10 @@ public class DSTransferProcess { try { for (CallBackDataListener receiveResponse : receiveResponses) { Object object = DSMsgResolverFactory.getDecoder(dsWriter, dsReader).decode(receiveResponse.getCallBackData()); -// System.out.println("ComputeDiffInfo object = "+object); if (object instanceof DataSequenceInfo) { DataSequenceInfo dsInfo = (DataSequenceInfo) object; long height = dsInfo.getHeight(); -// System.out.println("ComputeDiffInfo height = " +height); + // sava max height and its remote node if (maxHeight < height) { maxHeight = height; maxHeightRemoteNode = receiveResponse.remoteNode(); @@ -134,24 +152,17 @@ public class DSTransferProcess { } /** - * - * - */ - public void getDSInfo(String id) { - - } - - /** - * - * + * 获取本复制过程维护的远端会话表 + * @param + * @return 远端会话表数组 */ public RemoteSession[] getSessions() { return remoteSessions; } /** - * close all sessions - * + * 关闭本复制过程维护的所有远端会话 + * @return void */ public void close() { for (RemoteSession session : remoteSessions) { @@ -160,8 +171,8 @@ public class DSTransferProcess { } /** - * establish connections with target remote nodes - * + * 建立与远端目标结点的连接,产生本地维护的远端会话表 + * @return void */ public void start() { @@ -176,7 +187,7 @@ public class DSTransferProcess { /** - * data sequence transfer message type + * 数据序列状态传输使用的消息类型 * */ public enum DataSequenceMsgType { diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/result/DSDiffRequestResult.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/result/DSDiffRequestResult.java index f71ebbfb..af62bd6c 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/result/DSDiffRequestResult.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/result/DSDiffRequestResult.java @@ -1,5 +1,11 @@ package com.jd.blockchain.statetransfer.result; +/** + * 数据序列差异提供者解码请求者"CMD_GETDSDIFF_REQUEST"消息时得到的结果 + * @author zhangshuang + * @create 2019/4/18 + * @since 1.0.0 + */ public class DSDiffRequestResult { String id; diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/result/DSInfoResponseResult.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/result/DSInfoResponseResult.java index 9a7ea126..7f6d48cc 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/result/DSInfoResponseResult.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/result/DSInfoResponseResult.java @@ -1,13 +1,12 @@ package com.jd.blockchain.statetransfer.result; -import com.jd.blockchain.stp.communication.RemoteSession; import com.jd.blockchain.stp.communication.node.RemoteNode; /** - * - * - * - * + * 数据序列差异请求者解码提供者"CMD_DSINFO_RESPONSE"消息时得到的结果 + * @author zhangshuang + * @create 2019/4/18 + * @since 1.0.0 */ public class DSInfoResponseResult { diff --git a/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequence.java b/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequence.java index ed41757b..fcb932c3 100644 --- a/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequence.java +++ b/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequence.java @@ -6,11 +6,18 @@ import com.jd.blockchain.statetransfer.DataSequenceInfo; import java.net.InetSocketAddress; import java.util.LinkedList; +/** + * 测试过程建立的一个数据序列 + * @author zhangshuang + * @create 2019/4/18 + * @since 1.0.0 + */ public class DataSequence { private InetSocketAddress address; private String id; + // 每个数据序列维护了一系列的数据序列元素 private LinkedList dataSequenceElements = new LinkedList<>(); @@ -27,6 +34,7 @@ public class DataSequence { return address; } + public void addElements(DataSequenceElement[] elements) { for (DataSequenceElement element : elements) { addElement(element); diff --git a/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceReaderImpl.java b/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceReaderImpl.java index cbb97172..84b5477c 100644 --- a/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceReaderImpl.java +++ b/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceReaderImpl.java @@ -8,11 +8,10 @@ import java.net.InetSocketAddress; import java.util.LinkedList; /** - *数据序列差异的提供者需要使用的回调接口实现类 + * 数据序列差异的提供者需要使用的回调接口实现类(测试) * @author zhangshuang * @create 2019/4/22 * @since 1.0.0 - * */ public class DataSequenceReaderImpl implements DataSequenceReader { diff --git a/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceWriterImpl.java b/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceWriterImpl.java index 9da566c2..c3fb037e 100644 --- a/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceWriterImpl.java +++ b/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceWriterImpl.java @@ -5,11 +5,10 @@ import com.jd.blockchain.statetransfer.DataSequenceInfo; import com.jd.blockchain.statetransfer.callback.DataSequenceWriter; /** - *数据序列差异的请求者需要使用的回调接口实现类 + * 数据序列差异的请求者需要使用的回调接口实现类(测试) * @author zhangshuang * @create 2019/4/22 * @since 1.0.0 - * */ public class DataSequenceWriterImpl implements DataSequenceWriter { diff --git a/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/StateTransferLayerTest.java b/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/StateTransferLayerTest.java index 9a185d95..b42c0b4e 100644 --- a/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/StateTransferLayerTest.java +++ b/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/StateTransferLayerTest.java @@ -14,6 +14,11 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +/** + * @author zhangshuang + * @create 2019/4/18 + * @since 1.0.0 + */ public class StateTransferLayerTest { private final int[] listenPorts = new int[]{9000, 9010, 9020, 9030}; @@ -87,9 +92,9 @@ public class StateTransferLayerTest { } } - // 获得除监听结点之外的其他远端结点 InetSocketAddress[] getTargetNodesIp(InetSocketAddress listenIp, InetSocketAddress[] remoteNodeIps) { + // 获得除监听结点之外的其他远端结点 InetSocketAddress[] targets = new InetSocketAddress[remoteNodeIps.length - 1]; int j = 0; @@ -104,6 +109,7 @@ public class StateTransferLayerTest { } + DataSequence findDataSequence(String id, InetSocketAddress listenNodeAddr) { for (DataSequence dataSequence : dataSequencesPerNode) { if ((dataSequence.getAddress().getPort() == listenNodeAddr.getPort() && (dataSequence.getAddress().getHostName().equals(listenNodeAddr.getHostName())) From 9a6a9e4fd166faa80b4f918bde7dffdfb2ec6796 Mon Sep 17 00:00:00 2001 From: zhangshuang Date: Mon, 6 May 2019 16:26:21 +0800 Subject: [PATCH 17/43] adjustment code --- .../statetransfer/DataSequenceReaderImpl.java | 264 +++++++------- .../statetransfer/DataSequenceWriterImpl.java | 340 +++++++++--------- .../statetransfer/DataSequence.java | 5 +- .../callback}/DataSequenceReaderImpl.java | 8 +- .../callback/DataSequenceWriter.java | 2 +- .../callback/DataSequenceWriterImpl.java | 142 ++++++++ .../statetransfer/DataSequenceWriterImpl.java | 68 ---- .../statetransfer/StateTransferLayerTest.java | 3 + 8 files changed, 453 insertions(+), 379 deletions(-) rename source/state-transfer/src/{test/java/test => main/java}/com/jd/blockchain/statetransfer/DataSequence.java (92%) rename source/state-transfer/src/{test/java/test/com/jd/blockchain/statetransfer => main/java/com/jd/blockchain/statetransfer/callback}/DataSequenceReaderImpl.java (90%) create mode 100644 source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriterImpl.java delete mode 100644 source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceWriterImpl.java diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceReaderImpl.java b/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceReaderImpl.java index 620efcc5..71161411 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceReaderImpl.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceReaderImpl.java @@ -1,132 +1,132 @@ -package com.jd.blockchain.peer.statetransfer; - -import com.jd.blockchain.binaryproto.BinaryEncodingUtils; -import com.jd.blockchain.crypto.hash.HashDigest; -import com.jd.blockchain.ledger.LedgerBlock; -import com.jd.blockchain.ledger.LedgerTransaction; -import com.jd.blockchain.ledger.core.LedgerManage; -import com.jd.blockchain.ledger.core.LedgerRepository; -import com.jd.blockchain.ledger.core.TransactionSet; -import com.jd.blockchain.statetransfer.DataSequenceElement; -import com.jd.blockchain.statetransfer.DataSequenceInfo; -import com.jd.blockchain.statetransfer.callback.DataSequenceReader; -import com.jd.blockchain.storage.service.DbConnection; -import com.jd.blockchain.storage.service.DbConnectionFactory; -import com.jd.blockchain.tools.initializer.LedgerBindingConfig; -import com.jd.blockchain.utils.codec.Base58Utils; -import com.jd.blockchain.utils.codec.HexUtils; -import org.springframework.beans.factory.annotation.Autowired; - -/** - *数据序列差异的提供者需要使用的回调接口实现类 - * @author zhangshuang - * @create 2019/4/11 - * @since 1.0.0 - */ -public class DataSequenceReaderImpl implements DataSequenceReader { - - private LedgerManage ledgerManager; - - private DbConnectionFactory connFactory; - - private LedgerBindingConfig config; - - public DataSequenceReaderImpl(LedgerBindingConfig config, LedgerManage ledgerManager, DbConnectionFactory connFactory) { - this.config = config; - this.ledgerManager = ledgerManager; - this.connFactory = connFactory; - } - - - /** - * @param id 账本哈希的Base58编码 - * @return DataSequenceInfo 数据序列信息 - */ - @Override - public DataSequenceInfo getDSInfo(String id) { - - byte[] hashBytes = Base58Utils.decode(id); - - HashDigest ledgerHash = new HashDigest(hashBytes); - - LedgerBindingConfig.BindingConfig bindingConfig = config.getLedger(ledgerHash); - DbConnection dbConnNew = connFactory.connect(bindingConfig.getDbConnection().getUri(), - bindingConfig.getDbConnection().getPassword()); - LedgerRepository ledgerRepository = ledgerManager.register(ledgerHash, dbConnNew.getStorageService()); - - return new DataSequenceInfo(id, ledgerRepository.getLatestBlockHeight()); - } - - /** - * - * @param id 账本哈希的Base58编码 - * @param from 数据序列复制的起始高度 - * @param to 数据序列复制的结束高度 - * @return DataSequenceElement【】数据序列差异数据元素的数组 - */ - @Override - public DataSequenceElement[] getDSDiffContent(String id, long from, long to) { - - DataSequenceElement[] dataSequenceElements = new DataSequenceElement[(int)(to - from + 1)]; - for (long i = from; i < to + 1; i++) { - dataSequenceElements[(int)(i - from)] = getDSDiffContent(id, i); - } - - return dataSequenceElements; - } - - /** - * 账本交易序列化 - * @param transaction 账本交易 - * @return byte[] 对账本交易进行序列化的结果 - */ - private byte[] serialize(LedgerTransaction transaction) { - return BinaryEncodingUtils.encode(transaction, LedgerTransaction.class); - } - - /** - * 获得账本某一高度区块上的所有交易 - * @param id 账本哈希的Base58编码 - * @param height 账本的某个区块高度 - * @return DataSequenceElement 数据序列差异数据元素 - */ - @Override - public DataSequenceElement getDSDiffContent(String id, long height) { - - int lastHeightTxTotalNums = 0; - - byte[][] transacionDatas = null; - - byte[] hashBytes = Base58Utils.decode(id); - - HashDigest ledgerHash = new HashDigest(hashBytes); - - LedgerBindingConfig.BindingConfig bindingConfig = config.getLedger(ledgerHash); - DbConnection dbConnNew = connFactory.connect(bindingConfig.getDbConnection().getUri(), - bindingConfig.getDbConnection().getPassword()); - LedgerRepository ledgerRepository = ledgerManager.register(ledgerHash, dbConnNew.getStorageService()); - - LedgerBlock ledgerBlock = ledgerRepository.getBlock(height); - TransactionSet transactionSet = ledgerRepository.getTransactionSet(ledgerBlock); - - if (height > 0) { - lastHeightTxTotalNums = (int) ledgerRepository.getTransactionSet(ledgerRepository.getBlock(height - 1)).getTotalCount(); - } - - int currentHeightTxTotalNums = (int)ledgerRepository.getTransactionSet(ledgerRepository.getBlock(height)).getTotalCount(); - - // get all transactions from current height block - int currentHeightTxNums = currentHeightTxTotalNums - lastHeightTxTotalNums; - - LedgerTransaction[] transactions = transactionSet.getTxs(lastHeightTxTotalNums , currentHeightTxNums); - - for (int i = 0; i < transactions.length; i++) { - byte[] transactionData = serialize(transactions[i]); - transacionDatas[i] = transactionData; - } - - return new DataSequenceElement(id, height, transacionDatas); - } - - -} +//package com.jd.blockchain.peer.statetransfer; +// +//import com.jd.blockchain.binaryproto.BinaryEncodingUtils; +//import com.jd.blockchain.crypto.hash.HashDigest; +//import com.jd.blockchain.ledger.LedgerBlock; +//import com.jd.blockchain.ledger.LedgerTransaction; +//import com.jd.blockchain.ledger.core.LedgerManage; +//import com.jd.blockchain.ledger.core.LedgerRepository; +//import com.jd.blockchain.ledger.core.TransactionSet; +//import com.jd.blockchain.statetransfer.DataSequenceElement; +//import com.jd.blockchain.statetransfer.DataSequenceInfo; +//import com.jd.blockchain.statetransfer.callback.DataSequenceReader; +//import com.jd.blockchain.storage.service.DbConnection; +//import com.jd.blockchain.storage.service.DbConnectionFactory; +//import com.jd.blockchain.tools.initializer.LedgerBindingConfig; +//import com.jd.blockchain.utils.codec.Base58Utils; +//import com.jd.blockchain.utils.codec.HexUtils; +//import org.springframework.beans.factory.annotation.Autowired; +// +///** +// *数据序列差异的提供者需要使用的回调接口实现类 +// * @author zhangshuang +// * @create 2019/4/11 +// * @since 1.0.0 +// */ +//public class DataSequenceReaderImpl implements DataSequenceReader { +// +// private LedgerManage ledgerManager; +// +// private DbConnectionFactory connFactory; +// +// private LedgerBindingConfig config; +// +// public DataSequenceReaderImpl(LedgerBindingConfig config, LedgerManage ledgerManager, DbConnectionFactory connFactory) { +// this.config = config; +// this.ledgerManager = ledgerManager; +// this.connFactory = connFactory; +// } +// +// +// /** +// * @param id 账本哈希的Base58编码 +// * @return DataSequenceInfo 数据序列信息 +// */ +// @Override +// public DataSequenceInfo getDSInfo(String id) { +// +// byte[] hashBytes = Base58Utils.decode(id); +// +// HashDigest ledgerHash = new HashDigest(hashBytes); +// +// LedgerBindingConfig.BindingConfig bindingConfig = config.getLedger(ledgerHash); +// DbConnection dbConnNew = connFactory.connect(bindingConfig.getDbConnection().getUri(), +// bindingConfig.getDbConnection().getPassword()); +// LedgerRepository ledgerRepository = ledgerManager.register(ledgerHash, dbConnNew.getStorageService()); +// +// return new DataSequenceInfo(id, ledgerRepository.getLatestBlockHeight()); +// } +// +// /** +// * +// * @param id 账本哈希的Base58编码 +// * @param from 数据序列复制的起始高度 +// * @param to 数据序列复制的结束高度 +// * @return DataSequenceElement【】数据序列差异数据元素的数组 +// */ +// @Override +// public DataSequenceElement[] getDSDiffContent(String id, long from, long to) { +// +// DataSequenceElement[] dataSequenceElements = new DataSequenceElement[(int)(to - from + 1)]; +// for (long i = from; i < to + 1; i++) { +// dataSequenceElements[(int)(i - from)] = getDSDiffContent(id, i); +// } +// +// return dataSequenceElements; +// } +// +// /** +// * 账本交易序列化 +// * @param transaction 账本交易 +// * @return byte[] 对账本交易进行序列化的结果 +// */ +// private byte[] serialize(LedgerTransaction transaction) { +// return BinaryEncodingUtils.encode(transaction, LedgerTransaction.class); +// } +// +// /** +// * 获得账本某一高度区块上的所有交易 +// * @param id 账本哈希的Base58编码 +// * @param height 账本的某个区块高度 +// * @return DataSequenceElement 数据序列差异数据元素 +// */ +// @Override +// public DataSequenceElement getDSDiffContent(String id, long height) { +// +// int lastHeightTxTotalNums = 0; +// +// byte[][] transacionDatas = null; +// +// byte[] hashBytes = Base58Utils.decode(id); +// +// HashDigest ledgerHash = new HashDigest(hashBytes); +// +// LedgerBindingConfig.BindingConfig bindingConfig = config.getLedger(ledgerHash); +// DbConnection dbConnNew = connFactory.connect(bindingConfig.getDbConnection().getUri(), +// bindingConfig.getDbConnection().getPassword()); +// LedgerRepository ledgerRepository = ledgerManager.register(ledgerHash, dbConnNew.getStorageService()); +// +// LedgerBlock ledgerBlock = ledgerRepository.getBlock(height); +// TransactionSet transactionSet = ledgerRepository.getTransactionSet(ledgerBlock); +// +// if (height > 0) { +// lastHeightTxTotalNums = (int) ledgerRepository.getTransactionSet(ledgerRepository.getBlock(height - 1)).getTotalCount(); +// } +// +// int currentHeightTxTotalNums = (int)ledgerRepository.getTransactionSet(ledgerRepository.getBlock(height)).getTotalCount(); +// +// // get all transactions from current height block +// int currentHeightTxNums = currentHeightTxTotalNums - lastHeightTxTotalNums; +// +// LedgerTransaction[] transactions = transactionSet.getTxs(lastHeightTxTotalNums , currentHeightTxNums); +// +// for (int i = 0; i < transactions.length; i++) { +// byte[] transactionData = serialize(transactions[i]); +// transacionDatas[i] = transactionData; +// } +// +// return new DataSequenceElement(id, height, transacionDatas); +// } +// +// +//} diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceWriterImpl.java b/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceWriterImpl.java index 61cfde0f..774e69b5 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceWriterImpl.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceWriterImpl.java @@ -1,170 +1,170 @@ -package com.jd.blockchain.peer.statetransfer; - -import com.jd.blockchain.consensus.service.MessageHandle; -import com.jd.blockchain.ledger.TransactionState; -import com.jd.blockchain.statetransfer.DataSequenceElement; -import com.jd.blockchain.statetransfer.DataSequenceInfo; -import com.jd.blockchain.statetransfer.callback.DataSequenceWriter; -import com.jd.blockchain.statetransfer.comparator.DataSequenceComparator; - -import java.util.ArrayList; -import java.util.Collections; - -/** - *数据序列差异的请求者需要使用的回调接口实现类 - * @author zhangshuang - * @create 2019/4/11 - * @since 1.0.0 - */ -public class DataSequenceWriterImpl implements DataSequenceWriter { - - private long currHeight; - private ArrayList deceidedElements = new ArrayList(); - - private MessageHandle batchMessageHandle; - - - public DataSequenceWriterImpl(MessageHandle batchMessageHandle) { - this.batchMessageHandle = batchMessageHandle; - } - - /** - * 检查数据序列差异元素中的高度是否合理; - * @param currHeight 当前结点的账本高度 - * @param dsUpdateElements 需要更新到本地结点的数据序列元素List - * @return - */ - private int checkElementsHeight(long currHeight, ArrayList dsUpdateElements) { - boolean lossMiddleElements = false; - - // lose first element - if (currHeight + 1 < dsUpdateElements.get(0).getHeight()){ - System.out.println("Diff response loss first element error!"); - return DataSequenceErrorType.DATA_SEQUENCE_LOSS_FIRST_ELEMENT.CODE; - } - else { - for (int i = 0; i < dsUpdateElements.size(); i++) { - if (dsUpdateElements.get(i).getHeight() == currHeight + 1 + i) { - deceidedElements.add(dsUpdateElements.get(i)); - } - // lose middle elements - else { - lossMiddleElements = true; - break; - } - } - - if (lossMiddleElements) { - System.out.println("Diff response loss middle elements error!"); - return DataSequenceErrorType.DATA_SEQUENCE_LOSS_MIDDLE_ELEMENT.CODE; - } - - System.out.println("Diff response elements height normal!"); - return DataSequenceErrorType.DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL.CODE; - } - - } - - /** - * 对本地结点执行账本更新 - * @param realmName 账本哈希的Base58编码 - * @return void - */ - private void exeUpdate(String realmName) { - - for (int i = 0; i < deceidedElements.size(); i++) { - byte[][] element = deceidedElements.get(i).getData(); - - String batchId = batchMessageHandle.beginBatch(realmName); - try { - int msgId = 0; - for (byte[] txContent : element) { - batchMessageHandle.processOrdered(msgId++, txContent, realmName, batchId); - } - // 结块 - batchMessageHandle.completeBatch(realmName, batchId); - batchMessageHandle.commitBatch(realmName, batchId); - } catch (Exception e) { - // todo 需要处理应答码 404 - batchMessageHandle.rollbackBatch(realmName, batchId, TransactionState.DATA_SEQUENCE_UPDATE_ERROR.CODE); - } - } - - } - - /** - * @param dsInfo 当前结点的数据序列信息 - * @param diffContents 数据序列差异的数据元素数组 - * @return int 更新结果码 - */ - @Override - public int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement[] diffContents) { - int result = 0; - - try { - ArrayList dsUpdateElements = new ArrayList(); - //remove unexpected elements - for (int i = 0 ; i < diffContents.length; i++) { - if (diffContents[i].getId().equals(dsInfo.getId())) { - dsUpdateElements.add(diffContents[i]); - } - } - - // sort elements by height - Collections.sort(dsUpdateElements, new DataSequenceComparator()); - - currHeight = dsInfo.getHeight(); - - // check element's height - result = checkElementsHeight(currHeight, dsUpdateElements); - - // cann't exe update - if (result == DataSequenceErrorType.DATA_SEQUENCE_LOSS_FIRST_ELEMENT.CODE) { - return result; - } - // exe elements update - else { - exeUpdate(dsInfo.getId()); - return result; - } - } catch (Exception e) { - System.out.println(e.getMessage()); - e.printStackTrace(); - } - - return result; - } - - @Override - public int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement diffContents) { - return 0; - } - - - /** - * 数据序列更新错误码 - * @param - * @return - */ - public enum DataSequenceErrorType { - DATA_SEQUENCE_LOSS_FIRST_ELEMENT((byte) 0x1), - DATA_SEQUENCE_LOSS_MIDDLE_ELEMENT((byte) 0x2), - DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL((byte) 0x3), - ; - public final int CODE; - - private DataSequenceErrorType(byte code) { - this.CODE = code; - } - - public static DataSequenceErrorType valueOf(byte code) { - for (DataSequenceErrorType errorType : DataSequenceErrorType.values()) { - if (errorType.CODE == code) { - return errorType; - } - } - throw new IllegalArgumentException("Unsupported code[" + code + "] of errorType!"); - } - } - -} +//package com.jd.blockchain.peer.statetransfer; +// +//import com.jd.blockchain.consensus.service.MessageHandle; +//import com.jd.blockchain.ledger.TransactionState; +//import com.jd.blockchain.statetransfer.DataSequenceElement; +//import com.jd.blockchain.statetransfer.DataSequenceInfo; +//import com.jd.blockchain.statetransfer.callback.DataSequenceWriter; +//import com.jd.blockchain.statetransfer.comparator.DataSequenceComparator; +// +//import java.util.ArrayList; +//import java.util.Collections; +// +///** +// *数据序列差异的请求者需要使用的回调接口实现类 +// * @author zhangshuang +// * @create 2019/4/11 +// * @since 1.0.0 +// */ +//public class DataSequenceWriterImpl implements DataSequenceWriter { +// +// private long currHeight; +// private ArrayList deceidedElements = new ArrayList(); +// +// private MessageHandle batchMessageHandle; +// +// +// public DataSequenceWriterImpl(MessageHandle batchMessageHandle) { +// this.batchMessageHandle = batchMessageHandle; +// } +// +// /** +// * 检查数据序列差异元素中的高度是否合理; +// * @param currHeight 当前结点的账本高度 +// * @param dsUpdateElements 需要更新到本地结点的数据序列元素List +// * @return +// */ +// private int checkElementsHeight(long currHeight, ArrayList dsUpdateElements) { +// boolean lossMiddleElements = false; +// +// // lose first element +// if (currHeight + 1 < dsUpdateElements.get(0).getHeight()){ +// System.out.println("Diff response loss first element error!"); +// return DataSequenceErrorType.DATA_SEQUENCE_LOSS_FIRST_ELEMENT.CODE; +// } +// else { +// for (int i = 0; i < dsUpdateElements.size(); i++) { +// if (dsUpdateElements.get(i).getHeight() == currHeight + 1 + i) { +// deceidedElements.add(dsUpdateElements.get(i)); +// } +// // lose middle elements +// else { +// lossMiddleElements = true; +// break; +// } +// } +// +// if (lossMiddleElements) { +// System.out.println("Diff response loss middle elements error!"); +// return DataSequenceErrorType.DATA_SEQUENCE_LOSS_MIDDLE_ELEMENT.CODE; +// } +// +// System.out.println("Diff response elements height normal!"); +// return DataSequenceErrorType.DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL.CODE; +// } +// +// } +// +// /** +// * 对本地结点执行账本更新 +// * @param realmName 账本哈希的Base58编码 +// * @return void +// */ +// private void exeUpdate(String realmName) { +// +// for (int i = 0; i < deceidedElements.size(); i++) { +// byte[][] element = deceidedElements.get(i).getData(); +// +// String batchId = batchMessageHandle.beginBatch(realmName); +// try { +// int msgId = 0; +// for (byte[] txContent : element) { +// batchMessageHandle.processOrdered(msgId++, txContent, realmName, batchId); +// } +// // 结块 +// batchMessageHandle.completeBatch(realmName, batchId); +// batchMessageHandle.commitBatch(realmName, batchId); +// } catch (Exception e) { +// // todo 需要处理应答码 404 +// batchMessageHandle.rollbackBatch(realmName, batchId, TransactionState.DATA_SEQUENCE_UPDATE_ERROR.CODE); +// } +// } +// +// } +// +// /** +// * @param dsInfo 当前结点的数据序列信息 +// * @param diffContents 数据序列差异的数据元素数组 +// * @return int 更新结果码 +// */ +// @Override +// public int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement[] diffContents) { +// int result = 0; +// +// try { +// ArrayList dsUpdateElements = new ArrayList(); +// //remove unexpected elements +// for (int i = 0 ; i < diffContents.length; i++) { +// if (diffContents[i].getId().equals(dsInfo.getId())) { +// dsUpdateElements.add(diffContents[i]); +// } +// } +// +// // sort elements by height +// Collections.sort(dsUpdateElements, new DataSequenceComparator()); +// +// currHeight = dsInfo.getHeight(); +// +// // check element's height +// result = checkElementsHeight(currHeight, dsUpdateElements); +// +// // cann't exe update +// if (result == DataSequenceErrorType.DATA_SEQUENCE_LOSS_FIRST_ELEMENT.CODE) { +// return result; +// } +// // exe elements update +// else { +// exeUpdate(dsInfo.getId()); +// return result; +// } +// } catch (Exception e) { +// System.out.println(e.getMessage()); +// e.printStackTrace(); +// } +// +// return result; +// } +// +// @Override +// public int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement diffContents) { +// return 0; +// } +// +// +// /** +// * 数据序列更新错误码 +// * @param +// * @return +// */ +// public enum DataSequenceErrorType { +// DATA_SEQUENCE_LOSS_FIRST_ELEMENT((byte) 0x1), +// DATA_SEQUENCE_LOSS_MIDDLE_ELEMENT((byte) 0x2), +// DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL((byte) 0x3), +// ; +// public final int CODE; +// +// private DataSequenceErrorType(byte code) { +// this.CODE = code; +// } +// +// public static DataSequenceErrorType valueOf(byte code) { +// for (DataSequenceErrorType errorType : DataSequenceErrorType.values()) { +// if (errorType.CODE == code) { +// return errorType; +// } +// } +// throw new IllegalArgumentException("Unsupported code[" + code + "] of errorType!"); +// } +// } +// +//} diff --git a/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequence.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequence.java similarity index 92% rename from source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequence.java rename to source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequence.java index fcb932c3..237a6d47 100644 --- a/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequence.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequence.java @@ -1,7 +1,4 @@ -package test.com.jd.blockchain.statetransfer; - -import com.jd.blockchain.statetransfer.DataSequenceElement; -import com.jd.blockchain.statetransfer.DataSequenceInfo; +package com.jd.blockchain.statetransfer; import java.net.InetSocketAddress; import java.util.LinkedList; diff --git a/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceReaderImpl.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceReaderImpl.java similarity index 90% rename from source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceReaderImpl.java rename to source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceReaderImpl.java index 84b5477c..3d581b2d 100644 --- a/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceReaderImpl.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceReaderImpl.java @@ -1,14 +1,13 @@ -package test.com.jd.blockchain.statetransfer; +package com.jd.blockchain.statetransfer.callback; +import com.jd.blockchain.statetransfer.DataSequence; import com.jd.blockchain.statetransfer.DataSequenceElement; import com.jd.blockchain.statetransfer.DataSequenceInfo; -import com.jd.blockchain.statetransfer.callback.DataSequenceReader; -import java.net.InetSocketAddress; import java.util.LinkedList; /** - * 数据序列差异的提供者需要使用的回调接口实现类(测试) + * 数据序列差异的提供者需要使用的回调接口实现类 * @author zhangshuang * @create 2019/4/22 * @since 1.0.0 @@ -57,3 +56,4 @@ public class DataSequenceReaderImpl implements DataSequenceReader { return null; } } + diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriter.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriter.java index a38362c7..b45eb3ac 100644 --- a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriter.java +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriter.java @@ -25,6 +25,6 @@ public interface DataSequenceWriter { * @param diffContent 需要更新的差异元素 * @return 更新结果编码 */ - int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement diffContent); +// int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement diffContent); } diff --git a/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriterImpl.java b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriterImpl.java new file mode 100644 index 00000000..c510e843 --- /dev/null +++ b/source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriterImpl.java @@ -0,0 +1,142 @@ +package com.jd.blockchain.statetransfer.callback; + +import com.jd.blockchain.statetransfer.DataSequence; +import com.jd.blockchain.statetransfer.DataSequenceElement; +import com.jd.blockchain.statetransfer.DataSequenceInfo; + +import java.util.ArrayList; + +/** + * 数据序列差异的请求者需要使用的回调接口实现类 + * @author zhangshuang + * @create 2019/4/22 + * @since 1.0.0 + */ +public class DataSequenceWriterImpl implements DataSequenceWriter { + + private long currHeight; + private DataSequence currDataSequence; + private ArrayList deceidedElements = new ArrayList(); + + public DataSequenceWriterImpl(DataSequence currDataSequence) { + this.currDataSequence = currDataSequence; + } + + /** + * 检查数据序列差异元素中的高度是否合理; + * @param currHeight 当前结点的账本高度 + * @param dsUpdateElements 需要更新到本地结点的数据序列元素List + * @return + */ + private int checkElementsHeight(long currHeight, ArrayList dsUpdateElements) { + boolean lossMiddleElements = false; + + // lose first element + if (currHeight + 1 < dsUpdateElements.get(0).getHeight()){ + System.out.println("Diff response loss first element error!"); + return DataSequenceErrorType.DATA_SEQUENCE_LOSS_FIRST_ELEMENT.CODE; + } + else { + for (int i = 0; i < dsUpdateElements.size(); i++) { + if (dsUpdateElements.get(i).getHeight() == currHeight + 1 + i) { + deceidedElements.add(dsUpdateElements.get(i)); + } + // lose middle elements + else { + lossMiddleElements = true; + break; + } + } + + if (lossMiddleElements) { + System.out.println("Diff response loss middle elements error!"); + return DataSequenceErrorType.DATA_SEQUENCE_LOSS_MIDDLE_ELEMENT.CODE; + } + + System.out.println("Diff response elements height normal!"); + return DataSequenceErrorType.DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL.CODE; + } + + } + + @Override + public int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement[] diffContents) { + + int result = 0; + + try { + ArrayList dsUpdateElements = new ArrayList(); + + if (diffContents == null) { + throw new IllegalArgumentException("Update diffContents is null!"); + } + + //remove unexpected elements + for (int i = 0 ; i < diffContents.length; i++) { + if (diffContents[i].getId().equals(dsInfo.getId())) { + dsUpdateElements.add(diffContents[i]); + } + } + + currHeight = dsInfo.getHeight(); + + // check element's height + result = checkElementsHeight(currHeight, dsUpdateElements); + + // cann't exe update + if (result == DataSequenceErrorType.DATA_SEQUENCE_LOSS_FIRST_ELEMENT.CODE) { + return result; + } + // exe elements update + else { + System.out.println("Old data sequence state: "); + System.out.println(" Current height = " + currDataSequence.getDataSequenceElements().getLast().getHeight()); + currDataSequence.addElements(deceidedElements.toArray(new DataSequenceElement[deceidedElements.size()])); + + System.out.println("Update diffContents is completed!"); + System.out.println("New data sequence state: "); + System.out.println(" Current height = " + currDataSequence.getDataSequenceElements().getLast().getHeight()); + + return result; + } + + + + } catch (Exception e) { + System.out.println(e.getMessage()); + e.printStackTrace(); + } + + return DataSequenceErrorType.DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL.CODE; + + } + +// @Override +// public int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement diffContent) { +// currDataSequence.addElement(diffContent); +// return DataSequenceErrorType.DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL.CODE; +// } + + public enum DataSequenceErrorType { + DATA_SEQUENCE_LOSS_FIRST_ELEMENT((byte) 0x1), + DATA_SEQUENCE_LOSS_MIDDLE_ELEMENT((byte) 0x2), + DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL((byte) 0x3), + ; + public final int CODE; + + private DataSequenceErrorType(byte code) { + this.CODE = code; + } + + public static DataSequenceErrorType valueOf(byte code) { + for (DataSequenceErrorType errorType : DataSequenceErrorType.values()) { + if (errorType.CODE == code) { + return errorType; + } + } + throw new IllegalArgumentException("Unsupported code[" + code + "] of errorType!"); + } + } + +} + diff --git a/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceWriterImpl.java b/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceWriterImpl.java deleted file mode 100644 index c3fb037e..00000000 --- a/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceWriterImpl.java +++ /dev/null @@ -1,68 +0,0 @@ -package test.com.jd.blockchain.statetransfer; - -import com.jd.blockchain.statetransfer.DataSequenceElement; -import com.jd.blockchain.statetransfer.DataSequenceInfo; -import com.jd.blockchain.statetransfer.callback.DataSequenceWriter; - -/** - * 数据序列差异的请求者需要使用的回调接口实现类(测试) - * @author zhangshuang - * @create 2019/4/22 - * @since 1.0.0 - */ -public class DataSequenceWriterImpl implements DataSequenceWriter { - - DataSequence currDataSequence; - - public DataSequenceWriterImpl(DataSequence currDataSequence) { - this.currDataSequence = currDataSequence; - } - - @Override - public int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement[] diffContents) { - - if (diffContents == null) { - throw new IllegalArgumentException("Update diffContents is null!"); - } - - System.out.println("Old data sequence state: "); - System.out.println(" Current height = " + currDataSequence.getDataSequenceElements().getLast().getHeight()); - currDataSequence.addElements(diffContents); - - System.out.println("Update diffContents is completed!"); - System.out.println("New data sequence state: "); - System.out.println(" Current height = " + currDataSequence.getDataSequenceElements().getLast().getHeight()); - - - return DataSequenceErrorType.DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL.CODE; - - } - - @Override - public int updateDSInfo(DataSequenceInfo id, DataSequenceElement diffContent) { - currDataSequence.addElement(diffContent); - return DataSequenceErrorType.DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL.CODE; - } - - public enum DataSequenceErrorType { - DATA_SEQUENCE_LOSS_FIRST_ELEMENT((byte) 0x1), - DATA_SEQUENCE_LOSS_MIDDLE_ELEMENT((byte) 0x2), - DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL((byte) 0x3), - ; - public final int CODE; - - private DataSequenceErrorType(byte code) { - this.CODE = code; - } - - public static DataSequenceErrorType valueOf(byte code) { - for (DataSequenceErrorType errorType : DataSequenceErrorType.values()) { - if (errorType.CODE == code) { - return errorType; - } - } - throw new IllegalArgumentException("Unsupported code[" + code + "] of errorType!"); - } - } - -} diff --git a/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/StateTransferLayerTest.java b/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/StateTransferLayerTest.java index b42c0b4e..5741262e 100644 --- a/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/StateTransferLayerTest.java +++ b/source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/StateTransferLayerTest.java @@ -1,7 +1,10 @@ package test.com.jd.blockchain.statetransfer; +import com.jd.blockchain.statetransfer.DataSequence; import com.jd.blockchain.statetransfer.DataSequenceElement; import com.jd.blockchain.statetransfer.DataSequenceInfo; +import com.jd.blockchain.statetransfer.callback.DataSequenceReaderImpl; +import com.jd.blockchain.statetransfer.callback.DataSequenceWriterImpl; import com.jd.blockchain.statetransfer.process.DSProcessManager; import com.jd.blockchain.utils.codec.Base58Utils; import org.junit.Before; From a64ab90dd9785df28838154576c17bb196ae81be Mon Sep 17 00:00:00 2001 From: zhaoguangwei Date: Tue, 7 May 2019 15:38:46 +0800 Subject: [PATCH 18/43] =?UTF-8?q?=E5=9C=A8transactonContent=E5=AF=B9?= =?UTF-8?q?=E8=B1=A1=E4=B8=AD=E6=B7=BB=E5=8A=A0txOpTime=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=EF=BC=8C=E9=81=BF=E5=85=8D=E9=87=8D=E5=A4=8D=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E5=90=88=E7=BA=A6=E6=97=B6=EF=BC=8C=E5=87=BA=E7=8E=B0contentHa?= =?UTF-8?q?sh=E7=A2=B0=E6=92=9E=E7=9A=84=E9=97=AE=E9=A2=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ContractEventSendOperationHandle.java | 2 +- .../blockchain/ledger/TransactionContent.java | 46 ++-- .../ledger/TransactionContentBody.java | 80 +++---- .../jd/blockchain/ledger/data/TxBuilder.java | 177 ++++++++-------- .../blockchain/ledger/data/TxContentBlob.java | 196 ++++++++++-------- .../intgr/IntegrationTest4Bftsmart.java | 2 +- 6 files changed, 264 insertions(+), 239 deletions(-) diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractEventSendOperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractEventSendOperationHandle.java index 498457af..9edde458 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractEventSendOperationHandle.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractEventSendOperationHandle.java @@ -42,7 +42,7 @@ public class ContractEventSendOperationHandle implements OperationHandle { contract.getAddress().toBase58(),contract.getChaincodeVersion(),contract.getChainCode()). processEvent(localContractEventContext); } catch (Exception e) { - e.printStackTrace(); + throw new LedgerException("contract processEvent exception. detail:"+e.getMessage()); } } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContent.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContent.java index 136ce6e0..a081738f 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContent.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContent.java @@ -1,21 +1,25 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.base.data.TypeCodes; -import com.jd.blockchain.binaryproto.DataContract; -import com.jd.blockchain.binaryproto.DataField; -import com.jd.blockchain.crypto.hash.HashDigest; -import com.jd.blockchain.utils.ValueType; - -/** - * 交易内容; - * - * @author huanghaiquan - * - */ -@DataContract(code= TypeCodes.TX_CONTENT) -public interface TransactionContent extends TransactionContentBody, HashObject { - @Override - @DataField(order=1, primitiveType = ValueType.BYTES) - HashDigest getHash(); - -} +package com.jd.blockchain.ledger; + +import com.jd.blockchain.base.data.TypeCodes; +import com.jd.blockchain.binaryproto.DataContract; +import com.jd.blockchain.binaryproto.DataField; +import com.jd.blockchain.crypto.hash.HashDigest; +import com.jd.blockchain.utils.ValueType; + +/** + * 交易内容; + * + * @author huanghaiquan + * + */ +@DataContract(code= TypeCodes.TX_CONTENT) +public interface TransactionContent extends TransactionContentBody, HashObject { + @Override + @DataField(order=1, primitiveType = ValueType.BYTES) + HashDigest getHash(); + + //获得交易操作时间; + @DataField(order=2, primitiveType = ValueType.INT64) + Long getTxOpTime(); + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContentBody.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContentBody.java index 39a27256..82aaf23f 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContentBody.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContentBody.java @@ -1,36 +1,44 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.base.data.TypeCodes; -import com.jd.blockchain.binaryproto.DataContract; -import com.jd.blockchain.binaryproto.DataField; -import com.jd.blockchain.crypto.hash.HashDigest; -import com.jd.blockchain.utils.ValueType; - -/** - * 交易内容; - * - * @author huanghaiquan - * - */ -@DataContract(code = TypeCodes.TX_CONTENT_BODY) -public interface TransactionContentBody { - - /** - * 执行交易的账本地址; - * - * 注:除了账本的创世交易之外,任何交易的账本地址都不允许为 null; - * - * @return - */ - @DataField(order = 1, primitiveType = ValueType.BYTES) - HashDigest getLedgerHash(); - - /** - * 操作列表; - * - * @return - */ - @DataField(order = 2, list = true, refContract = true, genericContract = true) - Operation[] getOperations(); - -} +package com.jd.blockchain.ledger; + +import com.jd.blockchain.base.data.TypeCodes; +import com.jd.blockchain.binaryproto.DataContract; +import com.jd.blockchain.binaryproto.DataField; +import com.jd.blockchain.crypto.hash.HashDigest; +import com.jd.blockchain.utils.ValueType; + +/** + * 交易内容; + * + * @author huanghaiquan + * + */ +@DataContract(code = TypeCodes.TX_CONTENT_BODY) +public interface TransactionContentBody { + + /** + * 执行交易的账本地址; + * + * 注:除了账本的创世交易之外,任何交易的账本地址都不允许为 null; + * + * @return + */ + @DataField(order = 1, primitiveType = ValueType.BYTES) + HashDigest getLedgerHash(); + + /** + * 操作列表; + * + * @return + */ + @DataField(order = 2, list = true, refContract = true, genericContract = true) + Operation[] getOperations(); + + /** + * 交易操作时间 + * + * @return + */ + @DataField(order = 3, primitiveType = ValueType.INT64) + Long getTxOpTime(); + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/data/TxBuilder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/data/TxBuilder.java index fc2680ba..447feb47 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/data/TxBuilder.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/data/TxBuilder.java @@ -1,88 +1,89 @@ -package com.jd.blockchain.ledger.data; - -import com.jd.blockchain.binaryproto.BinaryEncodingUtils; -import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.crypto.CryptoAlgorithm; -import com.jd.blockchain.crypto.CryptoUtils; -import com.jd.blockchain.crypto.hash.HashDigest; -import com.jd.blockchain.ledger.TransactionBuilder; -import com.jd.blockchain.ledger.TransactionContent; -import com.jd.blockchain.ledger.TransactionContentBody; -import com.jd.blockchain.ledger.TransactionRequestBuilder; -import com.jd.blockchain.utils.Bytes; - -public class TxBuilder implements TransactionBuilder { - - static { - DataContractRegistry.register(TransactionContentBody.class); - } - - private BlockchainOperationFactory opFactory = new BlockchainOperationFactory(); - - private CryptoAlgorithm defaultHashAlgorithm = CryptoAlgorithm.SHA256; - - private HashDigest ledgerHash; - - public TxBuilder(HashDigest ledgerHash) { - this.ledgerHash = ledgerHash; - } - - @Override - public HashDigest getLedgerHash() { - return ledgerHash; - } - - @Override - public TransactionRequestBuilder prepareRequest() { - TransactionContent txContent = prepareContent(); - return new TxRequestBuilder(txContent); - } - - @Override - public TransactionContent prepareContent() { - TxContentBlob txContent = new TxContentBlob(ledgerHash); - txContent.addOperations(opFactory.getOperations()); - - byte[] contentBodyBytes = BinaryEncodingUtils.encode(txContent, TransactionContentBody.class); - HashDigest contentHash = CryptoUtils.hash(defaultHashAlgorithm).hash(contentBodyBytes); - txContent.setHash(contentHash); - - return txContent; - } - - @Override - public LedgerInitOperationBuilder ledgers() { - return opFactory.ledgers(); - } - - @Override - public UserRegisterOperationBuilder users() { - return opFactory.users(); - } - - @Override - public DataAccountRegisterOperationBuilder dataAccounts() { - return opFactory.dataAccounts(); - } - - @Override - public DataAccountKVSetOperationBuilder dataAccount(String accountAddress) { - return opFactory.dataAccount(accountAddress); - } - - @Override - public DataAccountKVSetOperationBuilder dataAccount(Bytes accountAddress) { - return opFactory.dataAccount(accountAddress); - } - - @Override - public ContractCodeDeployOperationBuilder contracts() { - return opFactory.contracts(); - } - - @Override - public ContractEventSendOperationBuilder contractEvents() { - return opFactory.contractEvents(); - } - -} +package com.jd.blockchain.ledger.data; + +import com.jd.blockchain.binaryproto.BinaryEncodingUtils; +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.crypto.CryptoAlgorithm; +import com.jd.blockchain.crypto.CryptoUtils; +import com.jd.blockchain.crypto.hash.HashDigest; +import com.jd.blockchain.ledger.TransactionBuilder; +import com.jd.blockchain.ledger.TransactionContent; +import com.jd.blockchain.ledger.TransactionContentBody; +import com.jd.blockchain.ledger.TransactionRequestBuilder; +import com.jd.blockchain.utils.Bytes; + +public class TxBuilder implements TransactionBuilder { + + static { + DataContractRegistry.register(TransactionContentBody.class); + } + + private BlockchainOperationFactory opFactory = new BlockchainOperationFactory(); + + private CryptoAlgorithm defaultHashAlgorithm = CryptoAlgorithm.SHA256; + + private HashDigest ledgerHash; + + public TxBuilder(HashDigest ledgerHash) { + this.ledgerHash = ledgerHash; + } + + @Override + public HashDigest getLedgerHash() { + return ledgerHash; + } + + @Override + public TransactionRequestBuilder prepareRequest() { + TransactionContent txContent = prepareContent(); + return new TxRequestBuilder(txContent); + } + + @Override + public TransactionContent prepareContent() { + TxContentBlob txContent = new TxContentBlob(ledgerHash); + txContent.addOperations(opFactory.getOperations()); + txContent.setTxOpTime(System.currentTimeMillis()); + + byte[] contentBodyBytes = BinaryEncodingUtils.encode(txContent, TransactionContentBody.class); + HashDigest contentHash = CryptoUtils.hash(defaultHashAlgorithm).hash(contentBodyBytes); + txContent.setHash(contentHash); + + return txContent; + } + + @Override + public LedgerInitOperationBuilder ledgers() { + return opFactory.ledgers(); + } + + @Override + public UserRegisterOperationBuilder users() { + return opFactory.users(); + } + + @Override + public DataAccountRegisterOperationBuilder dataAccounts() { + return opFactory.dataAccounts(); + } + + @Override + public DataAccountKVSetOperationBuilder dataAccount(String accountAddress) { + return opFactory.dataAccount(accountAddress); + } + + @Override + public DataAccountKVSetOperationBuilder dataAccount(Bytes accountAddress) { + return opFactory.dataAccount(accountAddress); + } + + @Override + public ContractCodeDeployOperationBuilder contracts() { + return opFactory.contracts(); + } + + @Override + public ContractEventSendOperationBuilder contractEvents() { + return opFactory.contractEvents(); + } + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/data/TxContentBlob.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/data/TxContentBlob.java index d669951f..8ee55cfa 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/data/TxContentBlob.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/data/TxContentBlob.java @@ -1,92 +1,104 @@ -package com.jd.blockchain.ledger.data; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import com.jd.blockchain.binaryproto.DConstructor; -import com.jd.blockchain.binaryproto.FieldSetter; -import com.jd.blockchain.crypto.hash.HashDigest; -import com.jd.blockchain.ledger.Operation; -import com.jd.blockchain.ledger.TransactionContent; -import com.jd.blockchain.utils.io.NumberMask; - -/** - * 交易内容的数据块; - *

- * - * 包含原始交易请求的数据块; - * - * @author huanghaiquan - * - */ -public class TxContentBlob implements TransactionContent { - - /** - * 操作数量的最大值; - */ - public static final int MAX_OP_COUNT = NumberMask.SHORT.MAX_BOUNDARY_SIZE; - - private List operationList = new ArrayList(); - - private HashDigest hash; - - private HashDigest ledgerHash; - - @DConstructor(name ="TxContentBlob") - public TxContentBlob(@FieldSetter(name="getLedgerHash", type="HashDigest") HashDigest ledgerHash) { - this.ledgerHash = ledgerHash; - } - - /** - * 交易内容的哈希值; - */ - @Override - public HashDigest getHash() { - return this.hash; - } - - /** - * 更新交易内容的哈希值; - *

- * 注:当前对象只充当值对象,不校验指定哈希值的完整性,调用者应该在外部实施完整性校验; - * @param hash - */ - public void setHash(HashDigest hash) { - this.hash = hash; - } - - /** - * 交易请求链的hash - * - * @return - */ - @Override - public HashDigest getLedgerHash() { - return ledgerHash; - } - public void setLedgerHash(HashDigest ledgerHash) { - this.ledgerHash = ledgerHash; - } - - @Override - public Operation[] getOperations() { - return operationList.toArray(new Operation[operationList.size()]); - } - - public void setOperations(Object[] operations) { - //in array's case ,cast will failed! - for (Object operation : operations) { - Operation op = (Operation)operation; - addOperation(op); - } - } - - public void addOperation(Operation operation) { - operationList.add(operation); - } - - public void addOperations(Collection operations) { - operationList.addAll(operations); - } -} +package com.jd.blockchain.ledger.data; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import com.jd.blockchain.binaryproto.DConstructor; +import com.jd.blockchain.binaryproto.FieldSetter; +import com.jd.blockchain.crypto.hash.HashDigest; +import com.jd.blockchain.ledger.Operation; +import com.jd.blockchain.ledger.TransactionContent; +import com.jd.blockchain.utils.io.NumberMask; + +/** + * 交易内容的数据块; + *

+ * + * 包含原始交易请求的数据块; + * + * @author huanghaiquan + * + */ +public class TxContentBlob implements TransactionContent { + + /** + * 操作数量的最大值; + */ + public static final int MAX_OP_COUNT = NumberMask.SHORT.MAX_BOUNDARY_SIZE; + + private List operationList = new ArrayList(); + + private HashDigest hash; + + private HashDigest ledgerHash; + + //交易操作时间; + private Long txOpTime; + + @DConstructor(name ="TxContentBlob") + public TxContentBlob(@FieldSetter(name="getLedgerHash", type="HashDigest") HashDigest ledgerHash) { + this.ledgerHash = ledgerHash; + } + + /** + * 交易内容的哈希值; + */ + @Override + public HashDigest getHash() { + return this.hash; + } + + /** + * 更新交易内容的哈希值; + *

+ * 注:当前对象只充当值对象,不校验指定哈希值的完整性,调用者应该在外部实施完整性校验; + * @param hash + */ + public void setHash(HashDigest hash) { + this.hash = hash; + } + + /** + * 交易请求链的hash + * + * @return + */ + @Override + public HashDigest getLedgerHash() { + return ledgerHash; + } + public void setLedgerHash(HashDigest ledgerHash) { + this.ledgerHash = ledgerHash; + } + + @Override + public Operation[] getOperations() { + return operationList.toArray(new Operation[operationList.size()]); + } + + public void setOperations(Object[] operations) { + //in array's case ,cast will failed! + for (Object operation : operations) { + Operation op = (Operation)operation; + addOperation(op); + } + } + + public void addOperation(Operation operation) { + operationList.add(operation); + } + + public void addOperations(Collection operations) { + operationList.addAll(operations); + } + + @Override + public Long getTxOpTime() { + return txOpTime; + } + + public void setTxOpTime(Long txOpTime) { + this.txOpTime = txOpTime; + } +} diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4Bftsmart.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4Bftsmart.java index 79b9e189..22aa9b1e 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4Bftsmart.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4Bftsmart.java @@ -139,7 +139,7 @@ public class IntegrationTest4Bftsmart { } try { - Thread.sleep(60000); + Thread.sleep(60000000); } catch (InterruptedException e) { e.printStackTrace(); } From 384c81393e5ed902f659859a65ce9b2d491348a6 Mon Sep 17 00:00:00 2001 From: zhaoguangwei Date: Wed, 8 May 2019 11:08:58 +0800 Subject: [PATCH 19/43] =?UTF-8?q?=E5=9C=A8transactonContent=E5=AF=B9?= =?UTF-8?q?=E8=B1=A1=E4=B8=AD=E6=B7=BB=E5=8A=A0txOpTime=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=EF=BC=8C=E9=81=BF=E5=85=8D=E9=87=8D=E5=A4=8D=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E5=90=88=E7=BA=A6=E6=97=B6=EF=BC=8C=E5=87=BA=E7=8E=B0contentHa?= =?UTF-8?q?sh=E7=A2=B0=E6=92=9E=E7=9A=84=E9=97=AE=E9=A2=98=E3=80=82=20slee?= =?UTF-8?q?p=E6=97=B6=E9=97=B4=E6=81=A2=E5=A4=8D=E5=8E=9F=E5=85=88?= =?UTF-8?q?=E5=80=BC=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../test/com/jd/blockchain/intgr/IntegrationTest4Bftsmart.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4Bftsmart.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4Bftsmart.java index 22aa9b1e..79b9e189 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4Bftsmart.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4Bftsmart.java @@ -139,7 +139,7 @@ public class IntegrationTest4Bftsmart { } try { - Thread.sleep(60000000); + Thread.sleep(60000); } catch (InterruptedException e) { e.printStackTrace(); } From dd8e38992c31bb9bdedf3fe3cb76c96ffefb7cb7 Mon Sep 17 00:00:00 2001 From: zhaoguangwei Date: Wed, 8 May 2019 11:22:01 +0800 Subject: [PATCH 20/43] =?UTF-8?q?=E5=8E=BB=E6=8E=89concat=E5=90=88?= =?UTF-8?q?=E5=B9=B6byte[]=E6=96=B9=E6=B3=95;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/jd/blockchain/utils/ArrayUtils.java | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/ArrayUtils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/ArrayUtils.java index bb04964e..c787a014 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/ArrayUtils.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/ArrayUtils.java @@ -1,14 +1,7 @@ package com.jd.blockchain.utils; import java.lang.reflect.Array; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; +import java.util.*; /** * @author haiq @@ -83,5 +76,4 @@ public abstract class ArrayUtils { } return new ReadonlyArrayListWrapper(array, fromIndex, toIndex); } - } From 5f1a80b08dc6349faedaa4223db01db9ea8110f0 Mon Sep 17 00:00:00 2001 From: zhaoguangwei Date: Wed, 8 May 2019 15:54:39 +0800 Subject: [PATCH 21/43] in bftsmart, fix the exception: Returned object not currently part of this pool. --- .../consensus/bftsmart/client/BftsmartConsensusClient.java | 2 +- .../consensus/bftsmart/service/BftsmartNodeServer.java | 2 +- .../test/com/jd/blockchain/intgr/IntegrationTest4Bftsmart.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartConsensusClient.java b/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartConsensusClient.java index 25a995c7..865d0e0a 100644 --- a/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartConsensusClient.java +++ b/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/client/BftsmartConsensusClient.java @@ -21,7 +21,7 @@ public class BftsmartConsensusClient implements ConsensusClient { this.clientSettings = clientSettings; this.gatewayId = clientSettings.getClientId(); - connect(); +// connect(); } diff --git a/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServer.java b/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServer.java index f25c8d61..a912b127 100644 --- a/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServer.java +++ b/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServer.java @@ -77,10 +77,10 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer //used later this.stateMachineReplicate = stateMachineReplicate; this.messageHandle = messageHandler; - this.manageService = new BftsmartConsensusManageService(this); createConfig(); serverId = findServerId(); initConfig(serverId, systemConfig, hostsConfig); + this.manageService = new BftsmartConsensusManageService(this); } protected int findServerId() { diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4Bftsmart.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4Bftsmart.java index 79b9e189..22aa9b1e 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4Bftsmart.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4Bftsmart.java @@ -139,7 +139,7 @@ public class IntegrationTest4Bftsmart { } try { - Thread.sleep(60000); + Thread.sleep(60000000); } catch (InterruptedException e) { e.printStackTrace(); } From 3d78edd1558413e452d99a1e28e94dcce9116640 Mon Sep 17 00:00:00 2001 From: zhaoguangwei Date: Thu, 9 May 2019 15:32:54 +0800 Subject: [PATCH 22/43] delete the txOpTime in transactionContent.java, now use it in the ContractEventSendOpTemplate, only for contract related; --- .../ledger/ContractEventSendOperation.java | 68 +++++++------ .../blockchain/ledger/TransactionContent.java | 4 - .../ledger/TransactionContentBody.java | 8 -- .../data/ContractEventSendOpTemplate.java | 98 ++++++++++--------- .../jd/blockchain/ledger/data/TxBuilder.java | 1 - .../blockchain/ledger/data/TxContentBlob.java | 12 --- 6 files changed, 88 insertions(+), 103 deletions(-) diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractEventSendOperation.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractEventSendOperation.java index dce287b8..a04c451f 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractEventSendOperation.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractEventSendOperation.java @@ -1,32 +1,36 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.base.data.TypeCodes; -import com.jd.blockchain.binaryproto.DataContract; -import com.jd.blockchain.binaryproto.DataField; -import com.jd.blockchain.utils.Bytes; -import com.jd.blockchain.utils.ValueType; - -/** - * @author huanghaiquan - * - */ -@DataContract(code= TypeCodes.TX_OP_CONTRACT_EVENT_SEND) -public interface ContractEventSendOperation extends Operation { - -// @DataField(order=1, refEnum=true) -// @Override -// default OperationType getType() { -// return OperationType.SEND_CONTRACT_EVENT; -// } - - @DataField(order=2, primitiveType=ValueType.BYTES) - Bytes getContractAddress(); - - @DataField(order=3, primitiveType=ValueType.TEXT) - String getEvent(); - - - @DataField(order=4, primitiveType=ValueType.BYTES) - byte[] getArgs(); - -} +package com.jd.blockchain.ledger; + +import com.jd.blockchain.base.data.TypeCodes; +import com.jd.blockchain.binaryproto.DataContract; +import com.jd.blockchain.binaryproto.DataField; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.ValueType; + +/** + * @author huanghaiquan + * + */ +@DataContract(code= TypeCodes.TX_OP_CONTRACT_EVENT_SEND) +public interface ContractEventSendOperation extends Operation { + +// @DataField(order=1, refEnum=true) +// @Override +// default OperationType getType() { +// return OperationType.SEND_CONTRACT_EVENT; +// } + + @DataField(order=2, primitiveType=ValueType.BYTES) + Bytes getContractAddress(); + + @DataField(order=3, primitiveType=ValueType.TEXT) + String getEvent(); + + + @DataField(order=4, primitiveType=ValueType.BYTES) + byte[] getArgs(); + + //获得交易操作时间; + @DataField(order=5, primitiveType=ValueType.INT64) + Long getTxOpTime(); + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContent.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContent.java index a081738f..59f6aa6f 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContent.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContent.java @@ -18,8 +18,4 @@ public interface TransactionContent extends TransactionContentBody, HashObject { @DataField(order=1, primitiveType = ValueType.BYTES) HashDigest getHash(); - //获得交易操作时间; - @DataField(order=2, primitiveType = ValueType.INT64) - Long getTxOpTime(); - } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContentBody.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContentBody.java index 82aaf23f..2f1abc3b 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContentBody.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContentBody.java @@ -33,12 +33,4 @@ public interface TransactionContentBody { @DataField(order = 2, list = true, refContract = true, genericContract = true) Operation[] getOperations(); - /** - * 交易操作时间 - * - * @return - */ - @DataField(order = 3, primitiveType = ValueType.INT64) - Long getTxOpTime(); - } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/data/ContractEventSendOpTemplate.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/data/ContractEventSendOpTemplate.java index d7d06d85..2751c60b 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/data/ContractEventSendOpTemplate.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/data/ContractEventSendOpTemplate.java @@ -1,46 +1,52 @@ -package com.jd.blockchain.ledger.data; - -import com.jd.blockchain.binaryproto.DConstructor; -import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.binaryproto.FieldSetter; -import com.jd.blockchain.ledger.ContractEventSendOperation; -import com.jd.blockchain.utils.Bytes; - -public class ContractEventSendOpTemplate implements ContractEventSendOperation { - static { - DataContractRegistry.register(ContractEventSendOperation.class); - } - - private Bytes contractAddress; - private byte[] args; - private String event; - - public ContractEventSendOpTemplate() { - } - - @DConstructor(name="ContractEventSendOpTemplate") - public ContractEventSendOpTemplate(@FieldSetter(name="getContractAddress", type="Bytes") Bytes contractAddress, - @FieldSetter(name="getEvent", type="String") String event, - @FieldSetter(name="getArgs", type="byte[]") byte[] args) { - this.contractAddress = contractAddress; - this.event = event; - this.args = args; - } - - @Override - public Bytes getContractAddress() { - return contractAddress; - } - - @Override - public String getEvent() { - return event; - } - - @Override - public byte[] getArgs() { - return args; - } - - -} +package com.jd.blockchain.ledger.data; + +import com.jd.blockchain.binaryproto.DConstructor; +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.binaryproto.FieldSetter; +import com.jd.blockchain.ledger.ContractEventSendOperation; +import com.jd.blockchain.utils.Bytes; + +public class ContractEventSendOpTemplate implements ContractEventSendOperation { + static { + DataContractRegistry.register(ContractEventSendOperation.class); + } + + private Bytes contractAddress; + private byte[] args; + private String event; + //交易操作时间; + private Long txOpTime; + + public ContractEventSendOpTemplate() { + } + + @DConstructor(name="ContractEventSendOpTemplate") + public ContractEventSendOpTemplate(@FieldSetter(name="getContractAddress", type="Bytes") Bytes contractAddress, + @FieldSetter(name="getEvent", type="String") String event, + @FieldSetter(name="getArgs", type="byte[]") byte[] args) { + this.contractAddress = contractAddress; + this.event = event; + this.args = args; + this.txOpTime = System.currentTimeMillis(); + } + + @Override + public Bytes getContractAddress() { + return contractAddress; + } + + @Override + public String getEvent() { + return event; + } + + @Override + public byte[] getArgs() { + return args; + } + + @Override + public Long getTxOpTime() { + return txOpTime; + } +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/data/TxBuilder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/data/TxBuilder.java index 447feb47..7bba3262 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/data/TxBuilder.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/data/TxBuilder.java @@ -42,7 +42,6 @@ public class TxBuilder implements TransactionBuilder { public TransactionContent prepareContent() { TxContentBlob txContent = new TxContentBlob(ledgerHash); txContent.addOperations(opFactory.getOperations()); - txContent.setTxOpTime(System.currentTimeMillis()); byte[] contentBodyBytes = BinaryEncodingUtils.encode(txContent, TransactionContentBody.class); HashDigest contentHash = CryptoUtils.hash(defaultHashAlgorithm).hash(contentBodyBytes); diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/data/TxContentBlob.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/data/TxContentBlob.java index 8ee55cfa..d4f5d925 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/data/TxContentBlob.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/data/TxContentBlob.java @@ -33,9 +33,6 @@ public class TxContentBlob implements TransactionContent { private HashDigest ledgerHash; - //交易操作时间; - private Long txOpTime; - @DConstructor(name ="TxContentBlob") public TxContentBlob(@FieldSetter(name="getLedgerHash", type="HashDigest") HashDigest ledgerHash) { this.ledgerHash = ledgerHash; @@ -92,13 +89,4 @@ public class TxContentBlob implements TransactionContent { public void addOperations(Collection operations) { operationList.addAll(operations); } - - @Override - public Long getTxOpTime() { - return txOpTime; - } - - public void setTxOpTime(Long txOpTime) { - this.txOpTime = txOpTime; - } } From 1e044787151f42ca8a72890575280bb5d79c25e1 Mon Sep 17 00:00:00 2001 From: zhaoguangwei Date: Thu, 9 May 2019 16:48:22 +0800 Subject: [PATCH 23/43] delete the txOpTime in transactionContent.java, now use it in the ContractEventSendOpTemplate, only for contract related; --- .../test/com/jd/blockchain/intgr/IntegrationTest4Bftsmart.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4Bftsmart.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4Bftsmart.java index 22aa9b1e..79b9e189 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4Bftsmart.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4Bftsmart.java @@ -139,7 +139,7 @@ public class IntegrationTest4Bftsmart { } try { - Thread.sleep(60000000); + Thread.sleep(60000); } catch (InterruptedException e) { e.printStackTrace(); } From be4f605174e317a3b736dad1f5786b78557a5875 Mon Sep 17 00:00:00 2001 From: zhanglin33 Date: Mon, 13 May 2019 10:12:50 +0800 Subject: [PATCH 24/43] add pki --- source/crypto/crypto-adv/pom.xml | 7 + source/crypto/crypto-classic/pom.xml | 6 + .../crypto/utils/classic/CSRTest.java | 58 +++++ .../crypto/utils/classic/CertTest.java | 81 +++++++ .../crypto/utils/classic/RSAUtilsTest.java | 19 +- .../crypto/utils/classic/SSHKeyUtilsTest.java | 212 ++++++++++++++++++ source/crypto/crypto-pki/pom.xml | 34 +++ .../com/jd/blockchain/crypto/CSRBuilder.java | 10 + .../com/jd/blockchain/crypto/CertParser.java | 10 + .../jd/blockchain/crypto/CSRBuilderTest.java | 161 +++++++++++++ .../jd/blockchain/crypto/CertParserTest.java | 10 + source/crypto/pom.xml | 1 + source/pom.xml | 6 + 13 files changed, 614 insertions(+), 1 deletion(-) create mode 100644 source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/CSRTest.java create mode 100644 source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/CertTest.java create mode 100644 source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/SSHKeyUtilsTest.java create mode 100644 source/crypto/crypto-pki/pom.xml create mode 100644 source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CSRBuilder.java create mode 100644 source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CertParser.java create mode 100644 source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CSRBuilderTest.java create mode 100644 source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CertParserTest.java diff --git a/source/crypto/crypto-adv/pom.xml b/source/crypto/crypto-adv/pom.xml index bf759175..6c3705f2 100644 --- a/source/crypto/crypto-adv/pom.xml +++ b/source/crypto/crypto-adv/pom.xml @@ -21,6 +21,13 @@ org.bouncycastle bcprov-jdk15on + + + org.bouncycastle + bcpkix-jdk15on + 1.61 + + com.jd.blockchain binary-proto diff --git a/source/crypto/crypto-classic/pom.xml b/source/crypto/crypto-classic/pom.xml index bd59aeb8..75ab597b 100644 --- a/source/crypto/crypto-classic/pom.xml +++ b/source/crypto/crypto-classic/pom.xml @@ -15,6 +15,12 @@ crypto-framework ${project.version} + + + org.bouncycastle + bcpkix-jdk15on + 1.61 + \ No newline at end of file diff --git a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/CSRTest.java b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/CSRTest.java new file mode 100644 index 00000000..ec28db62 --- /dev/null +++ b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/CSRTest.java @@ -0,0 +1,58 @@ +package test.com.jd.blockchain.crypto.utils.classic; + +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.operator.ContentSigner; +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder; + + +import java.io.IOException; +import java.security.*; + +/** + * @author zhanglin33 + * @title: CSRTest + * @description: TODO + * @date 2019-05-10, 12:55 + */ +public class CSRTest { + public static String genCSR(String subject, String alg,String provider) { + String signalg=""; + int alglength=0; + String keyAlg=""; + if(alg.toUpperCase().equals("RSA1024")){ + signalg="SHA1WithRSA"; + alglength=1024; + keyAlg="RSA"; + }else if(alg.toUpperCase().equals("RSA2048")){ + signalg="SHA1WithRSA"; + alglength=2048; + keyAlg="RSA"; + }else if(alg.toUpperCase().equals("SM2")){ + signalg="SM3withSM2"; + alglength=256; + keyAlg="SM2"; + } + KeyPairGenerator keyGen; + PKCS10CertificationRequestBuilder builder; + + try { + keyGen = KeyPairGenerator.getInstance(keyAlg); + keyGen.initialize(alglength); + KeyPair kp = keyGen.generateKeyPair(); + + + builder = new PKCS10CertificationRequestBuilder(new X500Name(subject), SubjectPublicKeyInfo.getInstance(kp.getPublic().getEncoded())); + JcaContentSignerBuilder jcaContentSignerBuilder = new JcaContentSignerBuilder(signalg); + jcaContentSignerBuilder.setProvider(provider); + ContentSigner contentSigner = jcaContentSignerBuilder.build(kp.getPrivate()); + builder.build(contentSigner); + return builder.toString(); + } catch (OperatorCreationException | NoSuchAlgorithmException e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/CertTest.java b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/CertTest.java new file mode 100644 index 00000000..94e5ad24 --- /dev/null +++ b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/CertTest.java @@ -0,0 +1,81 @@ +package test.com.jd.blockchain.crypto.utils.classic; + +import org.bouncycastle.util.encoders.Base64; +import org.bouncycastle.util.encoders.Hex; +import org.junit.Test; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.security.NoSuchProviderException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; + +/** + * @author zhanglin33 + * @title: CertTest + * @description: TODO + * @date 2019-05-09, 11:34 + */ +public class CertTest { + + private byte[] certBytes = Base64.decode("MIIEQDCCAyigAwIBAgIFICdVYzEwDQYJKoZIhvcNAQEFBQAwWTELMAkGA1UEBhMCQ04xMDAuBgNVBAoTJ0NoaW5hIEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEYMBYGA1UEAxMPQ0ZDQSBURVNUIE9DQTExMB4XDTE5MDUxMDExMjAyNFoXDTIxMDUxMDExMjAyNFowcjELMAkGA1UEBhMCQ04xGDAWBgNVBAoTD0NGQ0EgVEVTVCBPQ0ExMTERMA8GA1UECxMITG9jYWwgUkExFTATBgNVBAsTDEluZGl2aWR1YWwtMTEfMB0GA1UEAxQWMDUxQGFhYWFhQFpIMDkzNTgwMjhAMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJx3F2WD1dJPzK/nRHO7d1TJ1hTjzGTmv0PQ7ECsJAh3U3BtnGTpCB+b4+JMI4LO8nHkKIBQ3P9XnF+Bf1iXdWNAQ4aWCxa2nV7lCp4w0GliPu/EMgIfmsSDUtgqbM3cr8sR8r9m1xG3gt2TIQJ+jT7sAiguU/kyNzpjaccOUIgUFa8IDFq9UeB76MXtCuhlERRZQCl47e+9w7ZoxmE7e6IZORxPp7rQWVBHlR9ntWjJfNDTm3gMP5ehP+yIZnKx1LudxkBLQxpMmspzOyH1zqx5nkKe49AfWWpDxxRvYkriyYC3aE81qLsU/bhLwNEKOju7BGDF/mhJLZUedojM0gMCAwEAAaOB9TCB8jAfBgNVHSMEGDAWgBT8C7xEmg4xoYOpgYcnHgVCxr9W+DBIBgNVHSAEQTA/MD0GCGCBHIbvKgECMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2ZjYS5jb20uY24vdXMvdXMtMTUuaHRtMDoGA1UdHwQzMDEwL6AtoCuGKWh0dHA6Ly8yMTAuNzQuNDIuMy9PQ0ExMS9SU0EvY3JsMjU2OTMuY3JsMAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQU5oKGaQs7Jt5Gfbt1XhFTWAySEKswHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMA0GCSqGSIb3DQEBBQUAA4IBAQAlmPRaImZV51iKjtpMKuyLMw7dX8L0lY3tl+pVZZSxHuwsN4GCCtV0Ej50up+/6EbfL4NUTiuHVAjCroKKvb+94CrdEwdnQGM5IbGSjT78nQpeASXbIWuUwA+ImjvZOzvq/0b56AzonNzBxOMGko/bj5smM6X8jrgJ0NQppo2KNSVNC4JbuoNWI4FM94SE4DUi9H7EYl4JdOtDaDtCsq49o/A1CZyYrmoOPCgxpQQXmuB3lGq/jyoOlW2aW8uee/hYG1JJcSHLBjF0WBwdxssgbBotA5f1PebiIMSbFgjk57bd4M80hhU/rI4Hkn9pcp5R7NsX95TtyDIg90LboBnW"); + public static String getSubjectDN(byte[] der) { + String dn = ""; + try { + ByteArrayInputStream bIn = new ByteArrayInputStream(der); + //BouncyCastleProvider provider = new BouncyCastleProvider(); + //CertificateFactory cf = CertificateFactory.getInstance("X509", + //provider); + //CertificateFactory cf = CertificateFactory.getInstance("X.509", + // "SUN"); + //android 需采用bcprov + CertificateFactory cf = CertificateFactory.getInstance("X.509"); +// System.out.println(cf.getProvider().getName()); + X509Certificate cert = (X509Certificate) cf + .generateCertificate(bIn); + dn = cert.getSubjectDN().getName(); + + System.out.println(Hex.toHexString(cert.getEncoded())); + byte[] pubKeyBytes = cert.getPublicKey().getEncoded(); + System.out.println(Hex.toHexString(pubKeyBytes)); + System.out.println(cert.getSigAlgName()); + String issuerName = cert.getIssuerDN().getName(); + System.out.println(issuerName); + String oid = cert.getSigAlgOID(); + System.out.println(oid); + System.out.println(); + String name = cert.getIssuerX500Principal().getName(); + System.out.println(name); + bIn.close(); + } catch (CertificateException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return dn; + } + + +// public static String parseCertDN(String dn, String type) { +// type = type + "="; +// String[] split = dn.split(","); +// for (String x : split) { +// if (x.contains(type)) { +// x = x.trim(); +// return x.substring(type.length()); +// } +// } +// return null; +// } + + + @Test + public void cert1Test() { + String string = getSubjectDN(certBytes); + System.out.println(Hex.toHexString(certBytes)); + System.out.println(string); + } +} diff --git a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RSAUtilsTest.java b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RSAUtilsTest.java index 3e68c8c6..982cd35e 100644 --- a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RSAUtilsTest.java +++ b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RSAUtilsTest.java @@ -1,16 +1,22 @@ package test.com.jd.blockchain.crypto.utils.classic; import com.jd.blockchain.crypto.utils.classic.RSAUtils; +import org.bouncycastle.asn1.DERNull; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.params.AsymmetricKeyParameter; import org.bouncycastle.crypto.params.RSAKeyParameters; import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters; +import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil; +import org.bouncycastle.util.encoders.Hex; import org.junit.Test; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; +import java.io.IOException; import java.security.*; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; @@ -27,7 +33,7 @@ import static org.junit.Assert.*; public class RSAUtilsTest { @Test - public void generateKeyPairTest(){ + public void generateKeyPairTest() throws IOException { AsymmetricCipherKeyPair kp = RSAUtils.generateKeyPair(); RSAKeyParameters pubKey = (RSAKeyParameters) kp.getPublic(); RSAPrivateCrtKeyParameters privKey = (RSAPrivateCrtKeyParameters) kp.getPrivate(); @@ -59,6 +65,17 @@ public class RSAUtilsTest { byte[] pubKeyBytesConverted_PKCS8 = RSAUtils.pubKey2Bytes_PKCS8(RSAUtils.bytes2PubKey_PKCS8(pubKeyBytes_PKCS8)); assertArrayEquals(pubKeyBytes_PKCS8,pubKeyBytesConverted_PKCS8); +// +//// String str = "1.2.840.113549.1.1"; +//// System.out.println(Hex.toHexString(str.getBytes())); +// byte[] bytes = null; +// AlgorithmIdentifier RSA_ALGORITHM_IDENTIFIER = +// new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE); +//// byte[] result = KeyUtil.getEncodedSubjectPublicKeyInfo(RSA_ALGORITHM_IDENTIFIER, bytes); +// byte[] algo = RSA_ALGORITHM_IDENTIFIER.getEncoded(); +// System.out.println(Hex.toHexString(algo)); +//// System.out.println(Hex.toHexString(result)); +// System.out.println(Hex.toHexString(pubKeyBytes_PKCS8)); byte[] privKeyBytes_PKCS8 = RSAUtils.privKey2Bytes_PKCS8(privKey); byte[] privKeyBytesConverted_PKCS8 = diff --git a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/SSHKeyUtilsTest.java b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/SSHKeyUtilsTest.java new file mode 100644 index 00000000..1c2d7731 --- /dev/null +++ b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/SSHKeyUtilsTest.java @@ -0,0 +1,212 @@ +package test.com.jd.blockchain.crypto.utils.classic; + +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.crypto.params.RSAKeyParameters; +import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters; +import org.bouncycastle.crypto.util.OpenSSHPrivateKeyUtil; +import org.bouncycastle.crypto.util.OpenSSHPublicKeyUtil; +import org.bouncycastle.jce.spec.OpenSSHPrivateKeySpec; +import org.bouncycastle.jce.spec.OpenSSHPublicKeySpec; +import org.bouncycastle.util.Strings; +import org.bouncycastle.util.encoders.Base64; +import org.bouncycastle.util.encoders.Hex; +import org.bouncycastle.util.io.pem.PemReader; +import org.junit.Test; + +import java.io.IOException; +import java.io.StringReader; +import java.math.BigInteger; + +/** + * @author zhanglin33 + * @title: SSHKeyUtilsTest + * @description: Tests for methods in SSHKeyUtils + * @date 2019-05-07, 15:14 + */ +public class SSHKeyUtilsTest { + + @Test + public void parseRSAPublicKeyTest() { + + String pubKeyStr = "AAAAB3NzaC1yc2EAAAADAQABAAABAQCYwLN4EXy7g0Xugv4lQfoujbARi48gPSxVupt" + + "GsSoGqsS00e9rA7v0qzFKa9Zhnw1WkjCnEXRYAMiCAJYkM/mGI8mb3qkcdNhGWZmPnopV+D46CTFB1" + + "4yeR9mjoOPXs4pjX3zGveKx5Nx8jvdoFewbTCtdN0x1XWTjNT5bXqP/4gXkLENEU5tLsWVAOu0ME/N" + + "e/9gMujAtDoolJ181a9P06bvEpIw5cLtUnsm5CtvBuiL7WBXxDJ/IASJrKNGBdK8xib1+Kb8tNLAT6" + + "Dj25BwylqiRNhb5l1Ni4aKrE2FqSEc5Nx5+csQMEl9MBJ3pEsLHBNbohDL+jbwLguRVD6CJ"; + + byte[] pubKeyBytes = Base64.decode(pubKeyStr); + System.out.println(Hex.toHexString(pubKeyBytes)); + OpenSSHPublicKeySpec pubKeySpec = new OpenSSHPublicKeySpec(pubKeyBytes); + + String pubKeyFormat = pubKeySpec.getFormat(); + String pubKeyType = pubKeySpec.getType(); + System.out.println(pubKeyFormat); + System.out.println(pubKeyType); + + RSAKeyParameters pubKey = (RSAKeyParameters) OpenSSHPublicKeyUtil.parsePublicKey(pubKeyBytes); + BigInteger e = pubKey.getExponent(); + BigInteger n = pubKey.getModulus(); + System.out.println(Hex.toHexString(e.toByteArray())); + System.out.println(Hex.toHexString(n.toByteArray())); + + System.out.println(); + System.out.println("-------------------------------------------------------"); + System.out.println(); + + + } + + @Test + public void parseRSAPrivateKeyTest() { + + String str2 = "-----BEGIN OPENSSH PRIVATE KEY-----\n" + + "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn\n" + + "NhAAAAAwEAAQAAAQEAwFyeWgHFu/ZMvqWa28QUGlKMDV7vpbzT7kyA/4yuotfprZKHNeEy\n" + + "GugleJ/Kv5kqHh8Km4IZcfNcerTYds+U5m/uX4bSYpEbXco3DQ2lYQbYo7PBWwPMq2aIdd\n" + + "i7WxUAlt0z1ugLNimskPzJ7DNra+ax0Wh9RnMsjZkfuBZiKq7wbBm7NyJmpg2B7xo5cz+G\n" + + "Lw9e0tDlvgeLe+n68WvYWWFP59mfP6Qoy+NwjQnnwrhJi2j4dEexO97KmgnJhL07lu4eCQ\n" + + "fdv68Tai9+aeDNawe7nmFYf2eNjah2jW/DwOwA/ErXnvgjLSMsgc6WGKfokhytAOFDGgvH\n" + + "KKNd6BMYZwAAA9A7JircOyYq3AAAAAdzc2gtcnNhAAABAQDAXJ5aAcW79ky+pZrbxBQaUo\n" + + "wNXu+lvNPuTID/jK6i1+mtkoc14TIa6CV4n8q/mSoeHwqbghlx81x6tNh2z5Tmb+5fhtJi\n" + + "kRtdyjcNDaVhBtijs8FbA8yrZoh12LtbFQCW3TPW6As2KayQ/MnsM2tr5rHRaH1GcyyNmR\n" + + "+4FmIqrvBsGbs3ImamDYHvGjlzP4YvD17S0OW+B4t76frxa9hZYU/n2Z8/pCjL43CNCefC\n" + + "uEmLaPh0R7E73sqaCcmEvTuW7h4JB92/rxNqL35p4M1rB7ueYVh/Z42NqHaNb8PA7AD8St\n" + + "ee+CMtIyyBzpYYp+iSHK0A4UMaC8coo13oExhnAAAAAwEAAQAAAQAEEvIXnen+LR06/G7n\n" + + "MKPsWss0jUouDG3AokYpI2WfdUsxreTHM1nIUBpbD6dPn4LQ2H91A7BeRXUz9BiRi5vvtX\n" + + "cq9sQF6mTV+65mzF8wSuDTtr7lmpL/HlDNjiWJrEwy5cRvTMLQBtnsyC3OntgrlNs3QCtH\n" + + "DrFm3lNZpr+1f62Vu43dbcTPvLwcc335cJ73BU5WsMGaouCAqVXsVsgfkA66u6+gQs8O3F\n" + + "IQntdzS8vYpkzH8N9qqNZit7kbFCRUTI7CDLHquJmclzB8uVwO0pR5+Aross+YL3QxPZoJ\n" + + "+LXLlCi27oSmYk3fx3uh0XwwO3JFDQpeCxOuEsZbOy8BAAAAgCsktFksS0BViRuLyzC2H7\n" + + "X7Uonf+dr8e4Yn+RgR329KFh/ok28/KZndZHsUnhdmiIjPr+SplFZZMrV/uJDkGezUNWGf\n" + + "8qn+eEglm7nYfVf2EXTVNhpg8yfPChx90ybc8GYlqpEqf7LiCuEBCPqPJgq6K7i6UKbwn2\n" + + "SfqUOBcz5BAAAAgQDqszdiNv0cTvZ/Xg3qJPsHXqQuLBYoe2vhU+Pipt9HviruUD1y3Mso\n" + + "rOL9QBwjE7szGnwVE00J0mLp+s309+kftADLXqMyqFYiy7S8GIWQw0YNB2m8yjq+phHbBm\n" + + "/Gs2P4+s8yKTcVJvMTyWr02rpCHiLTKDHoXPJcJ8yVMTHFRwAAAIEA0dHB9fXiesEKfwcp\n" + + "X11IHAV8pTd+7VN81oGwxtRg88U7H2rmQFCxSZah2O/OCCmYLH3PHT95qnMHHqzcsVvoIy\n" + + "7AfnMpp4KYU0Ic3aFuRjZk2sDsYUniPcCpuCvs8Jb75sDwKDW2EM8MowiNylDnYMmfYj0l\n" + + "gIhz1/p79hXEI+EAAAAbemhhbmdsaW4zM0B6aGFuZ2xpbjMzLmxvY2Fs\n" + + "-----END OPENSSH PRIVATE KEY-----"; + + byte[] Bytes2 = null; + try { + Bytes2 = new PemReader(new StringReader(str2)).readPemObject().getContent(); + } catch (IOException e1) { + e1.printStackTrace(); + } + System.out.println(Hex.toHexString(Bytes2)); + + String str3 = "-----BEGIN OPENSSH PRIVATE KEY-----\n" + + "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn\n" + + "NhAAAAAwEAAQAAAQEAvummQZm1FUFc/cV5nQBeowhjX4vIU4kBmyPmXHMViX4ORvWvD1yi\n" + + "oxcaawPpP9QconpzjdCrNbmw0oZNt9UKlmrOU34YTRD5LFlEVOYjr/21/SO5yDGog8xJBU\n" + + "HQYnXY5L2q9EXKOF45e5P6gSGUovrhePEsaniuQN48GIObPCOFkEN0ZV2DqRsn3It1vY+D\n" + + "GiSb5EaZ2sNkudyzYfgFxcCbqBXmDa1WeyX5xYh8wldBJLUH+pO4gPoTXXX4UI4yNdDmPD\n" + + "BWFvPVIOdpfdBnDbEp1AoE5Jx/+tbwFBIEvTPOECtOUKDGIlXXIH0I4waHbwf6EnHD5+BR\n" + + "N0XwrzSkuwAAA9DYV/7H2Ff+xwAAAAdzc2gtcnNhAAABAQC+6aZBmbUVQVz9xXmdAF6jCG\n" + + "Nfi8hTiQGbI+ZccxWJfg5G9a8PXKKjFxprA+k/1ByienON0Ks1ubDShk231QqWas5TfhhN\n" + + "EPksWURU5iOv/bX9I7nIMaiDzEkFQdBiddjkvar0Rco4Xjl7k/qBIZSi+uF48SxqeK5A3j\n" + + "wYg5s8I4WQQ3RlXYOpGyfci3W9j4MaJJvkRpnaw2S53LNh+AXFwJuoFeYNrVZ7JfnFiHzC\n" + + "V0EktQf6k7iA+hNddfhQjjI10OY8MFYW89Ug52l90GcNsSnUCgTknH/61vAUEgS9M84QK0\n" + + "5QoMYiVdcgfQjjBodvB/oSccPn4FE3RfCvNKS7AAAAAwEAAQAAAQArRruxUy6BSvfRbtpK\n" + + "hLLvMg+UsRMQHJaInHKzskLHkBOcckTkrpMPdUU/zPsqxOJY0nkvRIYK/7TdhCRJ77ker8\n" + + "dllcfccGSLcRDUTfb5BgIjB94tS1Rvy/chgfHC4APyliwSg197t6BAKyM18m7HIyfJSqJO\n" + + "4FxfyADHbc3aq654tu+eaUtD7TEN1bH6PKMDvwSioMLgKU43GQeDJZbqamBE9y+KVhVx9y\n" + + "3DEHrOPkRkZIG33y9j7B/i0vl+WnwUTzmLGRR0U6J9wrzyANL8ODYaAvk4FvUED8hQ72jh\n" + + "NpAXsSgf6COUE1sUnO5DOwN1zHBNHaSo73Qu7aKZtL4BAAAAgDBW3ItiqU9Ip34KtLaayK\n" + + "/BkRDDwFNvAxpOw9alpfbLGF5xbVjRN4wy7HJ4eA+7JJnx6A6xYrzykbPP+dnUnfzYuxH8\n" + + "MrihOkYipw1VaR6/0XH+apmE1SmotuYbl+bpl9dlZYUI0pJ8wldqoDCNlSOcLy77HnKwu9\n" + + "GpJx9KmW9WAAAAgQDdnrwfVv5trAuZZIcw2vLRWhoDT196k/Ty1GP4zFpDttb8OyZ8Ygpx\n" + + "oA5PhYyl5M1g/2oR/Rpp3vfKDVThfn/bCnMtAbUHMfvYK3Oufvq5JmzT1rgGr3MEek+JBR\n" + + "O17I87m4GE7iM1LzCUs2G/fKt2uoVXdniv0Vn0iCiZZc7JmwAAAIEA3IdsccarkUfFcQ2c\n" + + "4TdHrx/RGmoTAO6k1xOHXZjWPmerinuOspIJL/ymWfqIxABCjub3UHyP7ap+1+AAnk+TMU\n" + + "eR3tLEp9tRM6n0Td56DnQ9Q+RZhPqR486/teZ33cMBMHg52aIs/3AzMpK9xTFCRgqsKa6e\n" + + "ednMB4Q1txvHU2EAAAAbemhhbmdsaW4zM0B6aGFuZ2xpbjMzLmxvY2Fs\n" + + "-----END OPENSSH PRIVATE KEY-----"; + + byte[] Bytes3 = null; + try { + Bytes3 = new PemReader(new StringReader(str3)).readPemObject().getContent(); + } catch (IOException e1) { + e1.printStackTrace(); + } + System.out.println(Hex.toHexString(Bytes3)); +// System.out.println(Hex.toHexString(Base64.decode("oNE9iA4ZyuZLbpEL7B29NaxGi4puT2Y5RDaMoEkoAKI"))); +// String test = "1ac477fa"; +// byte[] testBytes = Hex.decode(test); +// +// System.out.println(Base64.toBase64String(testBytes)); + + byte[] AUTH_MAGIC = Strings.toByteArray("openssh-key-v1\0"); + System.out.println(Hex.toHexString(AUTH_MAGIC)); + System.out.println(Base64.toBase64String(AUTH_MAGIC)); + String privKeyStr = "-----BEGIN OPENSSH PRIVATE KEY-----\n" + + "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn\n" + + "NhAAAAAwEAAQAAAQEAmMCzeBF8u4NF7oL+JUH6Lo2wEYuPID0sVbqbRrEqBqrEtNHvawO7\n" + + "9KsxSmvWYZ8NVpIwpxF0WADIggCWJDP5hiPJm96pHHTYRlmZj56KVfg+OgkxQdeMnkfZo6\n" + + "Dj17OKY198xr3iseTcfI73aBXsG0wrXTdMdV1k4zU+W16j/+IF5CxDRFObS7FlQDrtDBPz\n" + + "Xv/YDLowLQ6KJSdfNWvT9Om7xKSMOXC7VJ7JuQrbwboi+1gV8QyfyAEiayjRgXSvMYm9fi\n" + + "m/LTSwE+g49uQcMpaokTYW+ZdTYuGiqxNhakhHOTcefnLEDBJfTASd6RLCxwTW6IQy/o28\n" + + "C4LkVQ+giQAAA9AaxHf6GsR3+gAAAAdzc2gtcnNhAAABAQCYwLN4EXy7g0Xugv4lQfoujb\n" + + "ARi48gPSxVuptGsSoGqsS00e9rA7v0qzFKa9Zhnw1WkjCnEXRYAMiCAJYkM/mGI8mb3qkc\n" + + "dNhGWZmPnopV+D46CTFB14yeR9mjoOPXs4pjX3zGveKx5Nx8jvdoFewbTCtdN0x1XWTjNT\n" + + "5bXqP/4gXkLENEU5tLsWVAOu0ME/Ne/9gMujAtDoolJ181a9P06bvEpIw5cLtUnsm5CtvB\n" + + "uiL7WBXxDJ/IASJrKNGBdK8xib1+Kb8tNLAT6Dj25BwylqiRNhb5l1Ni4aKrE2FqSEc5Nx\n" + + "5+csQMEl9MBJ3pEsLHBNbohDL+jbwLguRVD6CJAAAAAwEAAQAAAQARfhfPSylei9TpUGTs\n" + + "PVb6F82u5K16QqceFiWL/ePTKaEnF9d0CNRwW15kqF6/hShQ3qLlrvEE1uofQRPwh2cuvl\n" + + "BrIh95m8PcoowcT0qGN8xgdwcGBDodMhsxSs5suCnD4X53f+1C8/Nv7CtW5xPHuHxKy3dd\n" + + "BVn1TvaaHgdn2PwJVKtZp+WVG3/UHr25nFHd8mYgpeHZqK9AW16N0UEMXMM1u8ZCubVOoS\n" + + "IGuMAXpTug0xA+BXHo17FcDGKSzcXFzh+urIz5glRp5zFioHBqxNmkKfQkG6C7UxnPGyS/\n" + + "/J+3lL2lvl0G8kO/5EDFMBhTMEy1NeR2b629S4G1qUxVAAAAgHDwE9kPiVETcxSzI4wotT\n" + + "1Ee9nKVVD3oGdRqefvX7EUR8bvdv4nCqHPNBx8C6l8zo7fsQD81YL85F4eWbtrdxEijRHX\n" + + "5m7J/muh/laY1Hq43WCkZGboO4fZ2HHi7oN096FqrKRpvbQGQi1FLbcISUdsitwrs6ywn3\n" + + "fNx3q+X3V6AAAAgQDJRo9v+0QvldI33cpJKPKiaop5QvfIDzMatD3vLA1qqycgIi4KOtb5\n" + + "+LP/jgIpCYah/sk+JpKNz/vsZmZmrfaVu9D3Le2LLBgMpEoSO8jOe9WGI4Ew75C7w7AZCa\n" + + "SyUnHIVX/9D8Y5tx4cKx6Im9AGbNF35XZoKO4KCk5VMTXhnwAAAIEAwkjKIpTYdeAQVTRf\n" + + "C13kg84Bu5n4WkiLnp1WOCg2GN5RekqprINtpjIMZoB9Fv292Np99La8yvmRoy5qzNHGdm\n" + + "Q6AMku8jP123jF2J+wDvF714VtZHNvdCYBGJS+rZ81xtJfHhKtZqRAVtbPertOWZeuRm9V\n" + + "o+/rEuEzgGYGXNcAAAAbemhhbmdsaW4zM0B6aGFuZ2xpbjMzLmxvY2Fs\n" + + "-----END OPENSSH PRIVATE KEY-----"; + + byte[] privKeyBytes = null; + try { + privKeyBytes = new PemReader(new StringReader(privKeyStr)).readPemObject().getContent(); + } catch (IOException e1) { + e1.printStackTrace(); + } + + assert privKeyBytes != null; + System.out.println(Hex.toHexString(privKeyBytes)); + + + OpenSSHPrivateKeySpec privKeySpec = new OpenSSHPrivateKeySpec(privKeyBytes); + + String privKeyFormat = privKeySpec.getFormat(); + System.out.println(privKeyFormat); + + RSAKeyParameters privKey = (RSAKeyParameters) OpenSSHPrivateKeyUtil.parsePrivateKeyBlob(privKeyBytes); + +// BigInteger e = privKey.getPublicExponent(); +// BigInteger n = privKey.getModulus(); +// +// BigInteger d = privKey.getExponent(); +// BigInteger p = privKey.getP(); +// BigInteger q = privKey.getQ(); +// BigInteger dP = privKey.getDP(); +// BigInteger dQ = privKey.getDQ(); +// BigInteger qInv = privKey.getQInv(); + +// System.out.println(Hex.toHexString(e.toByteArray())); +// System.out.println(Hex.toHexString(n.toByteArray())); +// +// System.out.println(Hex.toHexString(d.toByteArray())); +// System.out.println(Hex.toHexString(p.toByteArray())); +// System.out.println(Hex.toHexString(q.toByteArray())); +// System.out.println(Hex.toHexString(dP.toByteArray())); +// System.out.println(Hex.toHexString(dQ.toByteArray())); +// System.out.println(Hex.toHexString(qInv.toByteArray())); + + + + } + +} diff --git a/source/crypto/crypto-pki/pom.xml b/source/crypto/crypto-pki/pom.xml new file mode 100644 index 00000000..5256127d --- /dev/null +++ b/source/crypto/crypto-pki/pom.xml @@ -0,0 +1,34 @@ + + + + crypto + com.jd.blockchain + 0.9.0-SNAPSHOT + + 4.0.0 + + crypto-pki + + + + com.jd.blockchain + crypto-classic + ${project.version} + + + org.bouncycastle + bcprov-jdk15on + 1.61 + + + + org.bouncycastle + bcpkix-jdk15on + 1.61 + + + + + \ No newline at end of file diff --git a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CSRBuilder.java b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CSRBuilder.java new file mode 100644 index 00000000..76f16247 --- /dev/null +++ b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CSRBuilder.java @@ -0,0 +1,10 @@ +package com.jd.blockchain.crypto; + +/** + * @author zhanglin33 + * @title: CSRBuilder + * @description: A builder for certificate signing request, supporting rsa and sm2 + * @date 2019-05-10, 15:10 + */ +public class CSRBuilder { +} diff --git a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CertParser.java b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CertParser.java new file mode 100644 index 00000000..480b833c --- /dev/null +++ b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CertParser.java @@ -0,0 +1,10 @@ +package com.jd.blockchain.crypto; + +/** + * @author zhanglin33 + * @title: CertParser + * @description: TODO + * @date 2019-05-10, 15:17 + */ +public class CertParser { +} diff --git a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CSRBuilderTest.java b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CSRBuilderTest.java new file mode 100644 index 00000000..42ecff9e --- /dev/null +++ b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CSRBuilderTest.java @@ -0,0 +1,161 @@ +package com.jd.blockchain.crypto; + +import com.jd.blockchain.crypto.utils.classic.RSAUtils; +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.asn1.x500.X500NameBuilder; +import org.bouncycastle.asn1.x500.style.BCStrictStyle; +import org.bouncycastle.asn1.x500.style.BCStyle; +import org.bouncycastle.asn1.x500.style.RFC4519Style; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.crypto.AsymmetricCipherKeyPair; +import org.bouncycastle.jcajce.provider.asymmetric.rsa.BCRSAPublicKey; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.operator.ContentSigner; +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder; +import org.bouncycastle.pkcs.PKCS10CertificationRequest; +import org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder; +import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest; +import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder; +import org.bouncycastle.util.Arrays; +import org.bouncycastle.util.encoders.Base64; +import org.junit.Test; +import sun.security.rsa.RSAPublicKeyImpl; + +import java.io.IOException; +import java.security.*; + +import static org.junit.Assert.fail; + +/** + * @author zhanglin33 + * @title: CSRBuilderTest + * @description: TODO + * @date 2019-05-10, 17:22 + */ +public class CSRBuilderTest { + public static String genCSR(String subject, String alg, String provider) { + String signalg = ""; + int alglength = 0; + String keyAlg = ""; + if (alg.toUpperCase().equals("RSA1024")) { + signalg = "SHA1WithRSA"; + alglength = 1024; + keyAlg = "RSA"; + } else if (alg.toUpperCase().equals("RSA2048")) { + signalg = "SHA1WithRSA"; + alglength = 2048; + keyAlg = "RSA"; + } else if (alg.toUpperCase().equals("SM2")) { + signalg = "SM3withSM2"; + alglength = 256; + keyAlg = "SM2"; + } + KeyPairGenerator keyGen; + PKCS10CertificationRequestBuilder builder; + + try { + keyGen = KeyPairGenerator.getInstance(keyAlg); + keyGen.initialize(alglength); + KeyPair kp = keyGen.generateKeyPair(); + + + builder = new PKCS10CertificationRequestBuilder(new X500Name(subject), SubjectPublicKeyInfo.getInstance(kp.getPublic().getEncoded())); + JcaContentSignerBuilder jcaContentSignerBuilder = new JcaContentSignerBuilder(signalg); + jcaContentSignerBuilder.setProvider(provider); + ContentSigner contentSigner = jcaContentSignerBuilder.build(kp.getPrivate()); + builder.build(contentSigner); + return builder.toString(); + } catch (OperatorCreationException | NoSuchAlgorithmException e) { + e.printStackTrace(); + } + return null; + } + + @Test + public void csrTest() throws Exception{ + + Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); + + + String keyName = "RSA"; + String sigName = "SHA1withRSA"; + + String BC = BouncyCastleProvider.PROVIDER_NAME; + KeyPairGenerator kpg = KeyPairGenerator.getInstance(keyName, BC); + + kpg.initialize(2048); + + KeyPair kp = kpg.generateKeyPair(); +// AsymmetricCipherKeyPair keyPair = RSAUtils.generateKeyPair(); + + + X500NameBuilder builder = new X500NameBuilder(BCStrictStyle.INSTANCE); + + builder.addRDN(BCStyle.C,"CN"); // a country name, and China is short as CN + builder.addRDN(BCStyle.ST, "Beijing"); // a state or province name + builder.addRDN(BCStyle.L, "Beijing"); // a city name + builder.addRDN(BCStyle.O, "JD.com"); // an organization or corporation name + builder.addRDN(BCStyle.OU, "Blockchain Department"); // a division of your organization name + builder.addRDN(BCStyle.CN, "ledger.jd.com"); // a fully qualified domain name + builder.addRDN(BCStyle.EmailAddress, "zhanglin33@jd.com"); // an email address + + X500Name x500Name = builder.build(); + + PKCS10CertificationRequestBuilder requestBuilder = new JcaPKCS10CertificationRequestBuilder(x500Name, kp.getPublic()); + +// PKCS10CertificationRequest req = requestBuilder.build(new JcaContentSignerBuilder(sigName).setProvider(sigName).build(kp.getPrivate())); + PKCS10CertificationRequest req = requestBuilder.build(new JcaContentSignerBuilder(sigName).setProvider(BC).build(kp.getPrivate())); + + + byte[] csrBytes = req.getEncoded(); + String result = Base64.toBase64String(csrBytes); + System.out.println(result); + + } + + @Test + public void csr2Test() throws Exception { + Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); + generationTest(512, "RSA", "SHA1withRSA", "BC"); + } + + private void generationTest(int keySize, String keyName, String sigName, String provider) + throws Exception { + KeyPairGenerator kpg = KeyPairGenerator.getInstance(keyName, "BC"); + + kpg.initialize(keySize); + + KeyPair kp = kpg.generateKeyPair(); + + + X500NameBuilder x500NameBld = new X500NameBuilder(BCStyle.INSTANCE); + + x500NameBld.addRDN(BCStyle.C, "AU"); + x500NameBld.addRDN(BCStyle.O, "The Legion of the Bouncy Castle"); + x500NameBld.addRDN(BCStyle.L, "Melbourne"); + x500NameBld.addRDN(BCStyle.ST, "Victoria"); + + x500NameBld.addRDN(BCStyle.EmailAddress, "feedback-crypto@bouncycastle.org"); + + X500Name subject = x500NameBld.build(); + + PKCS10CertificationRequestBuilder requestBuilder = new JcaPKCS10CertificationRequestBuilder(subject, kp.getPublic()); + BCRSAPublicKey pubKey = (BCRSAPublicKey) kp.getPublic(); + System.out.println(pubKey.getModulus().bitLength()); + + PKCS10CertificationRequest req1 = requestBuilder.build(new JcaContentSignerBuilder(sigName).setProvider(provider).build(kp.getPrivate())); + + JcaPKCS10CertificationRequest req2 = new JcaPKCS10CertificationRequest(req1.getEncoded()).setProvider(provider); + + if (!req2.isSignatureValid(new JcaContentVerifierProviderBuilder().setProvider(provider).build(kp.getPublic()))) { + fail(sigName + ": Failed verify check."); + } + + if (!Arrays.areEqual(req2.getPublicKey().getEncoded(), req1.getSubjectPublicKeyInfo().getEncoded())) { + fail(keyName + ": Failed public key check."); + } + } + +} diff --git a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CertParserTest.java b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CertParserTest.java new file mode 100644 index 00000000..3a8ecc7a --- /dev/null +++ b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CertParserTest.java @@ -0,0 +1,10 @@ +package com.jd.blockchain.crypto; + +/** + * @author zhanglin33 + * @title: CertParserTest + * @description: TODO + * @date 2019-05-13, 10:05 + */ +public class CertParserTest { +} diff --git a/source/crypto/pom.xml b/source/crypto/pom.xml index fb6e71ba..f8b66416 100644 --- a/source/crypto/pom.xml +++ b/source/crypto/pom.xml @@ -16,6 +16,7 @@ crypto-sm crypto-adv + crypto-pki \ No newline at end of file diff --git a/source/pom.xml b/source/pom.xml index 6b1da241..35de30f4 100644 --- a/source/pom.xml +++ b/source/pom.xml @@ -281,6 +281,12 @@ bcprov-jdk15on 1.61 + + + org.bouncycastle + bcpkix-jdk15on + 1.61 + io.nats From 66a58d44afb5ed2ad3c94e1bd712d2c60068edcd Mon Sep 17 00:00:00 2001 From: zhanglin33 Date: Mon, 13 May 2019 11:36:16 +0800 Subject: [PATCH 25/43] add the standard public exponent form in RSAUtils --- .../crypto/utils/classic/RSAUtils.java | 16 ++++++++++ .../crypto/utils/classic/CertTest.java | 4 +-- .../crypto/utils/classic/RSAUtilsTest.java | 30 ++++++++----------- .../com/jd/blockchain/crypto/CSRBuilder.java | 19 ++++++++++++ 4 files changed, 49 insertions(+), 20 deletions(-) diff --git a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java index 3515a435..bc1e5bdc 100644 --- a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java +++ b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java @@ -49,6 +49,7 @@ public class RSAUtils { private static final int QINV_LENGTH = 1024 / 8; private static final BigInteger PUBEXP_0X03 = BigInteger.valueOf(0x03); + private static final BigInteger PUBEXP_0X010001 = BigInteger.valueOf(0x010001); private static final BigInteger VERSION_2PRIMES = BigInteger.valueOf(0); @@ -71,6 +72,21 @@ public class RSAUtils { } public static AsymmetricCipherKeyPair generateKeyPair(SecureRandom random){ + AsymmetricCipherKeyPairGenerator kpGen = new RSAKeyPairGenerator(); + kpGen.init(new RSAKeyGenerationParameters(PUBEXP_0X010001, random, KEYSIZEBITS, CERTAINTY)); + return kpGen.generateKeyPair(); + } + + /** + * key pair generation with short public exponent, resulting in verifying and encrypting more efficiently + * + * @return key pair + */ + public static AsymmetricCipherKeyPair generateKeyPair_shortExp(){ + return generateKeyPair(new SecureRandom()); + } + + public static AsymmetricCipherKeyPair generateKeyPair_shortExp(SecureRandom random){ AsymmetricCipherKeyPairGenerator kpGen = new RSAKeyPairGenerator(); kpGen.init(new RSAKeyGenerationParameters(PUBEXP_0X03, random, KEYSIZEBITS, CERTAINTY)); return kpGen.generateKeyPair(); diff --git a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/CertTest.java b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/CertTest.java index 94e5ad24..d392336d 100644 --- a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/CertTest.java +++ b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/CertTest.java @@ -50,9 +50,7 @@ public class CertTest { String name = cert.getIssuerX500Principal().getName(); System.out.println(name); bIn.close(); - } catch (CertificateException e) { - e.printStackTrace(); - } catch (IOException e) { + } catch (CertificateException | IOException e) { e.printStackTrace(); } return dn; diff --git a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RSAUtilsTest.java b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RSAUtilsTest.java index 982cd35e..114f8b55 100644 --- a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RSAUtilsTest.java +++ b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RSAUtilsTest.java @@ -33,10 +33,20 @@ import static org.junit.Assert.*; public class RSAUtilsTest { @Test - public void generateKeyPairTest() throws IOException { + public void generateKeyPairTest() { AsymmetricCipherKeyPair kp = RSAUtils.generateKeyPair(); - RSAKeyParameters pubKey = (RSAKeyParameters) kp.getPublic(); - RSAPrivateCrtKeyParameters privKey = (RSAPrivateCrtKeyParameters) kp.getPrivate(); + keyPairTest(kp); + } + + @Test + public void generateKeyPair_ShortExpTest() { + AsymmetricCipherKeyPair kp = RSAUtils.generateKeyPair_shortExp(); + keyPairTest(kp); + } + + private void keyPairTest(AsymmetricCipherKeyPair keyPair) { + RSAKeyParameters pubKey = (RSAKeyParameters) keyPair.getPublic(); + RSAPrivateCrtKeyParameters privKey = (RSAPrivateCrtKeyParameters) keyPair.getPrivate(); byte[] pubKeyBytes_RawKey = RSAUtils.pubKey2Bytes_RawKey(pubKey); byte[] pubKeyBytesConverted_RawKey = @@ -48,9 +58,6 @@ public class RSAUtilsTest { RSAUtils.privKey2Bytes_RawKey(RSAUtils.bytes2PrivKey_RawKey(privKeyBytes_RawKey)); assertArrayEquals(privKeyBytes_RawKey,privKeyBytesConverted_RawKey); - System.out.println(pubKeyBytes_RawKey.length); - System.out.println(privKeyBytes_RawKey.length); - byte[] pubKeyBytes_PKCS1 = RSAUtils.pubKey2Bytes_PKCS1(pubKey); byte[] pubKeyBytesConverted_PKCS1 = RSAUtils.pubKey2Bytes_PKCS1(RSAUtils.bytes2PubKey_PKCS1(pubKeyBytes_PKCS1)); @@ -65,17 +72,6 @@ public class RSAUtilsTest { byte[] pubKeyBytesConverted_PKCS8 = RSAUtils.pubKey2Bytes_PKCS8(RSAUtils.bytes2PubKey_PKCS8(pubKeyBytes_PKCS8)); assertArrayEquals(pubKeyBytes_PKCS8,pubKeyBytesConverted_PKCS8); -// -//// String str = "1.2.840.113549.1.1"; -//// System.out.println(Hex.toHexString(str.getBytes())); -// byte[] bytes = null; -// AlgorithmIdentifier RSA_ALGORITHM_IDENTIFIER = -// new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE); -//// byte[] result = KeyUtil.getEncodedSubjectPublicKeyInfo(RSA_ALGORITHM_IDENTIFIER, bytes); -// byte[] algo = RSA_ALGORITHM_IDENTIFIER.getEncoded(); -// System.out.println(Hex.toHexString(algo)); -//// System.out.println(Hex.toHexString(result)); -// System.out.println(Hex.toHexString(pubKeyBytes_PKCS8)); byte[] privKeyBytes_PKCS8 = RSAUtils.privKey2Bytes_PKCS8(privKey); byte[] privKeyBytesConverted_PKCS8 = diff --git a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CSRBuilder.java b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CSRBuilder.java index 76f16247..3cef8326 100644 --- a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CSRBuilder.java +++ b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CSRBuilder.java @@ -1,5 +1,7 @@ package com.jd.blockchain.crypto; +import org.bouncycastle.crypto.AsymmetricCipherKeyPair; + /** * @author zhanglin33 * @title: CSRBuilder @@ -7,4 +9,21 @@ package com.jd.blockchain.crypto; * @date 2019-05-10, 15:10 */ public class CSRBuilder { + + private String C; + private String ST; + private String L; + private String O; + private String OU; + private String CN; + private String E; + + public AsymmetricCipherKeyPair init() { + return null; + } + + public String buildRequest(String keyName, AsymmetricCipherKeyPair keyPair, String algoName, + String[] applicantInfo) { + return null; + } } From 6c7f5ada36cc4bae7f9475490ea8177a7d171957 Mon Sep 17 00:00:00 2001 From: zhaoguangwei Date: Mon, 13 May 2019 17:11:42 +0800 Subject: [PATCH 26/43] add new restful interface: ledgers/{ledgerHash}/accounts/{address}/entries-version test OK. --- .../com/jd/blockchain/ContractDeployMojo.java | 1 + .../java/com/jd/blockchain/StringUtils.java | 10 --- .../main/resources/sys-contract.properties | 6 +- source/contract/contract-tools/pom.xml | 80 ------------------- .../gateway/web/BlockBrowserController.java | 8 ++ .../ledger/core/impl/LedgerQueryService.java | 41 ++++++++++ .../impl/handles/ContractLedgerContext.java | 5 ++ .../transaction/BlockchainQueryService.java | 2 + .../peer/web/LedgerQueryController.java | 52 +++++++++++- .../sdk/proxy/BlockchainServiceProxy.java | 5 ++ .../sdk/proxy/HttpBlockchainQueryService.java | 8 +- .../com/jd/blockchain/utils/StringUtils.java | 24 ++++++ 12 files changed, 147 insertions(+), 95 deletions(-) delete mode 100644 source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/StringUtils.java delete mode 100644 source/contract/contract-tools/pom.xml create mode 100644 source/utils/utils-common/src/main/java/com/jd/blockchain/utils/StringUtils.java diff --git a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractDeployMojo.java b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractDeployMojo.java index 80be911f..3eac13bb 100644 --- a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractDeployMojo.java +++ b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractDeployMojo.java @@ -5,6 +5,7 @@ import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.ledger.BlockchainKeypair; import com.jd.blockchain.tools.keygen.KeyGenCommand; +import com.jd.blockchain.utils.StringUtils; import com.jd.blockchain.utils.codec.Base58Utils; import com.jd.blockchain.utils.io.FileUtils; import org.apache.maven.plugin.AbstractMojo; diff --git a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/StringUtils.java b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/StringUtils.java deleted file mode 100644 index f8fe1867..00000000 --- a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/StringUtils.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.jd.blockchain; -/** - * @Author zhaogw - * @Date 2018/11/26 20:46 - */ -public abstract class StringUtils { - public static boolean isEmpty(Object str) { - return str == null || "".equals(str); - } -} \ No newline at end of file diff --git a/source/contract/contract-maven-plugin/src/main/resources/sys-contract.properties b/source/contract/contract-maven-plugin/src/main/resources/sys-contract.properties index 6dd66e5e..a7179906 100644 --- a/source/contract/contract-maven-plugin/src/main/resources/sys-contract.properties +++ b/source/contract/contract-maven-plugin/src/main/resources/sys-contract.properties @@ -1,9 +1,9 @@ -#ĿԴļŵλ; +#PROJECT_BASE_DIR PROJECT_BASE_DIR=E:\\gitCode\\block\\prototype\\ -#ͬʹõŵλãܲĿУʲȫµĵַ; +#LEDGER_BASE_CLASS_PATH LEDGER_BASE_CLASS_PATH=E:\\gitCode\\block\\prototype\\libs\\ -#Ϊ˲ԣʱӵı; +#deploy and execute the contract; cParam=com.jd.blockchain.contract.AssetContract3 sParam=E:\\gitCode\\block\\prototype\\source\\sdk\\contract-sample\\src\\main\\java\\ eParam=utf-8 diff --git a/source/contract/contract-tools/pom.xml b/source/contract/contract-tools/pom.xml deleted file mode 100644 index da60f463..00000000 --- a/source/contract/contract-tools/pom.xml +++ /dev/null @@ -1,80 +0,0 @@ - - 4.0.0 - - com.jd.blockchain - contract - 0.9.0-SNAPSHOT - - contract-tools - - - - com.jd.blockchain - contract-compiler - ${project.version} - - - com.jd.blockchain - contract-jar - ${project.version} - - - commons-io - commons-io - ${commons-io.version} - - - junit - junit - test - - - org.mockito - mockito-core - test - - - org.slf4j - slf4j-log4j12 - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.5 - - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java b/source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java index 381cc50f..1094e9b9 100644 --- a/source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java +++ b/source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java @@ -239,6 +239,14 @@ public class BlockBrowserController implements BlockchainExtendQueryService { return peerService.getQueryService().getDataEntries(ledgerHash, address, keys); } + @RequestMapping(method = {RequestMethod.GET, RequestMethod.POST}, path = "ledgers/{ledgerHash}/accounts/{address}/entries-version") + public KVDataEntry[] getDataEntries(@PathVariable("ledgerHash") HashDigest ledgerHash, + @PathVariable("address") String address, + @RequestParam("keys") String keys[], + @RequestParam("versions") String versions[]) { + return peerService.getQueryService().getDataEntries(ledgerHash, address, keys, versions); + } + @RequestMapping(method = {RequestMethod.GET, RequestMethod.POST}, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries") @Override public KVDataEntry[] getDataEntries(@PathVariable("ledgerHash") HashDigest ledgerHash, diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java index 086b18ff..1ed2b6d9 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java @@ -2,6 +2,7 @@ package com.jd.blockchain.ledger.core.impl; import com.jd.blockchain.binaryproto.BinaryProtocol; import com.jd.blockchain.binaryproto.PrimitiveType; +import com.jd.blockchain.contract.ContractException; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.ledger.*; import com.jd.blockchain.ledger.core.ContractAccountSet; @@ -15,6 +16,7 @@ import com.jd.blockchain.ledger.core.UserAccountSet; import com.jd.blockchain.transaction.BlockchainQueryService; import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.QueryUtil; +import com.jd.blockchain.utils.StringUtils; public class LedgerQueryService implements BlockchainQueryService { @@ -263,6 +265,9 @@ public class LedgerQueryService implements BlockchainQueryService { long ver; for (int i = 0; i < entries.length; i++) { ver = dataAccount.getDataVersion(Bytes.fromString(keys[i])); + + dataAccount.getBytes(Bytes.fromString(keys[i]),1); + if (ver < 0) { entries[i] = new KVDataObject(keys[i], -1, PrimitiveType.NIL, null); }else { @@ -275,6 +280,42 @@ public class LedgerQueryService implements BlockchainQueryService { return entries; } + public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, String[] keys, String[] versions) { + if (keys == null || keys.length == 0) { + return null; + } + if (versions == null || versions.length == 0) { + return null; + } + if(keys.length != versions.length){ + throw new ContractException("keys.length!=versions.length!"); + } + + LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerBlock block = ledger.getLatestBlock(); + DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); + DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address)); + + KVDataEntry[] entries = new KVDataEntry[keys.length]; + long ver = -1; + for (int i = 0; i < entries.length; i++) { +// ver = dataAccount.getDataVersion(Bytes.fromString(keys[i])); +// dataAccount.getBytes(Bytes.fromString(keys[i]),1); + if(StringUtils.isNumber(versions[i])){ + ver = Long.parseLong(versions[i]); + } + if (ver < 0) { + entries[i] = new KVDataObject(keys[i], -1, PrimitiveType.NIL, null); + }else { + byte[] value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver); + BytesValue decodeData = BinaryProtocol.decode(value); + entries[i] = new KVDataObject(keys[i], ver, PrimitiveType.valueOf(decodeData.getType().CODE), decodeData.getValue().toBytes()); + } + } + + return entries; + } + @Override public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count) { diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractLedgerContext.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractLedgerContext.java index 2d51c185..92049f0f 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractLedgerContext.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractLedgerContext.java @@ -156,6 +156,11 @@ public class ContractLedgerContext implements LedgerContext { return innerQueryService.getDataEntries(ledgerHash, address, keys); } + @Override + public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, String[] keys, String[] versions) { + return innerQueryService.getDataEntries(ledgerHash, address, keys, versions); + } + @Override public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count) { return innerQueryService.getDataEntries(ledgerHash, address, fromIndex, count); diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java index 45301f13..26d719bd 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java @@ -261,6 +261,8 @@ public interface BlockchainQueryService { */ KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys); + KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, String[] keys, String[] versions); + /** * 返回指定数据账户中KV数据的总数;
* diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java b/source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java index 6db9674c..8487d67f 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java @@ -1,7 +1,8 @@ package com.jd.blockchain.peer.web; +import com.jd.blockchain.contract.ContractException; import com.jd.blockchain.ledger.*; -import com.jd.blockchain.ledger.core.*; +import com.jd.blockchain.utils.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @@ -12,6 +13,15 @@ import org.springframework.web.bind.annotation.RestController; import com.jd.blockchain.binaryproto.BinaryProtocol; import com.jd.blockchain.binaryproto.PrimitiveType; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.ledger.core.ContractAccountSet; +import com.jd.blockchain.ledger.core.DataAccount; +import com.jd.blockchain.ledger.core.DataAccountSet; +import com.jd.blockchain.ledger.core.LedgerAdministration; +import com.jd.blockchain.ledger.core.LedgerRepository; +import com.jd.blockchain.ledger.core.LedgerService; +import com.jd.blockchain.ledger.core.ParticipantCertData; +import com.jd.blockchain.ledger.core.TransactionSet; +import com.jd.blockchain.ledger.core.UserAccountSet; import com.jd.blockchain.transaction.BlockchainQueryService; import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.QueryUtil; @@ -342,6 +352,46 @@ public class LedgerQueryController implements BlockchainQueryService { return entries; } + @RequestMapping(method = {RequestMethod.GET, RequestMethod.POST}, path = "ledgers/{ledgerHash}/accounts/{address}/entries-version") + @Override + public KVDataEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, + @PathVariable(name = "address") String address, + @RequestParam("keys") String[] keys, + @RequestParam("versions") String[] versions) { + if (keys == null || keys.length == 0) { + return null; + } + if (versions == null || versions.length == 0) { + return null; + } + if(keys.length != versions.length){ + throw new ContractException("keys.length!=versions.length!"); + } + + LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerBlock block = ledger.getLatestBlock(); + DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); + DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address)); + + KVDataEntry[] entries = new KVDataEntry[keys.length]; + long ver = -1; + for (int i = 0; i < entries.length; i++) { +// ver = dataAccount.getDataVersion(Bytes.fromString(keys[i])); + if(StringUtils.isNumber(versions[i])){ + ver = Long.parseLong(versions[i]); + } + if (ver < 0) { + entries[i] = new KVDataObject(keys[i], -1, PrimitiveType.NIL, null); + }else { + byte[] value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver); + BytesValue decodeData = BinaryProtocol.decode(value); + entries[i] = new KVDataObject(keys[i], ver, PrimitiveType.valueOf(decodeData.getType().CODE), decodeData.getValue().toBytes()); + } + } + + return entries; + } + @RequestMapping(method = {RequestMethod.GET, RequestMethod.POST}, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries") @Override public KVDataEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java index 4dbe7bc9..fce0d410 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java @@ -147,6 +147,11 @@ public abstract class BlockchainServiceProxy implements BlockchainService { return getQueryService(ledgerHash).getDataEntries(ledgerHash, address, keys); } + @Override + public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, String[] keys, String[] versions) { + return getQueryService(ledgerHash).getDataEntries(ledgerHash, address, keys, versions); + } + @Override public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count) { return getQueryService(ledgerHash).getDataEntries(ledgerHash, address, fromIndex, count); diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java index bfdc0baf..90860f80 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java @@ -496,7 +496,12 @@ public interface HttpBlockchainQueryService extends BlockchainExtendQueryService @PathParam(name="address") String address, @RequestParam(name="keys", array = true) String... keys); - @HttpAction(method = HttpMethod.POST, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries") + @HttpAction(method=HttpMethod.POST, path="ledgers/{ledgerHash}/accounts/{address}/entries-version") + @Override + KVDataEntry[] getDataEntries(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash, + @PathParam(name="address") String address, + @RequestParam(name="keys", array = true) String[] keys, + @RequestParam(name="versions", array = true) String[] versions); /** * 返回数据账户中指定序号的最新值; @@ -513,6 +518,7 @@ public interface HttpBlockchainQueryService extends BlockchainExtendQueryService * 如果参数值为 -1,则返回全部的记录;
* @return */ + @HttpAction(method = HttpMethod.POST, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries") @Override KVDataEntry[] getDataEntries(@PathParam(name = "ledgerHash") HashDigest ledgerHash, @PathParam(name = "address") String address, diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/StringUtils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/StringUtils.java new file mode 100644 index 00000000..5ae1a856 --- /dev/null +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/StringUtils.java @@ -0,0 +1,24 @@ +package com.jd.blockchain.utils; + +import java.util.regex.Pattern; + +/** + * @Author zhaogw + * date 2018/11/26 20:46 + */ +public class StringUtils { + public static boolean isEmpty(Object str) { + return str == null || "".equals(str); + } + + /* + * 判断是否为整数 + * @param str 传入的字符串 + * @return 是整数返回true,否则返回false + */ + + public static boolean isNumber(String str) { + Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$"); + return pattern.matcher(str).matches(); + } +} \ No newline at end of file From 7b0cc1cafb06fd2fbfdf0e6ea3a0015513c28d9d Mon Sep 17 00:00:00 2001 From: zhanglin33 Date: Tue, 14 May 2019 16:30:29 +0800 Subject: [PATCH 27/43] add CSRBuilder and its junitTest --- .../crypto/utils/classic/RSAUtils.java | 2 +- .../com/jd/blockchain/crypto/CSRBuilder.java | 121 +++++++++- .../jd/blockchain/crypto/CSRBuilderTest.java | 214 +++++++----------- 3 files changed, 195 insertions(+), 142 deletions(-) diff --git a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java index bc1e5bdc..f17dcdf2 100644 --- a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java +++ b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java @@ -83,7 +83,7 @@ public class RSAUtils { * @return key pair */ public static AsymmetricCipherKeyPair generateKeyPair_shortExp(){ - return generateKeyPair(new SecureRandom()); + return generateKeyPair_shortExp(new SecureRandom()); } public static AsymmetricCipherKeyPair generateKeyPair_shortExp(SecureRandom random){ diff --git a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CSRBuilder.java b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CSRBuilder.java index 3cef8326..7ec35785 100644 --- a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CSRBuilder.java +++ b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CSRBuilder.java @@ -1,6 +1,25 @@ package com.jd.blockchain.crypto; +import com.jd.blockchain.crypto.utils.classic.RSAUtils; +import org.bouncycastle.asn1.x500.RDN; +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.asn1.x500.X500NameBuilder; +import org.bouncycastle.asn1.x500.style.BCStrictStyle; +import org.bouncycastle.asn1.x500.style.BCStyle; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; +import org.bouncycastle.crypto.params.AsymmetricKeyParameter; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.jce.spec.ECNamedCurveGenParameterSpec; +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.bouncycastle.pkcs.PKCS10CertificationRequest; +import org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder; +import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder; +import org.bouncycastle.util.encoders.Base64; + + +import java.io.IOException; +import java.security.*; /** * @author zhanglin33 @@ -10,20 +29,98 @@ import org.bouncycastle.crypto.AsymmetricCipherKeyPair; */ public class CSRBuilder { - private String C; - private String ST; - private String L; - private String O; - private String OU; - private String CN; - private String E; + private String BC = BouncyCastleProvider.PROVIDER_NAME; + + private PublicKey pubKey; + private PrivateKey privKey; + + private String algoName; + + public void init() { + Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); + algoName = "SHA1withRSA"; + KeyPairGenerator generator; + try { + generator = KeyPairGenerator.getInstance("RSA", BC); + generator.initialize(2048); + KeyPair keyPair = generator.generateKeyPair(); + pubKey = keyPair.getPublic(); + privKey = keyPair.getPrivate(); + } catch (NoSuchAlgorithmException | NoSuchProviderException e) { + throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e); + } + } + + public void init(String algoName, int KeyLength) { + + Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); + this.algoName = algoName; + + KeyPairGenerator generator; + KeyPair keyPair; + String[] hashAndSignature = algoName.split("with"); + + try { + switch (hashAndSignature[1]) { + case "RSA": { + generator = KeyPairGenerator.getInstance("RSA", BC); + generator.initialize(KeyLength); + keyPair = generator.generateKeyPair(); + pubKey = keyPair.getPublic(); + privKey = keyPair.getPrivate(); + } + + case "SM2": { + generator = KeyPairGenerator.getInstance("EC", BC); + generator.initialize(new ECNamedCurveGenParameterSpec("sm2p256v1")); + keyPair = generator.generateKeyPair(); + pubKey = keyPair.getPublic(); + privKey = keyPair.getPrivate(); + } + + default: throw new CryptoException("Unsupported key algorithm[" + algoName + "] in CSR!"); + } + } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) { + throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e); + } + } + + public String buildRequest(String countryName, String stateName, String cityName, + String organizationName, String departmentName, String domainName, + String emailName) { + + String result = null; + X500NameBuilder nameBuilder = new X500NameBuilder(BCStrictStyle.INSTANCE); + + nameBuilder.addRDN(BCStyle.C, countryName); // a country name, and China is short as CN + nameBuilder.addRDN(BCStyle.ST, stateName); // a state or province name + nameBuilder.addRDN(BCStyle.L, cityName); // a city name + nameBuilder.addRDN(BCStyle.O, organizationName); // an organization or corporation name + nameBuilder.addRDN(BCStyle.OU, departmentName); // a division of your organization name + nameBuilder.addRDN(BCStyle.CN, domainName); // a fully qualified domain name + nameBuilder.addRDN(BCStyle.E, emailName); // an email address + + try { + X500Name x500Name = nameBuilder.build(); + + PKCS10CertificationRequestBuilder requestBuilder + = new JcaPKCS10CertificationRequestBuilder(x500Name, pubKey); + PKCS10CertificationRequest request + = requestBuilder.build(new JcaContentSignerBuilder(algoName).setProvider(BC).build(privKey)); + byte[] csrBytes = request.getEncoded(); + result = Base64.toBase64String(csrBytes); + } catch (OperatorCreationException | IOException e) { + e.printStackTrace(); + } + + return result; + } - public AsymmetricCipherKeyPair init() { - return null; + public PublicKey getPubKey() { + return pubKey; } - public String buildRequest(String keyName, AsymmetricCipherKeyPair keyPair, String algoName, - String[] applicantInfo) { - return null; + public PrivateKey getPrivKey() { + return privKey; } } diff --git a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CSRBuilderTest.java b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CSRBuilderTest.java index 42ecff9e..b61f3ca1 100644 --- a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CSRBuilderTest.java +++ b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CSRBuilderTest.java @@ -1,32 +1,18 @@ package com.jd.blockchain.crypto; -import com.jd.blockchain.crypto.utils.classic.RSAUtils; -import org.bouncycastle.asn1.x500.X500Name; -import org.bouncycastle.asn1.x500.X500NameBuilder; -import org.bouncycastle.asn1.x500.style.BCStrictStyle; +import org.bouncycastle.asn1.ASN1Encoding; +import org.bouncycastle.asn1.DERSet; +import org.bouncycastle.asn1.pkcs.CertificationRequestInfo; +import org.bouncycastle.asn1.x500.RDN; import org.bouncycastle.asn1.x500.style.BCStyle; -import org.bouncycastle.asn1.x500.style.RFC4519Style; -import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; -import org.bouncycastle.crypto.AsymmetricCipherKeyPair; -import org.bouncycastle.jcajce.provider.asymmetric.rsa.BCRSAPublicKey; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.operator.ContentSigner; -import org.bouncycastle.operator.OperatorCreationException; -import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; -import org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder; import org.bouncycastle.pkcs.PKCS10CertificationRequest; -import org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder; -import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest; -import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder; -import org.bouncycastle.util.Arrays; import org.bouncycastle.util.encoders.Base64; import org.junit.Test; -import sun.security.rsa.RSAPublicKeyImpl; import java.io.IOException; import java.security.*; -import static org.junit.Assert.fail; +import static org.junit.Assert.*; /** * @author zhanglin33 @@ -35,127 +21,97 @@ import static org.junit.Assert.fail; * @date 2019-05-10, 17:22 */ public class CSRBuilderTest { - public static String genCSR(String subject, String alg, String provider) { - String signalg = ""; - int alglength = 0; - String keyAlg = ""; - if (alg.toUpperCase().equals("RSA1024")) { - signalg = "SHA1WithRSA"; - alglength = 1024; - keyAlg = "RSA"; - } else if (alg.toUpperCase().equals("RSA2048")) { - signalg = "SHA1WithRSA"; - alglength = 2048; - keyAlg = "RSA"; - } else if (alg.toUpperCase().equals("SM2")) { - signalg = "SM3withSM2"; - alglength = 256; - keyAlg = "SM2"; - } - KeyPairGenerator keyGen; - PKCS10CertificationRequestBuilder builder; - - try { - keyGen = KeyPairGenerator.getInstance(keyAlg); - keyGen.initialize(alglength); - KeyPair kp = keyGen.generateKeyPair(); - - - builder = new PKCS10CertificationRequestBuilder(new X500Name(subject), SubjectPublicKeyInfo.getInstance(kp.getPublic().getEncoded())); - JcaContentSignerBuilder jcaContentSignerBuilder = new JcaContentSignerBuilder(signalg); - jcaContentSignerBuilder.setProvider(provider); - ContentSigner contentSigner = jcaContentSignerBuilder.build(kp.getPrivate()); - builder.build(contentSigner); - return builder.toString(); - } catch (OperatorCreationException | NoSuchAlgorithmException e) { - e.printStackTrace(); - } - return null; - } - - @Test - public void csrTest() throws Exception{ - - Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); - - - String keyName = "RSA"; - String sigName = "SHA1withRSA"; - - String BC = BouncyCastleProvider.PROVIDER_NAME; - KeyPairGenerator kpg = KeyPairGenerator.getInstance(keyName, BC); - - kpg.initialize(2048); - - KeyPair kp = kpg.generateKeyPair(); -// AsymmetricCipherKeyPair keyPair = RSAUtils.generateKeyPair(); - - - X500NameBuilder builder = new X500NameBuilder(BCStrictStyle.INSTANCE); - - builder.addRDN(BCStyle.C,"CN"); // a country name, and China is short as CN - builder.addRDN(BCStyle.ST, "Beijing"); // a state or province name - builder.addRDN(BCStyle.L, "Beijing"); // a city name - builder.addRDN(BCStyle.O, "JD.com"); // an organization or corporation name - builder.addRDN(BCStyle.OU, "Blockchain Department"); // a division of your organization name - builder.addRDN(BCStyle.CN, "ledger.jd.com"); // a fully qualified domain name - builder.addRDN(BCStyle.EmailAddress, "zhanglin33@jd.com"); // an email address - - X500Name x500Name = builder.build(); - - PKCS10CertificationRequestBuilder requestBuilder = new JcaPKCS10CertificationRequestBuilder(x500Name, kp.getPublic()); - -// PKCS10CertificationRequest req = requestBuilder.build(new JcaContentSignerBuilder(sigName).setProvider(sigName).build(kp.getPrivate())); - PKCS10CertificationRequest req = requestBuilder.build(new JcaContentSignerBuilder(sigName).setProvider(BC).build(kp.getPrivate())); - - - byte[] csrBytes = req.getEncoded(); - String result = Base64.toBase64String(csrBytes); - System.out.println(result); - - } @Test - public void csr2Test() throws Exception { - Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); - generationTest(512, "RSA", "SHA1withRSA", "BC"); - } - - private void generationTest(int keySize, String keyName, String sigName, String provider) - throws Exception { - KeyPairGenerator kpg = KeyPairGenerator.getInstance(keyName, "BC"); - - kpg.initialize(keySize); - - KeyPair kp = kpg.generateKeyPair(); + public void defaultCSRTest(){ + String countryName = "CN"; + String stateName = "Beijing"; + String cityName = "Beijing"; + String organizationName = "JD.com"; + String departmentName = "Blockchain Department"; + String domainName = "ledger.jd.com"; + String emailName = "zhanglin33@jd.com"; - X500NameBuilder x500NameBld = new X500NameBuilder(BCStyle.INSTANCE); + CSRBuilder builder = new CSRBuilder(); - x500NameBld.addRDN(BCStyle.C, "AU"); - x500NameBld.addRDN(BCStyle.O, "The Legion of the Bouncy Castle"); - x500NameBld.addRDN(BCStyle.L, "Melbourne"); - x500NameBld.addRDN(BCStyle.ST, "Victoria"); + builder.init(); + String csr = builder.buildRequest(countryName,stateName,cityName, + organizationName,departmentName,domainName, + emailName); + System.out.println(csr); - x500NameBld.addRDN(BCStyle.EmailAddress, "feedback-crypto@bouncycastle.org"); + PublicKey pubKey = builder.getPubKey(); + PrivateKey privKey = builder.getPrivKey(); - X500Name subject = x500NameBld.build(); - - PKCS10CertificationRequestBuilder requestBuilder = new JcaPKCS10CertificationRequestBuilder(subject, kp.getPublic()); - BCRSAPublicKey pubKey = (BCRSAPublicKey) kp.getPublic(); - System.out.println(pubKey.getModulus().bitLength()); - - PKCS10CertificationRequest req1 = requestBuilder.build(new JcaContentSignerBuilder(sigName).setProvider(provider).build(kp.getPrivate())); - - JcaPKCS10CertificationRequest req2 = new JcaPKCS10CertificationRequest(req1.getEncoded()).setProvider(provider); + byte[] crsBytes = Base64.decode(csr); + PKCS10CertificationRequest request = null; + try { + request = new PKCS10CertificationRequest(crsBytes); + } catch (IOException e) { + e.printStackTrace(); + } + assertNotNull(request); + assertEquals("1.2.840.113549.1.1.5",request.getSignatureAlgorithm().getAlgorithm().getId()); + byte[] pubKeyBytes = new byte[0]; + try { + pubKeyBytes = request.getSubjectPublicKeyInfo().getEncoded(); + } catch (IOException e) { + e.printStackTrace(); + } + assertArrayEquals(pubKeyBytes,pubKey.getEncoded()); + + RDN[] rdns = request.getSubject().getRDNs(); + assertEquals(BCStyle.C, rdns[0].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.ST, rdns[1].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.L, rdns[2].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.O, rdns[3].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.OU, rdns[4].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.CN, rdns[5].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.E, rdns[6].getFirst().getType().toASN1Primitive()); + + assertEquals("CN", rdns[0].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("Beijing", rdns[1].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("Beijing", rdns[2].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("JD.com", rdns[3].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("Blockchain Department", rdns[4].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("ledger.jd.com", rdns[5].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("zhanglin33@jd.com", rdns[6].getFirst().getValue().toASN1Primitive().toString()); + + byte[] signature = request.getSignature(); + + CertificationRequestInfo requestInfo = new CertificationRequestInfo(request.getSubject(),request.getSubjectPublicKeyInfo(),new DERSet()); + byte[] message = new byte[0]; + try { + message = requestInfo.getEncoded(ASN1Encoding.DER); + } catch (IOException e) { + e.printStackTrace(); + } - if (!req2.isSignatureValid(new JcaContentVerifierProviderBuilder().setProvider(provider).build(kp.getPublic()))) { - fail(sigName + ": Failed verify check."); + Signature signer; + byte[] result = new byte[0]; + try { + signer = Signature.getInstance("SHA1withRSA"); + signer.initSign(privKey); + signer.update(message); + result = signer.sign(); + } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) { + e.printStackTrace(); } + assertArrayEquals(result,signature); - if (!Arrays.areEqual(req2.getPublicKey().getEncoded(), req1.getSubjectPublicKeyInfo().getEncoded())) { - fail(keyName + ": Failed public key check."); + Signature verifier; + boolean isValid = false; + try { + verifier = Signature.getInstance("SHA1withRSA"); + verifier.initVerify(pubKey); + verifier.update(message); + isValid = verifier.verify(signature); + } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) { + e.printStackTrace(); } + assertTrue(isValid); } + } From 8046ea08974c29e2063125d51c092084446354a9 Mon Sep 17 00:00:00 2001 From: zhaoguangwei Date: Tue, 14 May 2019 17:05:31 +0800 Subject: [PATCH 28/43] The original version did not meet the needs of the business side, and adopted the JSON mode again. --- .../gateway/web/BlockBrowserController.java | 5 ++-- .../ledger/core/impl/LedgerQueryService.java | 23 +++++++++++--- .../impl/handles/ContractLedgerContext.java | 4 +-- .../com/jd/blockchain/ledger/KVDataVO.java | 26 ++++++++++++++++ .../com/jd/blockchain/ledger/KVInfoVO.java | 18 +++++++++++ .../transaction/BlockchainQueryService.java | 2 +- .../peer/web/LedgerQueryController.java | 30 ++++++++++++------- .../sdk/proxy/BlockchainServiceProxy.java | 4 +-- .../sdk/proxy/HttpBlockchainQueryService.java | 3 +- 9 files changed, 91 insertions(+), 24 deletions(-) create mode 100644 source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataVO.java create mode 100644 source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVInfoVO.java diff --git a/source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java b/source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java index 1094e9b9..66f94b97 100644 --- a/source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java +++ b/source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java @@ -242,9 +242,8 @@ public class BlockBrowserController implements BlockchainExtendQueryService { @RequestMapping(method = {RequestMethod.GET, RequestMethod.POST}, path = "ledgers/{ledgerHash}/accounts/{address}/entries-version") public KVDataEntry[] getDataEntries(@PathVariable("ledgerHash") HashDigest ledgerHash, @PathVariable("address") String address, - @RequestParam("keys") String keys[], - @RequestParam("versions") String versions[]) { - return peerService.getQueryService().getDataEntries(ledgerHash, address, keys, versions); + @RequestBody KVInfoVO kvInfoVO) { + return peerService.getQueryService().getDataEntries(ledgerHash, address, kvInfoVO); } @RequestMapping(method = {RequestMethod.GET, RequestMethod.POST}, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries") diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java index 1ed2b6d9..c053b8b3 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java @@ -18,6 +18,9 @@ import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.QueryUtil; import com.jd.blockchain.utils.StringUtils; +import java.util.ArrayList; +import java.util.List; + public class LedgerQueryService implements BlockchainQueryService { private LedgerService ledgerService; @@ -280,7 +283,21 @@ public class LedgerQueryService implements BlockchainQueryService { return entries; } - public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, String[] keys, String[] versions) { + public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) { + //parse kvInfoVO; + List keyList = new ArrayList<>(); + List versionList = new ArrayList<>(); + if(kvInfoVO != null){ + for(KVDataVO kvDataVO : kvInfoVO.getData()){ + for(Long version : kvDataVO.getVersion()){ + keyList.add(kvDataVO.getKey()); + versionList.add(version); + } + } + } + String[] keys = keyList.toArray(new String[keyList.size()]); + Long[] versions = versionList.toArray(new Long[versionList.size()]); + if (keys == null || keys.length == 0) { return null; } @@ -301,9 +318,7 @@ public class LedgerQueryService implements BlockchainQueryService { for (int i = 0; i < entries.length; i++) { // ver = dataAccount.getDataVersion(Bytes.fromString(keys[i])); // dataAccount.getBytes(Bytes.fromString(keys[i]),1); - if(StringUtils.isNumber(versions[i])){ - ver = Long.parseLong(versions[i]); - } + ver = versions[i]; if (ver < 0) { entries[i] = new KVDataObject(keys[i], -1, PrimitiveType.NIL, null); }else { diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractLedgerContext.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractLedgerContext.java index 92049f0f..43595152 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractLedgerContext.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractLedgerContext.java @@ -157,8 +157,8 @@ public class ContractLedgerContext implements LedgerContext { } @Override - public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, String[] keys, String[] versions) { - return innerQueryService.getDataEntries(ledgerHash, address, keys, versions); + public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) { + return innerQueryService.getDataEntries(ledgerHash, address, kvInfoVO); } @Override diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataVO.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataVO.java new file mode 100644 index 00000000..4fc214d0 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataVO.java @@ -0,0 +1,26 @@ +package com.jd.blockchain.ledger; + +/** + * @author zhaogw + * date 2019/5/14 14:17 + */ +public class KVDataVO { + private String key; + private long[] version; + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public long[] getVersion() { + return version; + } + + public void setVersion(long[] version) { + this.version = version; + } +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVInfoVO.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVInfoVO.java new file mode 100644 index 00000000..5f49e3de --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVInfoVO.java @@ -0,0 +1,18 @@ +package com.jd.blockchain.ledger; + +/** + * for BlockBrowserController.java, param is json ,then match it; + * @author zhaogw + * date 2019/5/14 14:19 + */ +public class KVInfoVO { + private KVDataVO[] data; + + public KVDataVO[] getData() { + return data; + } + + public void setData(KVDataVO[] data) { + this.data = data; + } +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java index 26d719bd..1b46f1aa 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java @@ -261,7 +261,7 @@ public interface BlockchainQueryService { */ KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys); - KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, String[] keys, String[] versions); + KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO); /** * 返回指定数据账户中KV数据的总数;
diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java b/source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java index 8487d67f..637c9216 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java @@ -4,11 +4,7 @@ import com.jd.blockchain.contract.ContractException; import com.jd.blockchain.ledger.*; import com.jd.blockchain.utils.StringUtils; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import com.jd.blockchain.binaryproto.BinaryProtocol; import com.jd.blockchain.binaryproto.PrimitiveType; @@ -26,6 +22,9 @@ import com.jd.blockchain.transaction.BlockchainQueryService; import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.QueryUtil; +import java.util.ArrayList; +import java.util.List; + @RestController @RequestMapping(path = "/") public class LedgerQueryController implements BlockchainQueryService { @@ -356,8 +355,21 @@ public class LedgerQueryController implements BlockchainQueryService { @Override public KVDataEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, @PathVariable(name = "address") String address, - @RequestParam("keys") String[] keys, - @RequestParam("versions") String[] versions) { + @RequestBody KVInfoVO kvInfoVO) { + //parse kvInfoVO; + List keyList = new ArrayList<>(); + List versionList = new ArrayList<>(); + if(kvInfoVO != null){ + for(KVDataVO kvDataVO : kvInfoVO.getData()){ + for(Long version : kvDataVO.getVersion()){ + keyList.add(kvDataVO.getKey()); + versionList.add(version); + } + } + } + String[] keys = keyList.toArray(new String[keyList.size()]); + Long[] versions = versionList.toArray(new Long[versionList.size()]); + if (keys == null || keys.length == 0) { return null; } @@ -377,9 +389,7 @@ public class LedgerQueryController implements BlockchainQueryService { long ver = -1; for (int i = 0; i < entries.length; i++) { // ver = dataAccount.getDataVersion(Bytes.fromString(keys[i])); - if(StringUtils.isNumber(versions[i])){ - ver = Long.parseLong(versions[i]); - } + ver = versions[i]; if (ver < 0) { entries[i] = new KVDataObject(keys[i], -1, PrimitiveType.NIL, null); }else { diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java index fce0d410..e18f1df7 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java @@ -148,8 +148,8 @@ public abstract class BlockchainServiceProxy implements BlockchainService { } @Override - public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, String[] keys, String[] versions) { - return getQueryService(ledgerHash).getDataEntries(ledgerHash, address, keys, versions); + public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) { + return getQueryService(ledgerHash).getDataEntries(ledgerHash, address, kvInfoVO); } @Override diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java index 90860f80..bd063a5d 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java @@ -500,8 +500,7 @@ public interface HttpBlockchainQueryService extends BlockchainExtendQueryService @Override KVDataEntry[] getDataEntries(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash, @PathParam(name="address") String address, - @RequestParam(name="keys", array = true) String[] keys, - @RequestParam(name="versions", array = true) String[] versions); + @RequestBody KVInfoVO kvInfoVO); /** * 返回数据账户中指定序号的最新值; From 6920627ef33ba1310da98706e6775a0404a4c3fa Mon Sep 17 00:00:00 2001 From: zhanglin33 Date: Wed, 15 May 2019 16:17:54 +0800 Subject: [PATCH 29/43] add CertParser and its junitTest --- .../com/jd/blockchain/crypto/CSRBuilder.java | 18 ++- .../com/jd/blockchain/crypto/CertParser.java | 120 ++++++++++++++++++ .../jd/blockchain/crypto/CSRBuilderTest.java | 2 - .../jd/blockchain/crypto/CertParserTest.java | 38 ++++++ 4 files changed, 169 insertions(+), 9 deletions(-) diff --git a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CSRBuilder.java b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CSRBuilder.java index 7ec35785..9d84a952 100644 --- a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CSRBuilder.java +++ b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CSRBuilder.java @@ -1,13 +1,9 @@ package com.jd.blockchain.crypto; -import com.jd.blockchain.crypto.utils.classic.RSAUtils; -import org.bouncycastle.asn1.x500.RDN; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x500.X500NameBuilder; import org.bouncycastle.asn1.x500.style.BCStrictStyle; import org.bouncycastle.asn1.x500.style.BCStyle; -import org.bouncycastle.crypto.AsymmetricCipherKeyPair; -import org.bouncycastle.crypto.params.AsymmetricKeyParameter; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.jce.spec.ECNamedCurveGenParameterSpec; import org.bouncycastle.operator.OperatorCreationException; @@ -47,7 +43,7 @@ public class CSRBuilder { pubKey = keyPair.getPublic(); privKey = keyPair.getPrivate(); } catch (NoSuchAlgorithmException | NoSuchProviderException e) { - throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e); + throw new CryptoException(e.getMessage(), e); } } @@ -81,7 +77,7 @@ public class CSRBuilder { default: throw new CryptoException("Unsupported key algorithm[" + algoName + "] in CSR!"); } } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) { - throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e); + throw new CryptoException(e.getMessage(), e); } } @@ -110,7 +106,7 @@ public class CSRBuilder { byte[] csrBytes = request.getEncoded(); result = Base64.toBase64String(csrBytes); } catch (OperatorCreationException | IOException e) { - e.printStackTrace(); + throw new CryptoException(e.getMessage(), e); } return result; @@ -123,4 +119,12 @@ public class CSRBuilder { public PrivateKey getPrivKey() { return privKey; } + + public byte[] getPubKeyBytes() { + return pubKey.getEncoded(); + } + + public byte[] getPrivKeyBytes() { + return privKey.getEncoded(); + } } diff --git a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CertParser.java b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CertParser.java index 480b833c..004079c9 100644 --- a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CertParser.java +++ b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CertParser.java @@ -1,5 +1,17 @@ package com.jd.blockchain.crypto; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.util.encoders.Base64; +import org.bouncycastle.util.io.pem.PemReader; + +import javax.security.auth.x500.X500Principal; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.StringReader; +import java.security.*; +import java.security.cert.*; +import java.util.Date; + /** * @author zhanglin33 * @title: CertParser @@ -7,4 +19,112 @@ package com.jd.blockchain.crypto; * @date 2019-05-10, 15:17 */ public class CertParser { + + private PublicKey pubKey; + private String sigAlgName; + private String userName; + private String issuerName; + + private Date startTime; + private Date endTime; + + public void parse(String userCertificate, String issuerCertificate) { + + X509Certificate issuerCert = parseWithoutValidationProcess(issuerCertificate); + + // ensure that the certificate is within the validity period + try { + issuerCert.checkValidity(); + } catch (CertificateExpiredException | CertificateNotYetValidException e) { + e.printStackTrace(); + } + PublicKey issuerPubKey = issuerCert.getPublicKey(); + X500Principal issuerPrincipal = issuerCert.getSubjectX500Principal(); + + X509Certificate userCert = parseWithoutValidationProcess(userCertificate); + + // check consistency between issuer's names in userCertificate and issuerCertificate + if (!userCert.getIssuerX500Principal().equals(issuerPrincipal)) { + throw new CryptoException("Issuer in the targeted certificate is not " + + "compliance with the parent certificate!"); + } + + try { + userCert.checkValidity(); + } catch (CertificateExpiredException | CertificateNotYetValidException e) { + throw new CryptoException(e.getMessage(), e); + } + + // verify the signature in certificate with issuer's public key + try { + userCert.verify(issuerPubKey); + } catch (CertificateException | NoSuchAlgorithmException + | InvalidKeyException | NoSuchProviderException | SignatureException e) { + throw new CryptoException(e.getMessage(), e); + } + + startTime = userCert.getNotBefore(); + endTime = userCert.getNotAfter(); + + pubKey = userCert.getPublicKey(); + sigAlgName = userCert.getSigAlgName(); + issuerName = userCert.getIssuerX500Principal().getName(); + userName = userCert.getSubjectX500Principal().getName(); + } + + // certificate string in Base64 format + public X509Certificate parseWithoutValidationProcess(String certificate) { + + Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); + + byte[] certificateBytes; + String BEGIN = "-----BEGIN CERTIFICATE-----"; + String END = "-----END CERTIFICATE-----"; + if (!certificate.startsWith(BEGIN)) { + certificate = certificate.replaceAll("\\n", ""); + certificate = certificate.replaceAll(END, ""); + certificateBytes = Base64.decode(certificate); + } else { + try { + certificateBytes = new PemReader(new StringReader(certificate)).readPemObject().getContent(); + } catch (IOException e) { + throw new CryptoException(e.getMessage(), e); + } + } + + ByteArrayInputStream bytesIn = new ByteArrayInputStream(certificateBytes); + CertificateFactory factory; + X509Certificate cert; + try { + factory = CertificateFactory.getInstance("X509", BouncyCastleProvider.PROVIDER_NAME); + cert = (X509Certificate) factory.generateCertificate(bytesIn); + } catch (CertificateException | NoSuchProviderException e) { + throw new CryptoException(e.getMessage(), e); + } + return cert; + } + + public PublicKey getPubKey() { + return pubKey; + } + + public String getSigAlgName() { + return sigAlgName; + } + + public String getUserName() { + return userName; + } + + public String getIssuerName() { + return issuerName; + } + + public Date getStartTime() { + return startTime; + } + + public Date getEndTime() { + return endTime; + } } diff --git a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CSRBuilderTest.java b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CSRBuilderTest.java index b61f3ca1..a1bb5645 100644 --- a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CSRBuilderTest.java +++ b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CSRBuilderTest.java @@ -112,6 +112,4 @@ public class CSRBuilderTest { } assertTrue(isValid); } - - } diff --git a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CertParserTest.java b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CertParserTest.java index 3a8ecc7a..64b55d4a 100644 --- a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CertParserTest.java +++ b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CertParserTest.java @@ -1,5 +1,9 @@ package com.jd.blockchain.crypto; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + /** * @author zhanglin33 * @title: CertParserTest @@ -7,4 +11,38 @@ package com.jd.blockchain.crypto; * @date 2019-05-13, 10:05 */ public class CertParserTest { + + @Test + public void parseTest() { + CertParser parser = new CertParser(); + String issuerCert = + "-----BEGIN CERTIFICATE-----\n" + + "MIIDzzCCAregAwIBAgIKUalCR1Mt5ZSK8jANBgkqhkiG9w0BAQUFADBZMQswCQYD\n" + + "VQQGEwJDTjEwMC4GA1UEChMnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24g\n" + + "QXV0aG9yaXR5MRgwFgYDVQQDEw9DRkNBIFRFU1QgQ1MgQ0EwHhcNMTIwODI5MDU1\n" + + "NDM2WhcNMzIwODI0MDU1NDM2WjBZMQswCQYDVQQGEwJDTjEwMC4GA1UEChMnQ2hp\n" + + "bmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRgwFgYDVQQDEw9D\n" + + "RkNBIFRFU1QgT0NBMTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC8\n" + + "jn0n8Fp6hcRdACdn1+Y6GAkC6KGgNdKyHPrmsdmhCjnd/i4qUFwnG8cp3D4lFw1G\n" + + "jmjSO5yVYbik/NbS6lbNpRgTK3fDfMFvLJpRIC+IFhG9SdAC2hwjsH9qTpL9cK2M\n" + + "bSdrC6pBdDgnbzaM9AGBF4Y6vXhj5nah4ZMsBvDp19LzXjlGuTPLuAgv9ZlWknsd\n" + + "RN70PIAmvomd10uqX4GIJ4Jq/FdKXOLZ2DNK/NhRyN6Yq71L3ham6tutXeZow5t5\n" + + "0254AnUlo1u6SeH9F8itER653o/oMLFwp+63qXAcqrHUlOQPX+JI8fkumSqZ4F2F\n" + + "t/HfVMnqdtFNCnh5+eIBAgMBAAGjgZgwgZUwHwYDVR0jBBgwFoAUdN7FjQp9EBqq\n" + + "aYNbTSHOhpvMcTgwDAYDVR0TBAUwAwEB/zA4BgNVHR8EMTAvMC2gK6AphidodHRw\n" + + "Oi8vMjEwLjc0LjQyLjMvdGVzdHJjYS9SU0EvY3JsMS5jcmwwCwYDVR0PBAQDAgEG\n" + + "MB0GA1UdDgQWBBT8C7xEmg4xoYOpgYcnHgVCxr9W+DANBgkqhkiG9w0BAQUFAAOC\n" + + "AQEAb7W0K9fZPA+JPw6lRiMDaUJ0oh052yEXreMBfoPulxkBj439qombDiFggRLc\n" + + "3g8wIEKzMOzOKXTWtnzYwN3y/JQSuJb/M1QqOEEM2PZwCxI4AkBuH6jg03RjlkHg\n" + + "/kTtuIFp9ItBCC2/KkKlp0ENfn4XgVg2KtAjZ7lpyVU0LPnhEqqUVY/xthjlCSa7\n" + + "/XHNStRxsfCTIBUWJ8n2FZyQhfV/UkMNHDBIiJR0v6C4Ai0/290WvbPEIAq+03Si\n" + + "fsHzBeA0C8lP5VzfAr6wWePaZMCpStpLaoXNcAqReKxQllElOqAhRxC5VKH+rnIQ\n" + + "OMRZvB7FRyE9IfwKApngcZbA5g==\n" + + "-----END CERTIFICATE-----"; + + String userCert = "MIIEQDCCAyigAwIBAgIFICdVYzEwDQYJKoZIhvcNAQEFBQAwWTELMAkGA1UEBhMCQ04xMDAuBgNVBAoTJ0NoaW5hIEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEYMBYGA1UEAxMPQ0ZDQSBURVNUIE9DQTExMB4XDTE5MDUxMDExMjAyNFoXDTIxMDUxMDExMjAyNFowcjELMAkGA1UEBhMCQ04xGDAWBgNVBAoTD0NGQ0EgVEVTVCBPQ0ExMTERMA8GA1UECxMITG9jYWwgUkExFTATBgNVBAsTDEluZGl2aWR1YWwtMTEfMB0GA1UEAxQWMDUxQGFhYWFhQFpIMDkzNTgwMjhAMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJx3F2WD1dJPzK/nRHO7d1TJ1hTjzGTmv0PQ7ECsJAh3U3BtnGTpCB+b4+JMI4LO8nHkKIBQ3P9XnF+Bf1iXdWNAQ4aWCxa2nV7lCp4w0GliPu/EMgIfmsSDUtgqbM3cr8sR8r9m1xG3gt2TIQJ+jT7sAiguU/kyNzpjaccOUIgUFa8IDFq9UeB76MXtCuhlERRZQCl47e+9w7ZoxmE7e6IZORxPp7rQWVBHlR9ntWjJfNDTm3gMP5ehP+yIZnKx1LudxkBLQxpMmspzOyH1zqx5nkKe49AfWWpDxxRvYkriyYC3aE81qLsU/bhLwNEKOju7BGDF/mhJLZUedojM0gMCAwEAAaOB9TCB8jAfBgNVHSMEGDAWgBT8C7xEmg4xoYOpgYcnHgVCxr9W+DBIBgNVHSAEQTA/MD0GCGCBHIbvKgECMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2ZjYS5jb20uY24vdXMvdXMtMTUuaHRtMDoGA1UdHwQzMDEwL6AtoCuGKWh0dHA6Ly8yMTAuNzQuNDIuMy9PQ0ExMS9SU0EvY3JsMjU2OTMuY3JsMAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQU5oKGaQs7Jt5Gfbt1XhFTWAySEKswHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMA0GCSqGSIb3DQEBBQUAA4IBAQAlmPRaImZV51iKjtpMKuyLMw7dX8L0lY3tl+pVZZSxHuwsN4GCCtV0Ej50up+/6EbfL4NUTiuHVAjCroKKvb+94CrdEwdnQGM5IbGSjT78nQpeASXbIWuUwA+ImjvZOzvq/0b56AzonNzBxOMGko/bj5smM6X8jrgJ0NQppo2KNSVNC4JbuoNWI4FM94SE4DUi9H7EYl4JdOtDaDtCsq49o/A1CZyYrmoOPCgxpQQXmuB3lGq/jyoOlW2aW8uee/hYG1JJcSHLBjF0WBwdxssgbBotA5f1PebiIMSbFgjk57bd4M80hhU/rI4Hkn9pcp5R7NsX95TtyDIg90LboBnW"; + + parser.parse(userCert, issuerCert); + assertEquals("SHA1WITHRSA",parser.getSigAlgName()); + } } From 962e0f200b807c8971fb2c9be67d085813159fb9 Mon Sep 17 00:00:00 2001 From: zhanglin33 Date: Thu, 16 May 2019 08:50:41 +0800 Subject: [PATCH 30/43] add SHA1WITHRSA2048 without junitTest --- .../service/classic/RSACryptoFunction.java | 8 +- .../crypto/utils/classic/RSAUtils.java | 6 +- .../classic/RSACryptoFunctionTest.java | 12 +- .../crypto/service/pki/PKIAlgorithm.java | 26 +++ .../crypto/service/pki/PKICryptoService.java | 36 +++ .../pki/SHA1WITHRSA2048SignatureFunction.java | 206 ++++++++++++++++++ .../pki/SHA1WITHRSA4096SignatureFunction.java | 68 ++++++ .../pki/SM3WITHSM2SignatureFunction.java | 68 ++++++ .../crypto/{ => utils}/CSRBuilder.java | 3 +- .../crypto/{ => utils}/CertParser.java | 5 +- .../com.jd.blockchain.crypto.CryptoService | 1 + .../crypto/{ => utils}/CSRBuilderTest.java | 3 +- .../crypto/{ => utils}/CertParserTest.java | 3 +- 13 files changed, 427 insertions(+), 18 deletions(-) create mode 100644 source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/PKIAlgorithm.java create mode 100644 source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/PKICryptoService.java create mode 100644 source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunction.java create mode 100644 source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunction.java create mode 100644 source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SM3WITHSM2SignatureFunction.java rename source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/{ => utils}/CSRBuilder.java (98%) rename source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/{ => utils}/CertParser.java (96%) create mode 100644 source/crypto/crypto-pki/src/main/resources/services/com.jd.blockchain.crypto.CryptoService rename source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/{ => utils}/CSRBuilderTest.java (98%) rename source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/{ => utils}/CertParserTest.java (97%) diff --git a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/RSACryptoFunction.java b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/RSACryptoFunction.java index b7bd9c8d..ab078bfb 100644 --- a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/RSACryptoFunction.java +++ b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/RSACryptoFunction.java @@ -21,11 +21,11 @@ public class RSACryptoFunction implements AsymmetricEncryptionFunction, Signatur private static final CryptoAlgorithm RSA = ClassicAlgorithm.RSA; - // modulus.length = 256, publicExponent.length = 1 - private static final int PUBKEY_SIZE = 257; - // modulus.length = 256, publicExponent.length = 1, privateExponent.length = 256, p.length = 128, q.length =128, + // modulus.length = 256, publicExponent.length = 3 + private static final int PUBKEY_SIZE = 259; + // modulus.length = 256, publicExponent.length = 3, privateExponent.length = 256, p.length = 128, q.length =128, // dP.length = 128, dQ.length = 128, qInv.length = 128 - private static final int PRIVKEY_SIZE = 1153; + private static final int PRIVKEY_SIZE = 1155; private static final int SIGNATUREDIGEST_SIZE = 256; private static final int CIPHERTEXTBLOCK_SIZE = 256; diff --git a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java index f17dcdf2..b69a271b 100644 --- a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java +++ b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java @@ -308,14 +308,14 @@ public class RSAUtils { X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubKeyBytes); - KeyFactory keyFactory = null; + KeyFactory keyFactory; try { keyFactory = KeyFactory.getInstance("RSA"); } catch (NoSuchAlgorithmException e) { throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e); } - RSAPublicKey publicKey = null; + RSAPublicKey publicKey; try { publicKey = (RSAPublicKey) keyFactory.generatePublic(keySpec); } catch (InvalidKeySpecException e) { @@ -451,7 +451,7 @@ public class RSAUtils { PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privKeyBytes); - KeyFactory keyFactory = null; + KeyFactory keyFactory; try { keyFactory = KeyFactory.getInstance("RSA"); } catch (NoSuchAlgorithmException e) { diff --git a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/service/classic/RSACryptoFunctionTest.java b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/service/classic/RSACryptoFunctionTest.java index 3eefed1c..cff875f7 100644 --- a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/service/classic/RSACryptoFunctionTest.java +++ b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/service/classic/RSACryptoFunctionTest.java @@ -55,15 +55,15 @@ public class RSACryptoFunctionTest { PrivKey privKey = keyPair.getPrivKey(); assertEquals(PUBLIC.CODE, pubKey.getKeyType().CODE); - assertEquals(257, pubKey.getRawKeyBytes().length); + assertEquals(259, pubKey.getRawKeyBytes().length); assertEquals(PRIVATE.CODE, privKey.getKeyType().CODE); - assertEquals(1153, privKey.getRawKeyBytes().length); + assertEquals(1155, privKey.getRawKeyBytes().length); assertEquals(algorithm.code(), pubKey.getAlgorithm()); assertEquals(algorithm.code(), privKey.getAlgorithm()); - assertEquals(2 + 1 + 257, pubKey.toBytes().length); - assertEquals(2 + 1 + 1153, privKey.toBytes().length); + assertEquals(2 + 1 + 259, pubKey.toBytes().length); + assertEquals(2 + 1 + 1155, privKey.toBytes().length); byte[] algoBytes = CryptoAlgorithm.toBytes(algorithm); byte[] pubKeyTypeBytes = new byte[] { PUBLIC.CODE }; @@ -243,7 +243,7 @@ public class RSACryptoFunctionTest { PrivKey resolvedPrivKey = signatureFunction.resolvePrivKey(privKeyBytes); assertEquals(PRIVATE.CODE, resolvedPrivKey.getKeyType().CODE); - assertEquals(1153, resolvedPrivKey.getRawKeyBytes().length); + assertEquals(1155, resolvedPrivKey.getRawKeyBytes().length); assertEquals(ClassicAlgorithm.RSA.code(), resolvedPrivKey.getAlgorithm()); assertEquals((short) (SIGNATURE_ALGORITHM | ENCRYPTION_ALGORITHM | ASYMMETRIC_KEY | ((byte) 23 & 0x00FF)), resolvedPrivKey.getAlgorithm()); @@ -308,7 +308,7 @@ public class RSACryptoFunctionTest { PubKey resolvedPubKey = signatureFunction.resolvePubKey(pubKeyBytes); assertEquals(PUBLIC.CODE, resolvedPubKey.getKeyType().CODE); - assertEquals(257, resolvedPubKey.getRawKeyBytes().length); + assertEquals(259, resolvedPubKey.getRawKeyBytes().length); assertEquals(ClassicAlgorithm.RSA.code(), resolvedPubKey.getAlgorithm()); assertEquals((short) (SIGNATURE_ALGORITHM | ENCRYPTION_ALGORITHM | ASYMMETRIC_KEY | ((byte) 23 & 0x00FF)), resolvedPubKey.getAlgorithm()); diff --git a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/PKIAlgorithm.java b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/PKIAlgorithm.java new file mode 100644 index 00000000..0aff4c6b --- /dev/null +++ b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/PKIAlgorithm.java @@ -0,0 +1,26 @@ +package com.jd.blockchain.crypto.service.pki; + +import com.jd.blockchain.crypto.CryptoAlgorithm; +import com.jd.blockchain.crypto.CryptoAlgorithmDefinition; + +/** + * @author zhanglin33 + * @title: PKIAlgorithm + * @description: TODO + * @date 2019-05-15, 16:34 + */ +public class PKIAlgorithm { + + public static final CryptoAlgorithm SHA1WITHRSA2048 = CryptoAlgorithmDefinition.defineSignature("SHA1WITHRSA2048", + false, (byte) 31); + + public static final CryptoAlgorithm SHA1WITHRSA4096 = CryptoAlgorithmDefinition.defineSignature("SHA1WITHRSA4096", + false, (byte) 32); + + public static final CryptoAlgorithm SM3WITHSM2 = CryptoAlgorithmDefinition.defineSignature("SM3WITHSM2", + false, (byte) 33); + + private PKIAlgorithm() { + } + +} diff --git a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/PKICryptoService.java b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/PKICryptoService.java new file mode 100644 index 00000000..3c013bbc --- /dev/null +++ b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/PKICryptoService.java @@ -0,0 +1,36 @@ +package com.jd.blockchain.crypto.service.pki; + +import com.jd.blockchain.crypto.CryptoFunction; +import com.jd.blockchain.crypto.CryptoService; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +/** + * @author zhanglin33 + * @title: PKICryptoService + * @description: TODO + * @date 2019-05-15, 16:35 + */ +public class PKICryptoService implements CryptoService { + + public static final SHA1WITHRSA2048SignatureFunction SHA1WITHRSA2048 = new SHA1WITHRSA2048SignatureFunction(); + + public static final SHA1WITHRSA4096SignatureFunction SHA1WITHRSA4096 = new SHA1WITHRSA4096SignatureFunction(); + + public static final SM3WITHSM2SignatureFunction SM3WITHSM2 = new SM3WITHSM2SignatureFunction(); + + private static final Collection FUNCTIONS; + + static { + List funcs = Arrays.asList(SHA1WITHRSA2048, SHA1WITHRSA4096, SM3WITHSM2); + FUNCTIONS = Collections.unmodifiableList(funcs); + } + + @Override + public Collection getFunctions() { + return FUNCTIONS; + } +} diff --git a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunction.java b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunction.java new file mode 100644 index 00000000..48e65765 --- /dev/null +++ b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunction.java @@ -0,0 +1,206 @@ +package com.jd.blockchain.crypto.service.pki; + +import com.jd.blockchain.crypto.*; +import org.bouncycastle.asn1.DERNull; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.jcajce.provider.asymmetric.rsa.BCRSAPrivateCrtKey; +import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import sun.security.rsa.RSAPrivateCrtKeyImpl; +import sun.security.rsa.RSAPrivateKeyImpl; +import sun.security.rsa.RSAPublicKeyImpl; + +import java.math.BigInteger; +import java.security.*; +import java.security.interfaces.RSAPrivateCrtKey; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; + +import static com.jd.blockchain.crypto.BaseCryptoKey.KEY_TYPE_BYTES; +import static com.jd.blockchain.crypto.CryptoBytes.ALGORYTHM_CODE_SIZE; +import static com.jd.blockchain.crypto.CryptoKeyType.PRIVATE; +import static com.jd.blockchain.crypto.CryptoKeyType.PUBLIC; +import static com.jd.blockchain.crypto.service.pki.PKIAlgorithm.SHA1WITHRSA2048; + +/** + * @author zhanglin33 + * @title: SHA1WITHRSA2048SignatureFunction + * @description: TODO + * @date 2019-05-15, 16:37 + */ +public class SHA1WITHRSA2048SignatureFunction implements SignatureFunction { + + + private static final int RAW_PUBKEY_SIZE = 259; + private static final int RAW_PRIVKEY_SIZE = 1155; + + private static final int RAW_SIGNATUREDIGEST_SIZE = 256; + + private static final AlgorithmIdentifier RSA_ALGORITHM_IDENTIFIER = + new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE); + + @Override + public SignatureDigest sign(PrivKey privKey, byte[] data) { + + byte[] rawPrivKeyBytes = privKey.getRawKeyBytes(); + + if (rawPrivKeyBytes.length < RAW_PRIVKEY_SIZE) { + throw new CryptoException("This key has wrong format!"); + } + + if (privKey.getAlgorithm() != SHA1WITHRSA2048.code()) { + throw new CryptoException("This key is not SHA1WITHRSA2048 private key!"); + } + + RSAPrivateCrtKey rawPrivKey; + Signature signer; + byte[] signature; + try { + rawPrivKey = (RSAPrivateCrtKey) RSAPrivateCrtKeyImpl.newKey(rawPrivKeyBytes); + signer = Signature.getInstance("SHA1withRSA"); + signer.initSign(rawPrivKey); + signer.update(data); + signature = signer.sign(); + } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) { + throw new CryptoException(e.getMessage(), e); + } + + return new SignatureDigest(SHA1WITHRSA2048, signature); + } + + @Override + public boolean verify(SignatureDigest digest, PubKey pubKey, byte[] data) { + + byte[] rawPubKeyBytes = pubKey.getRawKeyBytes(); + byte[] rawDigestBytes = digest.getRawDigest(); + + if (rawPubKeyBytes.length < RAW_PUBKEY_SIZE) { + throw new CryptoException("This key has wrong format!"); + } + + if (pubKey.getAlgorithm() != SHA1WITHRSA2048.code()) { + throw new CryptoException("This key is not SHA1WITHRSA2048 public key!"); + } + + if (digest.getAlgorithm() != SHA1WITHRSA2048.code() || rawDigestBytes.length != RAW_SIGNATUREDIGEST_SIZE) { + throw new CryptoException("This is not SHA1WITHRSA2048 signature digest!"); + } + RSAPublicKeyImpl rawPubKey; + Signature verifier; + boolean isValid = false; + try { + rawPubKey = new RSAPublicKeyImpl(rawPubKeyBytes); + verifier = Signature.getInstance("SHA1withRSA"); + verifier.initVerify(rawPubKey); + verifier.update(data); + isValid = verifier.verify(rawDigestBytes); + } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) { + e.printStackTrace(); + } + + return isValid; + } + + @Override + public boolean supportPubKey(byte[] pubKeyBytes) { + return pubKeyBytes.length > (ALGORYTHM_CODE_SIZE + KEY_TYPE_BYTES + RAW_PUBKEY_SIZE) + && CryptoAlgorithm.match(SHA1WITHRSA2048, pubKeyBytes) + && pubKeyBytes[ALGORYTHM_CODE_SIZE] == PUBLIC.CODE; + } + + @Override + public PubKey resolvePubKey(byte[] pubKeyBytes) { + if (supportPubKey(pubKeyBytes)) { + return new PubKey(pubKeyBytes); + } else { + throw new CryptoException("pubKeyBytes are invalid!"); + } + } + + @Override + public boolean supportPrivKey(byte[] privKeyBytes) { + return privKeyBytes.length > (ALGORYTHM_CODE_SIZE + KEY_TYPE_BYTES + RAW_PRIVKEY_SIZE) + && CryptoAlgorithm.match(SHA1WITHRSA2048, privKeyBytes) + && privKeyBytes[ALGORYTHM_CODE_SIZE] == PRIVATE.CODE; + } + + @Override + public PrivKey resolvePrivKey(byte[] privKeyBytes) { + if (supportPrivKey(privKeyBytes)) { + return new PrivKey(privKeyBytes); + } else { + throw new CryptoException("privKeyBytes are invalid!"); + } + } + + @Override + public PubKey retrievePubKey(PrivKey privKey) { + + byte[] rawPrivKeyBytes = privKey.getRawKeyBytes(); + + if (rawPrivKeyBytes.length < RAW_PRIVKEY_SIZE) { + throw new CryptoException("This key has wrong format!"); + } + + if (privKey.getAlgorithm() != SHA1WITHRSA2048.code()) { + throw new CryptoException("This key is not SHA1WITHRSA2048 private key!"); + } + byte[] rawPubKeyBytes; + try { + RSAPrivateCrtKey rawPrivKey = (RSAPrivateCrtKey) RSAPrivateCrtKeyImpl.newKey(rawPrivKeyBytes); + BigInteger modulus = rawPrivKey.getModulus(); + BigInteger exponent = rawPrivKey.getPublicExponent(); + rawPubKeyBytes = KeyUtil.getEncodedSubjectPublicKeyInfo(RSA_ALGORITHM_IDENTIFIER, + new org.bouncycastle.asn1.pkcs.RSAPublicKey(modulus, exponent)); + } catch (InvalidKeyException e) { + throw new CryptoException(e.getMessage(), e); + } + + return new PubKey(SHA1WITHRSA2048, rawPubKeyBytes); + } + + @Override + public boolean supportDigest(byte[] digestBytes) { + return digestBytes.length == (RAW_SIGNATUREDIGEST_SIZE + ALGORYTHM_CODE_SIZE) + && CryptoAlgorithm.match(SHA1WITHRSA2048, digestBytes); + } + + @Override + public SignatureDigest resolveDigest(byte[] digestBytes) { + if (supportDigest(digestBytes)) { + return new SignatureDigest(digestBytes); + } else { + throw new CryptoException("digestBytes are invalid!"); + } + } + + @Override + public AsymmetricKeypair generateKeypair() { + + Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); + KeyPairGenerator generator; + PublicKey pubKey; + PrivateKey privKey; + try { + generator = KeyPairGenerator.getInstance("RSA", BouncyCastleProvider.PROVIDER_NAME); + generator.initialize(2048); + KeyPair keyPair = generator.generateKeyPair(); + pubKey = keyPair.getPublic(); + privKey = keyPair.getPrivate(); + } catch (NoSuchAlgorithmException | NoSuchProviderException e) { + throw new CryptoException(e.getMessage(), e); + } + + byte[] pubKeyBytes = pubKey.getEncoded(); + byte[] privKeyBytes = privKey.getEncoded(); + + return new AsymmetricKeypair(new PubKey(SHA1WITHRSA2048, pubKeyBytes), + new PrivKey(SHA1WITHRSA2048, privKeyBytes)); + } + + @Override + public CryptoAlgorithm getAlgorithm() { + return SHA1WITHRSA2048; + } +} diff --git a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunction.java b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunction.java new file mode 100644 index 00000000..2cde634b --- /dev/null +++ b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunction.java @@ -0,0 +1,68 @@ +package com.jd.blockchain.crypto.service.pki; + +import com.jd.blockchain.crypto.*; + +import static com.jd.blockchain.crypto.service.pki.PKIAlgorithm.SHA1WITHRSA4096; + +/** + * @author zhanglin33 + * @title: SHA1WITHRSA4096SignatureFunction + * @description: TODO + * @date 2019-05-15, 17:13 + */ +public class SHA1WITHRSA4096SignatureFunction implements SignatureFunction { + @Override + public SignatureDigest sign(PrivKey privKey, byte[] data) { + return null; + } + + @Override + public boolean verify(SignatureDigest digest, PubKey pubKey, byte[] data) { + return false; + } + + @Override + public PubKey retrievePubKey(PrivKey privKey) { + return null; + } + + @Override + public boolean supportPrivKey(byte[] privKeyBytes) { + return false; + } + + @Override + public PrivKey resolvePrivKey(byte[] privKeyBytes) { + return null; + } + + @Override + public boolean supportPubKey(byte[] pubKeyBytes) { + return false; + } + + @Override + public PubKey resolvePubKey(byte[] pubKeyBytes) { + return null; + } + + @Override + public boolean supportDigest(byte[] digestBytes) { + return false; + } + + @Override + public SignatureDigest resolveDigest(byte[] digestBytes) { + return null; + } + + @Override + public AsymmetricKeypair generateKeypair() { + return null; + } + + @Override + public CryptoAlgorithm getAlgorithm() { + return SHA1WITHRSA4096; + } +} diff --git a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SM3WITHSM2SignatureFunction.java b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SM3WITHSM2SignatureFunction.java new file mode 100644 index 00000000..7bbea7a1 --- /dev/null +++ b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SM3WITHSM2SignatureFunction.java @@ -0,0 +1,68 @@ +package com.jd.blockchain.crypto.service.pki; + +import com.jd.blockchain.crypto.*; + +import static com.jd.blockchain.crypto.service.pki.PKIAlgorithm.SM3WITHSM2; + +/** + * @author zhanglin33 + * @title: SM3WITHSM2SignatureFunction + * @description: TODO + * @date 2019-05-15, 16:39 + */ +public class SM3WITHSM2SignatureFunction implements SignatureFunction { + @Override + public SignatureDigest sign(PrivKey privKey, byte[] data) { + return null; + } + + @Override + public boolean verify(SignatureDigest digest, PubKey pubKey, byte[] data) { + return false; + } + + @Override + public PubKey retrievePubKey(PrivKey privKey) { + return null; + } + + @Override + public boolean supportPrivKey(byte[] privKeyBytes) { + return false; + } + + @Override + public PrivKey resolvePrivKey(byte[] privKeyBytes) { + return null; + } + + @Override + public boolean supportPubKey(byte[] pubKeyBytes) { + return false; + } + + @Override + public PubKey resolvePubKey(byte[] pubKeyBytes) { + return null; + } + + @Override + public boolean supportDigest(byte[] digestBytes) { + return false; + } + + @Override + public SignatureDigest resolveDigest(byte[] digestBytes) { + return null; + } + + @Override + public AsymmetricKeypair generateKeypair() { + return null; + } + + @Override + public CryptoAlgorithm getAlgorithm() { + return SM3WITHSM2; + } +} diff --git a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CSRBuilder.java b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CSRBuilder.java similarity index 98% rename from source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CSRBuilder.java rename to source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CSRBuilder.java index 9d84a952..6659134b 100644 --- a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CSRBuilder.java +++ b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CSRBuilder.java @@ -1,5 +1,6 @@ -package com.jd.blockchain.crypto; +package com.jd.blockchain.crypto.utils; +import com.jd.blockchain.crypto.CryptoException; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x500.X500NameBuilder; import org.bouncycastle.asn1.x500.style.BCStrictStyle; diff --git a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CertParser.java b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CertParser.java similarity index 96% rename from source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CertParser.java rename to source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CertParser.java index 004079c9..246c4759 100644 --- a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CertParser.java +++ b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CertParser.java @@ -1,5 +1,6 @@ -package com.jd.blockchain.crypto; +package com.jd.blockchain.crypto.utils; +import com.jd.blockchain.crypto.CryptoException; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.util.encoders.Base64; import org.bouncycastle.util.io.pem.PemReader; @@ -15,7 +16,7 @@ import java.util.Date; /** * @author zhanglin33 * @title: CertParser - * @description: TODO + * @description: A parser for standard certificate, along with validation process * @date 2019-05-10, 15:17 */ public class CertParser { diff --git a/source/crypto/crypto-pki/src/main/resources/services/com.jd.blockchain.crypto.CryptoService b/source/crypto/crypto-pki/src/main/resources/services/com.jd.blockchain.crypto.CryptoService new file mode 100644 index 00000000..14a8682f --- /dev/null +++ b/source/crypto/crypto-pki/src/main/resources/services/com.jd.blockchain.crypto.CryptoService @@ -0,0 +1 @@ +com.jd.blockchain.crypto.service.pki.PKICryptoService \ No newline at end of file diff --git a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CSRBuilderTest.java b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CSRBuilderTest.java similarity index 98% rename from source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CSRBuilderTest.java rename to source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CSRBuilderTest.java index a1bb5645..382ecefe 100644 --- a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CSRBuilderTest.java +++ b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CSRBuilderTest.java @@ -1,5 +1,6 @@ -package com.jd.blockchain.crypto; +package com.jd.blockchain.crypto.utils; +import com.jd.blockchain.crypto.utils.CSRBuilder; import org.bouncycastle.asn1.ASN1Encoding; import org.bouncycastle.asn1.DERSet; import org.bouncycastle.asn1.pkcs.CertificationRequestInfo; diff --git a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CertParserTest.java b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CertParserTest.java similarity index 97% rename from source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CertParserTest.java rename to source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CertParserTest.java index 64b55d4a..59ad3814 100644 --- a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CertParserTest.java +++ b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CertParserTest.java @@ -1,5 +1,6 @@ -package com.jd.blockchain.crypto; +package com.jd.blockchain.crypto.utils; +import com.jd.blockchain.crypto.utils.CertParser; import org.junit.Test; import static org.junit.Assert.assertEquals; From c6f693352bcc098337102c84d91cc816b37071ea Mon Sep 17 00:00:00 2001 From: zhaoguangwei Date: Thu, 16 May 2019 13:45:28 +0800 Subject: [PATCH 31/43] to the restful api:/entries-version, check the dataAddress and its version; --- .../com/jd/blockchain/ledger/core/DataAccount.java | 3 +++ .../ledger/core/impl/LedgerQueryService.java | 12 +++++++++--- .../blockchain/peer/web/LedgerQueryController.java | 12 +++++++++--- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java index aa51901a..0655cb24 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java @@ -157,6 +157,9 @@ public class DataAccount implements AccountHeader, MerkleProvable { * @return return total count; */ public long getDataEntriesTotalCount() { + if(baseAccount == null){ + return 0; + } return baseAccount.dataset.getDataCount(); } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java index c053b8b3..fba47095 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java @@ -322,9 +322,15 @@ public class LedgerQueryService implements BlockchainQueryService { if (ver < 0) { entries[i] = new KVDataObject(keys[i], -1, PrimitiveType.NIL, null); }else { - byte[] value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver); - BytesValue decodeData = BinaryProtocol.decode(value); - entries[i] = new KVDataObject(keys[i], ver, PrimitiveType.valueOf(decodeData.getType().CODE), decodeData.getValue().toBytes()); + if(dataAccount.getDataEntriesTotalCount()==0 || + dataAccount.getBytes(Bytes.fromString(keys[i]), ver) == null){ + //is the address is not exist; the result is null; + entries[i] = new KVDataObject(keys[i], -1, PrimitiveType.NIL, null); + } else { + byte[] value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver); + BytesValue decodeData = BinaryProtocol.decode(value); + entries[i] = new KVDataObject(keys[i], ver, PrimitiveType.valueOf(decodeData.getType().CODE), decodeData.getValue().toBytes()); + } } } diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java b/source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java index 637c9216..222d7bf6 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java @@ -393,9 +393,15 @@ public class LedgerQueryController implements BlockchainQueryService { if (ver < 0) { entries[i] = new KVDataObject(keys[i], -1, PrimitiveType.NIL, null); }else { - byte[] value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver); - BytesValue decodeData = BinaryProtocol.decode(value); - entries[i] = new KVDataObject(keys[i], ver, PrimitiveType.valueOf(decodeData.getType().CODE), decodeData.getValue().toBytes()); + if(dataAccount.getDataEntriesTotalCount()==0 || + dataAccount.getBytes(Bytes.fromString(keys[i]), ver) == null){ + //is the address is not exist; the result is null; + entries[i] = new KVDataObject(keys[i], -1, PrimitiveType.NIL, null); + } else { + byte[] value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver); + BytesValue decodeData = BinaryProtocol.decode(value); + entries[i] = new KVDataObject(keys[i], ver, PrimitiveType.valueOf(decodeData.getType().CODE), decodeData.getValue().toBytes()); + } } } From bf6ff4dfe7b66fef66fc50ca369ade339756721e Mon Sep 17 00:00:00 2001 From: zhanglin33 Date: Thu, 16 May 2019 14:39:09 +0800 Subject: [PATCH 32/43] SHA1WITHRSA2048 in crypto-pki module has been completed --- .../crypto/utils/classic/RSAUtils.java | 28 +- .../crypto/utils/classic/CSRTest.java | 58 --- .../crypto/utils/classic/CertTest.java | 79 ---- .../crypto/utils/classic/RSAUtilsTest.java | 7 +- .../crypto/utils/classic/SSHKeyUtilsTest.java | 418 +++++++++--------- source/crypto/crypto-pki/pom.xml | 2 +- .../crypto/service/pki/PKICryptoService.java | 2 + .../pki/SHA1WITHRSA2048SignatureFunction.java | 43 +- .../com.jd.blockchain.crypto.CryptoService | 0 .../SHA1WITHRSA2048SignatureFunctionTest.java | 273 ++++++++++++ .../crypto/utils/CSRBuilderTest.java | 1 - 11 files changed, 525 insertions(+), 386 deletions(-) delete mode 100644 source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/CSRTest.java delete mode 100644 source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/CertTest.java rename source/crypto/crypto-pki/src/main/resources/{ => META-INF}/services/com.jd.blockchain.crypto.CryptoService (100%) create mode 100644 source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunctionTest.java diff --git a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java index 7ee6de3a..a787b655 100644 --- a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java +++ b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java @@ -320,21 +320,15 @@ public class RSAUtils { X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubKeyBytes); KeyFactory keyFactory; - try { - keyFactory = KeyFactory.getInstance("RSA"); - } catch (NoSuchAlgorithmException e) { - throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e); - } - RSAPublicKey publicKey; + try { + keyFactory = KeyFactory.getInstance("RSA"); publicKey = (RSAPublicKey) keyFactory.generatePublic(keySpec); - } catch (InvalidKeySpecException e) { + } catch (InvalidKeySpecException | NoSuchAlgorithmException e) { throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e); } - assert publicKey != null; - BigInteger exponent = publicKey.getPublicExponent(); BigInteger modulus = publicKey.getModulus(); @@ -430,7 +424,7 @@ public class RSAUtils { BigInteger qInv = privKey.getQInv(); byte[] modulusBytes = bigInteger2Bytes(modulus,MODULUS_LENGTH); - byte[] pubExpBytes = pubExp.toByteArray(); + byte[] pubExpBytes = pubExp.toByteArray(); byte[] privExpBytes = bigInteger2Bytes(privExp,PRIVEXP_LENGTH); byte[] pBytes = bigInteger2Bytes(p,P_LENGTH); byte[] qBytes = bigInteger2Bytes(q,Q_LENGTH); @@ -463,21 +457,15 @@ public class RSAUtils { PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privKeyBytes); KeyFactory keyFactory; - try { - keyFactory = KeyFactory.getInstance("RSA"); - } catch (NoSuchAlgorithmException e) { - throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e); - } - RSAPrivateCrtKey privateKey; + try { + keyFactory = KeyFactory.getInstance("RSA"); privateKey = (RSAPrivateCrtKey) keyFactory.generatePrivate(keySpec); - } catch (InvalidKeySpecException e) { + } catch (InvalidKeySpecException | NoSuchAlgorithmException e) { throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e); } - assert privateKey != null; - BigInteger modulus = privateKey.getModulus(); BigInteger pubExp = privateKey.getPublicExponent(); BigInteger privExp = privateKey.getPrivateExponent(); @@ -540,7 +528,7 @@ public class RSAUtils { result,0, length); } else { System.arraycopy(srcBytes,0, - result,length - srcLength, length); + result,length - srcLength, srcLength); } return result; diff --git a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/CSRTest.java b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/CSRTest.java deleted file mode 100644 index ec28db62..00000000 --- a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/CSRTest.java +++ /dev/null @@ -1,58 +0,0 @@ -package test.com.jd.blockchain.crypto.utils.classic; - -import org.bouncycastle.asn1.x500.X500Name; -import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; -import org.bouncycastle.operator.ContentSigner; -import org.bouncycastle.operator.OperatorCreationException; -import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; -import org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder; - - -import java.io.IOException; -import java.security.*; - -/** - * @author zhanglin33 - * @title: CSRTest - * @description: TODO - * @date 2019-05-10, 12:55 - */ -public class CSRTest { - public static String genCSR(String subject, String alg,String provider) { - String signalg=""; - int alglength=0; - String keyAlg=""; - if(alg.toUpperCase().equals("RSA1024")){ - signalg="SHA1WithRSA"; - alglength=1024; - keyAlg="RSA"; - }else if(alg.toUpperCase().equals("RSA2048")){ - signalg="SHA1WithRSA"; - alglength=2048; - keyAlg="RSA"; - }else if(alg.toUpperCase().equals("SM2")){ - signalg="SM3withSM2"; - alglength=256; - keyAlg="SM2"; - } - KeyPairGenerator keyGen; - PKCS10CertificationRequestBuilder builder; - - try { - keyGen = KeyPairGenerator.getInstance(keyAlg); - keyGen.initialize(alglength); - KeyPair kp = keyGen.generateKeyPair(); - - - builder = new PKCS10CertificationRequestBuilder(new X500Name(subject), SubjectPublicKeyInfo.getInstance(kp.getPublic().getEncoded())); - JcaContentSignerBuilder jcaContentSignerBuilder = new JcaContentSignerBuilder(signalg); - jcaContentSignerBuilder.setProvider(provider); - ContentSigner contentSigner = jcaContentSignerBuilder.build(kp.getPrivate()); - builder.build(contentSigner); - return builder.toString(); - } catch (OperatorCreationException | NoSuchAlgorithmException e) { - e.printStackTrace(); - } - return null; - } -} diff --git a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/CertTest.java b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/CertTest.java deleted file mode 100644 index d392336d..00000000 --- a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/CertTest.java +++ /dev/null @@ -1,79 +0,0 @@ -package test.com.jd.blockchain.crypto.utils.classic; - -import org.bouncycastle.util.encoders.Base64; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Test; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.security.NoSuchProviderException; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; - -import org.bouncycastle.jce.provider.BouncyCastleProvider; - -/** - * @author zhanglin33 - * @title: CertTest - * @description: TODO - * @date 2019-05-09, 11:34 - */ -public class CertTest { - - private byte[] certBytes = Base64.decode("MIIEQDCCAyigAwIBAgIFICdVYzEwDQYJKoZIhvcNAQEFBQAwWTELMAkGA1UEBhMCQ04xMDAuBgNVBAoTJ0NoaW5hIEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEYMBYGA1UEAxMPQ0ZDQSBURVNUIE9DQTExMB4XDTE5MDUxMDExMjAyNFoXDTIxMDUxMDExMjAyNFowcjELMAkGA1UEBhMCQ04xGDAWBgNVBAoTD0NGQ0EgVEVTVCBPQ0ExMTERMA8GA1UECxMITG9jYWwgUkExFTATBgNVBAsTDEluZGl2aWR1YWwtMTEfMB0GA1UEAxQWMDUxQGFhYWFhQFpIMDkzNTgwMjhAMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJx3F2WD1dJPzK/nRHO7d1TJ1hTjzGTmv0PQ7ECsJAh3U3BtnGTpCB+b4+JMI4LO8nHkKIBQ3P9XnF+Bf1iXdWNAQ4aWCxa2nV7lCp4w0GliPu/EMgIfmsSDUtgqbM3cr8sR8r9m1xG3gt2TIQJ+jT7sAiguU/kyNzpjaccOUIgUFa8IDFq9UeB76MXtCuhlERRZQCl47e+9w7ZoxmE7e6IZORxPp7rQWVBHlR9ntWjJfNDTm3gMP5ehP+yIZnKx1LudxkBLQxpMmspzOyH1zqx5nkKe49AfWWpDxxRvYkriyYC3aE81qLsU/bhLwNEKOju7BGDF/mhJLZUedojM0gMCAwEAAaOB9TCB8jAfBgNVHSMEGDAWgBT8C7xEmg4xoYOpgYcnHgVCxr9W+DBIBgNVHSAEQTA/MD0GCGCBHIbvKgECMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2ZjYS5jb20uY24vdXMvdXMtMTUuaHRtMDoGA1UdHwQzMDEwL6AtoCuGKWh0dHA6Ly8yMTAuNzQuNDIuMy9PQ0ExMS9SU0EvY3JsMjU2OTMuY3JsMAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQU5oKGaQs7Jt5Gfbt1XhFTWAySEKswHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMA0GCSqGSIb3DQEBBQUAA4IBAQAlmPRaImZV51iKjtpMKuyLMw7dX8L0lY3tl+pVZZSxHuwsN4GCCtV0Ej50up+/6EbfL4NUTiuHVAjCroKKvb+94CrdEwdnQGM5IbGSjT78nQpeASXbIWuUwA+ImjvZOzvq/0b56AzonNzBxOMGko/bj5smM6X8jrgJ0NQppo2KNSVNC4JbuoNWI4FM94SE4DUi9H7EYl4JdOtDaDtCsq49o/A1CZyYrmoOPCgxpQQXmuB3lGq/jyoOlW2aW8uee/hYG1JJcSHLBjF0WBwdxssgbBotA5f1PebiIMSbFgjk57bd4M80hhU/rI4Hkn9pcp5R7NsX95TtyDIg90LboBnW"); - public static String getSubjectDN(byte[] der) { - String dn = ""; - try { - ByteArrayInputStream bIn = new ByteArrayInputStream(der); - //BouncyCastleProvider provider = new BouncyCastleProvider(); - //CertificateFactory cf = CertificateFactory.getInstance("X509", - //provider); - //CertificateFactory cf = CertificateFactory.getInstance("X.509", - // "SUN"); - //android 需采用bcprov - CertificateFactory cf = CertificateFactory.getInstance("X.509"); -// System.out.println(cf.getProvider().getName()); - X509Certificate cert = (X509Certificate) cf - .generateCertificate(bIn); - dn = cert.getSubjectDN().getName(); - - System.out.println(Hex.toHexString(cert.getEncoded())); - byte[] pubKeyBytes = cert.getPublicKey().getEncoded(); - System.out.println(Hex.toHexString(pubKeyBytes)); - System.out.println(cert.getSigAlgName()); - String issuerName = cert.getIssuerDN().getName(); - System.out.println(issuerName); - String oid = cert.getSigAlgOID(); - System.out.println(oid); - System.out.println(); - String name = cert.getIssuerX500Principal().getName(); - System.out.println(name); - bIn.close(); - } catch (CertificateException | IOException e) { - e.printStackTrace(); - } - return dn; - } - - -// public static String parseCertDN(String dn, String type) { -// type = type + "="; -// String[] split = dn.split(","); -// for (String x : split) { -// if (x.contains(type)) { -// x = x.trim(); -// return x.substring(type.length()); -// } -// } -// return null; -// } - - - @Test - public void cert1Test() { - String string = getSubjectDN(certBytes); - System.out.println(Hex.toHexString(certBytes)); - System.out.println(string); - } -} diff --git a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RSAUtilsTest.java b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RSAUtilsTest.java index 3247be8f..a809da47 100644 --- a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RSAUtilsTest.java +++ b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RSAUtilsTest.java @@ -159,10 +159,10 @@ public class RSAUtilsTest { AsymmetricKeyParameter privKey = keyPair.getPrivate(); byte[] privKeyBytes = RSAUtils.privKey2Bytes_RawKey((RSAPrivateCrtKeyParameters) privKey); + Random random = new Random(); + byte[] data; - for (int i = 1; i < 1024; i++) { - data = new byte[i]; - Random random = new Random(); + data = new byte[1024]; random.nextBytes(data); byte[] ciphertext = RSAUtils.encrypt(data, pubKey); @@ -171,7 +171,6 @@ public class RSAUtilsTest { assertArrayEquals(data, plaintextFromPrivKey); assertArrayEquals(data, plaintextFromPrivKeyBytes); - } } diff --git a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/SSHKeyUtilsTest.java b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/SSHKeyUtilsTest.java index 1c2d7731..5964adc3 100644 --- a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/SSHKeyUtilsTest.java +++ b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/SSHKeyUtilsTest.java @@ -1,212 +1,212 @@ -package test.com.jd.blockchain.crypto.utils.classic; - -import org.bouncycastle.asn1.ASN1Sequence; -import org.bouncycastle.crypto.params.RSAKeyParameters; -import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters; -import org.bouncycastle.crypto.util.OpenSSHPrivateKeyUtil; -import org.bouncycastle.crypto.util.OpenSSHPublicKeyUtil; -import org.bouncycastle.jce.spec.OpenSSHPrivateKeySpec; -import org.bouncycastle.jce.spec.OpenSSHPublicKeySpec; -import org.bouncycastle.util.Strings; -import org.bouncycastle.util.encoders.Base64; -import org.bouncycastle.util.encoders.Hex; -import org.bouncycastle.util.io.pem.PemReader; -import org.junit.Test; - -import java.io.IOException; -import java.io.StringReader; -import java.math.BigInteger; - -/** - * @author zhanglin33 - * @title: SSHKeyUtilsTest - * @description: Tests for methods in SSHKeyUtils - * @date 2019-05-07, 15:14 - */ -public class SSHKeyUtilsTest { - - @Test - public void parseRSAPublicKeyTest() { - - String pubKeyStr = "AAAAB3NzaC1yc2EAAAADAQABAAABAQCYwLN4EXy7g0Xugv4lQfoujbARi48gPSxVupt" + - "GsSoGqsS00e9rA7v0qzFKa9Zhnw1WkjCnEXRYAMiCAJYkM/mGI8mb3qkcdNhGWZmPnopV+D46CTFB1" + - "4yeR9mjoOPXs4pjX3zGveKx5Nx8jvdoFewbTCtdN0x1XWTjNT5bXqP/4gXkLENEU5tLsWVAOu0ME/N" + - "e/9gMujAtDoolJ181a9P06bvEpIw5cLtUnsm5CtvBuiL7WBXxDJ/IASJrKNGBdK8xib1+Kb8tNLAT6" + - "Dj25BwylqiRNhb5l1Ni4aKrE2FqSEc5Nx5+csQMEl9MBJ3pEsLHBNbohDL+jbwLguRVD6CJ"; - - byte[] pubKeyBytes = Base64.decode(pubKeyStr); - System.out.println(Hex.toHexString(pubKeyBytes)); - OpenSSHPublicKeySpec pubKeySpec = new OpenSSHPublicKeySpec(pubKeyBytes); - - String pubKeyFormat = pubKeySpec.getFormat(); - String pubKeyType = pubKeySpec.getType(); - System.out.println(pubKeyFormat); - System.out.println(pubKeyType); - - RSAKeyParameters pubKey = (RSAKeyParameters) OpenSSHPublicKeyUtil.parsePublicKey(pubKeyBytes); - BigInteger e = pubKey.getExponent(); - BigInteger n = pubKey.getModulus(); - System.out.println(Hex.toHexString(e.toByteArray())); - System.out.println(Hex.toHexString(n.toByteArray())); - - System.out.println(); - System.out.println("-------------------------------------------------------"); - System.out.println(); - - - } - - @Test - public void parseRSAPrivateKeyTest() { - - String str2 = "-----BEGIN OPENSSH PRIVATE KEY-----\n" + - "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn\n" + - "NhAAAAAwEAAQAAAQEAwFyeWgHFu/ZMvqWa28QUGlKMDV7vpbzT7kyA/4yuotfprZKHNeEy\n" + - "GugleJ/Kv5kqHh8Km4IZcfNcerTYds+U5m/uX4bSYpEbXco3DQ2lYQbYo7PBWwPMq2aIdd\n" + - "i7WxUAlt0z1ugLNimskPzJ7DNra+ax0Wh9RnMsjZkfuBZiKq7wbBm7NyJmpg2B7xo5cz+G\n" + - "Lw9e0tDlvgeLe+n68WvYWWFP59mfP6Qoy+NwjQnnwrhJi2j4dEexO97KmgnJhL07lu4eCQ\n" + - "fdv68Tai9+aeDNawe7nmFYf2eNjah2jW/DwOwA/ErXnvgjLSMsgc6WGKfokhytAOFDGgvH\n" + - "KKNd6BMYZwAAA9A7JircOyYq3AAAAAdzc2gtcnNhAAABAQDAXJ5aAcW79ky+pZrbxBQaUo\n" + - "wNXu+lvNPuTID/jK6i1+mtkoc14TIa6CV4n8q/mSoeHwqbghlx81x6tNh2z5Tmb+5fhtJi\n" + - "kRtdyjcNDaVhBtijs8FbA8yrZoh12LtbFQCW3TPW6As2KayQ/MnsM2tr5rHRaH1GcyyNmR\n" + - "+4FmIqrvBsGbs3ImamDYHvGjlzP4YvD17S0OW+B4t76frxa9hZYU/n2Z8/pCjL43CNCefC\n" + - "uEmLaPh0R7E73sqaCcmEvTuW7h4JB92/rxNqL35p4M1rB7ueYVh/Z42NqHaNb8PA7AD8St\n" + - "ee+CMtIyyBzpYYp+iSHK0A4UMaC8coo13oExhnAAAAAwEAAQAAAQAEEvIXnen+LR06/G7n\n" + - "MKPsWss0jUouDG3AokYpI2WfdUsxreTHM1nIUBpbD6dPn4LQ2H91A7BeRXUz9BiRi5vvtX\n" + - "cq9sQF6mTV+65mzF8wSuDTtr7lmpL/HlDNjiWJrEwy5cRvTMLQBtnsyC3OntgrlNs3QCtH\n" + - "DrFm3lNZpr+1f62Vu43dbcTPvLwcc335cJ73BU5WsMGaouCAqVXsVsgfkA66u6+gQs8O3F\n" + - "IQntdzS8vYpkzH8N9qqNZit7kbFCRUTI7CDLHquJmclzB8uVwO0pR5+Aross+YL3QxPZoJ\n" + - "+LXLlCi27oSmYk3fx3uh0XwwO3JFDQpeCxOuEsZbOy8BAAAAgCsktFksS0BViRuLyzC2H7\n" + - "X7Uonf+dr8e4Yn+RgR329KFh/ok28/KZndZHsUnhdmiIjPr+SplFZZMrV/uJDkGezUNWGf\n" + - "8qn+eEglm7nYfVf2EXTVNhpg8yfPChx90ybc8GYlqpEqf7LiCuEBCPqPJgq6K7i6UKbwn2\n" + - "SfqUOBcz5BAAAAgQDqszdiNv0cTvZ/Xg3qJPsHXqQuLBYoe2vhU+Pipt9HviruUD1y3Mso\n" + - "rOL9QBwjE7szGnwVE00J0mLp+s309+kftADLXqMyqFYiy7S8GIWQw0YNB2m8yjq+phHbBm\n" + - "/Gs2P4+s8yKTcVJvMTyWr02rpCHiLTKDHoXPJcJ8yVMTHFRwAAAIEA0dHB9fXiesEKfwcp\n" + - "X11IHAV8pTd+7VN81oGwxtRg88U7H2rmQFCxSZah2O/OCCmYLH3PHT95qnMHHqzcsVvoIy\n" + - "7AfnMpp4KYU0Ic3aFuRjZk2sDsYUniPcCpuCvs8Jb75sDwKDW2EM8MowiNylDnYMmfYj0l\n" + - "gIhz1/p79hXEI+EAAAAbemhhbmdsaW4zM0B6aGFuZ2xpbjMzLmxvY2Fs\n" + - "-----END OPENSSH PRIVATE KEY-----"; - - byte[] Bytes2 = null; - try { - Bytes2 = new PemReader(new StringReader(str2)).readPemObject().getContent(); - } catch (IOException e1) { - e1.printStackTrace(); - } - System.out.println(Hex.toHexString(Bytes2)); - - String str3 = "-----BEGIN OPENSSH PRIVATE KEY-----\n" + - "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn\n" + - "NhAAAAAwEAAQAAAQEAvummQZm1FUFc/cV5nQBeowhjX4vIU4kBmyPmXHMViX4ORvWvD1yi\n" + - "oxcaawPpP9QconpzjdCrNbmw0oZNt9UKlmrOU34YTRD5LFlEVOYjr/21/SO5yDGog8xJBU\n" + - "HQYnXY5L2q9EXKOF45e5P6gSGUovrhePEsaniuQN48GIObPCOFkEN0ZV2DqRsn3It1vY+D\n" + - "GiSb5EaZ2sNkudyzYfgFxcCbqBXmDa1WeyX5xYh8wldBJLUH+pO4gPoTXXX4UI4yNdDmPD\n" + - "BWFvPVIOdpfdBnDbEp1AoE5Jx/+tbwFBIEvTPOECtOUKDGIlXXIH0I4waHbwf6EnHD5+BR\n" + - "N0XwrzSkuwAAA9DYV/7H2Ff+xwAAAAdzc2gtcnNhAAABAQC+6aZBmbUVQVz9xXmdAF6jCG\n" + - "Nfi8hTiQGbI+ZccxWJfg5G9a8PXKKjFxprA+k/1ByienON0Ks1ubDShk231QqWas5TfhhN\n" + - "EPksWURU5iOv/bX9I7nIMaiDzEkFQdBiddjkvar0Rco4Xjl7k/qBIZSi+uF48SxqeK5A3j\n" + - "wYg5s8I4WQQ3RlXYOpGyfci3W9j4MaJJvkRpnaw2S53LNh+AXFwJuoFeYNrVZ7JfnFiHzC\n" + - "V0EktQf6k7iA+hNddfhQjjI10OY8MFYW89Ug52l90GcNsSnUCgTknH/61vAUEgS9M84QK0\n" + - "5QoMYiVdcgfQjjBodvB/oSccPn4FE3RfCvNKS7AAAAAwEAAQAAAQArRruxUy6BSvfRbtpK\n" + - "hLLvMg+UsRMQHJaInHKzskLHkBOcckTkrpMPdUU/zPsqxOJY0nkvRIYK/7TdhCRJ77ker8\n" + - "dllcfccGSLcRDUTfb5BgIjB94tS1Rvy/chgfHC4APyliwSg197t6BAKyM18m7HIyfJSqJO\n" + - "4FxfyADHbc3aq654tu+eaUtD7TEN1bH6PKMDvwSioMLgKU43GQeDJZbqamBE9y+KVhVx9y\n" + - "3DEHrOPkRkZIG33y9j7B/i0vl+WnwUTzmLGRR0U6J9wrzyANL8ODYaAvk4FvUED8hQ72jh\n" + - "NpAXsSgf6COUE1sUnO5DOwN1zHBNHaSo73Qu7aKZtL4BAAAAgDBW3ItiqU9Ip34KtLaayK\n" + - "/BkRDDwFNvAxpOw9alpfbLGF5xbVjRN4wy7HJ4eA+7JJnx6A6xYrzykbPP+dnUnfzYuxH8\n" + - "MrihOkYipw1VaR6/0XH+apmE1SmotuYbl+bpl9dlZYUI0pJ8wldqoDCNlSOcLy77HnKwu9\n" + - "GpJx9KmW9WAAAAgQDdnrwfVv5trAuZZIcw2vLRWhoDT196k/Ty1GP4zFpDttb8OyZ8Ygpx\n" + - "oA5PhYyl5M1g/2oR/Rpp3vfKDVThfn/bCnMtAbUHMfvYK3Oufvq5JmzT1rgGr3MEek+JBR\n" + - "O17I87m4GE7iM1LzCUs2G/fKt2uoVXdniv0Vn0iCiZZc7JmwAAAIEA3IdsccarkUfFcQ2c\n" + - "4TdHrx/RGmoTAO6k1xOHXZjWPmerinuOspIJL/ymWfqIxABCjub3UHyP7ap+1+AAnk+TMU\n" + - "eR3tLEp9tRM6n0Td56DnQ9Q+RZhPqR486/teZ33cMBMHg52aIs/3AzMpK9xTFCRgqsKa6e\n" + - "ednMB4Q1txvHU2EAAAAbemhhbmdsaW4zM0B6aGFuZ2xpbjMzLmxvY2Fs\n" + - "-----END OPENSSH PRIVATE KEY-----"; - - byte[] Bytes3 = null; - try { - Bytes3 = new PemReader(new StringReader(str3)).readPemObject().getContent(); - } catch (IOException e1) { - e1.printStackTrace(); - } - System.out.println(Hex.toHexString(Bytes3)); -// System.out.println(Hex.toHexString(Base64.decode("oNE9iA4ZyuZLbpEL7B29NaxGi4puT2Y5RDaMoEkoAKI"))); -// String test = "1ac477fa"; -// byte[] testBytes = Hex.decode(test); -// -// System.out.println(Base64.toBase64String(testBytes)); - - byte[] AUTH_MAGIC = Strings.toByteArray("openssh-key-v1\0"); - System.out.println(Hex.toHexString(AUTH_MAGIC)); - System.out.println(Base64.toBase64String(AUTH_MAGIC)); - String privKeyStr = "-----BEGIN OPENSSH PRIVATE KEY-----\n" + - "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn\n" + - "NhAAAAAwEAAQAAAQEAmMCzeBF8u4NF7oL+JUH6Lo2wEYuPID0sVbqbRrEqBqrEtNHvawO7\n" + - "9KsxSmvWYZ8NVpIwpxF0WADIggCWJDP5hiPJm96pHHTYRlmZj56KVfg+OgkxQdeMnkfZo6\n" + - "Dj17OKY198xr3iseTcfI73aBXsG0wrXTdMdV1k4zU+W16j/+IF5CxDRFObS7FlQDrtDBPz\n" + - "Xv/YDLowLQ6KJSdfNWvT9Om7xKSMOXC7VJ7JuQrbwboi+1gV8QyfyAEiayjRgXSvMYm9fi\n" + - "m/LTSwE+g49uQcMpaokTYW+ZdTYuGiqxNhakhHOTcefnLEDBJfTASd6RLCxwTW6IQy/o28\n" + - "C4LkVQ+giQAAA9AaxHf6GsR3+gAAAAdzc2gtcnNhAAABAQCYwLN4EXy7g0Xugv4lQfoujb\n" + - "ARi48gPSxVuptGsSoGqsS00e9rA7v0qzFKa9Zhnw1WkjCnEXRYAMiCAJYkM/mGI8mb3qkc\n" + - "dNhGWZmPnopV+D46CTFB14yeR9mjoOPXs4pjX3zGveKx5Nx8jvdoFewbTCtdN0x1XWTjNT\n" + - "5bXqP/4gXkLENEU5tLsWVAOu0ME/Ne/9gMujAtDoolJ181a9P06bvEpIw5cLtUnsm5CtvB\n" + - "uiL7WBXxDJ/IASJrKNGBdK8xib1+Kb8tNLAT6Dj25BwylqiRNhb5l1Ni4aKrE2FqSEc5Nx\n" + - "5+csQMEl9MBJ3pEsLHBNbohDL+jbwLguRVD6CJAAAAAwEAAQAAAQARfhfPSylei9TpUGTs\n" + - "PVb6F82u5K16QqceFiWL/ePTKaEnF9d0CNRwW15kqF6/hShQ3qLlrvEE1uofQRPwh2cuvl\n" + - "BrIh95m8PcoowcT0qGN8xgdwcGBDodMhsxSs5suCnD4X53f+1C8/Nv7CtW5xPHuHxKy3dd\n" + - "BVn1TvaaHgdn2PwJVKtZp+WVG3/UHr25nFHd8mYgpeHZqK9AW16N0UEMXMM1u8ZCubVOoS\n" + - "IGuMAXpTug0xA+BXHo17FcDGKSzcXFzh+urIz5glRp5zFioHBqxNmkKfQkG6C7UxnPGyS/\n" + - "/J+3lL2lvl0G8kO/5EDFMBhTMEy1NeR2b629S4G1qUxVAAAAgHDwE9kPiVETcxSzI4wotT\n" + - "1Ee9nKVVD3oGdRqefvX7EUR8bvdv4nCqHPNBx8C6l8zo7fsQD81YL85F4eWbtrdxEijRHX\n" + - "5m7J/muh/laY1Hq43WCkZGboO4fZ2HHi7oN096FqrKRpvbQGQi1FLbcISUdsitwrs6ywn3\n" + - "fNx3q+X3V6AAAAgQDJRo9v+0QvldI33cpJKPKiaop5QvfIDzMatD3vLA1qqycgIi4KOtb5\n" + - "+LP/jgIpCYah/sk+JpKNz/vsZmZmrfaVu9D3Le2LLBgMpEoSO8jOe9WGI4Ew75C7w7AZCa\n" + - "SyUnHIVX/9D8Y5tx4cKx6Im9AGbNF35XZoKO4KCk5VMTXhnwAAAIEAwkjKIpTYdeAQVTRf\n" + - "C13kg84Bu5n4WkiLnp1WOCg2GN5RekqprINtpjIMZoB9Fv292Np99La8yvmRoy5qzNHGdm\n" + - "Q6AMku8jP123jF2J+wDvF714VtZHNvdCYBGJS+rZ81xtJfHhKtZqRAVtbPertOWZeuRm9V\n" + - "o+/rEuEzgGYGXNcAAAAbemhhbmdsaW4zM0B6aGFuZ2xpbjMzLmxvY2Fs\n" + - "-----END OPENSSH PRIVATE KEY-----"; - - byte[] privKeyBytes = null; - try { - privKeyBytes = new PemReader(new StringReader(privKeyStr)).readPemObject().getContent(); - } catch (IOException e1) { - e1.printStackTrace(); - } - - assert privKeyBytes != null; - System.out.println(Hex.toHexString(privKeyBytes)); - - - OpenSSHPrivateKeySpec privKeySpec = new OpenSSHPrivateKeySpec(privKeyBytes); - - String privKeyFormat = privKeySpec.getFormat(); - System.out.println(privKeyFormat); - - RSAKeyParameters privKey = (RSAKeyParameters) OpenSSHPrivateKeyUtil.parsePrivateKeyBlob(privKeyBytes); - -// BigInteger e = privKey.getPublicExponent(); -// BigInteger n = privKey.getModulus(); -// -// BigInteger d = privKey.getExponent(); -// BigInteger p = privKey.getP(); -// BigInteger q = privKey.getQ(); -// BigInteger dP = privKey.getDP(); -// BigInteger dQ = privKey.getDQ(); -// BigInteger qInv = privKey.getQInv(); - +//package test.com.jd.blockchain.crypto.utils.classic; +// +//import org.bouncycastle.asn1.ASN1Sequence; +//import org.bouncycastle.crypto.params.RSAKeyParameters; +//import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters; +//import org.bouncycastle.crypto.util.OpenSSHPrivateKeyUtil; +//import org.bouncycastle.crypto.util.OpenSSHPublicKeyUtil; +//import org.bouncycastle.jce.spec.OpenSSHPrivateKeySpec; +//import org.bouncycastle.jce.spec.OpenSSHPublicKeySpec; +//import org.bouncycastle.util.Strings; +//import org.bouncycastle.util.encoders.Base64; +//import org.bouncycastle.util.encoders.Hex; +//import org.bouncycastle.util.io.pem.PemReader; +//import org.junit.Test; +// +//import java.io.IOException; +//import java.io.StringReader; +//import java.math.BigInteger; +// +///** +// * @author zhanglin33 +// * @title: SSHKeyUtilsTest +// * @description: Tests for methods in SSHKeyUtils +// * @date 2019-05-07, 15:14 +// */ +//public class SSHKeyUtilsTest { +// +// @Test +// public void parseRSAPublicKeyTest() { +// +// String pubKeyStr = "AAAAB3NzaC1yc2EAAAADAQABAAABAQCYwLN4EXy7g0Xugv4lQfoujbARi48gPSxVupt" + +// "GsSoGqsS00e9rA7v0qzFKa9Zhnw1WkjCnEXRYAMiCAJYkM/mGI8mb3qkcdNhGWZmPnopV+D46CTFB1" + +// "4yeR9mjoOPXs4pjX3zGveKx5Nx8jvdoFewbTCtdN0x1XWTjNT5bXqP/4gXkLENEU5tLsWVAOu0ME/N" + +// "e/9gMujAtDoolJ181a9P06bvEpIw5cLtUnsm5CtvBuiL7WBXxDJ/IASJrKNGBdK8xib1+Kb8tNLAT6" + +// "Dj25BwylqiRNhb5l1Ni4aKrE2FqSEc5Nx5+csQMEl9MBJ3pEsLHBNbohDL+jbwLguRVD6CJ"; +// +// byte[] pubKeyBytes = Base64.decode(pubKeyStr); +// System.out.println(Hex.toHexString(pubKeyBytes)); +// OpenSSHPublicKeySpec pubKeySpec = new OpenSSHPublicKeySpec(pubKeyBytes); +// +// String pubKeyFormat = pubKeySpec.getFormat(); +// String pubKeyType = pubKeySpec.getType(); +// System.out.println(pubKeyFormat); +// System.out.println(pubKeyType); +// +// RSAKeyParameters pubKey = (RSAKeyParameters) OpenSSHPublicKeyUtil.parsePublicKey(pubKeyBytes); +// BigInteger e = pubKey.getExponent(); +// BigInteger n = pubKey.getModulus(); // System.out.println(Hex.toHexString(e.toByteArray())); // System.out.println(Hex.toHexString(n.toByteArray())); // -// System.out.println(Hex.toHexString(d.toByteArray())); -// System.out.println(Hex.toHexString(p.toByteArray())); -// System.out.println(Hex.toHexString(q.toByteArray())); -// System.out.println(Hex.toHexString(dP.toByteArray())); -// System.out.println(Hex.toHexString(dQ.toByteArray())); -// System.out.println(Hex.toHexString(qInv.toByteArray())); - - - - } - -} +// System.out.println(); +// System.out.println("-------------------------------------------------------"); +// System.out.println(); +// +// +// } +// +// @Test +// public void parseRSAPrivateKeyTest() { +// +// String str2 = "-----BEGIN OPENSSH PRIVATE KEY-----\n" + +// "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn\n" + +// "NhAAAAAwEAAQAAAQEAwFyeWgHFu/ZMvqWa28QUGlKMDV7vpbzT7kyA/4yuotfprZKHNeEy\n" + +// "GugleJ/Kv5kqHh8Km4IZcfNcerTYds+U5m/uX4bSYpEbXco3DQ2lYQbYo7PBWwPMq2aIdd\n" + +// "i7WxUAlt0z1ugLNimskPzJ7DNra+ax0Wh9RnMsjZkfuBZiKq7wbBm7NyJmpg2B7xo5cz+G\n" + +// "Lw9e0tDlvgeLe+n68WvYWWFP59mfP6Qoy+NwjQnnwrhJi2j4dEexO97KmgnJhL07lu4eCQ\n" + +// "fdv68Tai9+aeDNawe7nmFYf2eNjah2jW/DwOwA/ErXnvgjLSMsgc6WGKfokhytAOFDGgvH\n" + +// "KKNd6BMYZwAAA9A7JircOyYq3AAAAAdzc2gtcnNhAAABAQDAXJ5aAcW79ky+pZrbxBQaUo\n" + +// "wNXu+lvNPuTID/jK6i1+mtkoc14TIa6CV4n8q/mSoeHwqbghlx81x6tNh2z5Tmb+5fhtJi\n" + +// "kRtdyjcNDaVhBtijs8FbA8yrZoh12LtbFQCW3TPW6As2KayQ/MnsM2tr5rHRaH1GcyyNmR\n" + +// "+4FmIqrvBsGbs3ImamDYHvGjlzP4YvD17S0OW+B4t76frxa9hZYU/n2Z8/pCjL43CNCefC\n" + +// "uEmLaPh0R7E73sqaCcmEvTuW7h4JB92/rxNqL35p4M1rB7ueYVh/Z42NqHaNb8PA7AD8St\n" + +// "ee+CMtIyyBzpYYp+iSHK0A4UMaC8coo13oExhnAAAAAwEAAQAAAQAEEvIXnen+LR06/G7n\n" + +// "MKPsWss0jUouDG3AokYpI2WfdUsxreTHM1nIUBpbD6dPn4LQ2H91A7BeRXUz9BiRi5vvtX\n" + +// "cq9sQF6mTV+65mzF8wSuDTtr7lmpL/HlDNjiWJrEwy5cRvTMLQBtnsyC3OntgrlNs3QCtH\n" + +// "DrFm3lNZpr+1f62Vu43dbcTPvLwcc335cJ73BU5WsMGaouCAqVXsVsgfkA66u6+gQs8O3F\n" + +// "IQntdzS8vYpkzH8N9qqNZit7kbFCRUTI7CDLHquJmclzB8uVwO0pR5+Aross+YL3QxPZoJ\n" + +// "+LXLlCi27oSmYk3fx3uh0XwwO3JFDQpeCxOuEsZbOy8BAAAAgCsktFksS0BViRuLyzC2H7\n" + +// "X7Uonf+dr8e4Yn+RgR329KFh/ok28/KZndZHsUnhdmiIjPr+SplFZZMrV/uJDkGezUNWGf\n" + +// "8qn+eEglm7nYfVf2EXTVNhpg8yfPChx90ybc8GYlqpEqf7LiCuEBCPqPJgq6K7i6UKbwn2\n" + +// "SfqUOBcz5BAAAAgQDqszdiNv0cTvZ/Xg3qJPsHXqQuLBYoe2vhU+Pipt9HviruUD1y3Mso\n" + +// "rOL9QBwjE7szGnwVE00J0mLp+s309+kftADLXqMyqFYiy7S8GIWQw0YNB2m8yjq+phHbBm\n" + +// "/Gs2P4+s8yKTcVJvMTyWr02rpCHiLTKDHoXPJcJ8yVMTHFRwAAAIEA0dHB9fXiesEKfwcp\n" + +// "X11IHAV8pTd+7VN81oGwxtRg88U7H2rmQFCxSZah2O/OCCmYLH3PHT95qnMHHqzcsVvoIy\n" + +// "7AfnMpp4KYU0Ic3aFuRjZk2sDsYUniPcCpuCvs8Jb75sDwKDW2EM8MowiNylDnYMmfYj0l\n" + +// "gIhz1/p79hXEI+EAAAAbemhhbmdsaW4zM0B6aGFuZ2xpbjMzLmxvY2Fs\n" + +// "-----END OPENSSH PRIVATE KEY-----"; +// +// byte[] Bytes2 = null; +// try { +// Bytes2 = new PemReader(new StringReader(str2)).readPemObject().getContent(); +// } catch (IOException e1) { +// e1.printStackTrace(); +// } +// System.out.println(Hex.toHexString(Bytes2)); +// +// String str3 = "-----BEGIN OPENSSH PRIVATE KEY-----\n" + +// "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn\n" + +// "NhAAAAAwEAAQAAAQEAvummQZm1FUFc/cV5nQBeowhjX4vIU4kBmyPmXHMViX4ORvWvD1yi\n" + +// "oxcaawPpP9QconpzjdCrNbmw0oZNt9UKlmrOU34YTRD5LFlEVOYjr/21/SO5yDGog8xJBU\n" + +// "HQYnXY5L2q9EXKOF45e5P6gSGUovrhePEsaniuQN48GIObPCOFkEN0ZV2DqRsn3It1vY+D\n" + +// "GiSb5EaZ2sNkudyzYfgFxcCbqBXmDa1WeyX5xYh8wldBJLUH+pO4gPoTXXX4UI4yNdDmPD\n" + +// "BWFvPVIOdpfdBnDbEp1AoE5Jx/+tbwFBIEvTPOECtOUKDGIlXXIH0I4waHbwf6EnHD5+BR\n" + +// "N0XwrzSkuwAAA9DYV/7H2Ff+xwAAAAdzc2gtcnNhAAABAQC+6aZBmbUVQVz9xXmdAF6jCG\n" + +// "Nfi8hTiQGbI+ZccxWJfg5G9a8PXKKjFxprA+k/1ByienON0Ks1ubDShk231QqWas5TfhhN\n" + +// "EPksWURU5iOv/bX9I7nIMaiDzEkFQdBiddjkvar0Rco4Xjl7k/qBIZSi+uF48SxqeK5A3j\n" + +// "wYg5s8I4WQQ3RlXYOpGyfci3W9j4MaJJvkRpnaw2S53LNh+AXFwJuoFeYNrVZ7JfnFiHzC\n" + +// "V0EktQf6k7iA+hNddfhQjjI10OY8MFYW89Ug52l90GcNsSnUCgTknH/61vAUEgS9M84QK0\n" + +// "5QoMYiVdcgfQjjBodvB/oSccPn4FE3RfCvNKS7AAAAAwEAAQAAAQArRruxUy6BSvfRbtpK\n" + +// "hLLvMg+UsRMQHJaInHKzskLHkBOcckTkrpMPdUU/zPsqxOJY0nkvRIYK/7TdhCRJ77ker8\n" + +// "dllcfccGSLcRDUTfb5BgIjB94tS1Rvy/chgfHC4APyliwSg197t6BAKyM18m7HIyfJSqJO\n" + +// "4FxfyADHbc3aq654tu+eaUtD7TEN1bH6PKMDvwSioMLgKU43GQeDJZbqamBE9y+KVhVx9y\n" + +// "3DEHrOPkRkZIG33y9j7B/i0vl+WnwUTzmLGRR0U6J9wrzyANL8ODYaAvk4FvUED8hQ72jh\n" + +// "NpAXsSgf6COUE1sUnO5DOwN1zHBNHaSo73Qu7aKZtL4BAAAAgDBW3ItiqU9Ip34KtLaayK\n" + +// "/BkRDDwFNvAxpOw9alpfbLGF5xbVjRN4wy7HJ4eA+7JJnx6A6xYrzykbPP+dnUnfzYuxH8\n" + +// "MrihOkYipw1VaR6/0XH+apmE1SmotuYbl+bpl9dlZYUI0pJ8wldqoDCNlSOcLy77HnKwu9\n" + +// "GpJx9KmW9WAAAAgQDdnrwfVv5trAuZZIcw2vLRWhoDT196k/Ty1GP4zFpDttb8OyZ8Ygpx\n" + +// "oA5PhYyl5M1g/2oR/Rpp3vfKDVThfn/bCnMtAbUHMfvYK3Oufvq5JmzT1rgGr3MEek+JBR\n" + +// "O17I87m4GE7iM1LzCUs2G/fKt2uoVXdniv0Vn0iCiZZc7JmwAAAIEA3IdsccarkUfFcQ2c\n" + +// "4TdHrx/RGmoTAO6k1xOHXZjWPmerinuOspIJL/ymWfqIxABCjub3UHyP7ap+1+AAnk+TMU\n" + +// "eR3tLEp9tRM6n0Td56DnQ9Q+RZhPqR486/teZ33cMBMHg52aIs/3AzMpK9xTFCRgqsKa6e\n" + +// "ednMB4Q1txvHU2EAAAAbemhhbmdsaW4zM0B6aGFuZ2xpbjMzLmxvY2Fs\n" + +// "-----END OPENSSH PRIVATE KEY-----"; +// +// byte[] Bytes3 = null; +// try { +// Bytes3 = new PemReader(new StringReader(str3)).readPemObject().getContent(); +// } catch (IOException e1) { +// e1.printStackTrace(); +// } +// System.out.println(Hex.toHexString(Bytes3)); +//// System.out.println(Hex.toHexString(Base64.decode("oNE9iA4ZyuZLbpEL7B29NaxGi4puT2Y5RDaMoEkoAKI"))); +//// String test = "1ac477fa"; +//// byte[] testBytes = Hex.decode(test); +//// +//// System.out.println(Base64.toBase64String(testBytes)); +// +// byte[] AUTH_MAGIC = Strings.toByteArray("openssh-key-v1\0"); +// System.out.println(Hex.toHexString(AUTH_MAGIC)); +// System.out.println(Base64.toBase64String(AUTH_MAGIC)); +// String privKeyStr = "-----BEGIN OPENSSH PRIVATE KEY-----\n" + +// "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn\n" + +// "NhAAAAAwEAAQAAAQEAmMCzeBF8u4NF7oL+JUH6Lo2wEYuPID0sVbqbRrEqBqrEtNHvawO7\n" + +// "9KsxSmvWYZ8NVpIwpxF0WADIggCWJDP5hiPJm96pHHTYRlmZj56KVfg+OgkxQdeMnkfZo6\n" + +// "Dj17OKY198xr3iseTcfI73aBXsG0wrXTdMdV1k4zU+W16j/+IF5CxDRFObS7FlQDrtDBPz\n" + +// "Xv/YDLowLQ6KJSdfNWvT9Om7xKSMOXC7VJ7JuQrbwboi+1gV8QyfyAEiayjRgXSvMYm9fi\n" + +// "m/LTSwE+g49uQcMpaokTYW+ZdTYuGiqxNhakhHOTcefnLEDBJfTASd6RLCxwTW6IQy/o28\n" + +// "C4LkVQ+giQAAA9AaxHf6GsR3+gAAAAdzc2gtcnNhAAABAQCYwLN4EXy7g0Xugv4lQfoujb\n" + +// "ARi48gPSxVuptGsSoGqsS00e9rA7v0qzFKa9Zhnw1WkjCnEXRYAMiCAJYkM/mGI8mb3qkc\n" + +// "dNhGWZmPnopV+D46CTFB14yeR9mjoOPXs4pjX3zGveKx5Nx8jvdoFewbTCtdN0x1XWTjNT\n" + +// "5bXqP/4gXkLENEU5tLsWVAOu0ME/Ne/9gMujAtDoolJ181a9P06bvEpIw5cLtUnsm5CtvB\n" + +// "uiL7WBXxDJ/IASJrKNGBdK8xib1+Kb8tNLAT6Dj25BwylqiRNhb5l1Ni4aKrE2FqSEc5Nx\n" + +// "5+csQMEl9MBJ3pEsLHBNbohDL+jbwLguRVD6CJAAAAAwEAAQAAAQARfhfPSylei9TpUGTs\n" + +// "PVb6F82u5K16QqceFiWL/ePTKaEnF9d0CNRwW15kqF6/hShQ3qLlrvEE1uofQRPwh2cuvl\n" + +// "BrIh95m8PcoowcT0qGN8xgdwcGBDodMhsxSs5suCnD4X53f+1C8/Nv7CtW5xPHuHxKy3dd\n" + +// "BVn1TvaaHgdn2PwJVKtZp+WVG3/UHr25nFHd8mYgpeHZqK9AW16N0UEMXMM1u8ZCubVOoS\n" + +// "IGuMAXpTug0xA+BXHo17FcDGKSzcXFzh+urIz5glRp5zFioHBqxNmkKfQkG6C7UxnPGyS/\n" + +// "/J+3lL2lvl0G8kO/5EDFMBhTMEy1NeR2b629S4G1qUxVAAAAgHDwE9kPiVETcxSzI4wotT\n" + +// "1Ee9nKVVD3oGdRqefvX7EUR8bvdv4nCqHPNBx8C6l8zo7fsQD81YL85F4eWbtrdxEijRHX\n" + +// "5m7J/muh/laY1Hq43WCkZGboO4fZ2HHi7oN096FqrKRpvbQGQi1FLbcISUdsitwrs6ywn3\n" + +// "fNx3q+X3V6AAAAgQDJRo9v+0QvldI33cpJKPKiaop5QvfIDzMatD3vLA1qqycgIi4KOtb5\n" + +// "+LP/jgIpCYah/sk+JpKNz/vsZmZmrfaVu9D3Le2LLBgMpEoSO8jOe9WGI4Ew75C7w7AZCa\n" + +// "SyUnHIVX/9D8Y5tx4cKx6Im9AGbNF35XZoKO4KCk5VMTXhnwAAAIEAwkjKIpTYdeAQVTRf\n" + +// "C13kg84Bu5n4WkiLnp1WOCg2GN5RekqprINtpjIMZoB9Fv292Np99La8yvmRoy5qzNHGdm\n" + +// "Q6AMku8jP123jF2J+wDvF714VtZHNvdCYBGJS+rZ81xtJfHhKtZqRAVtbPertOWZeuRm9V\n" + +// "o+/rEuEzgGYGXNcAAAAbemhhbmdsaW4zM0B6aGFuZ2xpbjMzLmxvY2Fs\n" + +// "-----END OPENSSH PRIVATE KEY-----"; +// +// byte[] privKeyBytes = null; +// try { +// privKeyBytes = new PemReader(new StringReader(privKeyStr)).readPemObject().getContent(); +// } catch (IOException e1) { +// e1.printStackTrace(); +// } +// +// assert privKeyBytes != null; +// System.out.println(Hex.toHexString(privKeyBytes)); +// +// +// OpenSSHPrivateKeySpec privKeySpec = new OpenSSHPrivateKeySpec(privKeyBytes); +// +// String privKeyFormat = privKeySpec.getFormat(); +// System.out.println(privKeyFormat); +// +// RSAKeyParameters privKey = (RSAKeyParameters) OpenSSHPrivateKeyUtil.parsePrivateKeyBlob(privKeyBytes); +// +//// BigInteger e = privKey.getPublicExponent(); +//// BigInteger n = privKey.getModulus(); +//// +//// BigInteger d = privKey.getExponent(); +//// BigInteger p = privKey.getP(); +//// BigInteger q = privKey.getQ(); +//// BigInteger dP = privKey.getDP(); +//// BigInteger dQ = privKey.getDQ(); +//// BigInteger qInv = privKey.getQInv(); +// +//// System.out.println(Hex.toHexString(e.toByteArray())); +//// System.out.println(Hex.toHexString(n.toByteArray())); +//// +//// System.out.println(Hex.toHexString(d.toByteArray())); +//// System.out.println(Hex.toHexString(p.toByteArray())); +//// System.out.println(Hex.toHexString(q.toByteArray())); +//// System.out.println(Hex.toHexString(dP.toByteArray())); +//// System.out.println(Hex.toHexString(dQ.toByteArray())); +//// System.out.println(Hex.toHexString(qInv.toByteArray())); +// +// +// +// } +// +//} diff --git a/source/crypto/crypto-pki/pom.xml b/source/crypto/crypto-pki/pom.xml index 5256127d..9c895b21 100644 --- a/source/crypto/crypto-pki/pom.xml +++ b/source/crypto/crypto-pki/pom.xml @@ -14,7 +14,7 @@ com.jd.blockchain - crypto-classic + crypto-framework ${project.version} diff --git a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/PKICryptoService.java b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/PKICryptoService.java index 3c013bbc..940d3168 100644 --- a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/PKICryptoService.java +++ b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/PKICryptoService.java @@ -2,6 +2,7 @@ package com.jd.blockchain.crypto.service.pki; import com.jd.blockchain.crypto.CryptoFunction; import com.jd.blockchain.crypto.CryptoService; +import com.jd.blockchain.provider.NamedProvider; import java.util.Arrays; import java.util.Collection; @@ -14,6 +15,7 @@ import java.util.List; * @description: TODO * @date 2019-05-15, 16:35 */ +@NamedProvider("PKI-SOFTWARE") public class PKICryptoService implements CryptoService { public static final SHA1WITHRSA2048SignatureFunction SHA1WITHRSA2048 = new SHA1WITHRSA2048SignatureFunction(); diff --git a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunction.java b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunction.java index 48e65765..297ba8bd 100644 --- a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunction.java +++ b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunction.java @@ -4,18 +4,16 @@ import com.jd.blockchain.crypto.*; import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; -import org.bouncycastle.jcajce.provider.asymmetric.rsa.BCRSAPrivateCrtKey; import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil; import org.bouncycastle.jce.provider.BouncyCastleProvider; -import sun.security.rsa.RSAPrivateCrtKeyImpl; -import sun.security.rsa.RSAPrivateKeyImpl; -import sun.security.rsa.RSAPublicKeyImpl; import java.math.BigInteger; import java.security.*; import java.security.interfaces.RSAPrivateCrtKey; -import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; import static com.jd.blockchain.crypto.BaseCryptoKey.KEY_TYPE_BYTES; import static com.jd.blockchain.crypto.CryptoBytes.ALGORYTHM_CODE_SIZE; @@ -53,16 +51,21 @@ public class SHA1WITHRSA2048SignatureFunction implements SignatureFunction { throw new CryptoException("This key is not SHA1WITHRSA2048 private key!"); } + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(rawPrivKeyBytes); + + KeyFactory keyFactory; RSAPrivateCrtKey rawPrivKey; Signature signer; byte[] signature; + try { - rawPrivKey = (RSAPrivateCrtKey) RSAPrivateCrtKeyImpl.newKey(rawPrivKeyBytes); + keyFactory = KeyFactory.getInstance("RSA"); + rawPrivKey = (RSAPrivateCrtKey) keyFactory.generatePrivate(keySpec); signer = Signature.getInstance("SHA1withRSA"); signer.initSign(rawPrivKey); signer.update(data); signature = signer.sign(); - } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) { + } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException | InvalidKeySpecException e) { throw new CryptoException(e.getMessage(), e); } @@ -86,17 +89,23 @@ public class SHA1WITHRSA2048SignatureFunction implements SignatureFunction { if (digest.getAlgorithm() != SHA1WITHRSA2048.code() || rawDigestBytes.length != RAW_SIGNATUREDIGEST_SIZE) { throw new CryptoException("This is not SHA1WITHRSA2048 signature digest!"); } - RSAPublicKeyImpl rawPubKey; + + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(rawPubKeyBytes); + + KeyFactory keyFactory; + RSAPublicKey rawPubKey; Signature verifier; - boolean isValid = false; + boolean isValid; + try { - rawPubKey = new RSAPublicKeyImpl(rawPubKeyBytes); + keyFactory = KeyFactory.getInstance("RSA"); + rawPubKey = (RSAPublicKey) keyFactory.generatePublic(keySpec); verifier = Signature.getInstance("SHA1withRSA"); verifier.initVerify(rawPubKey); verifier.update(data); isValid = verifier.verify(rawDigestBytes); - } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) { - e.printStackTrace(); + } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException | InvalidKeySpecException e) { + throw new CryptoException(e.getMessage(), e); } return isValid; @@ -146,14 +155,20 @@ public class SHA1WITHRSA2048SignatureFunction implements SignatureFunction { if (privKey.getAlgorithm() != SHA1WITHRSA2048.code()) { throw new CryptoException("This key is not SHA1WITHRSA2048 private key!"); } + + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(rawPrivKeyBytes); + + KeyFactory keyFactory; + RSAPrivateCrtKey rawPrivKey; byte[] rawPubKeyBytes; try { - RSAPrivateCrtKey rawPrivKey = (RSAPrivateCrtKey) RSAPrivateCrtKeyImpl.newKey(rawPrivKeyBytes); + keyFactory = KeyFactory.getInstance("RSA"); + rawPrivKey = (RSAPrivateCrtKey) keyFactory.generatePrivate(keySpec); BigInteger modulus = rawPrivKey.getModulus(); BigInteger exponent = rawPrivKey.getPublicExponent(); rawPubKeyBytes = KeyUtil.getEncodedSubjectPublicKeyInfo(RSA_ALGORITHM_IDENTIFIER, new org.bouncycastle.asn1.pkcs.RSAPublicKey(modulus, exponent)); - } catch (InvalidKeyException e) { + } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { throw new CryptoException(e.getMessage(), e); } diff --git a/source/crypto/crypto-pki/src/main/resources/services/com.jd.blockchain.crypto.CryptoService b/source/crypto/crypto-pki/src/main/resources/META-INF/services/com.jd.blockchain.crypto.CryptoService similarity index 100% rename from source/crypto/crypto-pki/src/main/resources/services/com.jd.blockchain.crypto.CryptoService rename to source/crypto/crypto-pki/src/main/resources/META-INF/services/com.jd.blockchain.crypto.CryptoService diff --git a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunctionTest.java b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunctionTest.java new file mode 100644 index 00000000..8b762ff9 --- /dev/null +++ b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunctionTest.java @@ -0,0 +1,273 @@ +package com.jd.blockchain.crypto.service.pki; + +import com.jd.blockchain.crypto.*; +import com.jd.blockchain.utils.io.BytesUtils; +import org.junit.Test; + +import java.util.Random; + +import static com.jd.blockchain.crypto.CryptoAlgorithm.*; +import static com.jd.blockchain.crypto.CryptoKeyType.PRIVATE; +import static com.jd.blockchain.crypto.CryptoKeyType.PUBLIC; +import static junit.framework.TestCase.assertNull; +import static org.junit.Assert.*; +import static org.junit.Assert.assertArrayEquals; + +/** + * @author zhanglin33 + * @title: SHA1WITHRSA2048SignatureFunctionTest + * @description: TODO + * @date 2019-05-16, 10:49 + */ +public class SHA1WITHRSA2048SignatureFunctionTest { + + @Test + public void getAlgorithmTest() { + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA2048"); + assertNotNull(algorithm); + + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + assertEquals(signatureFunction.getAlgorithm().name(), algorithm.name()); + assertEquals(signatureFunction.getAlgorithm().code(), algorithm.code()); + + algorithm = Crypto.getAlgorithm("SHA1withRsa2048"); + assertNotNull(algorithm); + + assertEquals(signatureFunction.getAlgorithm().name(), algorithm.name()); + assertEquals(signatureFunction.getAlgorithm().code(), algorithm.code()); + + algorithm = Crypto.getAlgorithm("rsa2048"); + assertNull(algorithm); + } + + @Test + public void generateKeyPairTest() { + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA2048"); + assertNotNull(algorithm); + + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); + + PubKey pubKey = keyPair.getPubKey(); + PrivKey privKey = keyPair.getPrivKey(); + + assertEquals(PUBLIC.CODE, pubKey.getKeyType().CODE); + assertTrue(pubKey.getRawKeyBytes().length > 259); + assertEquals(PRIVATE.CODE, privKey.getKeyType().CODE); + assertTrue(privKey.getRawKeyBytes().length > 1155); + + assertEquals(algorithm.code(), pubKey.getAlgorithm()); + assertEquals(algorithm.code(), privKey.getAlgorithm()); + + byte[] algoBytes = CryptoAlgorithm.getCodeBytes(algorithm); + byte[] pubKeyTypeBytes = new byte[] { PUBLIC.CODE }; + byte[] privKeyTypeBytes = new byte[] { PRIVATE.CODE }; + byte[] rawPubKeyBytes = pubKey.getRawKeyBytes(); + byte[] rawPrivKeyBytes = privKey.getRawKeyBytes(); + assertArrayEquals(BytesUtils.concat(algoBytes, pubKeyTypeBytes, rawPubKeyBytes), pubKey.toBytes()); + assertArrayEquals(BytesUtils.concat(algoBytes, privKeyTypeBytes, rawPrivKeyBytes), privKey.toBytes()); + } + + @Test + public void retrievePubKeyTest() { + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA2048"); + assertNotNull(algorithm); + + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); + + PubKey pubKey = keyPair.getPubKey(); + PrivKey privKey = keyPair.getPrivKey(); + + PubKey retrievedPubKey = signatureFunction.retrievePubKey(privKey); + + assertEquals(pubKey.getKeyType(), retrievedPubKey.getKeyType()); + assertEquals(pubKey.getRawKeyBytes().length, retrievedPubKey.getRawKeyBytes().length); + assertEquals(pubKey.getAlgorithm(), retrievedPubKey.getAlgorithm()); + assertArrayEquals(pubKey.toBytes(), retrievedPubKey.toBytes()); + } + + @Test + public void signTest() { + + byte[] data = new byte[1024]; + Random random = new Random(); + random.nextBytes(data); + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA2048"); + assertNotNull(algorithm); + + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); + + PrivKey privKey = keyPair.getPrivKey(); + SignatureDigest signatureDigest = signatureFunction.sign(privKey, data); + + byte[] signatureBytes = signatureDigest.toBytes(); + + assertEquals(2 + 256, signatureBytes.length); + assertEquals(algorithm.code(), signatureDigest.getAlgorithm()); + + assertEquals(PKIAlgorithm.SHA1WITHRSA2048.code(), signatureDigest.getAlgorithm()); + assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 31 & 0x00FF)), + signatureDigest.getAlgorithm()); + + byte[] algoBytes = BytesUtils.toBytes(signatureDigest.getAlgorithm()); + byte[] rawSinatureBytes = signatureDigest.getRawDigest(); + assertArrayEquals(BytesUtils.concat(algoBytes, rawSinatureBytes), signatureBytes); + } + + @Test + public void verifyTest() { + byte[] data = new byte[1024]; + Random random = new Random(); + random.nextBytes(data); + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA2048"); + assertNotNull(algorithm); + + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); + + PubKey pubKey = keyPair.getPubKey(); + PrivKey privKey = keyPair.getPrivKey(); + SignatureDigest signatureDigest = signatureFunction.sign(privKey, data); + + assertTrue(signatureFunction.verify(signatureDigest, pubKey, data)); + } + + @Test + public void supportPrivKeyTest() { + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA2048"); + assertNotNull(algorithm); + + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); + + PrivKey privKey = keyPair.getPrivKey(); + byte[] privKeyBytes = privKey.toBytes(); + + assertTrue(signatureFunction.supportPrivKey(privKeyBytes)); + } + + @Test + public void resolvePrivKeyTest() { + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA2048"); + assertNotNull(algorithm); + + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); + + PrivKey privKey = keyPair.getPrivKey(); + byte[] privKeyBytes = privKey.toBytes(); + + PrivKey resolvedPrivKey = signatureFunction.resolvePrivKey(privKeyBytes); + + assertEquals(PRIVATE.CODE, resolvedPrivKey.getKeyType().CODE); + assertEquals(PKIAlgorithm.SHA1WITHRSA2048.code(), resolvedPrivKey.getAlgorithm()); + assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 31 & 0x00FF)), + resolvedPrivKey.getAlgorithm()); + assertArrayEquals(privKeyBytes, resolvedPrivKey.toBytes()); + } + + @Test + public void supportPubKeyTest() { + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA2048"); + assertNotNull(algorithm); + + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); + + PubKey pubKey = keyPair.getPubKey(); + byte[] pubKeyBytes = pubKey.toBytes(); + + assertTrue(signatureFunction.supportPubKey(pubKeyBytes)); + } + + @Test + public void resolvePubKeyTest() { + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA2048"); + assertNotNull(algorithm); + + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); + + PubKey pubKey = keyPair.getPubKey(); + byte[] pubKeyBytes = pubKey.toBytes(); + + PubKey resolvedPubKey = signatureFunction.resolvePubKey(pubKeyBytes); + + assertEquals(PUBLIC.CODE, resolvedPubKey.getKeyType().CODE); + assertEquals(PKIAlgorithm.SHA1WITHRSA2048.code(), resolvedPubKey.getAlgorithm()); + assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 31 & 0x00FF)), + resolvedPubKey.getAlgorithm()); + assertArrayEquals(pubKeyBytes, resolvedPubKey.toBytes()); + } + + @Test + public void supportDigestTest() { + + byte[] data = new byte[1024]; + Random random = new Random(); + random.nextBytes(data); + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA2048"); + assertNotNull(algorithm); + + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); + + PrivKey privKey = keyPair.getPrivKey(); + + SignatureDigest signatureDigest = signatureFunction.sign(privKey, data); + + byte[] signatureDigestBytes = signatureDigest.toBytes(); + assertTrue(signatureFunction.supportDigest(signatureDigestBytes)); + } + + @Test + public void resolveDigestTest() { + + byte[] data = new byte[1024]; + Random random = new Random(); + random.nextBytes(data); + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA2048"); + assertNotNull(algorithm); + + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); + + PrivKey privKey = keyPair.getPrivKey(); + + SignatureDigest signatureDigest = signatureFunction.sign(privKey, data); + + byte[] signatureDigestBytes = signatureDigest.toBytes(); + + SignatureDigest resolvedSignatureDigest = signatureFunction.resolveDigest(signatureDigestBytes); + + assertEquals(256, resolvedSignatureDigest.getRawDigest().length); + assertEquals(PKIAlgorithm.SHA1WITHRSA2048.code(), resolvedSignatureDigest.getAlgorithm()); + assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 31 & 0x00FF)), + resolvedSignatureDigest.getAlgorithm()); + assertArrayEquals(signatureDigestBytes, resolvedSignatureDigest.toBytes()); + } +} diff --git a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CSRBuilderTest.java b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CSRBuilderTest.java index 382ecefe..d42c72f4 100644 --- a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CSRBuilderTest.java +++ b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CSRBuilderTest.java @@ -40,7 +40,6 @@ public class CSRBuilderTest { String csr = builder.buildRequest(countryName,stateName,cityName, organizationName,departmentName,domainName, emailName); - System.out.println(csr); PublicKey pubKey = builder.getPubKey(); PrivateKey privKey = builder.getPrivKey(); From de75122c6f45a4f638e42d650db82a01081608b8 Mon Sep 17 00:00:00 2001 From: zhaoguangwei Date: Thu, 16 May 2019 17:14:49 +0800 Subject: [PATCH 33/43] fix the interface: ledgers/xxx/settings --- .../transaction/ContractInvocationProxy.java | 47 +++++++++++++++---- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxy.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxy.java index c9b97e4d..00495bdb 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxy.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxy.java @@ -1,22 +1,53 @@ package com.jd.blockchain.transaction; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.serialize.binary.BinarySerializeUtils; + import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; -public class ContractInvocationProxy implements InvocationHandler { - - - private String contractMessage; - +public class ContractInvocationProxy implements InvocationHandler { + + // private String contractMessage; + + private Bytes contractAddress; + + private ContractType contractType; private ContractEventSendOperationBuilder sendOpBuilder; - - + + public ContractInvocationProxy(Bytes contractAddress, ContractType contractType, + ContractEventSendOperationBuilder sendOpBuilder) { + this.contractAddress = contractAddress; + this.contractType = contractType; + this.sendOpBuilder = sendOpBuilder; + } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - // TODO Auto-generated method stub + + if(contractType == null){ + return "contractType == null, no invoke really."; + } + + String event = contractType.getEvent(method); + if (event == null) { + // 适配 Object 对象的方法; + // toString 方法; + return String.format("[%s]-%s", contractAddress, contractType.toString()); + + // hashCode 方法; + } + // 合约方法; + byte[] argBytes = serializeArgs(args); + sendOpBuilder.send(contractAddress, event, argBytes); + + // TODO: 暂时未考虑有返回值的情况; return null; } + private byte[] serializeArgs(Object[] args) { + // TODO 根据方法参数的定义序列化参数; + return BinarySerializeUtils.serialize(args); + } } From 4061725dca8dab4013cfef6f5077366a4f9c9e90 Mon Sep 17 00:00:00 2001 From: zhanglin33 Date: Fri, 17 May 2019 14:47:27 +0800 Subject: [PATCH 34/43] SM3WITHSM2 and SHA1WITHRSA4096 in pki module have been completed --- .../pki/SHA1WITHRSA2048SignatureFunction.java | 1 - .../pki/SHA1WITHRSA4096SignatureFunction.java | 182 ++++++++++- .../pki/SM3WITHSM2SignatureFunction.java | 200 ++++++++++++- .../blockchain/crypto/utils/CSRBuilder.java | 20 +- .../SHA1WITHRSA4096SignatureFunctionTest.java | 197 ++++++++++++ .../pki/SM3WITHSM2SignatureFunctionTest.java | 274 +++++++++++++++++ .../crypto/utils/CSRBuilderTest.java | 283 +++++++++++++++++- .../crypto/utils/CertParserTest.java | 102 ++++++- 8 files changed, 1213 insertions(+), 46 deletions(-) create mode 100644 source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunctionTest.java create mode 100644 source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SM3WITHSM2SignatureFunctionTest.java diff --git a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunction.java b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunction.java index 297ba8bd..e8eafdad 100644 --- a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunction.java +++ b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunction.java @@ -29,7 +29,6 @@ import static com.jd.blockchain.crypto.service.pki.PKIAlgorithm.SHA1WITHRSA2048; */ public class SHA1WITHRSA2048SignatureFunction implements SignatureFunction { - private static final int RAW_PUBKEY_SIZE = 259; private static final int RAW_PRIVKEY_SIZE = 1155; diff --git a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunction.java b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunction.java index 2cde634b..486096bb 100644 --- a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunction.java +++ b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunction.java @@ -1,7 +1,24 @@ package com.jd.blockchain.crypto.service.pki; import com.jd.blockchain.crypto.*; +import org.bouncycastle.asn1.DERNull; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import java.math.BigInteger; +import java.security.*; +import java.security.interfaces.RSAPrivateCrtKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; + +import static com.jd.blockchain.crypto.BaseCryptoKey.KEY_TYPE_BYTES; +import static com.jd.blockchain.crypto.CryptoBytes.ALGORYTHM_CODE_SIZE; +import static com.jd.blockchain.crypto.CryptoKeyType.PRIVATE; +import static com.jd.blockchain.crypto.CryptoKeyType.PUBLIC; import static com.jd.blockchain.crypto.service.pki.PKIAlgorithm.SHA1WITHRSA4096; /** @@ -11,56 +28,191 @@ import static com.jd.blockchain.crypto.service.pki.PKIAlgorithm.SHA1WITHRSA4096; * @date 2019-05-15, 17:13 */ public class SHA1WITHRSA4096SignatureFunction implements SignatureFunction { + private static final int RAW_PUBKEY_SIZE = 515; + private static final int RAW_PRIVKEY_SIZE = 2307; + + private static final int RAW_SIGNATUREDIGEST_SIZE = 512; + + private static final AlgorithmIdentifier RSA_ALGORITHM_IDENTIFIER = + new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE); + @Override public SignatureDigest sign(PrivKey privKey, byte[] data) { - return null; + + byte[] rawPrivKeyBytes = privKey.getRawKeyBytes(); + + if (rawPrivKeyBytes.length < RAW_PRIVKEY_SIZE) { + throw new CryptoException("This key has wrong format!"); + } + + if (privKey.getAlgorithm() != SHA1WITHRSA4096.code()) { + throw new CryptoException("This key is not SHA1WITHRSA4096 private key!"); + } + + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(rawPrivKeyBytes); + + KeyFactory keyFactory; + RSAPrivateCrtKey rawPrivKey; + Signature signer; + byte[] signature; + + try { + keyFactory = KeyFactory.getInstance("RSA"); + rawPrivKey = (RSAPrivateCrtKey) keyFactory.generatePrivate(keySpec); + signer = Signature.getInstance("SHA1withRSA"); + signer.initSign(rawPrivKey); + signer.update(data); + signature = signer.sign(); + } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException | InvalidKeySpecException e) { + throw new CryptoException(e.getMessage(), e); + } + + return new SignatureDigest(SHA1WITHRSA4096, signature); } @Override public boolean verify(SignatureDigest digest, PubKey pubKey, byte[] data) { - return false; + + byte[] rawPubKeyBytes = pubKey.getRawKeyBytes(); + byte[] rawDigestBytes = digest.getRawDigest(); + + if (rawPubKeyBytes.length < RAW_PUBKEY_SIZE) { + throw new CryptoException("This key has wrong format!"); + } + + if (pubKey.getAlgorithm() != SHA1WITHRSA4096.code()) { + throw new CryptoException("This key is not SHA1WITHRSA4096 public key!"); + } + + if (digest.getAlgorithm() != SHA1WITHRSA4096.code() || rawDigestBytes.length != RAW_SIGNATUREDIGEST_SIZE) { + throw new CryptoException("This is not SHA1WITHRSA4096 signature digest!"); + } + + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(rawPubKeyBytes); + + KeyFactory keyFactory; + RSAPublicKey rawPubKey; + Signature verifier; + boolean isValid; + + try { + keyFactory = KeyFactory.getInstance("RSA"); + rawPubKey = (RSAPublicKey) keyFactory.generatePublic(keySpec); + verifier = Signature.getInstance("SHA1withRSA"); + verifier.initVerify(rawPubKey); + verifier.update(data); + isValid = verifier.verify(rawDigestBytes); + } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException | InvalidKeySpecException e) { + throw new CryptoException(e.getMessage(), e); + } + + return isValid; } @Override - public PubKey retrievePubKey(PrivKey privKey) { - return null; + public boolean supportPubKey(byte[] pubKeyBytes) { + return pubKeyBytes.length > (ALGORYTHM_CODE_SIZE + KEY_TYPE_BYTES + RAW_PUBKEY_SIZE) + && CryptoAlgorithm.match(SHA1WITHRSA4096, pubKeyBytes) + && pubKeyBytes[ALGORYTHM_CODE_SIZE] == PUBLIC.CODE; } @Override - public boolean supportPrivKey(byte[] privKeyBytes) { - return false; + public PubKey resolvePubKey(byte[] pubKeyBytes) { + if (supportPubKey(pubKeyBytes)) { + return new PubKey(pubKeyBytes); + } else { + throw new CryptoException("pubKeyBytes are invalid!"); + } } @Override - public PrivKey resolvePrivKey(byte[] privKeyBytes) { - return null; + public boolean supportPrivKey(byte[] privKeyBytes) { + return privKeyBytes.length > (ALGORYTHM_CODE_SIZE + KEY_TYPE_BYTES + RAW_PRIVKEY_SIZE) + && CryptoAlgorithm.match(SHA1WITHRSA4096, privKeyBytes) + && privKeyBytes[ALGORYTHM_CODE_SIZE] == PRIVATE.CODE; } @Override - public boolean supportPubKey(byte[] pubKeyBytes) { - return false; + public PrivKey resolvePrivKey(byte[] privKeyBytes) { + if (supportPrivKey(privKeyBytes)) { + return new PrivKey(privKeyBytes); + } else { + throw new CryptoException("privKeyBytes are invalid!"); + } } @Override - public PubKey resolvePubKey(byte[] pubKeyBytes) { - return null; + public PubKey retrievePubKey(PrivKey privKey) { + + byte[] rawPrivKeyBytes = privKey.getRawKeyBytes(); + + if (rawPrivKeyBytes.length < RAW_PRIVKEY_SIZE) { + throw new CryptoException("This key has wrong format!"); + } + + if (privKey.getAlgorithm() != SHA1WITHRSA4096.code()) { + throw new CryptoException("This key is not SHA1WITHRSA4096 private key!"); + } + + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(rawPrivKeyBytes); + + KeyFactory keyFactory; + RSAPrivateCrtKey rawPrivKey; + byte[] rawPubKeyBytes; + try { + keyFactory = KeyFactory.getInstance("RSA"); + rawPrivKey = (RSAPrivateCrtKey) keyFactory.generatePrivate(keySpec); + BigInteger modulus = rawPrivKey.getModulus(); + BigInteger exponent = rawPrivKey.getPublicExponent(); + rawPubKeyBytes = KeyUtil.getEncodedSubjectPublicKeyInfo(RSA_ALGORITHM_IDENTIFIER, + new org.bouncycastle.asn1.pkcs.RSAPublicKey(modulus, exponent)); + } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { + throw new CryptoException(e.getMessage(), e); + } + + return new PubKey(SHA1WITHRSA4096, rawPubKeyBytes); } @Override public boolean supportDigest(byte[] digestBytes) { - return false; + return digestBytes.length == (RAW_SIGNATUREDIGEST_SIZE + ALGORYTHM_CODE_SIZE) + && CryptoAlgorithm.match(SHA1WITHRSA4096, digestBytes); } @Override public SignatureDigest resolveDigest(byte[] digestBytes) { - return null; + if (supportDigest(digestBytes)) { + return new SignatureDigest(digestBytes); + } else { + throw new CryptoException("digestBytes are invalid!"); + } } @Override public AsymmetricKeypair generateKeypair() { - return null; + + Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); + KeyPairGenerator generator; + PublicKey pubKey; + PrivateKey privKey; + try { + generator = KeyPairGenerator.getInstance("RSA", BouncyCastleProvider.PROVIDER_NAME); + generator.initialize(4096); + KeyPair keyPair = generator.generateKeyPair(); + pubKey = keyPair.getPublic(); + privKey = keyPair.getPrivate(); + } catch (NoSuchAlgorithmException | NoSuchProviderException e) { + throw new CryptoException(e.getMessage(), e); + } + + byte[] pubKeyBytes = pubKey.getEncoded(); + byte[] privKeyBytes = privKey.getEncoded(); + + return new AsymmetricKeypair(new PubKey(SHA1WITHRSA4096, pubKeyBytes), + new PrivKey(SHA1WITHRSA4096, privKeyBytes)); } + @Override public CryptoAlgorithm getAlgorithm() { return SHA1WITHRSA4096; diff --git a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SM3WITHSM2SignatureFunction.java b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SM3WITHSM2SignatureFunction.java index 7bbea7a1..5b9978d7 100644 --- a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SM3WITHSM2SignatureFunction.java +++ b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/service/pki/SM3WITHSM2SignatureFunction.java @@ -1,7 +1,27 @@ package com.jd.blockchain.crypto.service.pki; import com.jd.blockchain.crypto.*; +import org.bouncycastle.asn1.gm.GMObjectIdentifiers; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; +import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.jce.spec.ECNamedCurveGenParameterSpec; +import org.bouncycastle.math.ec.ECPoint; +import org.bouncycastle.math.ec.custom.gm.SM2P256V1Curve; +import java.math.BigInteger; +import java.security.*; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; + +import static com.jd.blockchain.crypto.BaseCryptoKey.KEY_TYPE_BYTES; +import static com.jd.blockchain.crypto.CryptoBytes.ALGORYTHM_CODE_SIZE; +import static com.jd.blockchain.crypto.CryptoKeyType.PRIVATE; +import static com.jd.blockchain.crypto.CryptoKeyType.PUBLIC; import static com.jd.blockchain.crypto.service.pki.PKIAlgorithm.SM3WITHSM2; /** @@ -11,56 +31,204 @@ import static com.jd.blockchain.crypto.service.pki.PKIAlgorithm.SM3WITHSM2; * @date 2019-05-15, 16:39 */ public class SM3WITHSM2SignatureFunction implements SignatureFunction { + private static final int RAW_PUBKEY_SIZE = 65; + private static final int RAW_PRIVKEY_SIZE = 32 + 65; + + private static final int RAW_SIGNATUREDIGEST_SIZE = 64; + + private static final SM2P256V1Curve CURVE = new SM2P256V1Curve(); + private static final BigInteger GX = new BigInteger("32C4AE2C1F1981195F9904466A39C994" + + "8FE30BBFF2660BE1715A4589334C74C7", 16); + private static final BigInteger GY = new BigInteger("BC3736A2F4F6779C59BDCEE36B692153" + + "D0A9877CC62A474002DF32E52139F0A0", 16); + private static final ECPoint G = CURVE.createPoint(GX, GY); + + private static final AlgorithmIdentifier SM2_ALGORITHM_IDENTIFIER = new AlgorithmIdentifier( + X9ObjectIdentifiers.id_ecPublicKey, GMObjectIdentifiers.sm2p256v1); + + @Override public SignatureDigest sign(PrivKey privKey, byte[] data) { - return null; + + Security.addProvider(new BouncyCastleProvider()); + + byte[] rawPrivKeyBytes = privKey.getRawKeyBytes(); + + if (rawPrivKeyBytes.length < RAW_PRIVKEY_SIZE) { + throw new CryptoException("This key has wrong format!"); + } + + if (privKey.getAlgorithm() != SM3WITHSM2.code()) { + throw new CryptoException("This key is not SM3WITHSM2 private key!"); + } + + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(rawPrivKeyBytes); + + KeyFactory keyFactory; + ECPrivateKey rawPrivKey; + Signature signer; + byte[] signature; + + try { + keyFactory = KeyFactory.getInstance("EC", BouncyCastleProvider.PROVIDER_NAME); + rawPrivKey = (ECPrivateKey) keyFactory.generatePrivate(keySpec); + signer = Signature.getInstance("SM3withSM2", BouncyCastleProvider.PROVIDER_NAME); + + signer.initSign(rawPrivKey); + signer.update(data); + signature = signer.sign(); + } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException | + InvalidKeySpecException | NoSuchProviderException e) { + throw new CryptoException(e.getMessage(), e); + } + + return new SignatureDigest(SM3WITHSM2, signature); } @Override public boolean verify(SignatureDigest digest, PubKey pubKey, byte[] data) { - return false; + + Security.addProvider(new BouncyCastleProvider()); + + byte[] rawPubKeyBytes = pubKey.getRawKeyBytes(); + byte[] rawDigestBytes = digest.getRawDigest(); + + if (rawPubKeyBytes.length < RAW_PUBKEY_SIZE) { + throw new CryptoException("This key has wrong format!"); + } + + if (pubKey.getAlgorithm() != SM3WITHSM2.code()) { + throw new CryptoException("This key is not SM3WITHSM2 public key!"); + } + + if (digest.getAlgorithm() != SM3WITHSM2.code() || rawDigestBytes.length < RAW_SIGNATUREDIGEST_SIZE) { + throw new CryptoException("This is not SM3WITHSM2 signature digest!"); + } + + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(rawPubKeyBytes); + + KeyFactory keyFactory; + ECPublicKey rawPubKey; + Signature verifier; + boolean isValid; + + try { + keyFactory = KeyFactory.getInstance("EC", BouncyCastleProvider.PROVIDER_NAME); + rawPubKey = (ECPublicKey) keyFactory.generatePublic(keySpec); + verifier = Signature.getInstance("SM3withSM2", BouncyCastleProvider.PROVIDER_NAME); + verifier.initVerify(rawPubKey); + verifier.update(data); + isValid = verifier.verify(rawDigestBytes); + } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException | InvalidKeySpecException + | NoSuchProviderException e) { + throw new CryptoException(e.getMessage(), e); + } + + return isValid; } @Override - public PubKey retrievePubKey(PrivKey privKey) { - return null; + public boolean supportPubKey(byte[] pubKeyBytes) { + return pubKeyBytes.length > (ALGORYTHM_CODE_SIZE + KEY_TYPE_BYTES + RAW_PUBKEY_SIZE) + && CryptoAlgorithm.match(SM3WITHSM2, pubKeyBytes) + && pubKeyBytes[ALGORYTHM_CODE_SIZE] == PUBLIC.CODE; } @Override - public boolean supportPrivKey(byte[] privKeyBytes) { - return false; + public PubKey resolvePubKey(byte[] pubKeyBytes) { + if (supportPubKey(pubKeyBytes)) { + return new PubKey(pubKeyBytes); + } else { + throw new CryptoException("pubKeyBytes are invalid!"); + } } @Override - public PrivKey resolvePrivKey(byte[] privKeyBytes) { - return null; + public boolean supportPrivKey(byte[] privKeyBytes) { + return privKeyBytes.length > (ALGORYTHM_CODE_SIZE + KEY_TYPE_BYTES + RAW_PRIVKEY_SIZE) + && CryptoAlgorithm.match(SM3WITHSM2, privKeyBytes) + && privKeyBytes[ALGORYTHM_CODE_SIZE] == PRIVATE.CODE; } @Override - public boolean supportPubKey(byte[] pubKeyBytes) { - return false; + public PrivKey resolvePrivKey(byte[] privKeyBytes) { + if (supportPrivKey(privKeyBytes)) { + return new PrivKey(privKeyBytes); + } else { + throw new CryptoException("privKeyBytes are invalid!"); + } } @Override - public PubKey resolvePubKey(byte[] pubKeyBytes) { - return null; + public PubKey retrievePubKey(PrivKey privKey) { + + byte[] rawPrivKeyBytes = privKey.getRawKeyBytes(); + + if (rawPrivKeyBytes.length < RAW_PRIVKEY_SIZE) { + throw new CryptoException("This key has wrong format!"); + } + + if (privKey.getAlgorithm() != SM3WITHSM2.code()) { + throw new CryptoException("This key is not SM3WITHSM2 private key!"); + } + + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(rawPrivKeyBytes); + + KeyFactory keyFactory; + ECPrivateKey rawPrivKey; + byte[] rawPubKeyBytes; + try { + keyFactory = KeyFactory.getInstance("EC", BouncyCastleProvider.PROVIDER_NAME); + rawPrivKey = (ECPrivateKey) keyFactory.generatePrivate(keySpec); + BigInteger d = rawPrivKey.getS(); + ECPoint Q = G.multiply(d).normalize(); + rawPubKeyBytes = KeyUtil.getEncodedSubjectPublicKeyInfo(SM2_ALGORITHM_IDENTIFIER, + Q.getEncoded(false)); + } catch (NoSuchAlgorithmException | InvalidKeySpecException | NoSuchProviderException e) { + throw new CryptoException(e.getMessage(), e); + } + + return new PubKey(SM3WITHSM2, rawPubKeyBytes); } @Override public boolean supportDigest(byte[] digestBytes) { - return false; + return digestBytes.length > (RAW_SIGNATUREDIGEST_SIZE + ALGORYTHM_CODE_SIZE) + && CryptoAlgorithm.match(SM3WITHSM2, digestBytes); } @Override public SignatureDigest resolveDigest(byte[] digestBytes) { - return null; + if (supportDigest(digestBytes)) { + return new SignatureDigest(digestBytes); + } else { + throw new CryptoException("digestBytes are invalid!"); + } } @Override public AsymmetricKeypair generateKeypair() { - return null; - } + Security.addProvider(new BouncyCastleProvider()); + KeyPairGenerator generator; + PublicKey pubKey; + PrivateKey privKey; + try { + generator = KeyPairGenerator.getInstance("EC", BouncyCastleProvider.PROVIDER_NAME); + generator.initialize(new ECNamedCurveGenParameterSpec("sm2p256v1")); + KeyPair keyPair = generator.generateKeyPair(); + pubKey = keyPair.getPublic(); + privKey = keyPair.getPrivate(); + } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) { + throw new CryptoException(e.getMessage(), e); + } + + byte[] pubKeyBytes = pubKey.getEncoded(); + byte[] privKeyBytes = privKey.getEncoded(); + + return new AsymmetricKeypair(new PubKey(SM3WITHSM2, pubKeyBytes), + new PrivKey(SM3WITHSM2, privKeyBytes)); + } @Override public CryptoAlgorithm getAlgorithm() { return SM3WITHSM2; diff --git a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CSRBuilder.java b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CSRBuilder.java index 6659134b..790cb7db 100644 --- a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CSRBuilder.java +++ b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CSRBuilder.java @@ -14,7 +14,6 @@ import org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder; import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder; import org.bouncycastle.util.encoders.Base64; - import java.io.IOException; import java.security.*; @@ -65,17 +64,24 @@ public class CSRBuilder { keyPair = generator.generateKeyPair(); pubKey = keyPair.getPublic(); privKey = keyPair.getPrivate(); + break; } case "SM2": { generator = KeyPairGenerator.getInstance("EC", BC); + if (KeyLength != 256) { + throw new CryptoException("SM3withSM2 with unsupported key length [" + + KeyLength +"] in CSR!"); + } generator.initialize(new ECNamedCurveGenParameterSpec("sm2p256v1")); keyPair = generator.generateKeyPair(); pubKey = keyPair.getPublic(); privKey = keyPair.getPrivate(); + break; } - default: throw new CryptoException("Unsupported key algorithm[" + algoName + "] in CSR!"); + default: throw new CryptoException("Unsupported algorithm [" + algoName + "] with key length [" + + KeyLength +"] in CSR!"); } } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) { throw new CryptoException(e.getMessage(), e); @@ -86,7 +92,7 @@ public class CSRBuilder { String organizationName, String departmentName, String domainName, String emailName) { - String result = null; + String result; X500NameBuilder nameBuilder = new X500NameBuilder(BCStrictStyle.INSTANCE); nameBuilder.addRDN(BCStyle.C, countryName); // a country name, and China is short as CN @@ -120,12 +126,4 @@ public class CSRBuilder { public PrivateKey getPrivKey() { return privKey; } - - public byte[] getPubKeyBytes() { - return pubKey.getEncoded(); - } - - public byte[] getPrivKeyBytes() { - return privKey.getEncoded(); - } } diff --git a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunctionTest.java b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunctionTest.java new file mode 100644 index 00000000..9ab2ac7c --- /dev/null +++ b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunctionTest.java @@ -0,0 +1,197 @@ +package com.jd.blockchain.crypto.service.pki; + +import com.jd.blockchain.crypto.*; +import com.jd.blockchain.utils.io.BytesUtils; +import org.junit.Test; + +import java.util.Random; + +import static com.jd.blockchain.crypto.CryptoAlgorithm.ASYMMETRIC_KEY; +import static com.jd.blockchain.crypto.CryptoAlgorithm.SIGNATURE_ALGORITHM; +import static com.jd.blockchain.crypto.CryptoKeyType.PRIVATE; +import static com.jd.blockchain.crypto.CryptoKeyType.PUBLIC; +import static junit.framework.TestCase.assertNull; +import static org.junit.Assert.*; + +/** + * @author zhanglin33 + * @title: SHA1WITHRSA4096SignatureFunctionTest + * @description: TODO + * @date 2019-05-16, 10:49 + */ +public class SHA1WITHRSA4096SignatureFunctionTest { + + private AsymmetricKeypair keyPair = Crypto.getSignatureFunction(Crypto.getAlgorithm("SHA1WITHRSA4096")). + generateKeypair(); + + @Test + public void getAlgorithmTest() { + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA4096"); + assertNotNull(algorithm); + + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + assertEquals(signatureFunction.getAlgorithm().name(), algorithm.name()); + assertEquals(signatureFunction.getAlgorithm().code(), algorithm.code()); + + algorithm = Crypto.getAlgorithm("SHA1withRsa4096"); + assertNotNull(algorithm); + + assertEquals(signatureFunction.getAlgorithm().name(), algorithm.name()); + assertEquals(signatureFunction.getAlgorithm().code(), algorithm.code()); + + algorithm = Crypto.getAlgorithm("rsa2048"); + assertNull(algorithm); + } + + @Test + public void generateKeyPairTest() { + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA4096"); + assertNotNull(algorithm); + + PubKey pubKey = keyPair.getPubKey(); + PrivKey privKey = keyPair.getPrivKey(); + + assertEquals(PUBLIC.CODE, pubKey.getKeyType().CODE); + assertTrue(pubKey.getRawKeyBytes().length > 515); + assertEquals(PRIVATE.CODE, privKey.getKeyType().CODE); + assertTrue(privKey.getRawKeyBytes().length > 2307); + + assertEquals(algorithm.code(), pubKey.getAlgorithm()); + assertEquals(algorithm.code(), privKey.getAlgorithm()); + + byte[] algoBytes = CryptoAlgorithm.getCodeBytes(algorithm); + byte[] pubKeyTypeBytes = new byte[] { PUBLIC.CODE }; + byte[] privKeyTypeBytes = new byte[] { PRIVATE.CODE }; + byte[] rawPubKeyBytes = pubKey.getRawKeyBytes(); + byte[] rawPrivKeyBytes = privKey.getRawKeyBytes(); + assertArrayEquals(BytesUtils.concat(algoBytes, pubKeyTypeBytes, rawPubKeyBytes), pubKey.toBytes()); + assertArrayEquals(BytesUtils.concat(algoBytes, privKeyTypeBytes, rawPrivKeyBytes), privKey.toBytes()); + } + + @Test + public void retrievePubKeyTest() { + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA4096"); + assertNotNull(algorithm); + + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + PubKey pubKey = keyPair.getPubKey(); + PrivKey privKey = keyPair.getPrivKey(); + + PubKey retrievedPubKey = signatureFunction.retrievePubKey(privKey); + + assertEquals(pubKey.getKeyType(), retrievedPubKey.getKeyType()); + assertEquals(pubKey.getRawKeyBytes().length, retrievedPubKey.getRawKeyBytes().length); + assertEquals(pubKey.getAlgorithm(), retrievedPubKey.getAlgorithm()); + assertArrayEquals(pubKey.toBytes(), retrievedPubKey.toBytes()); + } + + @Test + public void signAndVerifyTest() { + + byte[] data = new byte[1024]; + Random random = new Random(); + random.nextBytes(data); + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA4096"); + assertNotNull(algorithm); + + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + PrivKey privKey = keyPair.getPrivKey(); + PubKey pubKey = keyPair.getPubKey(); + + SignatureDigest signatureDigest = signatureFunction.sign(privKey, data); + + byte[] signatureBytes = signatureDigest.toBytes(); + + assertEquals(2 + 512, signatureBytes.length); + assertEquals(algorithm.code(), signatureDigest.getAlgorithm()); + + assertEquals(PKIAlgorithm.SHA1WITHRSA4096.code(), signatureDigest.getAlgorithm()); + assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 32 & 0x00FF)), + signatureDigest.getAlgorithm()); + + byte[] algoBytes = BytesUtils.toBytes(signatureDigest.getAlgorithm()); + byte[] rawSinatureBytes = signatureDigest.getRawDigest(); + assertArrayEquals(BytesUtils.concat(algoBytes, rawSinatureBytes), signatureBytes); + + assertTrue(signatureFunction.verify(signatureDigest, pubKey, data)); + } + + @Test + public void supportAndResolvePrivKeyTest() { + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA4096"); + assertNotNull(algorithm); + + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + PrivKey privKey = keyPair.getPrivKey(); + byte[] privKeyBytes = privKey.toBytes(); + + assertTrue(signatureFunction.supportPrivKey(privKeyBytes)); + + PrivKey resolvedPrivKey = signatureFunction.resolvePrivKey(privKeyBytes); + + assertEquals(PRIVATE.CODE, resolvedPrivKey.getKeyType().CODE); + assertEquals(PKIAlgorithm.SHA1WITHRSA4096.code(), resolvedPrivKey.getAlgorithm()); + assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 32 & 0x00FF)), + resolvedPrivKey.getAlgorithm()); + assertArrayEquals(privKeyBytes, resolvedPrivKey.toBytes()); + } + + @Test + public void supportAndResolvePubKeyTest() { + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA4096"); + assertNotNull(algorithm); + + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + PubKey pubKey = keyPair.getPubKey(); + byte[] pubKeyBytes = pubKey.toBytes(); + + assertTrue(signatureFunction.supportPubKey(pubKeyBytes)); + + PubKey resolvedPubKey = signatureFunction.resolvePubKey(pubKeyBytes); + + assertEquals(PUBLIC.CODE, resolvedPubKey.getKeyType().CODE); + assertEquals(PKIAlgorithm.SHA1WITHRSA4096.code(), resolvedPubKey.getAlgorithm()); + assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 32 & 0x00FF)), + resolvedPubKey.getAlgorithm()); + assertArrayEquals(pubKeyBytes, resolvedPubKey.toBytes()); + } + + @Test + public void supportAndResolveDigestTest() { + + byte[] data = new byte[1024]; + Random random = new Random(); + random.nextBytes(data); + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA4096"); + assertNotNull(algorithm); + + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + PrivKey privKey = keyPair.getPrivKey(); + + SignatureDigest signatureDigest = signatureFunction.sign(privKey, data); + + byte[] signatureDigestBytes = signatureDigest.toBytes(); + assertTrue(signatureFunction.supportDigest(signatureDigestBytes)); + + SignatureDigest resolvedSignatureDigest = signatureFunction.resolveDigest(signatureDigestBytes); + + assertEquals(512, resolvedSignatureDigest.getRawDigest().length); + assertEquals(PKIAlgorithm.SHA1WITHRSA4096.code(), resolvedSignatureDigest.getAlgorithm()); + assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 32 & 0x00FF)), + resolvedSignatureDigest.getAlgorithm()); + assertArrayEquals(signatureDigestBytes, resolvedSignatureDigest.toBytes()); + } +} diff --git a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SM3WITHSM2SignatureFunctionTest.java b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SM3WITHSM2SignatureFunctionTest.java new file mode 100644 index 00000000..c9fa8311 --- /dev/null +++ b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SM3WITHSM2SignatureFunctionTest.java @@ -0,0 +1,274 @@ +package com.jd.blockchain.crypto.service.pki; + +import com.jd.blockchain.crypto.*; +import com.jd.blockchain.utils.io.BytesUtils; +import org.junit.Test; + +import java.util.Random; + +import static com.jd.blockchain.crypto.CryptoAlgorithm.ASYMMETRIC_KEY; +import static com.jd.blockchain.crypto.CryptoAlgorithm.SIGNATURE_ALGORITHM; +import static com.jd.blockchain.crypto.CryptoKeyType.PRIVATE; +import static com.jd.blockchain.crypto.CryptoKeyType.PUBLIC; +import static junit.framework.TestCase.assertNull; +import static org.junit.Assert.*; + +/** + * @author zhanglin33 + * @title: SM3WITHSM2SignatureFunctionTest + * @description: TODO + * @date 2019-05-16, 17:04 + */ +public class SM3WITHSM2SignatureFunctionTest { + + @Test + public void getAlgorithmTest() { + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SM3WITHSM2"); + assertNotNull(algorithm); + + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + assertEquals(signatureFunction.getAlgorithm().name(), algorithm.name()); + assertEquals(signatureFunction.getAlgorithm().code(), algorithm.code()); + + algorithm = Crypto.getAlgorithm("sm3withsm2"); + assertNotNull(algorithm); + + assertEquals(signatureFunction.getAlgorithm().name(), algorithm.name()); + assertEquals(signatureFunction.getAlgorithm().code(), algorithm.code()); + + algorithm = Crypto.getAlgorithm("sm3withs"); + assertNull(algorithm); + } + + @Test + public void generateKeyPairTest() { + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SM3WITHSM2"); + assertNotNull(algorithm); + + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); + + PubKey pubKey = keyPair.getPubKey(); + PrivKey privKey = keyPair.getPrivKey(); + + assertEquals(PUBLIC.CODE, pubKey.getKeyType().CODE); + assertTrue(pubKey.getRawKeyBytes().length > 32); + assertEquals(PRIVATE.CODE, privKey.getKeyType().CODE); + assertTrue(privKey.getRawKeyBytes().length > 65 + 32); + + assertEquals(algorithm.code(), pubKey.getAlgorithm()); + assertEquals(algorithm.code(), privKey.getAlgorithm()); + + byte[] algoBytes = CryptoAlgorithm.getCodeBytes(algorithm); + byte[] pubKeyTypeBytes = new byte[] { PUBLIC.CODE }; + byte[] privKeyTypeBytes = new byte[] { PRIVATE.CODE }; + byte[] rawPubKeyBytes = pubKey.getRawKeyBytes(); + byte[] rawPrivKeyBytes = privKey.getRawKeyBytes(); + assertArrayEquals(BytesUtils.concat(algoBytes, pubKeyTypeBytes, rawPubKeyBytes), pubKey.toBytes()); + assertArrayEquals(BytesUtils.concat(algoBytes, privKeyTypeBytes, rawPrivKeyBytes), privKey.toBytes()); + } + + @Test + public void retrievePubKeyTest() { + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SM3WITHSM2"); + assertNotNull(algorithm); + + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); + + PubKey pubKey = keyPair.getPubKey(); + PrivKey privKey = keyPair.getPrivKey(); + + PubKey retrievedPubKey = signatureFunction.retrievePubKey(privKey); + + assertEquals(pubKey.getKeyType(), retrievedPubKey.getKeyType()); + assertEquals(pubKey.getRawKeyBytes().length, retrievedPubKey.getRawKeyBytes().length); + assertEquals(pubKey.getAlgorithm(), retrievedPubKey.getAlgorithm()); + assertArrayEquals(pubKey.toBytes(), retrievedPubKey.toBytes()); + } + + @Test + public void signTest() { + + byte[] data = new byte[1024]; + Random random = new Random(); + random.nextBytes(data); + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SM3WITHSM2"); + assertNotNull(algorithm); + + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); + + PrivKey privKey = keyPair.getPrivKey(); + SignatureDigest signatureDigest = signatureFunction.sign(privKey, data); + + byte[] signatureBytes = signatureDigest.toBytes(); + + assertTrue(signatureBytes.length > 2 + 64); + assertEquals(algorithm.code(), signatureDigest.getAlgorithm()); + + assertEquals(PKIAlgorithm.SM3WITHSM2.code(), signatureDigest.getAlgorithm()); + assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 33 & 0x00FF)), + signatureDigest.getAlgorithm()); + + byte[] algoBytes = BytesUtils.toBytes(signatureDigest.getAlgorithm()); + byte[] rawSinatureBytes = signatureDigest.getRawDigest(); + assertArrayEquals(BytesUtils.concat(algoBytes, rawSinatureBytes), signatureBytes); + } + + @Test + public void verifyTest() { + byte[] data = new byte[1024]; + Random random = new Random(); + random.nextBytes(data); + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SM3WITHSM2"); + assertNotNull(algorithm); + + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); + + PubKey pubKey = keyPair.getPubKey(); + PrivKey privKey = keyPair.getPrivKey(); + SignatureDigest signatureDigest = signatureFunction.sign(privKey, data); + + System.out.println(signatureDigest.getRawDigest().length); + assertTrue(signatureFunction.verify(signatureDigest, pubKey, data)); + } + + @Test + public void supportPrivKeyTest() { + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SM3WITHSM2"); + assertNotNull(algorithm); + + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); + + PrivKey privKey = keyPair.getPrivKey(); + byte[] privKeyBytes = privKey.toBytes(); + + assertTrue(signatureFunction.supportPrivKey(privKeyBytes)); + } + + @Test + public void resolvePrivKeyTest() { + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SM3WITHSM2"); + assertNotNull(algorithm); + + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); + + PrivKey privKey = keyPair.getPrivKey(); + byte[] privKeyBytes = privKey.toBytes(); + + PrivKey resolvedPrivKey = signatureFunction.resolvePrivKey(privKeyBytes); + + assertEquals(PRIVATE.CODE, resolvedPrivKey.getKeyType().CODE); + assertEquals(PKIAlgorithm.SM3WITHSM2.code(), resolvedPrivKey.getAlgorithm()); + assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 33 & 0x00FF)), + resolvedPrivKey.getAlgorithm()); + assertArrayEquals(privKeyBytes, resolvedPrivKey.toBytes()); + } + + @Test + public void supportPubKeyTest() { + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SM3WITHSM2"); + assertNotNull(algorithm); + + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); + + PubKey pubKey = keyPair.getPubKey(); + byte[] pubKeyBytes = pubKey.toBytes(); + + assertTrue(signatureFunction.supportPubKey(pubKeyBytes)); + } + + @Test + public void resolvePubKeyTest() { + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SM3WITHSM2"); + assertNotNull(algorithm); + + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); + + PubKey pubKey = keyPair.getPubKey(); + byte[] pubKeyBytes = pubKey.toBytes(); + + PubKey resolvedPubKey = signatureFunction.resolvePubKey(pubKeyBytes); + + assertEquals(PUBLIC.CODE, resolvedPubKey.getKeyType().CODE); + assertEquals(PKIAlgorithm.SM3WITHSM2.code(), resolvedPubKey.getAlgorithm()); + assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 33 & 0x00FF)), + resolvedPubKey.getAlgorithm()); + assertArrayEquals(pubKeyBytes, resolvedPubKey.toBytes()); + } + + @Test + public void supportDigestTest() { + + byte[] data = new byte[1024]; + Random random = new Random(); + random.nextBytes(data); + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SM3WITHSM2"); + assertNotNull(algorithm); + + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); + + PrivKey privKey = keyPair.getPrivKey(); + + SignatureDigest signatureDigest = signatureFunction.sign(privKey, data); + + byte[] signatureDigestBytes = signatureDigest.toBytes(); + assertTrue(signatureFunction.supportDigest(signatureDigestBytes)); + } + + @Test + public void resolveDigestTest() { + + byte[] data = new byte[1024]; + Random random = new Random(); + random.nextBytes(data); + + CryptoAlgorithm algorithm = Crypto.getAlgorithm("SM3WITHSM2"); + assertNotNull(algorithm); + + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); + + PrivKey privKey = keyPair.getPrivKey(); + + SignatureDigest signatureDigest = signatureFunction.sign(privKey, data); + + byte[] signatureDigestBytes = signatureDigest.toBytes(); + + SignatureDigest resolvedSignatureDigest = signatureFunction.resolveDigest(signatureDigestBytes); + + assertTrue(resolvedSignatureDigest.getRawDigest().length > 64); + assertEquals(PKIAlgorithm.SM3WITHSM2.code(), resolvedSignatureDigest.getAlgorithm()); + assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 33 & 0x00FF)), + resolvedSignatureDigest.getAlgorithm()); + assertArrayEquals(signatureDigestBytes, resolvedSignatureDigest.toBytes()); + } +} diff --git a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CSRBuilderTest.java b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CSRBuilderTest.java index d42c72f4..f309ff52 100644 --- a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CSRBuilderTest.java +++ b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CSRBuilderTest.java @@ -1,6 +1,5 @@ package com.jd.blockchain.crypto.utils; -import com.jd.blockchain.crypto.utils.CSRBuilder; import org.bouncycastle.asn1.ASN1Encoding; import org.bouncycastle.asn1.DERSet; import org.bouncycastle.asn1.pkcs.CertificationRequestInfo; @@ -112,4 +111,286 @@ public class CSRBuilderTest { } assertTrue(isValid); } + + @Test + public void SHA1withRSA2048CSRTest(){ + + String countryName = "CN"; + String stateName = "Beijing"; + String cityName = "Beijing"; + String organizationName = "JD.com"; + String departmentName = "Blockchain Department"; + String domainName = "ledger.jd.com"; + String emailName = "zhanglin33@jd.com"; + + CSRBuilder builder = new CSRBuilder(); + + builder.init("SHA1withRSA",2048); + String csr = builder.buildRequest(countryName,stateName,cityName, + organizationName,departmentName,domainName, + emailName); + + PublicKey pubKey = builder.getPubKey(); + PrivateKey privKey = builder.getPrivKey(); + + byte[] crsBytes = Base64.decode(csr); + PKCS10CertificationRequest request = null; + try { + request = new PKCS10CertificationRequest(crsBytes); + } catch (IOException e) { + e.printStackTrace(); + } + assertNotNull(request); + assertEquals("1.2.840.113549.1.1.5",request.getSignatureAlgorithm().getAlgorithm().getId()); + byte[] pubKeyBytes = new byte[0]; + try { + pubKeyBytes = request.getSubjectPublicKeyInfo().getEncoded(); + } catch (IOException e) { + e.printStackTrace(); + } + assertArrayEquals(pubKeyBytes,pubKey.getEncoded()); + + RDN[] rdns = request.getSubject().getRDNs(); + assertEquals(BCStyle.C, rdns[0].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.ST, rdns[1].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.L, rdns[2].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.O, rdns[3].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.OU, rdns[4].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.CN, rdns[5].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.E, rdns[6].getFirst().getType().toASN1Primitive()); + + assertEquals("CN", rdns[0].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("Beijing", rdns[1].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("Beijing", rdns[2].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("JD.com", rdns[3].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("Blockchain Department", rdns[4].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("ledger.jd.com", rdns[5].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("zhanglin33@jd.com", rdns[6].getFirst().getValue().toASN1Primitive().toString()); + + byte[] signature = request.getSignature(); + + CertificationRequestInfo requestInfo = new CertificationRequestInfo(request.getSubject(),request.getSubjectPublicKeyInfo(),new DERSet()); + byte[] message = new byte[0]; + try { + message = requestInfo.getEncoded(ASN1Encoding.DER); + } catch (IOException e) { + e.printStackTrace(); + } + + Signature signer; + byte[] result = new byte[0]; + try { + signer = Signature.getInstance("SHA1withRSA"); + signer.initSign(privKey); + signer.update(message); + result = signer.sign(); + } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) { + e.printStackTrace(); + } + assertArrayEquals(result,signature); + + Signature verifier; + boolean isValid = false; + try { + verifier = Signature.getInstance("SHA1withRSA"); + verifier.initVerify(pubKey); + verifier.update(message); + isValid = verifier.verify(signature); + } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) { + e.printStackTrace(); + } + assertTrue(isValid); + } + + + @Test + public void SHA1withRSA4096CSRTest(){ + + String countryName = "CN"; + String stateName = "Beijing"; + String cityName = "Beijing"; + String organizationName = "JD.com"; + String departmentName = "Blockchain Department"; + String domainName = "ledger.jd.com"; + String emailName = "zhanglin33@jd.com"; + + CSRBuilder builder = new CSRBuilder(); + + builder.init("SHA1withRSA",4096); + String csr = builder.buildRequest(countryName,stateName,cityName, + organizationName,departmentName,domainName, + emailName); + + PublicKey pubKey = builder.getPubKey(); + PrivateKey privKey = builder.getPrivKey(); + + byte[] crsBytes = Base64.decode(csr); + PKCS10CertificationRequest request = null; + try { + request = new PKCS10CertificationRequest(crsBytes); + } catch (IOException e) { + e.printStackTrace(); + } + assertNotNull(request); + assertEquals("1.2.840.113549.1.1.5",request.getSignatureAlgorithm().getAlgorithm().getId()); + byte[] pubKeyBytes = new byte[0]; + try { + pubKeyBytes = request.getSubjectPublicKeyInfo().getEncoded(); + } catch (IOException e) { + e.printStackTrace(); + } + assertArrayEquals(pubKeyBytes,pubKey.getEncoded()); + + RDN[] rdns = request.getSubject().getRDNs(); + assertEquals(BCStyle.C, rdns[0].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.ST, rdns[1].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.L, rdns[2].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.O, rdns[3].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.OU, rdns[4].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.CN, rdns[5].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.E, rdns[6].getFirst().getType().toASN1Primitive()); + + assertEquals("CN", rdns[0].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("Beijing", rdns[1].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("Beijing", rdns[2].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("JD.com", rdns[3].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("Blockchain Department", rdns[4].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("ledger.jd.com", rdns[5].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("zhanglin33@jd.com", rdns[6].getFirst().getValue().toASN1Primitive().toString()); + + byte[] signature = request.getSignature(); + + CertificationRequestInfo requestInfo = new CertificationRequestInfo(request.getSubject(),request.getSubjectPublicKeyInfo(),new DERSet()); + byte[] message = new byte[0]; + try { + message = requestInfo.getEncoded(ASN1Encoding.DER); + } catch (IOException e) { + e.printStackTrace(); + } + + Signature signer; + byte[] result = new byte[0]; + try { + signer = Signature.getInstance("SHA1withRSA"); + signer.initSign(privKey); + signer.update(message); + result = signer.sign(); + } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) { + e.printStackTrace(); + } + assertArrayEquals(result,signature); + + Signature verifier; + boolean isValid = false; + try { + verifier = Signature.getInstance("SHA1withRSA"); + verifier.initVerify(pubKey); + verifier.update(message); + isValid = verifier.verify(signature); + } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) { + e.printStackTrace(); + } + assertTrue(isValid); + } + + + @Test + public void SM3withSM2CSRTest(){ + + String countryName = "CN"; + String stateName = "Beijing"; + String cityName = "Beijing"; + String organizationName = "JD.com"; + String departmentName = "Blockchain Department"; + String domainName = "ledger.jd.com"; + String emailName = "zhanglin33@jd.com"; + + CSRBuilder builder = new CSRBuilder(); + + builder.init("SM3withSM2",256); + String csr = builder.buildRequest(countryName,stateName,cityName, + organizationName,departmentName,domainName, + emailName); + + System.out.println(csr); + PublicKey pubKey = builder.getPubKey(); + PrivateKey privKey = builder.getPrivKey(); + + byte[] crsBytes = Base64.decode(csr); + PKCS10CertificationRequest request = null; + try { + request = new PKCS10CertificationRequest(crsBytes); + } catch (IOException e) { + e.printStackTrace(); + } + assertNotNull(request); + assertEquals("1.2.156.10197.1.501",request.getSignatureAlgorithm().getAlgorithm().getId()); + byte[] pubKeyBytes = new byte[0]; + try { + pubKeyBytes = request.getSubjectPublicKeyInfo().getEncoded(); + } catch (IOException e) { + e.printStackTrace(); + } + assertArrayEquals(pubKeyBytes,pubKey.getEncoded()); + + RDN[] rdns = request.getSubject().getRDNs(); + assertEquals(BCStyle.C, rdns[0].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.ST, rdns[1].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.L, rdns[2].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.O, rdns[3].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.OU, rdns[4].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.CN, rdns[5].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.E, rdns[6].getFirst().getType().toASN1Primitive()); + + assertEquals("CN", rdns[0].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("Beijing", rdns[1].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("Beijing", rdns[2].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("JD.com", rdns[3].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("Blockchain Department", rdns[4].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("ledger.jd.com", rdns[5].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("zhanglin33@jd.com", rdns[6].getFirst().getValue().toASN1Primitive().toString()); + + byte[] signature = request.getSignature(); + + CertificationRequestInfo requestInfo = new CertificationRequestInfo(request.getSubject(),request.getSubjectPublicKeyInfo(),new DERSet()); + byte[] message = new byte[0]; + try { + message = requestInfo.getEncoded(ASN1Encoding.DER); + } catch (IOException e) { + e.printStackTrace(); + } + + Signature signer; + byte[] result = new byte[0]; + try { + signer = Signature.getInstance("SM3withSM2"); + signer.initSign(privKey); + signer.update(message); + result = signer.sign(); + } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) { + e.printStackTrace(); + } + + Signature verifier; + boolean isValid = false; + try { + verifier = Signature.getInstance("SM3withSM2"); + verifier.initVerify(pubKey); + verifier.update(message); + isValid = verifier.verify(signature); + } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) { + e.printStackTrace(); + } + assertTrue(isValid); + + try { + verifier = Signature.getInstance("SM3withSM2"); + verifier.initVerify(pubKey); + verifier.update(message); + isValid = verifier.verify(result); + } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) { + e.printStackTrace(); + } + assertTrue(isValid); + } } diff --git a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CertParserTest.java b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CertParserTest.java index 59ad3814..7f106a2d 100644 --- a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CertParserTest.java +++ b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CertParserTest.java @@ -1,6 +1,6 @@ package com.jd.blockchain.crypto.utils; -import com.jd.blockchain.crypto.utils.CertParser; +import org.bouncycastle.util.encoders.Hex; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -14,7 +14,7 @@ import static org.junit.Assert.assertEquals; public class CertParserTest { @Test - public void parseTest() { + public void parseSHA1WITHRSA2048Test() { CertParser parser = new CertParser(); String issuerCert = "-----BEGIN CERTIFICATE-----\n" + @@ -46,4 +46,102 @@ public class CertParserTest { parser.parse(userCert, issuerCert); assertEquals("SHA1WITHRSA",parser.getSigAlgName()); } + + @Test + public void parseSHA1WITHRSA4096Test() { + CertParser parser = new CertParser(); + String issuerCert = + "-----BEGIN CERTIFICATE-----\n" + + "MIIDzzCCAregAwIBAgIKUalCR1Mt5ZSK8jANBgkqhkiG9w0BAQUFADBZMQswCQYD\n" + + "VQQGEwJDTjEwMC4GA1UEChMnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24g\n" + + "QXV0aG9yaXR5MRgwFgYDVQQDEw9DRkNBIFRFU1QgQ1MgQ0EwHhcNMTIwODI5MDU1\n" + + "NDM2WhcNMzIwODI0MDU1NDM2WjBZMQswCQYDVQQGEwJDTjEwMC4GA1UEChMnQ2hp\n" + + "bmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRgwFgYDVQQDEw9D\n" + + "RkNBIFRFU1QgT0NBMTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC8\n" + + "jn0n8Fp6hcRdACdn1+Y6GAkC6KGgNdKyHPrmsdmhCjnd/i4qUFwnG8cp3D4lFw1G\n" + + "jmjSO5yVYbik/NbS6lbNpRgTK3fDfMFvLJpRIC+IFhG9SdAC2hwjsH9qTpL9cK2M\n" + + "bSdrC6pBdDgnbzaM9AGBF4Y6vXhj5nah4ZMsBvDp19LzXjlGuTPLuAgv9ZlWknsd\n" + + "RN70PIAmvomd10uqX4GIJ4Jq/FdKXOLZ2DNK/NhRyN6Yq71L3ham6tutXeZow5t5\n" + + "0254AnUlo1u6SeH9F8itER653o/oMLFwp+63qXAcqrHUlOQPX+JI8fkumSqZ4F2F\n" + + "t/HfVMnqdtFNCnh5+eIBAgMBAAGjgZgwgZUwHwYDVR0jBBgwFoAUdN7FjQp9EBqq\n" + + "aYNbTSHOhpvMcTgwDAYDVR0TBAUwAwEB/zA4BgNVHR8EMTAvMC2gK6AphidodHRw\n" + + "Oi8vMjEwLjc0LjQyLjMvdGVzdHJjYS9SU0EvY3JsMS5jcmwwCwYDVR0PBAQDAgEG\n" + + "MB0GA1UdDgQWBBT8C7xEmg4xoYOpgYcnHgVCxr9W+DANBgkqhkiG9w0BAQUFAAOC\n" + + "AQEAb7W0K9fZPA+JPw6lRiMDaUJ0oh052yEXreMBfoPulxkBj439qombDiFggRLc\n" + + "3g8wIEKzMOzOKXTWtnzYwN3y/JQSuJb/M1QqOEEM2PZwCxI4AkBuH6jg03RjlkHg\n" + + "/kTtuIFp9ItBCC2/KkKlp0ENfn4XgVg2KtAjZ7lpyVU0LPnhEqqUVY/xthjlCSa7\n" + + "/XHNStRxsfCTIBUWJ8n2FZyQhfV/UkMNHDBIiJR0v6C4Ai0/290WvbPEIAq+03Si\n" + + "fsHzBeA0C8lP5VzfAr6wWePaZMCpStpLaoXNcAqReKxQllElOqAhRxC5VKH+rnIQ\n" + + "OMRZvB7FRyE9IfwKApngcZbA5g==\n" + + "-----END CERTIFICATE-----"; + + String userCert = "MIIFRjCCBC6gAwIBAgIFICdWiDMwDQYJKoZIhvcNAQEFBQAwWTELMAkGA1UEBhMCQ04xMDAuBgNVBAoTJ0NoaW5hIEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEYMBYGA1UEAxMPQ0ZDQSBURVNUIE9DQTExMB4XDTE5MDUxNjA3MDcyMloXDTIxMDUxNjA3MDcyMloweDELMAkGA1UEBhMCQ04xGDAWBgNVBAoTD0NGQ0EgVEVTVCBPQ0ExMTERMA8GA1UECxMITG9jYWwgUkExFTATBgNVBAsTDEluZGl2aWR1YWwtMTElMCMGA1UEAxQcMDUxQHpoYW5nbGluIUBaMTg2MTIyMjkyOTVAMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL0rTOxd8rsjPtFJ0aGVh9bZPy5Xo0SADaP7BbJsG4+ykLQMZHg9hTf/6fv1OsD2HEKFoMpIkW2gwCJW2nvicHcVql/shCoktc6ZBW6Dr/DxOgbO9tpoGxZ50xdI4Q0NsrxqtbCldW4ozPHdjgRJ83i1KSFh7evNrVByN/mB+jchrVGLWyJ1uIRgUUgpRZmZPoOHaizVJqrqWJGGk6xbDLR2gUQ1hTzetQaz1OeKtelHDk9FY08XSmNGssSMpuSjrxn78S888VW5WIxyo4cwrXSXFk3J7LNTy70Oga16HZjJD/vLTM6a4riPa8+uivPinKxK38/++nlBPNwhx6n46uYkd9Zvw+SJiJgpnuPJLtMZpKpJx7V1BDVEydKPUthilTdsmJtkBFSlFw0G1aKfuciBGzzJ3SKngJF/JqJAWIonVAFBGb6Gokp1Sw+T4KqXrdbjxYxiyyjZ++8O1vydgFAkx/NjsuwJnpKETiRKFJmY7YawcUvC4ixF7XQc0luFWRDYcbxOppir+ieMqhGXyaFhLUuB4WXv+rFxfa3NmkBW8q5TPzt/PwWcXpITsYTZYla/E/grB+OeZLYgjigT5YlgytPHG6Gt1ySCCd8WXFWpkBbQfXzqcvtU27RCcAUgfXk5NLb7NZCQg7heGjgzOdYJCPsa1d3m7l04+VIKGCZdAgMBAAGjgfUwgfIwHwYDVR0jBBgwFoAU/Au8RJoOMaGDqYGHJx4FQsa/VvgwSAYDVR0gBEEwPzA9BghggRyG7yoBAjAxMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmNmY2EuY29tLmNuL3VzL3VzLTE1Lmh0bTA6BgNVHR8EMzAxMC+gLaArhilodHRwOi8vMjEwLjc0LjQyLjMvT0NBMTEvUlNBL2NybDI1NzE3LmNybDALBgNVHQ8EBAMCA+gwHQYDVR0OBBYEFMjh6AzDCuNkD+pqQfiS6bqPGpI4MB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDBDANBgkqhkiG9w0BAQUFAAOCAQEApZaLXS6/6FudPA3l2xom5U7nJUOpQ1E6DO/ic9dFGtLE0WgyAqB3JVPvXEntppX55x/dAV7rvvz9NaEdiAe8DAj7qyoPDvC8ZWQK8U4n9l8N78QwALOURxzQNs+CBatJQzbu2w1RKVwkfE6xEIVnu+wjiAtymfwdLHMagHxDIC/eOPbTnbbtITJk2ukFfoc0WJ6Awg5lW+x7nGokEn/XAjKyRHCpkRUFGQm4ww41zlrqCqQqnVGVABJtjbdtFf7nh33QHl0fkj19nfMox9eGuntPyM0bNA0XqPMA+FWSCqeDT6uLbyaOKWxlhv53U/NCJl76U3tssMEWsm9amEDDQg=="; + + parser.parse(userCert, issuerCert); + assertEquals("SHA1WITHRSA",parser.getSigAlgName()); + } + + @Test + public void parseSM3WITHSM2Test() { + CertParser parser = new CertParser(); + String issuerCert = + "-----BEGIN CERTIFICATE-----\n" + + "MIICTzCCAfOgAwIBAgIKJFSZ4SRVDndYUTAMBggqgRzPVQGDdQUAMF0xCzAJBgNV\n" + + "BAYTAkNOMTAwLgYDVQQKDCdDaGluYSBGaW5hbmNpYWwgQ2VydGlmaWNhdGlvbiBB\n" + + "dXRob3JpdHkxHDAaBgNVBAMME0NGQ0EgVEVTVCBDUyBTTTIgQ0EwHhcNMTIwODI5\n" + + "MDU0ODQ3WhcNMzIwODI0MDU0ODQ3WjBdMQswCQYDVQQGEwJDTjEwMC4GA1UECgwn\n" + + "Q2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRwwGgYDVQQD\n" + + "DBNDRkNBIFRFU1QgU00yIE9DQTExMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE\n" + + "L1mx4wriQUojGsIkNL14kslv9nwiqsiVpELOZauzghrbccNlPYKNYKZOCvXwIIqU\n" + + "9QY02d4weqKqo/JMcNsKEaOBmDCBlTAfBgNVHSMEGDAWgBS12JBvXPDYM9JjvX6y\n" + + "w43GTxJ6YTAMBgNVHRMEBTADAQH/MDgGA1UdHwQxMC8wLaAroCmGJ2h0dHA6Ly8y\n" + + "MTAuNzQuNDIuMy90ZXN0cmNhL1NNMi9jcmwxLmNybDALBgNVHQ8EBAMCAQYwHQYD\n" + + "VR0OBBYEFL6mfk09fI+gVebBLwkuLCBDs0J/MAwGCCqBHM9VAYN1BQADSAAwRQIh\n" + + "AKuk7s3eYCZDck5NWU0eNQmLhBN/1zmKs517qFrDrkJWAiAP4cVfLtdza/OkwU9P\n" + + "PrIDl+E4aL3FypntFXHG3T+Keg==\n" + + "-----END CERTIFICATE-----"; + + String userCert = "MIICwDCCAmWgAwIBAgIFICdWkWgwDAYIKoEcz1UBg3UFADBdMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRwwGgYDVQQDDBNDRkNBIFRFU1QgU00yIE9DQTExMB4XDTE5MDUxNjA4MTA1MVoXDTIxMDUxNjA4MTA1MVoweDELMAkGA1UEBhMCQ04xGDAWBgNVBAoMD0NGQ0EgVEVTVCBPQ0ExMTERMA8GA1UECwwITG9jYWwgUkExFTATBgNVBAsMDEluZGl2aWR1YWwtMTElMCMGA1UEAwwcMDUxQHpoYW5nbGluIUBaMTg2MTIyMjkyOTVAMzBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABPvNXpdZ4/4g+wx5qKS94CPkMqpEDhlnXYYW7ZzsbNI4d28sVBz5Ji6dTT1Zx627Kvw4tdUaUt7BVMvZsu3BFlyjgfQwgfEwHwYDVR0jBBgwFoAUvqZ+TT18j6BV5sEvCS4sIEOzQn8wSAYDVR0gBEEwPzA9BghggRyG7yoBAjAxMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmNmY2EuY29tLmNuL3VzL3VzLTE1Lmh0bTA5BgNVHR8EMjAwMC6gLKAqhihodHRwOi8vMjEwLjc0LjQyLjMvT0NBMTEvU00yL2NybDIxMDkuY3JsMAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQUxR5C/VjASus5zrAAFS4ulMpRjKgwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMAwGCCqBHM9VAYN1BQADRwAwRAIgVBzVi/fgkknr+2BH2wXeGMXC+Pa6p7rbldUsYMOYoyUCIAmQ4KEk2U1xJZSBpOPy5jN9kmRb+0YH6x04O/2tqCgq"; + + parser.parse(userCert, issuerCert); + assertEquals("SM3WITHSM2",parser.getSigAlgName()); + } + + @Test + public void authenticateIssuerByCATest() { + CertParser parser = new CertParser(); + String CACert = + "-----BEGIN CERTIFICATE-----\n" + + "MIICFDCCAbegAwIBAgIKPYozwkCO86Nd9TAMBggqgRzPVQGDdQUAMF0xCzAJBgNV\n" + + "BAYTAkNOMTAwLgYDVQQKDCdDaGluYSBGaW5hbmNpYWwgQ2VydGlmaWNhdGlvbiBB\n" + + "dXRob3JpdHkxHDAaBgNVBAMME0NGQ0EgVEVTVCBDUyBTTTIgQ0EwHhcNMTIwODI5\n" + + "MDMyOTQ2WhcNMzIwODI5MDMyOTQ2WjBdMQswCQYDVQQGEwJDTjEwMC4GA1UECgwn\n" + + "Q2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRwwGgYDVQQD\n" + + "DBNDRkNBIFRFU1QgQ1MgU00yIENBMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE\n" + + "tTjB3O4JueYFDDOtxH678HBZbEmrsgd3BDIdGf0BekyA26n9S0/pKPnjBh/zLouS\n" + + "8+GB5EEnjbn4An24yo1Gv6NdMFswHwYDVR0jBBgwFoAUtdiQb1zw2DPSY71+ssON\n" + + "xk8SemEwDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFLXYkG9c\n" + + "8Ngz0mO9frLDjcZPEnphMAwGCCqBHM9VAYN1BQADSQAwRgIhAKwuuqoBS1bwDowW\n" + + "a4IU//UsvudswJYSlltqrd/PQ9q+AiEAyTUAjFdaGI+8yPdr3A93UiA38wtGPf9e\n" + + "6B6O/6abyWE=\n" + + "-----END CERTIFICATE-----"; + + String issuerCert = "-----BEGIN CERTIFICATE-----\n" + + "MIICTzCCAfOgAwIBAgIKJFSZ4SRVDndYUTAMBggqgRzPVQGDdQUAMF0xCzAJBgNV\n" + + "BAYTAkNOMTAwLgYDVQQKDCdDaGluYSBGaW5hbmNpYWwgQ2VydGlmaWNhdGlvbiBB\n" + + "dXRob3JpdHkxHDAaBgNVBAMME0NGQ0EgVEVTVCBDUyBTTTIgQ0EwHhcNMTIwODI5\n" + + "MDU0ODQ3WhcNMzIwODI0MDU0ODQ3WjBdMQswCQYDVQQGEwJDTjEwMC4GA1UECgwn\n" + + "Q2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRwwGgYDVQQD\n" + + "DBNDRkNBIFRFU1QgU00yIE9DQTExMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE\n" + + "L1mx4wriQUojGsIkNL14kslv9nwiqsiVpELOZauzghrbccNlPYKNYKZOCvXwIIqU\n" + + "9QY02d4weqKqo/JMcNsKEaOBmDCBlTAfBgNVHSMEGDAWgBS12JBvXPDYM9JjvX6y\n" + + "w43GTxJ6YTAMBgNVHRMEBTADAQH/MDgGA1UdHwQxMC8wLaAroCmGJ2h0dHA6Ly8y\n" + + "MTAuNzQuNDIuMy90ZXN0cmNhL1NNMi9jcmwxLmNybDALBgNVHQ8EBAMCAQYwHQYD\n" + + "VR0OBBYEFL6mfk09fI+gVebBLwkuLCBDs0J/MAwGCCqBHM9VAYN1BQADSAAwRQIh\n" + + "AKuk7s3eYCZDck5NWU0eNQmLhBN/1zmKs517qFrDrkJWAiAP4cVfLtdza/OkwU9P\n" + + "PrIDl+E4aL3FypntFXHG3T+Keg==\n" + + "-----END CERTIFICATE-----"; + parser.parse(issuerCert, CACert); + assertEquals("SM3WITHSM2",parser.getSigAlgName()); + } } From 0da0219341c70257a2c482de5d6cb501090163fa Mon Sep 17 00:00:00 2001 From: zhanglin33 Date: Fri, 17 May 2019 15:11:57 +0800 Subject: [PATCH 35/43] remove useless imports --- .../service/pki/SHA1WITHRSA2048SignatureFunctionTest.java | 2 -- .../service/pki/SHA1WITHRSA4096SignatureFunctionTest.java | 1 - .../crypto/service/pki/SM3WITHSM2SignatureFunctionTest.java | 1 - .../java/com/jd/blockchain/crypto/utils/CertParserTest.java | 1 - 4 files changed, 5 deletions(-) diff --git a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunctionTest.java b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunctionTest.java index 8b762ff9..9b6952be 100644 --- a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunctionTest.java +++ b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunctionTest.java @@ -9,9 +9,7 @@ import java.util.Random; import static com.jd.blockchain.crypto.CryptoAlgorithm.*; import static com.jd.blockchain.crypto.CryptoKeyType.PRIVATE; import static com.jd.blockchain.crypto.CryptoKeyType.PUBLIC; -import static junit.framework.TestCase.assertNull; import static org.junit.Assert.*; -import static org.junit.Assert.assertArrayEquals; /** * @author zhanglin33 diff --git a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunctionTest.java b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunctionTest.java index 9ab2ac7c..5b976c72 100644 --- a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunctionTest.java +++ b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunctionTest.java @@ -10,7 +10,6 @@ import static com.jd.blockchain.crypto.CryptoAlgorithm.ASYMMETRIC_KEY; import static com.jd.blockchain.crypto.CryptoAlgorithm.SIGNATURE_ALGORITHM; import static com.jd.blockchain.crypto.CryptoKeyType.PRIVATE; import static com.jd.blockchain.crypto.CryptoKeyType.PUBLIC; -import static junit.framework.TestCase.assertNull; import static org.junit.Assert.*; /** diff --git a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SM3WITHSM2SignatureFunctionTest.java b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SM3WITHSM2SignatureFunctionTest.java index c9fa8311..0b8063a9 100644 --- a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SM3WITHSM2SignatureFunctionTest.java +++ b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SM3WITHSM2SignatureFunctionTest.java @@ -10,7 +10,6 @@ import static com.jd.blockchain.crypto.CryptoAlgorithm.ASYMMETRIC_KEY; import static com.jd.blockchain.crypto.CryptoAlgorithm.SIGNATURE_ALGORITHM; import static com.jd.blockchain.crypto.CryptoKeyType.PRIVATE; import static com.jd.blockchain.crypto.CryptoKeyType.PUBLIC; -import static junit.framework.TestCase.assertNull; import static org.junit.Assert.*; /** diff --git a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CertParserTest.java b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CertParserTest.java index 7f106a2d..24cdc414 100644 --- a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CertParserTest.java +++ b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CertParserTest.java @@ -1,6 +1,5 @@ package com.jd.blockchain.crypto.utils; -import org.bouncycastle.util.encoders.Hex; import org.junit.Test; import static org.junit.Assert.assertEquals; From dd021222d783144f74a414e6c47b87939e9e6266 Mon Sep 17 00:00:00 2001 From: huanghaiquan Date: Sun, 19 May 2019 01:15:06 +0800 Subject: [PATCH 36/43] Added crypto-provider attribute to the settings of ledger; --- .../com/jd/blockchain/consts/DataCodes.java | 2 + .../blockchain/provider/ProviderManager.java | 31 ++++++++--- .../java/com/jd/blockchain/crypto/Crypto.java | 32 +++++++++++ .../jd/blockchain/crypto/CryptoAlgorithm.java | 10 +++- .../crypto/CryptoAlgorithmDefinition.java | 38 +++++-------- .../jd/blockchain/crypto/CryptoProvider.java | 17 ++++++ .../blockchain/crypto/CryptoProviderInfo.java | 24 +++++++++ .../blockchain/ledger/core/CryptoConfig.java | 53 ++++++++++++++++++- .../jd/blockchain/ledger/AccountSetTest.java | 14 +++++ .../jd/blockchain/ledger/BaseAccountTest.java | 13 +++++ .../ledger/LedgerAdminAccountTest.java | 13 +++++ .../blockchain/ledger/LedgerEditerTest.java | 13 +++++ .../ledger/LedgerInitOperationTest.java | 12 +++++ .../ledger/LedgerInitSettingTest.java | 13 +++++ .../blockchain/ledger/LedgerManagerTest.java | 16 ++++++ .../blockchain/ledger/LedgerMetaDataTest.java | 27 ++++++++++ .../jd/blockchain/ledger/LedgerTestUtils.java | 13 +++++ .../blockchain/ledger/MerkleDataSetTest.java | 26 +++++++++ .../blockchain/ledger/CryptoProviderInfo.java | 12 ----- .../jd/blockchain/ledger/CryptoSetting.java | 13 ++++- .../DataAccountKVSetOpTemplate.java | 4 +- .../initializer/LedgerInitializeTest.java | 11 ++++ .../web/LedgerInitializeWebController.java | 12 +++++ 23 files changed, 370 insertions(+), 49 deletions(-) create mode 100644 source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/CryptoProvider.java create mode 100644 source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/CryptoProviderInfo.java delete mode 100644 source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/CryptoProviderInfo.java diff --git a/source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java b/source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java index e4e17a14..6b47a505 100644 --- a/source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java +++ b/source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java @@ -68,6 +68,8 @@ public interface DataCodes { // public static final int METADATA_PARTICIPANT_INFO = 0x640; public static final int METADATA_CRYPTO_SETTING = 0x642; + + public static final int METADATA_CRYPTO_SETTING_PROVIDER = 0x643; // public static final int ACCOUNT = 0x700; diff --git a/source/base/src/main/java/com/jd/blockchain/provider/ProviderManager.java b/source/base/src/main/java/com/jd/blockchain/provider/ProviderManager.java index 447ba3db..98584de4 100644 --- a/source/base/src/main/java/com/jd/blockchain/provider/ProviderManager.java +++ b/source/base/src/main/java/com/jd/blockchain/provider/ProviderManager.java @@ -4,6 +4,7 @@ import java.security.AccessControlContext; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; @@ -48,32 +49,45 @@ public final class ProviderManager { * @return */ public S getService(Class serviceClazz, String providerName) { - NamedProviders providers = getServiceProvider(serviceClazz); + NamedProviders providers = getNamedProviders(serviceClazz); return providers.getService(providerName); } + + public Provider getProvider(Class serviceClazz, String providerName) { + @SuppressWarnings("unchecked") + NamedProviders providers = (NamedProviders) serviceProviders.get(serviceClazz); + if (providers == null) { + return null; + } + return providers.getProvider(providerName); + } public Collection> getAllProviders(Class serviceClazz) { - NamedProviders providers = getServiceProvider(serviceClazz); + @SuppressWarnings("unchecked") + NamedProviders providers = (NamedProviders) serviceProviders.get(serviceClazz); + if (providers == null) { + return Collections.emptyList(); + } return providers.getProviders(); } public S installProvider(Class serviceClazz, String providerFullName) { - NamedProviders providers = getServiceProvider(serviceClazz); + NamedProviders providers = getNamedProviders(serviceClazz); return providers.install(providerFullName); } public S installProvider(Class service, String providerFullName, ClassLoader classLoader) { - NamedProviders providers = getServiceProvider(service); + NamedProviders providers = getNamedProviders(service); return providers.install(providerFullName, classLoader); } public void installAllProviders(Class serviceClazz, ClassLoader classLoader) { - NamedProviders providers = getServiceProvider(serviceClazz); + NamedProviders providers = getNamedProviders(serviceClazz); providers.installAll(classLoader); } @SuppressWarnings("unchecked") - private NamedProviders getServiceProvider(Class serviceClazz) { + private NamedProviders getNamedProviders(Class serviceClazz) { NamedProviders providers = (NamedProviders) serviceProviders.get(serviceClazz); if (providers == null) { synchronized (mutex) { @@ -189,6 +203,11 @@ public final class ProviderManager { public Collection> getProviders() { return namedProviders.values(); } + + + public Provider getProvider(String providerFullName) { + return namedProviders.get(providerFullName); + } public S getService(String name) { String fullName = shortNames.get(name); diff --git a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/Crypto.java b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/Crypto.java index 86dbf55b..b6b94603 100644 --- a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/Crypto.java +++ b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/Crypto.java @@ -106,6 +106,38 @@ public final class Crypto { private Crypto() { } + public static CryptoProvider[] getProviders() { + Collection> providers = pm.getAllProviders(CryptoService.class); + CryptoProvider[] infos = new CryptoProvider[providers.size()]; + + int i = 0; + for (Provider pd : providers) { + CryptoProviderInfo info = getProviderInfo(pd); + infos[i] = info; + } + + return infos; + } + + private static CryptoProviderInfo getProviderInfo(Provider pd) { + Collection functions = pd.getService().getFunctions(); + CryptoAlgorithm[] algorithms = new CryptoAlgorithm[functions.size()]; + int i = 0; + for (CryptoFunction function : functions) { + algorithms[i] = function.getAlgorithm(); + i++; + } + return new CryptoProviderInfo(pd.getFullName(), algorithms); + } + + public static CryptoProvider getProvider(String providerFullName) { + Provider pd = pm.getProvider(CryptoService.class, providerFullName); + if (pd == null) { + return null; + } + return getProviderInfo(pd); + } + public static Collection getAllAlgorithms() { return algorithms.values(); } diff --git a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/CryptoAlgorithm.java b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/CryptoAlgorithm.java index 4f505ba9..b501626f 100644 --- a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/CryptoAlgorithm.java +++ b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/CryptoAlgorithm.java @@ -9,7 +9,7 @@ import com.jd.blockchain.binaryproto.PrimitiveType; import com.jd.blockchain.consts.DataCodes; import com.jd.blockchain.utils.io.BytesUtils; -//@DataContract(code = DataCodes.CRYPTO_ALGORITHM) +@DataContract(code = DataCodes.CRYPTO_ALGORITHM) public interface CryptoAlgorithm { /** @@ -63,7 +63,7 @@ public interface CryptoAlgorithm { * {@link #EXT_ALGORITHM}) 5 种); 接下来4位标识密钥类型(包括:{@link #SYMMETRIC_KEY}, * {@link #ASYMMETRIC_KEY}); 最后8位是算法唯一ID; */ -// @DataField(primitiveType = PrimitiveType.INT16, order = 0) + @DataField(order = 0, primitiveType = PrimitiveType.INT16) short code(); /** @@ -75,7 +75,13 @@ public interface CryptoAlgorithm { * * @return */ + @DataField(order = 1, primitiveType = PrimitiveType.TEXT) String name(); + + + public static String getString(CryptoAlgorithm algorithm) { + return String.format("%s[%s]", algorithm.name(), (algorithm.code() & 0xFFFF)); + } /** * diff --git a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/CryptoAlgorithmDefinition.java b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/CryptoAlgorithmDefinition.java index 64b6a3e1..4e9f94b0 100644 --- a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/CryptoAlgorithmDefinition.java +++ b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/CryptoAlgorithmDefinition.java @@ -23,16 +23,14 @@ public final class CryptoAlgorithmDefinition implements CryptoAlgorithm { @Override public String toString() { - return name + "[" + (code & 0xFFFF) + "]"; + return CryptoAlgorithm.getString(this); } /** * 声明一项哈希算法; * - * @param name - * 算法名称; - * @param uid - * 算法ID;需要在同类算法中保持唯一性; + * @param name 算法名称; + * @param uid 算法ID;需要在同类算法中保持唯一性; * @return */ public static CryptoAlgorithm defineHash(String name, byte uid) { @@ -43,10 +41,8 @@ public final class CryptoAlgorithmDefinition implements CryptoAlgorithm { /** * 声明一项非对称密码算法; * - * @param name - * 算法名称; - * @param uid - * 算法ID;需要在同类算法中保持唯一性; + * @param name 算法名称; + * @param uid 算法ID;需要在同类算法中保持唯一性; * @return */ public static CryptoAlgorithm defineSignature(String name, boolean encryptable, byte uid) { @@ -62,10 +58,8 @@ public final class CryptoAlgorithmDefinition implements CryptoAlgorithm { /** * 声明一项非对称加密算法; * - * @param name - * 算法名称; - * @param uid - * 算法ID;需要在同类算法中保持唯一性; + * @param name 算法名称; + * @param uid 算法ID;需要在同类算法中保持唯一性; * @return */ public static CryptoAlgorithm defineAsymmetricEncryption(String name, byte uid) { @@ -76,10 +70,8 @@ public final class CryptoAlgorithmDefinition implements CryptoAlgorithm { /** * 声明一项对称密码算法; * - * @param name - * 算法名称; - * @param uid - * 算法ID;需要在同类算法中保持唯一性; + * @param name 算法名称; + * @param uid 算法ID;需要在同类算法中保持唯一性; * @return */ public static CryptoAlgorithm defineSymmetricEncryption(String name, byte uid) { @@ -90,10 +82,8 @@ public final class CryptoAlgorithmDefinition implements CryptoAlgorithm { /** * 声明一项随机数算法; * - * @param name - * 算法名称; - * @param uid - * 算法ID;需要在同类算法中保持唯一性; + * @param name 算法名称; + * @param uid 算法ID;需要在同类算法中保持唯一性; * @return */ public static CryptoAlgorithm defineRandom(String name, byte uid) { @@ -104,10 +94,8 @@ public final class CryptoAlgorithmDefinition implements CryptoAlgorithm { /** * 声明一项扩展的密码算法; * - * @param name - * 算法名称; - * @param uid - * 算法ID;需要在同类算法中保持唯一性; + * @param name 算法名称; + * @param uid 算法ID;需要在同类算法中保持唯一性; * @return */ public static CryptoAlgorithm definExt(String name, byte uid) { diff --git a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/CryptoProvider.java b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/CryptoProvider.java new file mode 100644 index 00000000..57b06831 --- /dev/null +++ b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/CryptoProvider.java @@ -0,0 +1,17 @@ +package com.jd.blockchain.crypto; + +import com.jd.blockchain.binaryproto.DataContract; +import com.jd.blockchain.binaryproto.DataField; +import com.jd.blockchain.binaryproto.PrimitiveType; +import com.jd.blockchain.consts.DataCodes; + +@DataContract(code = DataCodes.METADATA_CRYPTO_SETTING_PROVIDER) +public interface CryptoProvider { + + @DataField(order = 0, primitiveType = PrimitiveType.TEXT) + String getName(); + + @DataField(order = 1, list = true, refContract = true) + CryptoAlgorithm[] getAlgorithms(); + +} diff --git a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/CryptoProviderInfo.java b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/CryptoProviderInfo.java new file mode 100644 index 00000000..b0b17231 --- /dev/null +++ b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/CryptoProviderInfo.java @@ -0,0 +1,24 @@ +package com.jd.blockchain.crypto; + +class CryptoProviderInfo implements CryptoProvider { + + private String name; + + private CryptoAlgorithm[] algorithms; + + public CryptoProviderInfo(String name, CryptoAlgorithm[] algorithms) { + this.name = name; + this.algorithms = algorithms; + } + + @Override + public String getName() { + return name; + } + + @Override + public CryptoAlgorithm[] getAlgorithms() { + return algorithms.clone(); + } + +} diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/CryptoConfig.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/CryptoConfig.java index 6244d018..1939e36b 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/CryptoConfig.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/CryptoConfig.java @@ -1,13 +1,23 @@ package com.jd.blockchain.ledger.core; +import java.util.HashMap; + import com.jd.blockchain.crypto.CryptoAlgorithm; +import com.jd.blockchain.crypto.CryptoProvider; import com.jd.blockchain.ledger.CryptoSetting; public class CryptoConfig implements CryptoSetting { + private CryptoProvider[] cryptoProviders; + private short hashAlgorithm; private boolean autoVerifyHash; + + HashMap providers; + HashMap nameAlgorithms; + HashMap codeAlgorithms; + public CryptoConfig() { } @@ -17,6 +27,11 @@ public class CryptoConfig implements CryptoSetting { this.autoVerifyHash = setting.getAutoVerifyHash(); } + @Override + public CryptoProvider[] getSupportedProviders() { + return cryptoProviders == null ? null : cryptoProviders.clone(); + } + @Override public short getHashAlgorithm() { return hashAlgorithm; @@ -27,11 +42,47 @@ public class CryptoConfig implements CryptoSetting { return autoVerifyHash; } + public void setSupportedProviders(CryptoProvider[] supportedProviders) { + HashMap providers = new HashMap(); + HashMap nameAlgorithms = new HashMap(); + HashMap codeAlgorithms = new HashMap(); + if (supportedProviders != null) { + // 检查是否存在重复的提供者以及算法; + for (CryptoProvider cryptoProvider : supportedProviders) { + if (providers.containsKey(cryptoProvider.getName())) { + throw new LedgerException("Duplicate crypto providers [" + cryptoProvider.getName() + "]!"); + } + CryptoAlgorithm[] algorithms = cryptoProvider.getAlgorithms(); + for (CryptoAlgorithm alg : algorithms) { + if (nameAlgorithms.containsKey(alg.name())) { + throw new LedgerException("Duplicate crypto algorithms [" + alg.toString() + "] from provider " + + cryptoProvider.getName() + "!"); + } + if (codeAlgorithms.containsKey(alg.code())) { + throw new LedgerException("Duplicate crypto algorithms [" + alg.toString() + "] from provider" + + cryptoProvider.getName() + "!"); + } + nameAlgorithms.put(alg.name(), alg); + codeAlgorithms.put(alg.code(), alg); + } + providers.put(cryptoProvider.getName(), cryptoProvider); + } + } + this.providers = providers; + this.nameAlgorithms = nameAlgorithms; + this.codeAlgorithms = codeAlgorithms; + + this.cryptoProviders = supportedProviders; + } + public void setHashAlgorithm(CryptoAlgorithm hashAlgorithm) { - this.hashAlgorithm = hashAlgorithm.code(); + setHashAlgorithm(hashAlgorithm.code()); } public void setHashAlgorithm(short hashAlgorithm) { + if (codeAlgorithms == null || !codeAlgorithms.containsKey(hashAlgorithm)) { + throw new LedgerException("The specified algorithm has no provider!"); + } this.hashAlgorithm = hashAlgorithm; } diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/AccountSetTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/AccountSetTest.java index 1334bdf5..5b69b118 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/AccountSetTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/AccountSetTest.java @@ -6,8 +6,12 @@ import static org.junit.Assert.assertTrue; import org.junit.Test; +import com.jd.blockchain.crypto.Crypto; +import com.jd.blockchain.crypto.CryptoProvider; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm; +import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; +import com.jd.blockchain.crypto.service.sm.SMCryptoService; import com.jd.blockchain.ledger.BlockchainKeyGenerator; import com.jd.blockchain.ledger.BlockchainKeypair; import com.jd.blockchain.ledger.core.AccountSet; @@ -17,6 +21,11 @@ import com.jd.blockchain.ledger.core.impl.OpeningAccessPolicy; import com.jd.blockchain.storage.service.utils.MemoryKVStorage; public class AccountSetTest { + + + private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(), + SMCryptoService.class.getName() }; + @Test public void test() { @@ -24,7 +33,12 @@ public class AccountSetTest { MemoryKVStorage storage = new MemoryKVStorage(); + CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length]; + for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) { + supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]); + } CryptoConfig cryptoConf = new CryptoConfig(); + cryptoConf.setSupportedProviders(supportedProviders); cryptoConf.setAutoVerifyHash(true); cryptoConf.setHashAlgorithm(ClassicAlgorithm.SHA256); diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/BaseAccountTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/BaseAccountTest.java index 5d11b337..23b3445a 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/BaseAccountTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/BaseAccountTest.java @@ -5,7 +5,11 @@ import static org.junit.Assert.assertFalse; import org.junit.Test; +import com.jd.blockchain.crypto.Crypto; +import com.jd.blockchain.crypto.CryptoProvider; import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm; +import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; +import com.jd.blockchain.crypto.service.sm.SMCryptoService; import com.jd.blockchain.ledger.BlockchainKeyGenerator; import com.jd.blockchain.ledger.BlockchainKeypair; import com.jd.blockchain.ledger.core.BaseAccount; @@ -22,12 +26,21 @@ import com.jd.blockchain.utils.io.BytesUtils; */ public class BaseAccountTest { + public static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(), + SMCryptoService.class.getName() }; + @Test public void basicTest() { String keyPrefix = ""; MemoryKVStorage testStorage = new MemoryKVStorage(); + CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length]; + for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) { + supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]); + } + CryptoConfig cryptoConf = new CryptoConfig(); + cryptoConf.setSupportedProviders(supportedProviders); cryptoConf.setAutoVerifyHash(true); cryptoConf.setHashAlgorithm(ClassicAlgorithm.SHA256); diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerAdminAccountTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerAdminAccountTest.java index 823b3397..1293a9d8 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerAdminAccountTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerAdminAccountTest.java @@ -13,8 +13,12 @@ import com.jd.blockchain.ledger.LedgerMetadata; import org.junit.Test; import com.jd.blockchain.crypto.AddressEncoding; +import com.jd.blockchain.crypto.Crypto; +import com.jd.blockchain.crypto.CryptoProvider; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm; +import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; +import com.jd.blockchain.crypto.service.sm.SMCryptoService; import com.jd.blockchain.ledger.BlockchainKeyGenerator; import com.jd.blockchain.ledger.BlockchainKeypair; import com.jd.blockchain.ledger.ParticipantNode; @@ -30,6 +34,9 @@ import com.jd.blockchain.utils.net.NetworkAddress; public class LedgerAdminAccountTest { + private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(), + SMCryptoService.class.getName() }; + private Random rand = new Random(); @Test @@ -55,7 +62,13 @@ public class LedgerAdminAccountTest { initSetting.setConsensusSettings(new Bytes(csSysSettingBytes)); initSetting.setConsensusProvider("consensus-provider"); + CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length]; + for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) { + supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]); + } + CryptoConfig cryptoSetting = new CryptoConfig(); + cryptoSetting.setSupportedProviders(supportedProviders); cryptoSetting.setAutoVerifyHash(true); cryptoSetting.setHashAlgorithm(ClassicAlgorithm.SHA256); initSetting.setCryptoSetting(cryptoSetting); diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerEditerTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerEditerTest.java index 621aa6fc..3ae78c32 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerEditerTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerEditerTest.java @@ -11,8 +11,11 @@ import com.jd.blockchain.binaryproto.DataContractRegistry; import com.jd.blockchain.crypto.AddressEncoding; import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.Crypto; +import com.jd.blockchain.crypto.CryptoProvider; import com.jd.blockchain.crypto.SignatureFunction; import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm; +import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; +import com.jd.blockchain.crypto.service.sm.SMCryptoService; import com.jd.blockchain.ledger.BlockchainKeypair; import com.jd.blockchain.ledger.LedgerBlock; import com.jd.blockchain.ledger.LedgerInitSetting; @@ -34,6 +37,10 @@ import com.jd.blockchain.utils.io.BytesUtils; import com.jd.blockchain.utils.net.NetworkAddress; public class LedgerEditerTest { + + private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(), + SMCryptoService.class.getName() }; + static { DataContractRegistry.register(com.jd.blockchain.ledger.TransactionContent.class); @@ -109,8 +116,14 @@ public class LedgerEditerTest { private LedgerInitSetting createLedgerInitSetting() { SignatureFunction signFunc = Crypto.getSignatureFunction("ED25519"); + + CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length]; + for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) { + supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]); + } CryptoConfig defCryptoSetting = new CryptoConfig(); + defCryptoSetting.setSupportedProviders(supportedProviders); defCryptoSetting.setAutoVerifyHash(true); defCryptoSetting.setHashAlgorithm(ClassicAlgorithm.SHA256); diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitOperationTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitOperationTest.java index e9ae7693..9cee71df 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitOperationTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitOperationTest.java @@ -12,7 +12,11 @@ import org.junit.Test; import com.jd.blockchain.binaryproto.BinaryProtocol; import com.jd.blockchain.binaryproto.DataContractRegistry; import com.jd.blockchain.crypto.AddressEncoding; +import com.jd.blockchain.crypto.Crypto; +import com.jd.blockchain.crypto.CryptoProvider; import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm; +import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; +import com.jd.blockchain.crypto.service.sm.SMCryptoService; import com.jd.blockchain.ledger.BlockchainKeyGenerator; import com.jd.blockchain.ledger.BlockchainKeypair; import com.jd.blockchain.ledger.LedgerInitOperation; @@ -27,6 +31,9 @@ import com.jd.blockchain.utils.net.NetworkAddress; public class LedgerInitOperationTest { + private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(), + SMCryptoService.class.getName() }; + byte[] seed = null; byte[] csSysSettingBytes = null; LedgerInitSettingData ledgerInitSettingData = new LedgerInitSettingData(); @@ -44,7 +51,12 @@ public class LedgerInitOperationTest { csSysSettingBytes = new byte[64]; rand.nextBytes(csSysSettingBytes); + CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length]; + for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) { + supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]); + } CryptoConfig cryptoConfig = new CryptoConfig(); + cryptoConfig.setSupportedProviders(supportedProviders); cryptoConfig.setAutoVerifyHash(true); cryptoConfig.setHashAlgorithm(ClassicAlgorithm.SHA256); diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitSettingTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitSettingTest.java index 7f9a4e7c..7e2c6850 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitSettingTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitSettingTest.java @@ -12,7 +12,11 @@ import org.junit.Test; import com.jd.blockchain.binaryproto.BinaryProtocol; import com.jd.blockchain.binaryproto.DataContractRegistry; import com.jd.blockchain.crypto.AddressEncoding; +import com.jd.blockchain.crypto.Crypto; +import com.jd.blockchain.crypto.CryptoProvider; import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm; +import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; +import com.jd.blockchain.crypto.service.sm.SMCryptoService; import com.jd.blockchain.ledger.BlockchainKeyGenerator; import com.jd.blockchain.ledger.BlockchainKeypair; import com.jd.blockchain.ledger.LedgerInitSetting; @@ -30,6 +34,9 @@ public class LedgerInitSettingTest { LedgerInitSettingData ledgerInitSettingData = new LedgerInitSettingData(); LedgerInitOpTemplate template = new LedgerInitOpTemplate(); + private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(), + SMCryptoService.class.getName() }; + @Before public void initCfg() { @@ -41,7 +48,13 @@ public class LedgerInitSettingTest { csSysSettingBytes = new byte[64]; rand.nextBytes(csSysSettingBytes); + CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length]; + for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) { + supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]); + } + CryptoConfig cryptoConfig = new CryptoConfig(); + cryptoConfig.setSupportedProviders(supportedProviders); cryptoConfig.setAutoVerifyHash(true); cryptoConfig.setHashAlgorithm(ClassicAlgorithm.SHA256); diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerManagerTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerManagerTest.java index 9974d5d8..066151cd 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerManagerTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerManagerTest.java @@ -13,9 +13,12 @@ import com.jd.blockchain.binaryproto.DataContractRegistry; import com.jd.blockchain.crypto.AddressEncoding; import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.Crypto; +import com.jd.blockchain.crypto.CryptoProvider; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.SignatureFunction; import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm; +import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; +import com.jd.blockchain.crypto.service.sm.SMCryptoService; import com.jd.blockchain.ledger.BlockBody; import com.jd.blockchain.ledger.BlockchainKeyGenerator; import com.jd.blockchain.ledger.BlockchainKeypair; @@ -55,6 +58,10 @@ public class LedgerManagerTest { DataContractRegistry.register(DataAccountRegisterOperation.class); DataContractRegistry.register(BlockBody.class); } + + + public static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(), + SMCryptoService.class.getName() }; private SignatureFunction signatureFunction; @@ -170,7 +177,16 @@ public class LedgerManagerTest { } private LedgerInitSetting createLedgerInitSetting() { + + CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length]; + for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) { + supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]); + } + CryptoConfig defCryptoSetting = new CryptoConfig(); + + defCryptoSetting.setSupportedProviders(supportedProviders); + defCryptoSetting.setAutoVerifyHash(true); defCryptoSetting.setHashAlgorithm(ClassicAlgorithm.SHA256); diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerMetaDataTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerMetaDataTest.java index f744780d..401c5de2 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerMetaDataTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerMetaDataTest.java @@ -15,9 +15,13 @@ import org.junit.Test; import com.jd.blockchain.binaryproto.BinaryProtocol; import com.jd.blockchain.binaryproto.DataContractRegistry; import com.jd.blockchain.crypto.AddressEncoding; +import com.jd.blockchain.crypto.Crypto; +import com.jd.blockchain.crypto.CryptoProvider; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm; +import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; +import com.jd.blockchain.crypto.service.sm.SMCryptoService; import com.jd.blockchain.ledger.CryptoSetting; import com.jd.blockchain.ledger.ParticipantNode; import com.jd.blockchain.ledger.core.CryptoConfig; @@ -30,6 +34,10 @@ import com.jd.blockchain.utils.Bytes; * Created by zhangshuang3 on 2018/8/31. */ public class LedgerMetaDataTest { + + private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(), + SMCryptoService.class.getName() }; + byte[] seed = null; String consensusProvider = "test-provider"; byte[] consensusSettingBytes = null; @@ -56,7 +64,13 @@ public class LedgerMetaDataTest { // ConsensusConfig consensusConfig = new ConsensusConfig(); // consensusConfig.setValue(settingValue);ClassicCryptoService.ED25519_ALGORITHM + CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length]; + for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) { + supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]); + } + CryptoConfig cryptoConfig = new CryptoConfig(); + cryptoConfig.setSupportedProviders(supportedProviders); cryptoConfig.setAutoVerifyHash(true); cryptoConfig.setHashAlgorithm(ClassicAlgorithm.SHA256); @@ -93,7 +107,13 @@ public class LedgerMetaDataTest { // ConsensusConfig consensusConfig = new ConsensusConfig(); // consensusConfig.setValue(settingValue); + CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length]; + for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) { + supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]); + } + CryptoConfig cryptoConfig = new CryptoConfig(); + cryptoConfig.setSupportedProviders(supportedProviders); cryptoConfig.setAutoVerifyHash(true); cryptoConfig.setHashAlgorithm(ClassicAlgorithm.SHA256); @@ -133,7 +153,14 @@ public class LedgerMetaDataTest { @Test public void testSerialize_CryptoSetting() { // LedgerCodes.METADATA_LEDGER_SETTING_CRYPTO + + CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length]; + for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) { + supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]); + } + CryptoConfig cryptoConfig = new CryptoConfig(); + cryptoConfig.setSupportedProviders(supportedProviders); cryptoConfig.setAutoVerifyHash(true); cryptoConfig.setHashAlgorithm(ClassicAlgorithm.SHA256); byte[] encodeBytes = BinaryProtocol.encode(cryptoConfig, CryptoSetting.class); diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerTestUtils.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerTestUtils.java index d6f6ae43..9bfdcc6a 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerTestUtils.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerTestUtils.java @@ -4,10 +4,13 @@ import java.util.Random; import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.Crypto; +import com.jd.blockchain.crypto.CryptoProvider; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.crypto.SignatureFunction; import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm; +import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; +import com.jd.blockchain.crypto.service.sm.SMCryptoService; import com.jd.blockchain.ledger.BlockchainIdentityData; import com.jd.blockchain.ledger.CryptoSetting; import com.jd.blockchain.ledger.PreparedTransaction; @@ -22,6 +25,9 @@ public class LedgerTestUtils { // private static ThreadLocalRandom rand = ThreadLocalRandom.current(); + private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(), + SMCryptoService.class.getName() }; + private static Random rand = new Random(); public static TransactionRequest createTxRequest(HashDigest ledgerHash) { @@ -76,7 +82,14 @@ public class LedgerTestUtils { } public static CryptoSetting createDefaultCryptoSetting() { + + CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length]; + for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) { + supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]); + } + CryptoConfig cryptoSetting = new CryptoConfig(); + cryptoSetting.setSupportedProviders(supportedProviders); cryptoSetting.setAutoVerifyHash(true); cryptoSetting.setHashAlgorithm(ClassicAlgorithm.SHA256); return cryptoSetting; diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/MerkleDataSetTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/MerkleDataSetTest.java index 2e966c50..fbb5eb09 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/MerkleDataSetTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/MerkleDataSetTest.java @@ -14,8 +14,12 @@ import java.util.Set; import org.junit.Test; +import com.jd.blockchain.crypto.Crypto; +import com.jd.blockchain.crypto.CryptoProvider; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm; +import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; +import com.jd.blockchain.crypto.service.sm.SMCryptoService; import com.jd.blockchain.ledger.core.CryptoConfig; import com.jd.blockchain.ledger.core.MerkleDataSet; import com.jd.blockchain.ledger.core.MerkleProof; @@ -26,13 +30,23 @@ import com.jd.blockchain.utils.io.BytesUtils; public class MerkleDataSetTest { + private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(), + SMCryptoService.class.getName() }; + /** * 测试存储的增长; */ @Test public void testStorageIncreasement() { + + CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length]; + for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) { + supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]); + } + String keyPrefix = ""; CryptoConfig cryptoConfig = new CryptoConfig(); + cryptoConfig.setSupportedProviders(supportedProviders); cryptoConfig.setHashAlgorithm(ClassicAlgorithm.SHA256); cryptoConfig.setAutoVerifyHash(true); @@ -116,7 +130,13 @@ public class MerkleDataSetTest { String keyPrefix = ""; Random rand = new Random(); + CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length]; + for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) { + supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]); + } + CryptoConfig cryptoConfig = new CryptoConfig(); + cryptoConfig.setSupportedProviders(supportedProviders); cryptoConfig.setHashAlgorithm(ClassicAlgorithm.SHA256); cryptoConfig.setAutoVerifyHash(true); @@ -281,7 +301,13 @@ public class MerkleDataSetTest { String keyPrefix = ""; Random rand = new Random(); + CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length]; + for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) { + supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]); + } + CryptoConfig cryptoConfig = new CryptoConfig(); + cryptoConfig.setSupportedProviders(supportedProviders); cryptoConfig.setHashAlgorithm(ClassicAlgorithm.SHA256); cryptoConfig.setAutoVerifyHash(true); diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/CryptoProviderInfo.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/CryptoProviderInfo.java deleted file mode 100644 index 01527459..00000000 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/CryptoProviderInfo.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.crypto.CryptoAlgorithm; - -public interface CryptoProviderInfo { - - String getName(); - - CryptoAlgorithm[] getAlgorithms(); - - -} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/CryptoSetting.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/CryptoSetting.java index cb41c645..373fd1b3 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/CryptoSetting.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/CryptoSetting.java @@ -4,6 +4,7 @@ import com.jd.blockchain.binaryproto.DataContract; import com.jd.blockchain.binaryproto.DataField; import com.jd.blockchain.binaryproto.PrimitiveType; import com.jd.blockchain.consts.DataCodes; +import com.jd.blockchain.crypto.CryptoProvider; /** * 默克尔树算法相关的配置; @@ -14,6 +15,15 @@ import com.jd.blockchain.consts.DataCodes; @DataContract(code = DataCodes.METADATA_CRYPTO_SETTING) public interface CryptoSetting { + /** + * 系统支持的密码服务提供者; + * + * @return + */ + public CryptoProvider[] getSupportedProviders(); + + + /** * 系统中使用的 Hash 算法;
* @@ -27,7 +37,7 @@ public interface CryptoSetting { public short getHashAlgorithm(); /** - * 当有完整性证明的数据被从持久化介质中加载时,是否对其进行完整性校验(重新计算 hash 比对是否一致);
+ * 当有加载附带哈希摘要的数据时,是否重新计算哈希摘要进行完整性校验;
* * 如果为 true ,则自动进行校验,如果校验失败,会引发异常;
* @@ -37,5 +47,6 @@ public interface CryptoSetting { */ @DataField(order = 2, primitiveType = PrimitiveType.BOOLEAN) public boolean getAutoVerifyHash(); + } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOpTemplate.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOpTemplate.java index 5a1b48ab..a9873c4c 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOpTemplate.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOpTemplate.java @@ -49,7 +49,7 @@ public class DataAccountKVSetOpTemplate implements DataAccountKVSetOperation { public void set(String key, BytesValue value, long expVersion) { if (kvset.containsKey(key)) { - throw new IllegalArgumentException("Cann't set the same key repeatly!"); + throw new IllegalArgumentException("Cann't set the same key repeatedly!"); } KVData kvdata = new KVData(key, value, expVersion); kvset.put(key, kvdata); @@ -57,7 +57,7 @@ public class DataAccountKVSetOpTemplate implements DataAccountKVSetOperation { public void set(KVData kvData) { if (kvset.containsKey(kvData.getKey())) { - throw new IllegalArgumentException("Cann't set the same key repeatly!"); + throw new IllegalArgumentException("Cann't set the same key repeatedly!"); } kvset.put(kvData.getKey(), kvData); } diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeTest.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeTest.java index e96d3c18..3fee1d32 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeTest.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeTest.java @@ -19,12 +19,15 @@ import com.jd.blockchain.consensus.ConsensusProviders; import com.jd.blockchain.consensus.ConsensusSettings; import com.jd.blockchain.crypto.AddressEncoding; import com.jd.blockchain.crypto.CryptoAlgorithm; +import com.jd.blockchain.crypto.CryptoProvider; import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.Crypto; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.crypto.SignatureDigest; +import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; +import com.jd.blockchain.crypto.service.sm.SMCryptoService; import com.jd.blockchain.ledger.LedgerBlock; import com.jd.blockchain.ledger.LedgerInitOperation; import com.jd.blockchain.ledger.UserRegisterOperation; @@ -60,6 +63,9 @@ public class LedgerInitializeTest { DataContractRegistry.register(UserRegisterOperation.class); } + private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(), + SMCryptoService.class.getName() }; + public static final String PASSWORD = IntegrationBase.PASSWORD; public static final String[] PUB_KEYS = IntegrationBase.PUB_KEYS; @@ -254,7 +260,12 @@ public class LedgerInitializeTest { ConsensusSettings csProps, ConsensusProvider csProvider, DBConnectionConfig dbConnConfig, Prompter prompter, boolean autoVerifyHash) { + CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length]; + for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) { + supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]); + } CryptoConfig cryptoSetting = new CryptoConfig(); + cryptoSetting.setSupportedProviders(supportedProviders); cryptoSetting.setAutoVerifyHash(autoVerifyHash); cryptoSetting.setHashAlgorithm(Crypto.getAlgorithm("SHA256")); diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitializeWebController.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitializeWebController.java index 42e1d5d6..546e154b 100644 --- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitializeWebController.java +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitializeWebController.java @@ -20,12 +20,15 @@ import com.jd.blockchain.binaryproto.DataContractRegistry; import com.jd.blockchain.consensus.ConsensusProvider; import com.jd.blockchain.consensus.ConsensusSettings; import com.jd.blockchain.crypto.CryptoAlgorithm; +import com.jd.blockchain.crypto.CryptoProvider; import com.jd.blockchain.crypto.Crypto; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.crypto.SignatureDigest; import com.jd.blockchain.crypto.SignatureFunction; +import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; +import com.jd.blockchain.crypto.service.sm.SMCryptoService; import com.jd.blockchain.ledger.BlockchainIdentity; import com.jd.blockchain.ledger.BlockchainIdentityData; import com.jd.blockchain.ledger.CryptoSetting; @@ -75,6 +78,10 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI static { DataContractRegistry.register(TransactionRequest.class); } + + private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(), + SMCryptoService.class.getName() }; + private static final String DEFAULT_SIGN_ALGORITHM = "ED25519"; @@ -299,7 +306,12 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI } public CryptoSetting createDefaultCryptoSetting() { + CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length]; + for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) { + supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]); + } CryptoConfig defCryptoSetting = new CryptoConfig(); + defCryptoSetting.setSupportedProviders(supportedProviders); defCryptoSetting.setAutoVerifyHash(true); defCryptoSetting.setHashAlgorithm(Crypto.getAlgorithm("SHA256")); From 03e850ba0d6e8c3dd620d70d5cc63fa771ea723d Mon Sep 17 00:00:00 2001 From: huanghaiquan Date: Mon, 20 May 2019 03:52:43 +0800 Subject: [PATCH 37/43] Optimized ledger init configuration: add consensus service provider attributes; --- ...va => LedgerInitSettingSerializeTest.java} | 4 +- .../intgr/PresetAnswerPrompter.java | 10 +- .../intgr/consensus/ConsensusTest.java | 25 ++- .../intgr/perf/GlobalPerformanceTest.java | 10 +- .../intgr/perf/LedgerInitializeTest.java | 34 ++-- .../intgr/perf/LedgerInitializeWebTest.java | 27 ++- .../com/jd/blockchain/intgr/perf/Utils.java | 9 +- .../blockchain/intgr/IntegrationBaseTest.java | 43 ++-- .../jd/blockchain/intgr/IntegrationTest2.java | 34 ++-- .../intgr/IntegrationTestDataAccount.java | 28 +-- .../initializer/LedgerInitSettingTest.java | 15 +- .../initializer/LedgerInitializeTest.java | 34 ++-- .../LedgerInitializeWeb4Nodes.java | 24 ++- .../LedgerInitializeWeb4SingleStepsTest.java | 16 +- .../ledger/LedgerBlockGeneratingTest.java | 25 +-- .../src/test/resources/keys/parti2.pub | 1 + .../src/test/resources/ledger.init | 9 +- .../src/test/resources/ledger_init_test.init | 6 + .../test/resources/ledger_init_test_web2.init | 6 + .../tools/initializer/LedgerInitCommand.java | 108 +++++----- .../tools/initializer/LedgerInitProcess.java | 28 +-- .../initializer/LedgerInitProperties.java | 184 ++++++------------ .../tools/initializer/LocalConfig.java | 64 +----- .../tools/initializer/Prompter.java | 22 +++ .../web/LedgerInitializeWebController.java | 96 +++++---- .../jd/blockchain/utils/PropertiesUtils.java | 88 ++++----- .../utils/concurrent/InvocationResult.java | 10 +- .../com/jd/blockchain/utils/io/FileUtils.java | 82 +++++--- 28 files changed, 469 insertions(+), 573 deletions(-) rename source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/{LedgerInitSettingTest.java => LedgerInitSettingSerializeTest.java} (99%) create mode 100644 source/test/test-integration/src/test/resources/keys/parti2.pub diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitSettingTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitSettingSerializeTest.java similarity index 99% rename from source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitSettingTest.java rename to source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitSettingSerializeTest.java index 7e2c6850..f867ae9b 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitSettingTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitSettingSerializeTest.java @@ -28,7 +28,7 @@ import com.jd.blockchain.transaction.LedgerInitSettingData; import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.net.NetworkAddress; -public class LedgerInitSettingTest { +public class LedgerInitSettingSerializeTest { byte[] seed = null; byte[] csSysSettingBytes = null; LedgerInitSettingData ledgerInitSettingData = new LedgerInitSettingData(); @@ -84,7 +84,7 @@ public class LedgerInitSettingTest { ConsensusParticipantData[] parties1 = Arrays.copyOf(parties, 4); ledgerInitSettingData.setConsensusParticipants(parties1); - + byte[] encode = BinaryProtocol.encode(ledgerInitSettingData, LedgerInitSetting.class); LedgerInitSetting decode = BinaryProtocol.decode(encode); diff --git a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/PresetAnswerPrompter.java b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/PresetAnswerPrompter.java index 152ee356..d6ccbc6a 100644 --- a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/PresetAnswerPrompter.java +++ b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/PresetAnswerPrompter.java @@ -7,13 +7,13 @@ import com.jd.blockchain.tools.initializer.ConsolePrompter; public class PresetAnswerPrompter extends ConsolePrompter { private Properties answers = new Properties(); - + private String defaultAnswer; - + public PresetAnswerPrompter(String defaultAnswer) { this.defaultAnswer = defaultAnswer; } - + public void setAnswer(String tag, String answer) { answers.setProperty(tag, answer); } @@ -21,7 +21,7 @@ public class PresetAnswerPrompter extends ConsolePrompter { public void setDefaultAnswer(String defaultAnswer) { this.defaultAnswer = defaultAnswer; } - + @Override public String confirm(String tag, String format, Object... args) { System.out.print(String.format(format, args)); @@ -29,7 +29,5 @@ public class PresetAnswerPrompter extends ConsolePrompter { System.out.println(String.format("\r\n [Mocked answer:%s]", answer)); return answer; } - - } diff --git a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/consensus/ConsensusTest.java b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/consensus/ConsensusTest.java index bfb0a392..d7f66545 100644 --- a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/consensus/ConsensusTest.java +++ b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/consensus/ConsensusTest.java @@ -215,26 +215,26 @@ public class ConsensusTest { DBConnectionConfig testDb0 = new DBConnectionConfig(); testDb0.setConnectionUri("memory://local/0"); LedgerBindingConfig bindingConfig0 = new LedgerBindingConfig(); - AsyncCallback callback0 = nodeCtx0.startInitCommand(privkey0, encodedPassword, initSetting, csProps,csProvider, - testDb0, consolePrompter, bindingConfig0, quitLatch); + AsyncCallback callback0 = nodeCtx0.startInitCommand(privkey0, encodedPassword, initSetting, csProps, + csProvider, testDb0, consolePrompter, bindingConfig0, quitLatch); DBConnectionConfig testDb1 = new DBConnectionConfig(); testDb1.setConnectionUri("memory://local/1"); LedgerBindingConfig bindingConfig1 = new LedgerBindingConfig(); - AsyncCallback callback1 = nodeCtx1.startInitCommand(privkey1, encodedPassword, initSetting, csProps,csProvider, - testDb1, consolePrompter, bindingConfig1, quitLatch); + AsyncCallback callback1 = nodeCtx1.startInitCommand(privkey1, encodedPassword, initSetting, csProps, + csProvider, testDb1, consolePrompter, bindingConfig1, quitLatch); DBConnectionConfig testDb2 = new DBConnectionConfig(); testDb2.setConnectionUri("memory://local/2"); LedgerBindingConfig bindingConfig2 = new LedgerBindingConfig(); - AsyncCallback callback2 = nodeCtx2.startInitCommand(privkey2, encodedPassword, initSetting, csProps,csProvider, - testDb2, consolePrompter, bindingConfig2, quitLatch); + AsyncCallback callback2 = nodeCtx2.startInitCommand(privkey2, encodedPassword, initSetting, csProps, + csProvider, testDb2, consolePrompter, bindingConfig2, quitLatch); DBConnectionConfig testDb3 = new DBConnectionConfig(); testDb3.setConnectionUri("memory://local/3"); LedgerBindingConfig bindingConfig3 = new LedgerBindingConfig(); - AsyncCallback callback3 = nodeCtx3.startInitCommand(privkey3, encodedPassword, initSetting, csProps,csProvider, - testDb3, consolePrompter, bindingConfig3, quitLatch); + AsyncCallback callback3 = nodeCtx3.startInitCommand(privkey3, encodedPassword, initSetting, csProps, + csProvider, testDb3, consolePrompter, bindingConfig3, quitLatch); HashDigest ledgerHash0 = callback0.waitReturn(); HashDigest ledgerHash1 = callback1.waitReturn(); @@ -354,8 +354,8 @@ public class ConsensusTest { } public AsyncCallback startInit(PrivKey privKey, LedgerInitProperties setting, - ConsensusSettings csProps, ConsensusProvider csProvider, DBConnectionConfig dbConnConfig, Prompter prompter, - CountDownLatch quitLatch) { + ConsensusSettings csProps, ConsensusProvider csProvider, DBConnectionConfig dbConnConfig, + Prompter prompter, CountDownLatch quitLatch) { ThreadInvoker invoker = new ThreadInvoker() { @Override @@ -364,7 +364,7 @@ public class ConsensusTest { // NodeWebContext.this.initProcess = ctx.getBean(LedgerInitProcess.class); NodeInitContext.this.dbConnConfig = dbConnConfig; - HashDigest ledgerHash = NodeInitContext.this.initProcess.initialize(id, privKey, setting, csProps, csProvider, + HashDigest ledgerHash = NodeInitContext.this.initProcess.initialize(id, privKey, setting, dbConnConfig, prompter); quitLatch.countDown(); @@ -386,8 +386,7 @@ public class ConsensusTest { @Override protected HashDigest invoke() throws Exception { LedgerInitCommand initCmd = new LedgerInitCommand(); - HashDigest ledgerHash = initCmd.startInit(id, privKey, base58Pwd, ledgerSetting, csProps, - csProvider, dbConnConfig, prompter, conf, db); + HashDigest ledgerHash = initCmd.startInit(id, privKey, base58Pwd, ledgerSetting, dbConnConfig, prompter, conf, db); NodeInitContext.this.ledgerManager = initCmd.getLedgerManager(); quitLatch.countDown(); return ledgerHash; diff --git a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/GlobalPerformanceTest.java b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/GlobalPerformanceTest.java index ee1ecf4e..a35584c0 100644 --- a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/GlobalPerformanceTest.java +++ b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/GlobalPerformanceTest.java @@ -187,7 +187,7 @@ public class GlobalPerformanceTest { Properties props = Utils.loadConsensusSetting(); ConsensusProvider csProvider = getConsensusProvider(); ConsensusSettings csProps = csProvider.getSettingsFactory().getConsensusSettingsBuilder().createSettings(props); - + // 启动服务器; NetworkAddress initAddr0 = initSetting.getConsensusParticipant(0).getInitializerAddress(); NodeInitContext nodeCtx0 = new NodeInitContext(0, initAddr0); @@ -365,8 +365,8 @@ public class GlobalPerformanceTest { // NodeWebContext.this.initProcess = ctx.getBean(LedgerInitProcess.class); NodeInitContext.this.dbConnConfig = dbConnConfig; - HashDigest ledgerHash = NodeInitContext.this.initProcess.initialize(id, privKey, setting, csProps, - csProvider, dbConnConfig, prompter); + HashDigest ledgerHash = NodeInitContext.this.initProcess.initialize(id, privKey, setting, + dbConnConfig, prompter); quitLatch.countDown(); return ledgerHash; @@ -387,8 +387,8 @@ public class GlobalPerformanceTest { @Override protected HashDigest invoke() throws Exception { LedgerInitCommand initCmd = new LedgerInitCommand(); - HashDigest ledgerHash = initCmd.startInit(id, privKey, base58Pwd, ledgerSetting, csProps, - csProvider, dbConnConfig, prompter, conf, db); + HashDigest ledgerHash = initCmd.startInit(id, privKey, base58Pwd, ledgerSetting, dbConnConfig, + prompter, conf, db); NodeInitContext.this.ledgerManager = initCmd.getLedgerManager(); quitLatch.countDown(); return ledgerHash; diff --git a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerInitializeTest.java b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerInitializeTest.java index 9a5cbd36..dbd8b21b 100644 --- a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerInitializeTest.java +++ b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerInitializeTest.java @@ -68,9 +68,6 @@ public class LedgerInitializeTest { public void testInitWith4Nodes() { Prompter consolePrompter = new PresetAnswerPrompter("N"); // new ConsolePrompter(); LedgerInitProperties initSetting = loadInitSetting(); - Properties props = loadConsensusSetting(); - ConsensusProvider csProvider = getConsensusProvider(); - ConsensusSettings csProps = csProvider.getSettingsFactory().getConsensusSettingsBuilder().createSettings(props); NodeContext node0 = new NodeContext(initSetting.getConsensusParticipant(0).getInitializerAddress(), serviceRegisterMap); @@ -81,31 +78,28 @@ public class LedgerInitializeTest { NodeContext node3 = new NodeContext(initSetting.getConsensusParticipant(3).getInitializerAddress(), serviceRegisterMap); - String[] memoryConnString = new String[]{"memory://local/0", "memory://local/1", "memory://local/2", "memory://local/3"}; + String[] memoryConnString = new String[] { "memory://local/0", "memory://local/1", "memory://local/2", + "memory://local/3" }; PrivKey privkey0 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[0], PASSWORD); DBConnectionConfig testDb0 = new DBConnectionConfig(); testDb0.setConnectionUri(memoryConnString[0]); - AsyncCallback callback0 = node0.startInit(0, privkey0, initSetting, csProps, csProvider, testDb0, - consolePrompter); + AsyncCallback callback0 = node0.startInit(0, privkey0, initSetting, testDb0, consolePrompter); PrivKey privkey1 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[1], PASSWORD); DBConnectionConfig testDb1 = new DBConnectionConfig(); testDb1.setConnectionUri(memoryConnString[1]); - AsyncCallback callback1 = node1.startInit(1, privkey1, initSetting, csProps, csProvider, testDb1, - consolePrompter); + AsyncCallback callback1 = node1.startInit(1, privkey1, initSetting, testDb1, consolePrompter); PrivKey privkey2 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[2], PASSWORD); DBConnectionConfig testDb2 = new DBConnectionConfig(); testDb2.setConnectionUri(memoryConnString[2]); - AsyncCallback callback2 = node2.startInit(2, privkey2, initSetting, csProps, csProvider, testDb2, - consolePrompter); + AsyncCallback callback2 = node2.startInit(2, privkey2, initSetting, testDb2, consolePrompter); PrivKey privkey3 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[3], PASSWORD); DBConnectionConfig testDb03 = new DBConnectionConfig(); testDb03.setConnectionUri(memoryConnString[3]); - AsyncCallback callback3 = node3.startInit(3, privkey3, initSetting, csProps, csProvider, testDb03, - consolePrompter); + AsyncCallback callback3 = node3.startInit(3, privkey3, initSetting, testDb03, consolePrompter); HashDigest ledgerHash0 = callback0.waitReturn(); HashDigest ledgerHash1 = callback1.waitReturn(); @@ -188,23 +182,21 @@ public class LedgerInitializeTest { public NodeContext(NetworkAddress address, Map serviceRegisterMap) { this.initCsServiceFactory = new MultiThreadInterInvokerFactory(serviceRegisterMap); - LedgerInitializeWebController initController = new LedgerInitializeWebController(ledgerManager, memoryDBConnFactory, - initCsServiceFactory); + LedgerInitializeWebController initController = new LedgerInitializeWebController(ledgerManager, + memoryDBConnFactory, initCsServiceFactory); serviceRegisterMap.put(address, initController); this.initProcess = initController; } public AsyncCallback startInit(int currentId, PrivKey privKey, LedgerInitProperties setting, - ConsensusSettings csProps, ConsensusProvider csProvider, DBConnectionConfig dbConnConfig, - Prompter prompter) { + DBConnectionConfig dbConnConfig, Prompter prompter) { partiKey = new AsymmetricKeypair(setting.getConsensusParticipant(0).getPubKey(), privKey); ThreadInvoker invoker = new ThreadInvoker() { @Override protected HashDigest invoke() throws Exception { - return initProcess.initialize(currentId, privKey, setting, csProps, csProvider, dbConnConfig, - prompter); + return initProcess.initialize(currentId, privKey, setting, dbConnConfig, prompter); } }; @@ -212,8 +204,7 @@ public class LedgerInitializeTest { } public AsyncCallback startInit(int currentId, PrivKey privKey, LedgerInitProperties setting, - ConsensusSettings csProps, ConsensusProvider csProvider, DBConnectionConfig dbConnConfig, - Prompter prompter, boolean autoVerifyHash) { + DBConnectionConfig dbConnConfig, Prompter prompter, boolean autoVerifyHash) { CryptoConfig cryptoSetting = new CryptoConfig(); cryptoSetting.setAutoVerifyHash(autoVerifyHash); @@ -224,8 +215,7 @@ public class LedgerInitializeTest { ThreadInvoker invoker = new ThreadInvoker() { @Override protected HashDigest invoke() throws Exception { - return initProcess.initialize(currentId, privKey, setting, csProps, csProvider, dbConnConfig, - prompter, cryptoSetting); + return initProcess.initialize(currentId, privKey, setting, dbConnConfig, prompter, cryptoSetting); } }; diff --git a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerInitializeWebTest.java b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerInitializeWebTest.java index 2a72c515..fe0d8bbc 100644 --- a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerInitializeWebTest.java +++ b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerInitializeWebTest.java @@ -264,23 +264,23 @@ public class LedgerInitializeWebTest { DBConnectionConfig testDb0 = new DBConnectionConfig(); testDb0.setConnectionUri("memory://local/0"); - AsyncCallback callback0 = node0.startInit(privkey0, initSetting, csProps, csProvider, testDb0, - consolePrompter, quitLatch); + AsyncCallback callback0 = node0.startInit(privkey0, initSetting, testDb0, consolePrompter, + quitLatch); DBConnectionConfig testDb1 = new DBConnectionConfig(); testDb1.setConnectionUri("memory://local/1"); - AsyncCallback callback1 = node1.startInit(privkey1, initSetting, csProps, csProvider, testDb1, - consolePrompter, quitLatch); + AsyncCallback callback1 = node1.startInit(privkey1, initSetting, testDb1, consolePrompter, + quitLatch); DBConnectionConfig testDb2 = new DBConnectionConfig(); testDb2.setConnectionUri("memory://local/2"); - AsyncCallback callback2 = node2.startInit(privkey2, initSetting, csProps, csProvider, testDb2, - consolePrompter, quitLatch); + AsyncCallback callback2 = node2.startInit(privkey2, initSetting, testDb2, consolePrompter, + quitLatch); DBConnectionConfig testDb03 = new DBConnectionConfig(); testDb03.setConnectionUri("memory://local/3"); - AsyncCallback callback3 = node3.startInit(privkey3, initSetting, csProps, csProvider, testDb03, - consolePrompter, quitLatch); + AsyncCallback callback3 = node3.startInit(privkey3, initSetting, testDb03, consolePrompter, + quitLatch); HashDigest ledgerHash0 = callback0.waitReturn(); HashDigest ledgerHash1 = callback1.waitReturn(); @@ -402,8 +402,7 @@ public class LedgerInitializeWebTest { } public AsyncCallback startInit(PrivKey privKey, LedgerInitProperties setting, - ConsensusSettings csProps, ConsensusProvider csProvider, DBConnectionConfig dbConnConfig, - Prompter prompter, CountDownLatch quitLatch) { + DBConnectionConfig dbConnConfig, Prompter prompter, CountDownLatch quitLatch) { ThreadInvoker invoker = new ThreadInvoker() { @Override @@ -412,8 +411,8 @@ public class LedgerInitializeWebTest { // NodeWebContext.this.initProcess = ctx.getBean(LedgerInitProcess.class); NodeWebContext.this.dbConnConfig = dbConnConfig; - HashDigest ledgerHash = NodeWebContext.this.initProcess.initialize(id, privKey, setting, csProps, - csProvider, dbConnConfig, prompter); + HashDigest ledgerHash = NodeWebContext.this.initProcess.initialize(id, privKey, setting, + dbConnConfig, prompter); quitLatch.countDown(); return ledgerHash; @@ -443,8 +442,8 @@ public class LedgerInitializeWebTest { @Override protected HashDigest invoke() throws Exception { LedgerInitCommand initCmd = new LedgerInitCommand(); - HashDigest ledgerHash = initCmd.startInit(id, privKey, base58Pwd, ledgerSetting, csProps, - csProvider, dbConnConfig, prompter, conf, db); + HashDigest ledgerHash = initCmd.startInit(id, privKey, base58Pwd, ledgerSetting, dbConnConfig, + prompter, conf, db); NodeWebContext.this.ledgerManager = initCmd.getLedgerManager(); quitLatch.countDown(); return ledgerHash; diff --git a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/Utils.java b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/Utils.java index 7bd15006..33d494a3 100644 --- a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/Utils.java +++ b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/Utils.java @@ -106,16 +106,14 @@ public class Utils { } public AsyncCallback startInit(int currentId, PrivKey privKey, LedgerInitProperties setting, - ConsensusSettings csProps, ConsensusProvider consensusProvider, DBConnectionConfig dbConnConfig, - Prompter prompter) { + DBConnectionConfig dbConnConfig, Prompter prompter) { partiKey = new AsymmetricKeypair(setting.getConsensusParticipant(0).getPubKey(), privKey); ThreadInvoker invoker = new ThreadInvoker() { @Override protected HashDigest invoke() throws Exception { - return initProcess.initialize(currentId, privKey, setting, csProps, consensusProvider, dbConnConfig, - prompter); + return initProcess.initialize(currentId, privKey, setting, dbConnConfig, prompter); } }; @@ -150,8 +148,7 @@ public class Utils { ThreadInvoker invoker = new ThreadInvoker() { @Override protected HashDigest invoke() throws Exception { - return initProcess.initialize(currentId, privKey, setting, csProps, consensusProvider, dbConnConfig, - prompter, cryptoSetting); + return initProcess.initialize(currentId, privKey, setting, dbConnConfig, prompter, cryptoSetting); } }; diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBaseTest.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBaseTest.java index da0e82b8..0703ef98 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBaseTest.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBaseTest.java @@ -1,7 +1,16 @@ package test.com.jd.blockchain.intgr; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; +import java.util.concurrent.CountDownLatch; + +import org.springframework.core.io.ClassPathResource; + import com.jd.blockchain.consensus.ConsensusProvider; -import com.jd.blockchain.consensus.ConsensusProviders; import com.jd.blockchain.consensus.ConsensusSettings; import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.HashDigest; @@ -9,27 +18,21 @@ import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig; import com.jd.blockchain.ledger.LedgerBlock; import com.jd.blockchain.ledger.core.LedgerRepository; -import com.jd.blockchain.tools.initializer.*; +import com.jd.blockchain.tools.initializer.DBConnectionConfig; +import com.jd.blockchain.tools.initializer.LedgerBindingConfig; +import com.jd.blockchain.tools.initializer.LedgerInitProperties; +import com.jd.blockchain.tools.initializer.Prompter; import com.jd.blockchain.tools.keygen.KeyGenCommand; import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback; import com.jd.blockchain.utils.net.NetworkAddress; -import org.springframework.core.io.ClassPathResource; import test.com.jd.blockchain.intgr.IntegratedContext.Node; import test.com.jd.blockchain.intgr.initializer.LedgerInitializeWeb4SingleStepsTest; import test.com.jd.blockchain.intgr.initializer.LedgerInitializeWeb4SingleStepsTest.NodeWebContext; -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; -import java.util.concurrent.CountDownLatch; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - public class IntegrationBaseTest { - LedgerInitConsensusConfig.ConsensusConfig bftsmartConfig = LedgerInitConsensusConfig.bftsmartConfig; + LedgerInitConsensusConfig.ConsensusConfig bftsmartConfig = LedgerInitConsensusConfig.bftsmartConfig; public IntegratedContext context = initLedgers(bftsmartConfig.getConfigPath(), bftsmartConfig.getProvider()); public GatewayTestRunner gateway0; @@ -150,26 +153,26 @@ public class IntegrationBaseTest { DBConnectionConfig testDb0 = new DBConnectionConfig(); testDb0.setConnectionUri(LedgerInitConsensusConfig.memConnectionStrings[0]); LedgerBindingConfig bindingConfig0 = new LedgerBindingConfig(); - AsyncCallback callback0 = nodeCtx0.startInitCommand(privkey0, encodedPassword, initSetting, csProps, - csProvider, testDb0, consolePrompter, bindingConfig0, quitLatch); + AsyncCallback callback0 = nodeCtx0.startInitCommand(privkey0, encodedPassword, initSetting, testDb0, + consolePrompter, bindingConfig0, quitLatch); DBConnectionConfig testDb1 = new DBConnectionConfig(); testDb1.setConnectionUri(LedgerInitConsensusConfig.memConnectionStrings[1]); LedgerBindingConfig bindingConfig1 = new LedgerBindingConfig(); - AsyncCallback callback1 = nodeCtx1.startInitCommand(privkey1, encodedPassword, initSetting, csProps, - csProvider, testDb1, consolePrompter, bindingConfig1, quitLatch); + AsyncCallback callback1 = nodeCtx1.startInitCommand(privkey1, encodedPassword, initSetting, testDb1, + consolePrompter, bindingConfig1, quitLatch); DBConnectionConfig testDb2 = new DBConnectionConfig(); testDb2.setConnectionUri(LedgerInitConsensusConfig.memConnectionStrings[2]); LedgerBindingConfig bindingConfig2 = new LedgerBindingConfig(); - AsyncCallback callback2 = nodeCtx2.startInitCommand(privkey2, encodedPassword, initSetting, csProps, - csProvider, testDb2, consolePrompter, bindingConfig2, quitLatch); + AsyncCallback callback2 = nodeCtx2.startInitCommand(privkey2, encodedPassword, initSetting, testDb2, + consolePrompter, bindingConfig2, quitLatch); DBConnectionConfig testDb3 = new DBConnectionConfig(); testDb3.setConnectionUri(LedgerInitConsensusConfig.memConnectionStrings[3]); LedgerBindingConfig bindingConfig3 = new LedgerBindingConfig(); - AsyncCallback callback3 = nodeCtx3.startInitCommand(privkey3, encodedPassword, initSetting, csProps, - csProvider, testDb3, consolePrompter, bindingConfig3, quitLatch); + AsyncCallback callback3 = nodeCtx3.startInitCommand(privkey3, encodedPassword, initSetting, testDb3, + consolePrompter, bindingConfig3, quitLatch); HashDigest ledgerHash0 = callback0.waitReturn(); HashDigest ledgerHash1 = callback1.waitReturn(); diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest2.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest2.java index 4e8d317b..a6f2f30a 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest2.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest2.java @@ -57,7 +57,7 @@ public class IntegrationTest2 { public void test() { // init ledgers of all nodes ; IntegratedContext context = initLedgers(LedgerInitConsensusConfig.mqConfig, - LedgerInitConsensusConfig.memConnectionStrings); + LedgerInitConsensusConfig.memConnectionStrings); Node node0 = context.getNode(0); Node node1 = context.getNode(1); Node node2 = context.getNode(2); @@ -70,10 +70,10 @@ public class IntegrationTest2 { PeerTestRunner peer1 = new PeerTestRunner(peerSrvAddr1, node1.getBindingConfig(), node1.getStorageDB()); NetworkAddress peerSrvAddr2 = new NetworkAddress("127.0.0.1", 13220); - PeerTestRunner peer2 = new PeerTestRunner(peerSrvAddr2,node2.getBindingConfig(), node2.getStorageDB()); + PeerTestRunner peer2 = new PeerTestRunner(peerSrvAddr2, node2.getBindingConfig(), node2.getStorageDB()); NetworkAddress peerSrvAddr3 = new NetworkAddress("127.0.0.1", 13230); - PeerTestRunner peer3 = new PeerTestRunner(peerSrvAddr3,node3.getBindingConfig(), node3.getStorageDB()); + PeerTestRunner peer3 = new PeerTestRunner(peerSrvAddr3, node3.getBindingConfig(), node3.getStorageDB()); AsyncCallback peerStarting0 = peer0.start(); AsyncCallback peerStarting1 = peer1.start(); @@ -192,26 +192,26 @@ public class IntegrationTest2 { DBConnectionConfig testDb0 = new DBConnectionConfig(); testDb0.setConnectionUri(dbConns[0]); LedgerBindingConfig bindingConfig0 = new LedgerBindingConfig(); - AsyncCallback callback0 = nodeCtx0.startInitCommand(privkey0, encodedPassword, initSetting, csProps, csProvider, - testDb0, consolePrompter, bindingConfig0, quitLatch); + AsyncCallback callback0 = nodeCtx0.startInitCommand(privkey0, encodedPassword, initSetting, testDb0, + consolePrompter, bindingConfig0, quitLatch); DBConnectionConfig testDb1 = new DBConnectionConfig(); testDb1.setConnectionUri(dbConns[1]); LedgerBindingConfig bindingConfig1 = new LedgerBindingConfig(); - AsyncCallback callback1 = nodeCtx1.startInitCommand(privkey1, encodedPassword, initSetting, csProps,csProvider, - testDb1, consolePrompter, bindingConfig1, quitLatch); + AsyncCallback callback1 = nodeCtx1.startInitCommand(privkey1, encodedPassword, initSetting, testDb1, + consolePrompter, bindingConfig1, quitLatch); DBConnectionConfig testDb2 = new DBConnectionConfig(); testDb2.setConnectionUri(dbConns[2]); LedgerBindingConfig bindingConfig2 = new LedgerBindingConfig(); - AsyncCallback callback2 = nodeCtx2.startInitCommand(privkey2, encodedPassword, initSetting, csProps,csProvider, - testDb2, consolePrompter, bindingConfig2, quitLatch); + AsyncCallback callback2 = nodeCtx2.startInitCommand(privkey2, encodedPassword, initSetting, testDb2, + consolePrompter, bindingConfig2, quitLatch); DBConnectionConfig testDb3 = new DBConnectionConfig(); testDb3.setConnectionUri(dbConns[3]); LedgerBindingConfig bindingConfig3 = new LedgerBindingConfig(); - AsyncCallback callback3 = nodeCtx3.startInitCommand(privkey3, encodedPassword, initSetting, csProps,csProvider, - testDb3, consolePrompter, bindingConfig3, quitLatch); + AsyncCallback callback3 = nodeCtx3.startInitCommand(privkey3, encodedPassword, initSetting, testDb3, + consolePrompter, bindingConfig3, quitLatch); HashDigest ledgerHash0 = callback0.waitReturn(); HashDigest ledgerHash1 = callback1.waitReturn(); @@ -286,7 +286,7 @@ public class IntegrationTest2 { } private void testSDK_Contract(AsymmetricKeypair adminKey, HashDigest ledgerHash, - BlockchainService blockchainService, IntegratedContext context) { + BlockchainService blockchainService, IntegratedContext context) { BlockchainKeypair userKey = BlockchainKeyGenerator.getInstance().generate(); // 定义交易; @@ -304,19 +304,18 @@ public class IntegrationTest2 { assertTrue(txResp.isSuccess()); // execute the contract; - testContractExe(adminKey, ledgerHash, userKey, blockchainService, context); + testContractExe(adminKey, ledgerHash, userKey, blockchainService, context); } private void testContractExe(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainKeypair userKey, - BlockchainService blockchainService, IntegratedContext context) { + BlockchainService blockchainService, IntegratedContext context) { LedgerInfo ledgerInfo = blockchainService.getLedger(ledgerHash); - LedgerBlock previousBlock = blockchainService.getBlock(ledgerHash, ledgerInfo.getLatestBlockHeight()-1); + LedgerBlock previousBlock = blockchainService.getBlock(ledgerHash, ledgerInfo.getLatestBlockHeight() - 1); // 定义交易; TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); - txTpl.contractEvents().send(contractDeployKey.getAddress(), eventName, - ("888##999##abc").getBytes()); + txTpl.contractEvents().send(contractDeployKey.getAddress(), eventName, ("888##999##abc").getBytes()); // 签名; PreparedTransaction ptx = txTpl.prepare(); @@ -327,7 +326,6 @@ public class IntegrationTest2 { assertTrue(txResp.isSuccess()); } - /** * 根据合约构建字节数组; * diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestDataAccount.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestDataAccount.java index bc16860c..5b1b5457 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestDataAccount.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestDataAccount.java @@ -8,13 +8,11 @@ import java.io.InputStream; import java.util.Properties; import java.util.concurrent.CountDownLatch; -import com.jd.blockchain.storage.service.DbConnection; import org.junit.Test; import org.springframework.core.io.ClassPathResource; import com.alibaba.fastjson.JSON; import com.jd.blockchain.consensus.ConsensusProvider; -import com.jd.blockchain.consensus.ConsensusProviders; import com.jd.blockchain.consensus.ConsensusSettings; import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.HashDigest; @@ -34,6 +32,7 @@ import com.jd.blockchain.ledger.core.LedgerRepository; import com.jd.blockchain.ledger.core.impl.LedgerManager; import com.jd.blockchain.sdk.BlockchainService; import com.jd.blockchain.sdk.client.GatewayServiceFactory; +import com.jd.blockchain.storage.service.DbConnection; import com.jd.blockchain.tools.initializer.DBConnectionConfig; import com.jd.blockchain.tools.initializer.LedgerBindingConfig; import com.jd.blockchain.tools.initializer.LedgerInitProperties; @@ -50,7 +49,7 @@ import test.com.jd.blockchain.intgr.initializer.LedgerInitializeWeb4SingleStepsT public class IntegrationTestDataAccount { - LedgerInitConsensusConfig.ConsensusConfig config = LedgerInitConsensusConfig.mqConfig; + LedgerInitConsensusConfig.ConsensusConfig config = LedgerInitConsensusConfig.mqConfig; public IntegratedContext context = initLedgers(config, LedgerInitConsensusConfig.memConnectionStrings); public GatewayTestRunner gateway0; @@ -173,8 +172,8 @@ public class IntegrationTestDataAccount { } // 通过调用SDK->GATEWAY,测试一个区块包含多个交易时的写入情况,并验证写入结果; - private void testAddKvOpToDataAccount(GatewayTestRunner gateway, AsymmetricKeypair adminKey, IntegratedContext context, - Bytes dataAddr) { + private void testAddKvOpToDataAccount(GatewayTestRunner gateway, AsymmetricKeypair adminKey, + IntegratedContext context, Bytes dataAddr) { GatewayServiceFactory gwsrvFact = GatewayServiceFactory.connect(gateway.getServiceAddress()); BlockchainService blockchainService = gwsrvFact.getBlockchainService(); @@ -182,7 +181,8 @@ public class IntegrationTestDataAccount { LedgerManager ledgerManager = context.getNode(0).getLedgerManager(); - DbConnection memoryBasedDb = context.getNode(0).getStorageDB().connect(LedgerInitConsensusConfig.memConnectionStrings[0]); + DbConnection memoryBasedDb = context.getNode(0).getStorageDB() + .connect(LedgerInitConsensusConfig.memConnectionStrings[0]); LedgerRepository ledgerRepository = ledgerManager.register(ledgerHashs[0], memoryBasedDb.getStorageService()); @@ -288,26 +288,26 @@ public class IntegrationTestDataAccount { DBConnectionConfig testDb0 = new DBConnectionConfig(); testDb0.setConnectionUri(dbConns[0]); LedgerBindingConfig bindingConfig0 = new LedgerBindingConfig(); - AsyncCallback callback0 = nodeCtx0.startInitCommand(privkey0, encodedPassword, initSetting, csProps, - csProvider, testDb0, consolePrompter, bindingConfig0, quitLatch); + AsyncCallback callback0 = nodeCtx0.startInitCommand(privkey0, encodedPassword, initSetting, testDb0, + consolePrompter, bindingConfig0, quitLatch); DBConnectionConfig testDb1 = new DBConnectionConfig(); testDb1.setConnectionUri(dbConns[1]); LedgerBindingConfig bindingConfig1 = new LedgerBindingConfig(); - AsyncCallback callback1 = nodeCtx1.startInitCommand(privkey1, encodedPassword, initSetting, csProps, - csProvider, testDb1, consolePrompter, bindingConfig1, quitLatch); + AsyncCallback callback1 = nodeCtx1.startInitCommand(privkey1, encodedPassword, initSetting, testDb1, + consolePrompter, bindingConfig1, quitLatch); DBConnectionConfig testDb2 = new DBConnectionConfig(); testDb2.setConnectionUri(dbConns[2]); LedgerBindingConfig bindingConfig2 = new LedgerBindingConfig(); - AsyncCallback callback2 = nodeCtx2.startInitCommand(privkey2, encodedPassword, initSetting, csProps, - csProvider, testDb2, consolePrompter, bindingConfig2, quitLatch); + AsyncCallback callback2 = nodeCtx2.startInitCommand(privkey2, encodedPassword, initSetting, testDb2, + consolePrompter, bindingConfig2, quitLatch); DBConnectionConfig testDb3 = new DBConnectionConfig(); testDb3.setConnectionUri(dbConns[3]); LedgerBindingConfig bindingConfig3 = new LedgerBindingConfig(); - AsyncCallback callback3 = nodeCtx3.startInitCommand(privkey3, encodedPassword, initSetting, csProps, - csProvider, testDb3, consolePrompter, bindingConfig3, quitLatch); + AsyncCallback callback3 = nodeCtx3.startInitCommand(privkey3, encodedPassword, initSetting, testDb3, + consolePrompter, bindingConfig3, quitLatch); HashDigest ledgerHash0 = callback0.waitReturn(); HashDigest ledgerHash1 = callback1.waitReturn(); diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitSettingTest.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitSettingTest.java index f0100d9f..02e4ca0a 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitSettingTest.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitSettingTest.java @@ -25,13 +25,14 @@ public class LedgerInitSettingTest { try { LedgerInitProperties setting = LedgerInitProperties.resolve(in); assertEquals(4, setting.getConsensusParticipantCount()); - String expectedLedgerSeed = "932dfe23-fe23232f-283f32fa-dd32aa76-8322ca2f-56236cda-7136b322-cb323ffe".replace("-", ""); + String expectedLedgerSeed = "932dfe23-fe23232f-283f32fa-dd32aa76-8322ca2f-56236cda-7136b322-cb323ffe" + .replace("-", ""); String actualLedgerSeed = HexUtils.encode(setting.getLedgerSeed()); assertEquals(expectedLedgerSeed, actualLedgerSeed); - + ConsensusParticipantConfig part0 = setting.getConsensusParticipant(0); assertEquals("jd.com", part0.getName()); - assertEquals("keys/jd-com.pub", part0.getPubKeyPath()); +// assertEquals("keys/jd-com.pub", part0.getPubKeyPath()); PubKey pubKey0 = KeyGenCommand.decodePubKey("3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9"); assertEquals(pubKey0, part0.getPubKey()); // assertEquals("127.0.0.1", part0.getConsensusAddress().getHost()); @@ -40,15 +41,15 @@ public class LedgerInitSettingTest { assertEquals("127.0.0.1", part0.getInitializerAddress().getHost()); assertEquals(8800, part0.getInitializerAddress().getPort()); assertEquals(true, part0.getInitializerAddress().isSecure()); - + ConsensusParticipantConfig part1 = setting.getConsensusParticipant(1); assertEquals(false, part1.getInitializerAddress().isSecure()); PubKey pubKey1 = KeyGenCommand.decodePubKey("3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX"); assertEquals(pubKey1, part1.getPubKey()); - + ConsensusParticipantConfig part2 = setting.getConsensusParticipant(2); - assertEquals(null, part2.getPubKey()); - + assertEquals("7VeRAr3dSbi1xatq11ZcF7sEPkaMmtZhV9shonGJWk9T4pLe", part2.getPubKey().toBase58()); + } finally { in.close(); } diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeTest.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeTest.java index 3fee1d32..09ddf134 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeTest.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeTest.java @@ -9,19 +9,16 @@ import java.util.Map; import java.util.Properties; import java.util.concurrent.ConcurrentHashMap; -import com.jd.blockchain.storage.service.utils.MemoryDBConnFactory; import org.junit.Test; import org.springframework.core.io.ClassPathResource; import com.jd.blockchain.binaryproto.DataContractRegistry; import com.jd.blockchain.consensus.ConsensusProvider; -import com.jd.blockchain.consensus.ConsensusProviders; import com.jd.blockchain.consensus.ConsensusSettings; import com.jd.blockchain.crypto.AddressEncoding; -import com.jd.blockchain.crypto.CryptoAlgorithm; -import com.jd.blockchain.crypto.CryptoProvider; import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.Crypto; +import com.jd.blockchain.crypto.CryptoProvider; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PubKey; @@ -38,6 +35,7 @@ import com.jd.blockchain.ledger.core.LedgerRepository; import com.jd.blockchain.ledger.core.UserAccount; import com.jd.blockchain.ledger.core.UserAccountSet; import com.jd.blockchain.ledger.core.impl.LedgerManager; +import com.jd.blockchain.storage.service.utils.MemoryDBConnFactory; import com.jd.blockchain.tools.initializer.DBConnectionConfig; import com.jd.blockchain.tools.initializer.LedgerInitProcess; import com.jd.blockchain.tools.initializer.LedgerInitProperties; @@ -91,8 +89,8 @@ public class LedgerInitializeTest { Prompter consolePrompter = new PresetAnswerPrompter("N"); // new ConsolePrompter(); LedgerInitProperties initSetting = loadInitSetting(); Properties props = loadConsensusSetting(config.getConfigPath()); - ConsensusProvider csProvider = LedgerInitConsensusConfig.getConsensusProvider(config.getProvider()); - ConsensusSettings csProps = csProvider.getSettingsFactory().getConsensusSettingsBuilder().createSettings(props); +// ConsensusProvider csProvider = LedgerInitConsensusConfig.getConsensusProvider(config.getProvider()); +// ConsensusSettings csProps = csProvider.getSettingsFactory().getConsensusSettingsBuilder().createSettings(props); NodeContext node0 = new NodeContext(initSetting.getConsensusParticipant(0).getInitializerAddress(), serviceRegisterMap); @@ -106,26 +104,22 @@ public class LedgerInitializeTest { PrivKey privkey0 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[0], PASSWORD); DBConnectionConfig testDb0 = new DBConnectionConfig(); testDb0.setConnectionUri(dbConnections[0]); - AsyncCallback callback0 = node0.startInit(0, privkey0, initSetting, csProps, csProvider, testDb0, - consolePrompter); + AsyncCallback callback0 = node0.startInit(0, privkey0, initSetting, testDb0, consolePrompter); PrivKey privkey1 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[1], PASSWORD); DBConnectionConfig testDb1 = new DBConnectionConfig(); testDb1.setConnectionUri(dbConnections[1]); - AsyncCallback callback1 = node1.startInit(1, privkey1, initSetting, csProps, csProvider, testDb1, - consolePrompter); + AsyncCallback callback1 = node1.startInit(1, privkey1, initSetting, testDb1, consolePrompter); PrivKey privkey2 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[2], PASSWORD); DBConnectionConfig testDb2 = new DBConnectionConfig(); testDb2.setConnectionUri(dbConnections[2]); - AsyncCallback callback2 = node2.startInit(2, privkey2, initSetting, csProps, csProvider, testDb2, - consolePrompter); + AsyncCallback callback2 = node2.startInit(2, privkey2, initSetting, testDb2, consolePrompter); PrivKey privkey3 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[3], PASSWORD); DBConnectionConfig testDb03 = new DBConnectionConfig(); testDb03.setConnectionUri(dbConnections[3]); - AsyncCallback callback3 = node3.startInit(3, privkey3, initSetting, csProps, csProvider, testDb03, - consolePrompter); + AsyncCallback callback3 = node3.startInit(3, privkey3, initSetting, testDb03, consolePrompter); HashDigest ledgerHash0 = callback0.waitReturn(); HashDigest ledgerHash1 = callback1.waitReturn(); @@ -240,16 +234,14 @@ public class LedgerInitializeTest { } public AsyncCallback startInit(int currentId, PrivKey privKey, LedgerInitProperties setting, - ConsensusSettings csProps, ConsensusProvider csProvider, DBConnectionConfig dbConnConfig, - Prompter prompter) { + DBConnectionConfig dbConnConfig, Prompter prompter) { partiKey = new AsymmetricKeypair(setting.getConsensusParticipant(0).getPubKey(), privKey); ThreadInvoker invoker = new ThreadInvoker() { @Override protected HashDigest invoke() throws Exception { - return initProcess.initialize(currentId, privKey, setting, csProps, csProvider, dbConnConfig, - prompter); + return initProcess.initialize(currentId, privKey, setting, dbConnConfig, prompter); } }; @@ -257,8 +249,7 @@ public class LedgerInitializeTest { } public AsyncCallback startInit(int currentId, PrivKey privKey, LedgerInitProperties setting, - ConsensusSettings csProps, ConsensusProvider csProvider, DBConnectionConfig dbConnConfig, - Prompter prompter, boolean autoVerifyHash) { + DBConnectionConfig dbConnConfig, Prompter prompter, boolean autoVerifyHash) { CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length]; for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) { @@ -274,8 +265,7 @@ public class LedgerInitializeTest { ThreadInvoker invoker = new ThreadInvoker() { @Override protected HashDigest invoke() throws Exception { - return initProcess.initialize(currentId, privKey, setting, csProps, csProvider, dbConnConfig, - prompter, cryptoSetting); + return initProcess.initialize(currentId, privKey, setting, dbConnConfig, prompter, cryptoSetting); } }; diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeWeb4Nodes.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeWeb4Nodes.java index ec80dd18..ef18078f 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeWeb4Nodes.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeWeb4Nodes.java @@ -94,23 +94,23 @@ public class LedgerInitializeWeb4Nodes { DBConnectionConfig testDb0 = new DBConnectionConfig(); testDb0.setConnectionUri(dbConns[0]); - AsyncCallback callback0 = node0.startInit(privkey0, initSetting, csProps, csProvider, testDb0, - consolePrompter, quitLatch); + AsyncCallback callback0 = node0.startInit(privkey0, initSetting, testDb0, consolePrompter, + quitLatch); DBConnectionConfig testDb1 = new DBConnectionConfig(); testDb1.setConnectionUri(dbConns[1]); - AsyncCallback callback1 = node1.startInit(privkey1, initSetting, csProps, csProvider, testDb1, - consolePrompter, quitLatch); + AsyncCallback callback1 = node1.startInit(privkey1, initSetting, testDb1, consolePrompter, + quitLatch); DBConnectionConfig testDb2 = new DBConnectionConfig(); testDb2.setConnectionUri(dbConns[2]); - AsyncCallback callback2 = node2.startInit(privkey2, initSetting, csProps, csProvider, testDb2, - consolePrompter, quitLatch); + AsyncCallback callback2 = node2.startInit(privkey2, initSetting, testDb2, consolePrompter, + quitLatch); DBConnectionConfig testDb03 = new DBConnectionConfig(); testDb03.setConnectionUri(dbConns[3]); - AsyncCallback callback3 = node3.startInit(privkey3, initSetting, csProps, csProvider, testDb03, - consolePrompter, quitLatch); + AsyncCallback callback3 = node3.startInit(privkey3, initSetting, testDb03, consolePrompter, + quitLatch); HashDigest ledgerHash0 = callback0.waitReturn(); HashDigest ledgerHash1 = callback1.waitReturn(); @@ -230,8 +230,7 @@ public class LedgerInitializeWeb4Nodes { } public AsyncCallback startInit(PrivKey privKey, LedgerInitProperties setting, - ConsensusSettings csProps, ConsensusProvider csProvider, DBConnectionConfig dbConnConfig, - Prompter prompter, CountDownLatch quitLatch) { + DBConnectionConfig dbConnConfig, Prompter prompter, CountDownLatch quitLatch) { ThreadInvoker invoker = new ThreadInvoker() { @Override @@ -239,8 +238,8 @@ public class LedgerInitializeWeb4Nodes { doStartServer(); NodeWebContext.this.dbConnConfig = dbConnConfig; - HashDigest ledgerHash = NodeWebContext.this.initProcess.initialize(id, privKey, setting, csProps, - csProvider, dbConnConfig, prompter); + HashDigest ledgerHash = NodeWebContext.this.initProcess.initialize(id, privKey, setting, + dbConnConfig, prompter); System.out.printf("ledgerHash = %s \r\n", ledgerHash.toBase58()); @@ -252,7 +251,6 @@ public class LedgerInitializeWeb4Nodes { return invoker.start(); } - public void doStartServer() { String argServerAddress = String.format("--server.address=%s", serverAddress.getHost()); String argServerPort = String.format("--server.port=%s", serverAddress.getPort()); diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeWeb4SingleStepsTest.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeWeb4SingleStepsTest.java index bdc80ae4..3426b296 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeWeb4SingleStepsTest.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeWeb4SingleStepsTest.java @@ -340,8 +340,7 @@ public class LedgerInitializeWeb4SingleStepsTest { } public AsyncCallback startInit(PrivKey privKey, LedgerInitProperties setting, - ConsensusSettings csProps, ConsensusProvider csProvider, DBConnectionConfig dbConnConfig, - Prompter prompter, CountDownLatch quitLatch) { + DBConnectionConfig dbConnConfig, Prompter prompter, CountDownLatch quitLatch) { ThreadInvoker invoker = new ThreadInvoker() { @Override @@ -350,8 +349,8 @@ public class LedgerInitializeWeb4SingleStepsTest { // NodeWebContext.this.initProcess = ctx.getBean(LedgerInitProcess.class); NodeWebContext.this.dbConnConfig = dbConnConfig; - HashDigest ledgerHash = NodeWebContext.this.initProcess.initialize(id, privKey, setting, csProps, - csProvider, dbConnConfig, prompter); + HashDigest ledgerHash = NodeWebContext.this.initProcess.initialize(id, privKey, setting, + dbConnConfig, prompter); quitLatch.countDown(); return ledgerHash; @@ -362,9 +361,8 @@ public class LedgerInitializeWeb4SingleStepsTest { } public AsyncCallback startInitCommand(PrivKey privKey, String base58Pwd, - LedgerInitProperties ledgerSetting, ConsensusSettings csProps, ConsensusProvider csProvider, - DBConnectionConfig dbConnConfig, Prompter prompter, LedgerBindingConfig conf, - CountDownLatch quitLatch) { + LedgerInitProperties ledgerSetting, DBConnectionConfig dbConnConfig, Prompter prompter, + LedgerBindingConfig conf, CountDownLatch quitLatch) { this.db = new CompositeConnectionFactory(); this.dbConnConfig = dbConnConfig; @@ -372,8 +370,8 @@ public class LedgerInitializeWeb4SingleStepsTest { @Override protected HashDigest invoke() throws Exception { LedgerInitCommand initCmd = new LedgerInitCommand(); - HashDigest ledgerHash = initCmd.startInit(id, privKey, base58Pwd, ledgerSetting, csProps, - csProvider, dbConnConfig, prompter, conf, db); + HashDigest ledgerHash = initCmd.startInit(id, privKey, base58Pwd, ledgerSetting, dbConnConfig, + prompter, conf, db); NodeWebContext.this.ledgerManager = initCmd.getLedgerManager(); quitLatch.countDown(); return ledgerHash; diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/ledger/LedgerBlockGeneratingTest.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/ledger/LedgerBlockGeneratingTest.java index c350f232..a97a26c4 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/ledger/LedgerBlockGeneratingTest.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/ledger/LedgerBlockGeneratingTest.java @@ -141,41 +141,36 @@ public class LedgerBlockGeneratingTest { NodeContext node3 = new NodeContext(initSetting.getConsensusParticipant(3).getInitializerAddress(), serviceRegisterMap); - String[] memConns = new String[]{ - "memory://local/0", - "memory://local/1", - "memory://local/2", - "memory://local/3" - }; - + String[] memConns = new String[] { "memory://local/0", "memory://local/1", "memory://local/2", + "memory://local/3" }; PrivKey privkey0 = KeyGenCommand.decodePrivKeyWithRawPassword(LedgerInitializeTest.PRIV_KEYS[0], LedgerInitializeTest.PASSWORD); DBConnectionConfig testDb0 = new DBConnectionConfig(); testDb0.setConnectionUri(memConns[0]); - AsyncCallback callback0 = node0.startInit(0, privkey0, initSetting, csProps, csProvider, testDb0, - consolePrompter, !optimized); + AsyncCallback callback0 = node0.startInit(0, privkey0, initSetting, testDb0, consolePrompter, + !optimized); PrivKey privkey1 = KeyGenCommand.decodePrivKeyWithRawPassword(LedgerInitializeTest.PRIV_KEYS[1], LedgerInitializeTest.PASSWORD); DBConnectionConfig testDb1 = new DBConnectionConfig(); testDb1.setConnectionUri(memConns[1]); - AsyncCallback callback1 = node1.startInit(1, privkey1, initSetting, csProps, csProvider, testDb1, - consolePrompter, !optimized); + AsyncCallback callback1 = node1.startInit(1, privkey1, initSetting, testDb1, consolePrompter, + !optimized); PrivKey privkey2 = KeyGenCommand.decodePrivKeyWithRawPassword(LedgerInitializeTest.PRIV_KEYS[2], LedgerInitializeTest.PASSWORD); DBConnectionConfig testDb2 = new DBConnectionConfig(); testDb2.setConnectionUri(memConns[2]); - AsyncCallback callback2 = node2.startInit(2, privkey2, initSetting, csProps, csProvider, testDb2, - consolePrompter, !optimized); + AsyncCallback callback2 = node2.startInit(2, privkey2, initSetting, testDb2, consolePrompter, + !optimized); PrivKey privkey3 = KeyGenCommand.decodePrivKeyWithRawPassword(LedgerInitializeTest.PRIV_KEYS[3], LedgerInitializeTest.PASSWORD); DBConnectionConfig testDb03 = new DBConnectionConfig(); testDb03.setConnectionUri(memConns[3]); - AsyncCallback callback3 = node3.startInit(3, privkey3, initSetting, csProps, csProvider, testDb03, - consolePrompter, !optimized); + AsyncCallback callback3 = node3.startInit(3, privkey3, initSetting, testDb03, consolePrompter, + !optimized); HashDigest ledgerHash0 = callback0.waitReturn(); HashDigest ledgerHash1 = callback1.waitReturn(); diff --git a/source/test/test-integration/src/test/resources/keys/parti2.pub b/source/test/test-integration/src/test/resources/keys/parti2.pub new file mode 100644 index 00000000..dde44b8e --- /dev/null +++ b/source/test/test-integration/src/test/resources/keys/parti2.pub @@ -0,0 +1 @@ +3snPdw7i7PZi6TStiyc6mzjprnNhgs2atSGNS8wPYzhbKaUWGFJt7x \ No newline at end of file diff --git a/source/test/test-integration/src/test/resources/ledger.init b/source/test/test-integration/src/test/resources/ledger.init index d25b002d..74dd2585 100644 --- a/source/test/test-integration/src/test/resources/ledger.init +++ b/source/test/test-integration/src/test/resources/ledger.init @@ -5,6 +5,13 @@ ledger.seed=932dfe23-fe23232f-283f32fa-dd32aa76-8322ca2f-56236cda-7136b322-cb323 #账本的描述名称;此属性不参与共识,仅仅在当前参与方的本地节点用于描述用途; ledger.name= + +#共识服务提供者;必须; +consensus.service-provider=com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider + +#共识服务的参数配置;必须; +consensus.conf=classpath:bftsmart.config + #参与方的个数,后续以 cons_parti.id 分别标识每一个参与方的配置; cons_parti.count=4 @@ -49,7 +56,7 @@ cons_parti.1.initializer.secure=false #第2个参与方的名称; cons_parti.2.name=bt.com #第2个参与方的公钥文件路径; -cons_parti.2.pubkey-path=keys/bt-com.pub +cons_parti.2.pubkey-path=classpath:keys/parti2.pub #第2个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数; cons_parti.2.pubkey= #第2个参与方的共识服务的主机地址; diff --git a/source/test/test-integration/src/test/resources/ledger_init_test.init b/source/test/test-integration/src/test/resources/ledger_init_test.init index 9c9959c2..2f4427ba 100644 --- a/source/test/test-integration/src/test/resources/ledger_init_test.init +++ b/source/test/test-integration/src/test/resources/ledger_init_test.init @@ -5,6 +5,12 @@ ledger.seed=932dfe23-fe23232f-283f32fa-dd32aa76-8322ca2f-56236cda-7136b322-cb323 #账本的描述名称;此属性不参与共识,仅仅在当前参与方的本地节点用于描述用途; ledger.name= +#共识服务提供者;必须; +consensus.service-provider=com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider + +#共识服务的参数配置;必须; +consensus.conf=classpath:bftsmart.config + #参与方的个数,后续以 cons_parti.id 分别标识每一个参与方的配置; cons_parti.count=4 diff --git a/source/test/test-integration/src/test/resources/ledger_init_test_web2.init b/source/test/test-integration/src/test/resources/ledger_init_test_web2.init index 849f223e..f661bd0e 100644 --- a/source/test/test-integration/src/test/resources/ledger_init_test_web2.init +++ b/source/test/test-integration/src/test/resources/ledger_init_test_web2.init @@ -5,6 +5,12 @@ ledger.seed=932dfe23-fe23232f-283f32fa-dd32aa76-8322ca2f-56236cda-7136b322-cb323 #账本的描述名称;此属性不参与共识,仅仅在当前参与方的本地节点用于描述用途; #ledger.name= +#共识服务提供者;必须; +consensus.service-provider=com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider + +#共识服务的参数配置;必须; +consensus.conf=classpath:bftsmart.config + #参与方的个数,后续以 cons_parti.id 分别标识每一个参与方的配置; cons_parti.count=4 diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitCommand.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitCommand.java index f010164d..4947975a 100644 --- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitCommand.java +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitCommand.java @@ -1,7 +1,6 @@ package com.jd.blockchain.tools.initializer; import java.io.File; -import java.util.Properties; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.boot.SpringApplication; @@ -11,9 +10,6 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; -import com.jd.blockchain.consensus.ConsensusProvider; -import com.jd.blockchain.consensus.ConsensusProviders; -import com.jd.blockchain.consensus.ConsensusSettings; import com.jd.blockchain.crypto.AddressEncoding; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.PrivKey; @@ -23,7 +19,6 @@ import com.jd.blockchain.tools.initializer.LedgerBindingConfig.BindingConfig; import com.jd.blockchain.tools.initializer.LedgerInitProperties.ConsensusParticipantConfig; import com.jd.blockchain.tools.keygen.KeyGenCommand; import com.jd.blockchain.utils.ArgumentSet; -import com.jd.blockchain.utils.ConsoleUtils; import com.jd.blockchain.utils.ArgumentSet.ArgEntry; import com.jd.blockchain.utils.ArgumentSet.Setting; import com.jd.blockchain.utils.io.FileUtils; @@ -51,72 +46,68 @@ public class LedgerInitCommand { // 是否输出调试信息; private static final String DEBUG_OPT = "-debug"; + private static final Prompter DEFAULT_PROMPTER = new ConsolePrompter(); + /** * 入口; * * @param args */ public static void main(String[] args) { + Prompter prompter = DEFAULT_PROMPTER; + Setting argSetting = ArgumentSet.setting().prefix(LOCAL_ARG, INI_ARG).option(DEBUG_OPT); ArgumentSet argset = ArgumentSet.resolve(args, argSetting); try { ArgEntry localArg = argset.getArg(LOCAL_ARG); if (localArg == null) { - ConsoleUtils.info("Miss local config file which can be specified with arg [%s]!!!", LOCAL_ARG); + prompter.info("Miss local config file which can be specified with arg [%s]!!!", LOCAL_ARG); } LocalConfig localConf = LocalConfig.resolve(localArg.getValue()); ArgEntry iniArg = argset.getArg(INI_ARG); if (iniArg == null) { - ConsoleUtils.info("Miss ledger initializing config file which can be specified with arg [%s]!!!", - INI_ARG); + prompter.info("Miss ledger initializing config file which can be specified with arg [%s]!!!", INI_ARG); return; } - // // load ledger init setting; - LedgerInitProperties ledgerInitSetting = LedgerInitProperties.resolve(iniArg.getValue()); + // load ledger init setting; + LedgerInitProperties ledgerInitProperties = LedgerInitProperties.resolve(iniArg.getValue()); String localNodePubKeyString = localConf.getLocal().getPubKeyString(); PubKey localNodePubKey = KeyGenCommand.decodePubKey(localNodePubKeyString); // 地址根据公钥生成 String localNodeAddress = AddressEncoding.generateAddress(localNodePubKey).toBase58(); - // load all pub keys; + // 加载全部公钥; int currId = -1; - for (int i = 0; i < ledgerInitSetting.getConsensusParticipantCount(); i++) { - ConsensusParticipantConfig pconf = ledgerInitSetting.getConsensusParticipant(i); - String currPartAddress = pconf.getAddress(); - if (currPartAddress == null) { - if (pconf.getPubKeyPath() != null) { - PubKey pubKey = KeyGenCommand.readPubKey(pconf.getPubKeyPath()); - pconf.setPubKey(pubKey); - currPartAddress = pconf.getAddress(); - } - } - if (localNodeAddress.equals(currPartAddress)) { + for (int i = 0; i < ledgerInitProperties.getConsensusParticipantCount(); i++) { + ConsensusParticipantConfig partiConf = ledgerInitProperties.getConsensusParticipant(i); +// String partiAddress = partiConf.getAddress(); +// if (partiAddress == null) { +// if (partiConf.getPubKeyPath() != null) { +// PubKey pubKey = KeyGenCommand.readPubKey(partiConf.getPubKeyPath()); +// partiConf.setPubKey(pubKey); +// partiAddress = partiConf.getAddress(); +// } +// } + if (localNodeAddress.equals(partiConf.getAddress())) { currId = i; } } if (currId == -1) { - throw new IllegalStateException("The current node specified in local.conf is not found in ledger.init!"); + throw new IllegalStateException( + "The current node specified in local.conf is not found in ledger.init!"); } + // 加载当前节点的私钥; String base58Pwd = localConf.getLocal().getPassword(); if (base58Pwd == null) { base58Pwd = KeyGenCommand.readPasswordString(); } PrivKey privKey = KeyGenCommand.decodePrivKey(localConf.getLocal().getPrivKeyString(), base58Pwd); - // Load consensus properties; - Properties props = FileUtils.readProperties(localConf.getConsensusConfig()); - ConsensusProvider csProvider = ConsensusProviders.getProvider(localConf.getConsensusProvider()); - ConsensusSettings csSettings = csProvider.getSettingsFactory().getConsensusSettingsBuilder() - .createSettings(props); - - - // ConsensusProperties csProps = new ConsensusProperties(props); - // Output ledger binding config of peer; if (!FileUtils.existDirectory(localConf.getBindingOutDir())) { FileUtils.makeDirectory(localConf.getBindingOutDir()); @@ -131,27 +122,26 @@ public class LedgerInitCommand { // 启动初始化; LedgerInitCommand initCommand = new LedgerInitCommand(); - HashDigest newLedgerHash = initCommand.startInit(currId, privKey, base58Pwd, ledgerInitSetting, csSettings, csProvider, - localConf.getStoragedDb(), new ConsolePrompter(), conf); + HashDigest newLedgerHash = initCommand.startInit(currId, privKey, base58Pwd, ledgerInitProperties, + localConf.getStoragedDb(), prompter, conf); if (newLedgerHash != null) { // success; // so save ledger binding config to file system; conf.store(ledgerBindingFile); - ConsoleUtils.info("\r\n------ Update Ledger binding configuration success! ------[%s]", + prompter.info("\r\n------ Update Ledger binding configuration success! ------[%s]", ledgerBindingFile.getAbsolutePath()); } - // ConsoleUtils.confirm("\r\n\r\n Press any key to quit. :>"); - } catch (Exception e) { - ConsoleUtils.error("\r\nError!! -- %s\r\n", e.getMessage()); + prompter.error("\r\nError!! -- %s\r\n", e.getMessage()); if (argset.hasOption(DEBUG_OPT)) { e.printStackTrace(); } - ConsoleUtils.error("\r\n Ledger init process has been broken by error!"); + prompter.error("\r\n Ledger init process has been broken by error!"); } + prompter.confirm(InitializingStep.LEDGER_INIT_COMPLETED.toString(), "\r\n\r\n Press any key to quit. :>"); } @@ -164,20 +154,19 @@ public class LedgerInitCommand { public LedgerInitCommand() { } - public HashDigest startInit(int currId, PrivKey privKey, String base58Pwd, LedgerInitProperties ledgerSetting, - ConsensusSettings csSettings, ConsensusProvider csProvider, DBConnectionConfig dbConnConfig, - Prompter prompter, LedgerBindingConfig conf, Object... extBeans) { - if (currId < 0 || currId >= ledgerSetting.getConsensusParticipantCount()) { - ConsoleUtils.info( + public HashDigest startInit(int currId, PrivKey privKey, String base58Pwd, + LedgerInitProperties ledgerInitProperties, DBConnectionConfig dbConnConfig, Prompter prompter, + LedgerBindingConfig conf, Object... extBeans) { + if (currId < 0 || currId >= ledgerInitProperties.getConsensusParticipantCount()) { + prompter.info( "Your participant id is illegal which is less than 1 or great than the total participants count[%s]!!!", - ledgerSetting.getConsensusParticipantCount()); + ledgerInitProperties.getConsensusParticipantCount()); return null; } // generate binding config; BindingConfig bindingConf = new BindingConfig(); - // bindingConf.setCsConfigFile(localConf.getConsensusConfig()); - bindingConf.getParticipant().setAddress(ledgerSetting.getConsensusParticipant(currId).getAddress()); + bindingConf.getParticipant().setAddress(ledgerInitProperties.getConsensusParticipant(currId).getAddress()); String encodedPrivKey = KeyGenCommand.encodePrivKey(privKey, base58Pwd); bindingConf.getParticipant().setPk(encodedPrivKey); bindingConf.getParticipant().setPassword(base58Pwd); @@ -185,16 +174,13 @@ public class LedgerInitCommand { bindingConf.getDbConnection().setConnectionUri(dbConnConfig.getUri()); bindingConf.getDbConnection().setPassword(dbConnConfig.getPassword()); - // bindingConf.getMqConnection().setServer(mqConnConfig.getServer()); - // bindingConf.getMqConnection().setTopic(mqConnConfig.getTopic()); - // confirm continue; prompter.info("\r\n\r\n This is participant [%s], the ledger initialization is ready to start!\r\n", currId); - // ConsoleUtils.confirm("Press any key to continue... "); - // prompter.confirm("Press any key to continue... "); +// ConsoleUtils.confirm("Press any key to continue... "); +// prompter.confirm("Press any key to continue... "); - // start web listener; - NetworkAddress serverAddress = ledgerSetting.getConsensusParticipant(currId).getInitializerAddress(); + // start the web controller of Ledger Initializer; + NetworkAddress serverAddress = ledgerInitProperties.getConsensusParticipant(currId).getInitializerAddress(); String argServerAddress = String.format("--server.address=%s", serverAddress.getHost()); String argServerPort = String.format("--server.port=%s", serverAddress.getPort()); String[] innerArgs = { argServerAddress, argServerPort }; @@ -211,21 +197,21 @@ public class LedgerInitCommand { ConfigurableApplicationContext ctx = app.run(innerArgs); this.ledgerManager = ctx.getBean(LedgerManager.class); - prompter.info("\r\n------ Web listener[%s:%s] was started. ------\r\n", serverAddress.getHost(), - serverAddress.getPort()); + prompter.info("\r\n------ Web controller of Ledger Initializer[%s:%s] was started. ------\r\n", + serverAddress.getHost(), serverAddress.getPort()); try { LedgerInitProcess initProc = ctx.getBean(LedgerInitProcess.class); - HashDigest ledgerHash = initProc.initialize(currId, privKey, ledgerSetting, csSettings, csProvider, + HashDigest ledgerHash = initProc.initialize(currId, privKey, ledgerInitProperties, bindingConf.getDbConnection(), prompter); if (ledgerHash == null) { // ledger init fail; - ConsoleUtils.error("\r\n------ Ledger initialize fail! ------\r\n"); + prompter.error("\r\n------ Ledger initialize fail! ------\r\n"); return null; } else { - ConsoleUtils.info("\r\n------ Ledger initialize success! ------"); - ConsoleUtils.info("New Ledger Hash is :[%s]", ledgerHash.toBase58()); + prompter.info("\r\n------ Ledger initialize success! ------"); + prompter.info("New Ledger Hash is :[%s]", ledgerHash.toBase58()); if (conf == null) { conf = new LedgerBindingConfig(); @@ -237,7 +223,7 @@ public class LedgerInitCommand { } } finally { ctx.close(); - ConsoleUtils.info("\r\n------ Web listener[%s:%s] was closed. ------\r\n", serverAddress.getHost(), + prompter.info("\r\n------ Web listener[%s:%s] was closed. ------\r\n", serverAddress.getHost(), serverAddress.getPort()); } } diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProcess.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProcess.java index 1e19232d..ee1b1692 100644 --- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProcess.java +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProcess.java @@ -17,44 +17,26 @@ public interface LedgerInitProcess { /** * Init a new ledger; * - * @param currentId - * @param privKey - * @param ledgerInitProps - * 账本初始化配置属性; - * @param consensusSettings - * 共识配置属性; - * @param consensusServiceProvider - * @param prompter - * @return 返回新账本的 hash;如果未初始化成功,则返回 null; - */ - /** - * Init a new ledger; - * @param currentId Id of current participant; - * @param privKey Private key of current participant; - * @param ledgerInitProps The settings about this initialization; - * @param consensusSettings The consensus settings - * @param consensusProvider - * @param dbConnConfig - * @param prompter + * @param currentId Id of current participant. + * @param privKey Private key of current participant. + * @param ledgerInitProps The settings about this initialization. + * @param dbConnConfig The configuration of DB Connection. + * @param prompter Prompter for interaction. * @return */ HashDigest initialize(int currentId, PrivKey privKey, LedgerInitProperties ledgerInitProps, - ConsensusSettings consensusSettings, ConsensusProvider consensusProvider, DBConnectionConfig dbConnConfig, Prompter prompter); /** * @param currentId * @param privKey * @param ledgerInitProps - * @param consensusSettings - * @param consensusProvider * @param dbConnConfig * @param prompter * @param cryptoSetting * @return */ HashDigest initialize(int currentId, PrivKey privKey, LedgerInitProperties ledgerInitProps, - ConsensusSettings consensusSettings, ConsensusProvider consensusProvider, DBConnectionConfig dbConnConfig, Prompter prompter, CryptoSetting cryptoSetting); } diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProperties.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProperties.java index 805315f9..66868f66 100644 --- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProperties.java +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProperties.java @@ -1,23 +1,23 @@ package com.jd.blockchain.tools.initializer; -import java.io.ByteArrayOutputStream; +import java.io.File; import java.io.FileNotFoundException; -import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.Properties; +import org.springframework.util.ResourceUtils; + import com.jd.blockchain.crypto.AddressEncoding; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.ledger.ParticipantNode; import com.jd.blockchain.tools.keygen.KeyGenCommand; +import com.jd.blockchain.utils.PropertiesUtils; import com.jd.blockchain.utils.codec.HexUtils; import com.jd.blockchain.utils.io.FileUtils; import com.jd.blockchain.utils.net.NetworkAddress; -import org.springframework.core.io.ClassPathResource; - public class LedgerInitProperties { // 账本种子; @@ -32,12 +32,7 @@ public class LedgerInitProperties { public static final String PART_PUBKEY_PATH = "pubkey-path"; // 参与方的公钥文件路径; public static final String PART_PUBKEY = "pubkey"; - // //共识参与方的共识服务的主机地址; - // public static final String PART_CONSENSUS_HOST = "consensus.host"; - // // 共识参与方的共识服务的端口; - // public static final String PART_CONSENSUS_PORT = "consensus.port"; - // // 共识参与方的共识服务是否开启安全连接; - // public static final String PART_CONSENSUS_SECURE = "consensus.secure"; + // 共识参与方的账本初始服务的主机; public static final String PART_INITIALIZER_HOST = "initializer.host"; // 共识参与方的账本初始服务的端口; @@ -45,70 +40,30 @@ public class LedgerInitProperties { // 共识参与方的账本初始服务是否开启安全连接; public static final String PART_INITIALIZER_SECURE = "initializer.secure"; + // 共识服务的参数配置;必须; + public static final String CONSENSUS_CONFIG = "consensus.conf"; + + // 共识服务提供者;必须; + public static final String CONSENSUS_SERVICE_PROVIDER = "consensus.service-provider"; + private byte[] ledgerSeed; private List consensusParticipants = new ArrayList<>(); + private String consensusProvider; + + private Properties consensusConfig; + public byte[] getLedgerSeed() { return ledgerSeed; } - public static byte[] getHostSettingValue() throws Exception { - ClassPathResource hostConfigResource = new ClassPathResource("hosts.config"); - InputStream fis = hostConfigResource.getInputStream(); - ByteArrayOutputStream bos = null; - byte[] buffer = null; - try { - bos = new ByteArrayOutputStream(1000); - byte[] b = new byte[1000]; - int n; - while ((n = fis.read(b)) != -1) { - bos.write(b, 0, n); - } - // host file to bytes - buffer = bos.toByteArray(); - } catch (FileNotFoundException e) { - throw new Exception(e.getMessage(), e); - } catch (IOException e) { - throw new Exception(e.getMessage(), e); - } finally { - if (fis != null) { - fis.close(); - } - if (bos != null) { - bos.close(); - } - } - return buffer; + public Properties getConsensusConfig() { + return consensusConfig; } - public static byte[] getSystemSettingValue() throws Exception { - ClassPathResource systemConfigResource = new ClassPathResource("bftsmart.config"); - InputStream fis = systemConfigResource.getInputStream(); - ByteArrayOutputStream bos = null; - byte[] buffer = null; - try { - bos = new ByteArrayOutputStream(1000); - byte[] b = new byte[1000]; - int n; - while ((n = fis.read(b)) != -1) { - bos.write(b, 0, n); - } - // file to bytes - buffer = bos.toByteArray(); - } catch (FileNotFoundException e) { - throw new Exception(e.getMessage(), e); - } catch (IOException e) { - throw new Exception(e.getMessage(), e); - } finally { - if (fis != null) { - fis.close(); - } - if (bos != null) { - bos.close(); - } - } - return buffer; + public String getConsensusProvider() { + return consensusProvider; } public int getConsensusParticipantCount() { @@ -119,20 +74,15 @@ public class LedgerInitProperties { return consensusParticipants; } - public ConsensusParticipantConfig[] getConsensusParticipantArray() { - return consensusParticipants.toArray(new ConsensusParticipantConfig[consensusParticipants.size()]); - } - /** * 返回参与者; * - * @param address - * 从 1 开始; 小于等于 {@link #getConsensusParticipantCount()}; + * @param address 从 1 开始; 小于等于 {@link #getConsensusParticipantCount()}; * @return */ public ConsensusParticipantConfig getConsensusParticipant(int id) { for (ConsensusParticipantConfig p : consensusParticipants) { - if (p.getId()== id) { + if (p.getId() == id) { return p; } } @@ -163,11 +113,23 @@ public class LedgerInitProperties { } private static LedgerInitProperties resolve(Properties props) { - String hexLedgerSeed = getProperty(props, LEDGER_SEED).replace("-", ""); + String hexLedgerSeed = PropertiesUtils.getRequiredProperty(props, LEDGER_SEED).replace("-", ""); byte[] ledgerSeed = HexUtils.decode(hexLedgerSeed); - LedgerInitProperties setting = new LedgerInitProperties(ledgerSeed); + LedgerInitProperties initProps = new LedgerInitProperties(ledgerSeed); + + // 解析共识相关的属性; + initProps.consensusProvider = PropertiesUtils.getRequiredProperty(props, CONSENSUS_SERVICE_PROVIDER); + String consensusConfigFilePath = PropertiesUtils.getRequiredProperty(props, CONSENSUS_CONFIG); + try { + File consensusConfigFile = ResourceUtils.getFile(consensusConfigFilePath); + initProps.consensusConfig = FileUtils.readProperties(consensusConfigFile); + } catch (FileNotFoundException e) { + throw new IllegalArgumentException( + String.format("Consensus config file[%s] doesn't exist! ", consensusConfigFilePath), e); + } - int partCount = getInt(getProperty(props, PART_COUNT)); + // 解析参与方节点列表; + int partCount = getInt(PropertiesUtils.getRequiredProperty(props, PART_COUNT)); if (partCount < 0) { throw new IllegalArgumentException(String.format("Property[%s] is negative!", PART_COUNT)); } @@ -180,62 +142,40 @@ public class LedgerInitProperties { parti.setId(i); String nameKey = getKeyOfCsParti(i, PART_NAME); - parti.setName(getProperty(props, nameKey)); + parti.setName(PropertiesUtils.getRequiredProperty(props, nameKey)); String pubkeyPathKey = getKeyOfCsParti(i, PART_PUBKEY_PATH); - parti.setPubKeyPath(getProperty(props, pubkeyPathKey)); + String pubkeyPath = PropertiesUtils.getProperty(props, pubkeyPathKey, false); String pubkeyKey = getKeyOfCsParti(i, PART_PUBKEY); - String base58PubKey = getProperty(props, pubkeyKey); + String base58PubKey = PropertiesUtils.getProperty(props, pubkeyKey, false); if (base58PubKey != null) { PubKey pubKey = KeyGenCommand.decodePubKey(base58PubKey); parti.setPubKey(pubKey); + } else if (pubkeyPath != null) { + PubKey pubKey = KeyGenCommand.readPubKey(pubkeyPath); + parti.setPubKey(pubKey); + } else { + throw new IllegalArgumentException( + String.format("Property[%s] and property[%s] are all empty!", pubkeyKey, pubkeyPathKey)); } - // String consensusHostKey = getKeyOfCsParti(i, PART_CONSENSUS_HOST); - // String consensusHost = getProperty(props, consensusHostKey); - // - // String consensusPortKey = getKeyOfCsParti(i, PART_CONSENSUS_PORT); - // int consensusPort = getInt(getProperty(props, consensusPortKey)); - // - // String consensusSecureKey = getKeyOfCsParti(i, PART_CONSENSUS_SECURE); - // boolean consensusSecure = Boolean.parseBoolean(getProperty(props, - // consensusSecureKey)); - // NetworkAddress consensusAddress = new NetworkAddress(consensusHost, - // consensusPort, consensusSecure); - // parti.setConsensusAddress(consensusAddress); - String initializerHostKey = getKeyOfCsParti(i, PART_INITIALIZER_HOST); - String initializerHost = getProperty(props, initializerHostKey); + String initializerHost = PropertiesUtils.getRequiredProperty(props, initializerHostKey); String initializerPortKey = getKeyOfCsParti(i, PART_INITIALIZER_PORT); - int initializerPort = getInt(getProperty(props, initializerPortKey)); + int initializerPort = getInt(PropertiesUtils.getRequiredProperty(props, initializerPortKey)); String initializerSecureKey = getKeyOfCsParti(i, PART_INITIALIZER_SECURE); - boolean initializerSecure = Boolean.parseBoolean(getProperty(props, initializerSecureKey)); + boolean initializerSecure = Boolean + .parseBoolean(PropertiesUtils.getRequiredProperty(props, initializerSecureKey)); NetworkAddress initializerAddress = new NetworkAddress(initializerHost, initializerPort, initializerSecure); parti.setInitializerAddress(initializerAddress); - setting.addConsensusParticipant(parti); + initProps.addConsensusParticipant(parti); } - return setting; - } - - private static String getProperty(Properties props, String key) { - return getProperty(props, key, true); - } - - private static String getProperty(Properties props, String key, boolean required) { - String value = props.getProperty(key); - if (value == null) { - if (required) { - throw new IllegalArgumentException("Miss property[" + key + "]!"); - } - return null; - } - value = value.trim(); - return value.length() == 0 ? null : value; + return initProps; } private static int getInt(String strInt) { @@ -249,14 +189,14 @@ public class LedgerInitProperties { * */ public static class ConsensusParticipantConfig implements ParticipantNode { - + private int id; - + private String address; private String name; - private String pubKeyPath; +// private String pubKeyPath; private PubKey pubKey; @@ -271,7 +211,7 @@ public class LedgerInitProperties { public void setId(int id) { this.id = id; } - + @Override public String getAddress() { return address; @@ -285,13 +225,13 @@ public class LedgerInitProperties { this.name = name; } - public String getPubKeyPath() { - return pubKeyPath; - } - - public void setPubKeyPath(String pubKeyPath) { - this.pubKeyPath = pubKeyPath; - } +// public String getPubKeyPath() { +// return pubKeyPath; +// } +// +// public void setPubKeyPath(String pubKeyPath) { +// this.pubKeyPath = pubKeyPath; +// } public NetworkAddress getInitializerAddress() { return initializerAddress; diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LocalConfig.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LocalConfig.java index 8696263c..c3ad268e 100644 --- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LocalConfig.java +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LocalConfig.java @@ -2,8 +2,6 @@ package com.jd.blockchain.tools.initializer; import java.io.File; import java.io.InputStream; -import java.net.URI; -import java.nio.file.Path; import java.util.Properties; import com.jd.blockchain.utils.PathUtils; @@ -30,17 +28,11 @@ public class LocalConfig { // 账本数据库的连接口令; public static final String LEDGER_DB_PWD = "ledger.db.pwd"; - // 账本消息队列的地址 -// public static final String LEDGER_MQ_SERVER = "ledger.mq.server"; -// -// // 账本消息队列的主题 -// public static final String LEDGER_MQ_TOPIC = "ledger.mq.topic"; - - // 共识系统的参数配置;必须参数; - public static final String CONSENSUS_CONF = "consensus.conf"; - - // 共识系统的参数配置;必须参数; - public static final String CONSENSUS_SERVICE_PROVIDER = "consensus.service-provider"; +// // 共识系统的参数配置;必须参数; +// public static final String CONSENSUS_CONF = "consensus.conf"; +// +// // 共识系统的参数配置;必须参数; +// public static final String CONSENSUS_SERVICE_PROVIDER = "consensus.service-provider"; private LocalParticipantConfig local = new LocalParticipantConfig(); @@ -48,10 +40,9 @@ public class LocalConfig { private DBConnectionConfig storagedDb = new DBConnectionConfig(); -// private MQConnectionConfig handleMq = new MQConnectionConfig(); - private String consensusConfig; - private String consensusProvider; +// private String consensusConfig; +// private String consensusProvider; public LocalParticipantConfig getLocal() { return local; @@ -77,22 +68,6 @@ public class LocalConfig { this.storagedDb = storagedDb; } -// public MQConnectionConfig getHandleMq() { -// return handleMq; -// } -// -// public void setHandleMq(MQConnectionConfig handleMq) { -// this.handleMq = handleMq; -// } - - public String getConsensusConfig() { - return consensusConfig; - } - - public void setConsensusConfig(String consensusConfig) { - this.consensusConfig = consensusConfig; - } - public static LocalConfig resolve(String initSettingFile) { Properties props = FileUtils.readProperties(initSettingFile, "UTF-8"); return resolve(props, initSettingFile); @@ -118,17 +93,12 @@ public class LocalConfig { if (initSettingFile == null) { conf.bindingOutDir = PropertiesUtils.getRequiredProperty(props, LEDGER_BINDING_OUT); - conf.consensusConfig = PropertiesUtils.getRequiredProperty(props, CONSENSUS_CONF); } else { String bindingOutDir = PropertiesUtils.getRequiredProperty(props, LEDGER_BINDING_OUT); - String consensusConfig = PropertiesUtils.getRequiredProperty(props, CONSENSUS_CONF); String initSettingDir = PathUtils.concatPaths(initSettingFile, "../"); conf.bindingOutDir = absolutePath(initSettingDir, bindingOutDir); - conf.consensusConfig = absolutePath(initSettingDir, consensusConfig); } - conf.consensusProvider = PropertiesUtils.getRequiredProperty(props, CONSENSUS_SERVICE_PROVIDER); - return conf; } @@ -141,18 +111,6 @@ public class LocalConfig { return absolutePath; } - private static int getInt(String strInt) { - return Integer.parseInt(strInt.trim()); - } - - public String getConsensusProvider() { - return consensusProvider; - } - - public void setConsensusProvider(String consensusProvider) { - this.consensusProvider = consensusProvider; - } - /** * 当前参与方的本地配置信息; * @@ -192,12 +150,4 @@ public class LocalConfig { } - public static void main(String[] args) { - String currPath = "/Users/zhanglin33/Ddisk/20mintest/0/config/init/local.conf"; -// String settingPath = "../"; - String settingPath = "bftsmart.config"; - String path = absolutePath(PathUtils.concatPaths(currPath, "../"), settingPath); - System.out.println(path); - - } } diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/Prompter.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/Prompter.java index 663a2c46..b1f589dd 100644 --- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/Prompter.java +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/Prompter.java @@ -2,6 +2,28 @@ package com.jd.blockchain.tools.initializer; public interface Prompter { + //定义一些常用的问答常量; + + /** + * 询问是或否; + */ + public static final String QUESTION_YESNO = "YES/NO"; + + /** + * 提示按任意键继续; + */ + public static final String PROMPT_ANYKEY_TO_CONTINUE = "ANYKEY"; + + /** + * + */ + public static final String ANSWER_YES = "Y"; + + public static final String ANSWER_NO = "N"; + + + + void info(String format, Object... args); void error(String format, Object... args); diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitializeWebController.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitializeWebController.java index 546e154b..4c9af288 100644 --- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitializeWebController.java +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitializeWebController.java @@ -5,6 +5,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.List; +import java.util.Properties; import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -18,10 +19,10 @@ import org.springframework.web.bind.annotation.RestController; import com.jd.blockchain.binaryproto.DataContractRegistry; import com.jd.blockchain.consensus.ConsensusProvider; +import com.jd.blockchain.consensus.ConsensusProviders; import com.jd.blockchain.consensus.ConsensusSettings; -import com.jd.blockchain.crypto.CryptoAlgorithm; -import com.jd.blockchain.crypto.CryptoProvider; import com.jd.blockchain.crypto.Crypto; +import com.jd.blockchain.crypto.CryptoProvider; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PubKey; @@ -56,11 +57,11 @@ import com.jd.blockchain.tools.initializer.LedgerInitException; import com.jd.blockchain.tools.initializer.LedgerInitProcess; import com.jd.blockchain.tools.initializer.LedgerInitProperties; import com.jd.blockchain.tools.initializer.LedgerInitProperties.ConsensusParticipantConfig; +import com.jd.blockchain.tools.initializer.Prompter; import com.jd.blockchain.transaction.DigitalSignatureBlob; import com.jd.blockchain.transaction.LedgerInitSettingData; import com.jd.blockchain.transaction.TxBuilder; import com.jd.blockchain.transaction.TxRequestBuilder; -import com.jd.blockchain.tools.initializer.Prompter; import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.concurrent.InvocationResult; import com.jd.blockchain.utils.io.BytesUtils; @@ -78,13 +79,12 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI static { DataContractRegistry.register(TransactionRequest.class); } - + private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(), SMCryptoService.class.getName() }; - private static final String DEFAULT_SIGN_ALGORITHM = "ED25519"; - + private final SignatureFunction SIGN_FUNC; private volatile LedgerInitPermission localPermission; @@ -129,7 +129,7 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI public LedgerInitializeWebController(LedgerManage ledgerManager, DbConnectionFactory dbConnFactory, InitConsensusServiceFactory initCsServiceFactory) { this.SIGN_FUNC = Crypto.getSignatureFunction(DEFAULT_SIGN_ALGORITHM); - + this.ledgerManager = ledgerManager; this.dbConnFactory = dbConnFactory; this.initCsServiceFactory = initCsServiceFactory; @@ -155,36 +155,39 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI this.prompter = prompter; } - public ConsensusProvider getConsensusProvider() { - return consensusProvider; - } +// private ConsensusProvider getConsensusProvider() { +// return consensusProvider; +// } - public void setConsensusProvider(ConsensusProvider consensusProvider) { + private void setConsensusProvider(ConsensusProvider consensusProvider) { this.consensusProvider = consensusProvider; } @Override public HashDigest initialize(int currentId, PrivKey privKey, LedgerInitProperties ledgerInitProps, - ConsensusSettings csSettings, ConsensusProvider csProvider, DBConnectionConfig dbConnConfig, - Prompter prompter) { - return initialize(currentId, privKey, ledgerInitProps, csSettings, csProvider, dbConnConfig, prompter, - createDefaultCryptoSetting()); + DBConnectionConfig dbConnConfig, Prompter prompter) { + return initialize(currentId, privKey, ledgerInitProps, dbConnConfig, prompter, createDefaultCryptoSetting()); } @Override public HashDigest initialize(int currentId, PrivKey privKey, LedgerInitProperties ledgerInitProps, - ConsensusSettings consensusProps, ConsensusProvider csProvider, DBConnectionConfig dbConnConfig, - Prompter prompter, CryptoSetting cryptoSetting) { + DBConnectionConfig dbConnConfig, Prompter prompter, CryptoSetting cryptoSetting) { if (this.ledgerInitSetting != null) { throw new IllegalStateException("ledger init process has already started."); } setPrompter(prompter); + + Properties csProps = ledgerInitProps.getConsensusConfig(); + ConsensusProvider csProvider = ConsensusProviders.getProvider(ledgerInitProps.getConsensusProvider()); + ConsensusSettings csSettings = csProvider.getSettingsFactory().getConsensusSettingsBuilder() + .createSettings(csProps); setConsensusProvider(csProvider); + prompter.info("Init settings and sign permision..."); - prepareLocalPermission(currentId, privKey, ledgerInitProps, consensusProps, cryptoSetting); + prepareLocalPermission(currentId, privKey, ledgerInitProps, csSettings, cryptoSetting); prompter.confirm(InitializingStep.PERMISSION_READY.toString(), "Ledger init permission has already prepared! Any key to continue..."); @@ -237,7 +240,7 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI this.decisions[i] = new DecisionResultHandle(i); } // 预置当前参与方的“决定”到列表,避免向自己发起请求; - this.decisions[currentId].setResult(localDecision); + this.decisions[currentId].setValue(localDecision); return localDecision; } @@ -330,7 +333,9 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI LedgerInitSettingData initSetting = new LedgerInitSettingData(); initSetting.setLedgerSeed(ledgerProps.getLedgerSeed()); initSetting.setCryptoSetting(cryptoSetting); - ConsensusParticipantConfig[] parties = ledgerProps.getConsensusParticipantArray(); + + List partiList = ledgerProps.getConsensusParticipants(); + ConsensusParticipantConfig[] parties = partiList.toArray(new ConsensusParticipantConfig[partiList.size()]); ConsensusParticipantConfig[] orderedParties = sortAndVerify(parties); initSetting.setConsensusParticipants(orderedParties); @@ -459,7 +464,7 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI List waitingIds = new ArrayList<>(); for (int i = 0; i < results.length; i++) { if (results[i] != null) { - if (results[i].getResult() == null) { + if (results[i].getValue() == null) { waitingIds.add("" + (i + 1)); } } @@ -486,7 +491,7 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI continue; } PubKey pubKey = participants[i].getPubKey(); - LedgerInitPermission permission = (LedgerInitPermission) results[i].getResult(); + LedgerInitPermission permission = (LedgerInitPermission) results[i].getValue(); if (permission.getParticipantId() != participants[i].getId()) { prompter.error("\r\nThe id of received permission isn't equal to it's participant ! --[Id=%s][name=%s]", participants[i].getAddress(), participants[i].getName()); @@ -537,7 +542,7 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI public void run() { try { LedgerInitPermission permission = initConsensus.requestPermission(currentId, reqAuthSign); - result.setResult(permission); + result.setValue(permission); } catch (Exception e) { result.setError(e); } finally { @@ -607,7 +612,7 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI while (!allDecided) { allDecided = true; for (int i = 0; i < randDecHdls.length; i++) { - if (randDecHdls[i].getResult() != null) { + if (randDecHdls[i].getValue() != null) { // 忽略当前参与方自己(在初始化“决定”时已经置为非空),以及已经收到主动提交“决定”的参与方; continue; } @@ -648,10 +653,11 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI try { targetDecision = initConsensus.synchronizeDecision(localDecision); } catch (Exception e1) { - prompter.info("Error occurred on synchronizing decision . --%s", e1.getMessage()); + prompter.info("Error occurred on synchronizing decision . --[%s] %s", e1.getClass().getName(), + e1.getMessage()); } if (targetDecision == null) { - if (resultHandle.getResult() != null) { + if (resultHandle.getValue() != null) { // 已经验证过; return true; } @@ -678,7 +684,7 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI } } while (targetDecision == null); - if (targetDecision.getParticipantId() != targetId && resultHandle.getResult() == null) { + if (targetDecision.getParticipantId() != targetId && resultHandle.getValue() == null) { prompter.error( "The received id of participant isn't equal to id of request target participant! --[Id=%s]", targetId); @@ -696,7 +702,7 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI /** * 校验并记录指定的参与方做出的决定; *

- * 注:对 {@link DecisionResultHandle#setResult(LedgerInitDecision)} + * 注:对 {@link DecisionResultHandle#setValue(LedgerInitDecision)} * 方法的调用不是线程安全的,但由于是在满足有效性校验之后才调用,具有幂等性,所以不必对该方法的多处调用进行同步; * * @param targetDecision @@ -707,7 +713,7 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI private synchronized boolean validateAndRecordDecision(LedgerInitDecision targetDecision, DecisionResultHandle resultHandle) { if ((!localDecision.getLedgerHash().equals(targetDecision.getLedgerHash())) - && resultHandle.getResult() == null) { + && resultHandle.getValue() == null) { // 如果结果已经被 prompter.error( "The received ledger hash of participant isn't equal to ledger hash of current participant! --[Id=%s]", @@ -720,13 +726,13 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI .getPubKey(); byte[] deciBytes = getDecisionBytes(targetDecision.getParticipantId(), targetDecision.getLedgerHash()); if ((!SIGN_FUNC.verify(targetDecision.getSignature(), targetPubKey, deciBytes)) - && resultHandle.getResult() == null) { + && resultHandle.getValue() == null) { prompter.error("The signature of received decision is invalid! --[Id=%s]", targetDecision.getParticipantId()); return false; } - resultHandle.setResult(targetDecision); + resultHandle.setValue(targetDecision); return true; } @@ -735,20 +741,38 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI public LedgerInitDecision synchronizeDecision(@RequestBody LedgerInitDecision initDecision) { int remoteId = initDecision.getParticipantId(); if (remoteId == currentId) { + prompter.error("Reject decision because of self-synchronization! --[Id=%s]", remoteId); throw new LedgerInitException( String.format("Reject decision because of self-synchronization! --[Id=%s]", remoteId)); } + if (this.genesisBlock == null) { // 当前参与者尚未准备就绪,返回 null; + prompter.info("Not ready for genesis block! --[RemoteId=%s][CurrentId=%s]", remoteId, currentId); return null; } - DecisionResultHandle resultHandle = this.decisions[remoteId]; - if (!validateAndRecordDecision(initDecision, resultHandle)) { - // 签名无效; + + prompter.info("Received request of synchronizing decision! --[RemoteId=%s][CurrentId=%s]", remoteId, currentId); + + try { + + DecisionResultHandle resultHandle = this.decisions[remoteId]; + if (!validateAndRecordDecision(initDecision, resultHandle)) { + // 签名无效; + prompter.error("Reject decision because of invalid signature! --[RemoteId=%s][CurrentId=%s]", remoteId, + currentId); + throw new LedgerInitException( + String.format("Reject decision because of invalid signature! --[RemoteId=%s][CurrentId=%s]", + remoteId, currentId)); + } + return localDecision; + } catch (Exception e) { + prompter.error(e, + "Error occurred while receiving the request of synchronizing decision! --[RemoteId=%s][CurrentId=%s] %s", + remoteId, currentId, e.getMessage()); throw new LedgerInitException( - String.format("Reject decision because of invalid signature! --[Id=%s]", remoteId)); + "Error occurred while receiving the request of synchronizing decision! --" + e.getMessage(), e); } - return localDecision; } /** diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/PropertiesUtils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/PropertiesUtils.java index ec6f5da9..994272b0 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/PropertiesUtils.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/PropertiesUtils.java @@ -37,9 +37,10 @@ public abstract class PropertiesUtils { /** * 创建配置对象的实例,并且从指定的属性表中初始化对应的实例字段; + * * @param configClass configClass - * @param properties properties - * @param T + * @param properties properties + * @param T * @return T */ @SuppressWarnings("unchecked") @@ -56,13 +57,10 @@ public abstract class PropertiesUtils { /** * 创建配置对象的实例,并且从指定的属性表中初始化对应的实例字段; * - * @param configClass - * 配置对象的类型; - * @param properties - * 属性表; - * @param propsPrefix - * 在属性表中与配置对象相关的属性的key的前缀; - * @param T + * @param configClass 配置对象的类型; + * @param properties 属性表; + * @param propsPrefix 在属性表中与配置对象相关的属性的key的前缀; + * @param T * @return T */ public static T createInstance(Class configClass, Properties properties, String propsPrefix) { @@ -77,12 +75,9 @@ public abstract class PropertiesUtils { /** * 设置配置值; * - * @param obj - * 配置对象;配置值将设置到此对象匹配的属性; - * @param configValues - * 配置值; - * @param propPrefix - * 自动加入的属性前缀; + * @param obj 配置对象;配置值将设置到此对象匹配的属性; + * @param configValues 配置值; + * @param propPrefix 自动加入的属性前缀; */ public static void setValues(Object obj, Properties configValues, String propPrefix) { Properties values = new Properties(); @@ -93,10 +88,8 @@ public abstract class PropertiesUtils { /** * 设置配置值; * - * @param obj - * 配置对象;配置值将设置到此对象匹配的属性; - * @param configValues - * 配置值; + * @param obj 配置对象;配置值将设置到此对象匹配的属性; + * @param configValues 配置值; */ public static void setValues(Object obj, Properties configValues) { BeanWrapper confBean = new BeanWrapperImpl(obj); @@ -109,13 +102,10 @@ public abstract class PropertiesUtils { /** * 从指定的路径加载配置; * - * @param configClass - * 配置对象的类型; - * @param configFilePathPattern - * properties配置文件的路径;可以指定 spring 资源路径表达式; - * @param charset - * 字符集; - * @param class + * @param configClass 配置对象的类型; + * @param configFilePathPattern properties配置文件的路径;可以指定 spring 资源路径表达式; + * @param charset 字符集; + * @param class * @return T * @throws IOException exception */ @@ -127,12 +117,9 @@ public abstract class PropertiesUtils { /** * 从指定的路径加载配置; * - * @param obj - * 配置对象;配置文件的值将设置到此对象匹配的属性; - * @param configFilePathPattern - * properties配置文件的路径;可以指定 spring 资源路径表达式; - * @param charset - * 字符集; + * @param obj 配置对象;配置文件的值将设置到此对象匹配的属性; + * @param configFilePathPattern properties配置文件的路径;可以指定 spring 资源路径表达式; + * @param charset 字符集; * @throws IOException exception */ public static void load(Object obj, String configFilePathPattern, String charset) throws IOException { @@ -180,10 +167,8 @@ public abstract class PropertiesUtils { /** * 合并两个 properties ; * - * @param props - * 要将其它值合并进来的属性集合;操作将对其产生修改; - * @param from - * 属性值将要合并进入其它属性集合;操作不对其产生修改; + * @param props 要将其它值合并进来的属性集合;操作将对其产生修改; + * @param from 属性值将要合并进入其它属性集合;操作不对其产生修改; */ public static void mergeFrom(Properties props, Properties from) { mergeFrom(props, from, null); @@ -192,12 +177,9 @@ public abstract class PropertiesUtils { /** * 合并两个 properties ; * - * @param props - * 要将其它值合并进来的属性集合;操作将对其产生修改; - * @param from - * 属性值将要合并进入其它属性集合;操作不对其产生修改; - * @param propertyNamePrefix - * 属性名称前缀; + * @param props 要将其它值合并进来的属性集合;操作将对其产生修改; + * @param from 属性值将要合并进入其它属性集合;操作不对其产生修改; + * @param propertyNamePrefix 属性名称前缀; */ public static void mergeFrom(Properties props, Properties from, String propertyNamePrefix) { if (propertyNamePrefix == null || propertyNamePrefix.length() == 0) { @@ -214,12 +196,9 @@ public abstract class PropertiesUtils { /** * 获取指定 properties 中以指定的前缀开头的子集; * - * @param props - * 要抽取的属性集合; - * @param propertyNamePrefix - * 属性名称前缀; - * @param trimPrefix - * 是否在复制的新的属性集合去掉指定的前缀; + * @param props 要抽取的属性集合; + * @param propertyNamePrefix 属性名称前缀; + * @param trimPrefix 是否在复制的新的属性集合去掉指定的前缀; * @return properties */ public static Properties subset(Properties props, String propertyNamePrefix, boolean trimPrefix) { @@ -278,13 +257,22 @@ public abstract class PropertiesUtils { * 如果不存在,或者返回值为空(null 或 空白字符),则抛出 {@link IllegalArgumentException} 异常; * * @param props props - * @param key key + * @param key key * @return String */ public static String getRequiredProperty(Properties props, String key) { return getProperty(props, key, true); } + /** + * 返回指定的属性;
+ * + * @param props 属性表; + * @param key 要查找的 key; + * @param required 值为 false 时,如果不存在则返回 null;值为 true 时,如果不存在,或者返回值为空(null 或 + * 空白字符),则抛出 {@link IllegalArgumentException} 异常; + * @return + */ public static String getProperty(Properties props, String key, boolean required) { String value = props.getProperty(key); if (value == null) { @@ -319,7 +307,7 @@ public abstract class PropertiesUtils { setValues(props, propValues); return props; } - + public static Properties setValues(Properties props, Property[] propValues) { for (Property p : propValues) { props.setProperty(p.getName(), p.getValue()); diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/InvocationResult.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/InvocationResult.java index 84533ba7..27a7e68f 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/InvocationResult.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/InvocationResult.java @@ -2,16 +2,16 @@ package com.jd.blockchain.utils.concurrent; public class InvocationResult { - private volatile T result; + private volatile T value; private volatile Exception error; - public T getResult() { - return result; + public T getValue() { + return value; } - public void setResult(T result) { - this.result = result; + public void setValue(T value) { + this.value = value; } public Exception getError() { diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/FileUtils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/FileUtils.java index e5ba84f9..77cfca01 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/FileUtils.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/FileUtils.java @@ -1,9 +1,23 @@ package com.jd.blockchain.utils.io; -import java.io.*; +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; import java.util.ArrayList; import java.util.Properties; +import org.springframework.util.ResourceUtils; + /** * @author haiq * @@ -41,7 +55,7 @@ public class FileUtils { throw new IllegalStateException(e.getMessage(), e); } } - + /** * 返回父目录的路径; * @@ -67,9 +81,8 @@ public class FileUtils { /** * 读取指定文件的首行; * - * @param file file - * @param charset - * 字符集; + * @param file file + * @param charset 字符集; * @return 返回首行非空行;返回结果不会自动截取两头的空字符串; * @throws IOException exception */ @@ -90,9 +103,8 @@ public class FileUtils { /** * 返回指定文件的所有行; * - * @param file file - * @param charset - * 字符集; + * @param file file + * @param charset 字符集; * @return 返回首行非空行;返回结果不会自动截取两头的空字符串; */ public static String[] readLines(File file, String charset) { @@ -155,10 +167,8 @@ public class FileUtils { /** * 以默认字符集(UTF-8)将指定的文本保存到指定的文件中; * - * @param file - * 要保存的文件; - * @param text - * 文本内容; + * @param file 要保存的文件; + * @param text 文本内容; */ public static void writeText(String text, File file) { writeText(text, file, DEFAULT_CHARSET); @@ -166,12 +176,10 @@ public class FileUtils { /** * 将指定的文本保存到指定的文件中; - * @param text - * 文本内容; - * @param file - * 要保存的文件; - * @param charset - * 字符集; + * + * @param text 文本内容; + * @param file 要保存的文件; + * @param charset 字符集; */ public static void writeText(String text, File file, String charset) { try (FileOutputStream out = new FileOutputStream(file, false)) { @@ -181,7 +189,7 @@ public class FileUtils { throw new RuntimeIOException(e.getMessage(), e); } } - + public static void writeBytes(byte[] content, File file) { try (FileOutputStream out = new FileOutputStream(file, false)) { out.write(content); @@ -190,7 +198,7 @@ public class FileUtils { throw new RuntimeIOException(e.getMessage(), e); } } - + public static void appendBytes(byte[] content, File file) { try (FileOutputStream out = new FileOutputStream(file, true)) { out.write(content); @@ -224,16 +232,23 @@ public class FileUtils { /** * 以默认字符集(UTF-8)从文件读取文本; + * * @param file file * @return String */ - public static String readText(String file) { - return readText(new File(file), DEFAULT_CHARSET); + public static String readText(String filePath) { + try { + File file = ResourceUtils.getFile(filePath); + return readText(file, DEFAULT_CHARSET); + } catch (FileNotFoundException e) { + throw new RuntimeIOException(e.getMessage(), e); + } } /** * 从文件读取文本; - * @param file file + * + * @param file file * @param charset charset * @return String */ @@ -254,7 +269,7 @@ public class FileUtils { /** * 从文件读取文本; * - * @param file file + * @param file file * @param charset charset * @return String */ @@ -278,7 +293,7 @@ public class FileUtils { /** * 从流读取文本; * - * @param in in + * @param in in * @param charset charset * @return String * @throws IOException exception @@ -310,7 +325,7 @@ public class FileUtils { throw new RuntimeIOException(e.getMessage(), e); } } - + public static byte[] readBytes(File file) { try { FileInputStream in = new FileInputStream(file); @@ -324,8 +339,12 @@ public class FileUtils { } } - public static Properties readProperties(String systemConfig) { - return readProperties(systemConfig, DEFAULT_CHARSET); + public static Properties readProperties(String file) { + return readProperties(file, DEFAULT_CHARSET); + } + + public static Properties readProperties(File file) { + return readProperties(file, DEFAULT_CHARSET); } public static Properties readProperties(String file, String charset) { @@ -417,11 +436,11 @@ public class FileUtils { throw new IllegalStateException(e.getMessage(), e); } } - + public static void deleteFile(String dir) { deleteFile(dir, false); } - + public static void deleteFile(File file) { deleteFile(file, false); } @@ -435,8 +454,7 @@ public class FileUtils { * 删除文件; * * @param file - * @param silent - * 是否静默删除;如果为 true ,则吞噬删除过程中的异常,意味着方法即便正常返回时也有可能删除不完全; + * @param silent 是否静默删除;如果为 true ,则吞噬删除过程中的异常,意味着方法即便正常返回时也有可能删除不完全; */ public static void deleteFile(File file, boolean silent) { if (file.isFile()) { From fa92f402277aaf980101eebcd6f8f560f73105b7 Mon Sep 17 00:00:00 2001 From: zhanglin33 Date: Mon, 20 May 2019 10:34:15 +0800 Subject: [PATCH 38/43] renew RSA junitTests to save compiling time --- .../crypto/paillier/PaillierUtilsTest.java | 47 +--- .../crypto/utils/classic/SSHKeyParser.java | 49 ++++ .../classic/RSACryptoFunctionTest.java | 255 +----------------- .../crypto/utils/classic/RSAUtilsTest.java | 66 +---- .../crypto/utils/classic/SSHKeyUtilsTest.java | 51 ++-- .../blockchain/crypto/utils/CertParser.java | 2 +- .../SHA1WITHRSA2048SignatureFunctionTest.java | 165 +----------- .../SHA1WITHRSA4096SignatureFunctionTest.java | 86 +----- .../crypto/utils/CSRBuilderTest.java | 2 +- 9 files changed, 129 insertions(+), 594 deletions(-) create mode 100644 source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/SSHKeyParser.java diff --git a/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/PaillierUtilsTest.java b/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/PaillierUtilsTest.java index 8ace44d1..a88b14ed 100644 --- a/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/PaillierUtilsTest.java +++ b/source/crypto/crypto-adv/src/test/java/test/com/jd/blockchain/crypto/paillier/PaillierUtilsTest.java @@ -19,7 +19,7 @@ import static org.junit.Assert.assertEquals; */ public class PaillierUtilsTest { @Test - public void generateKeyPairTest() { + public void test() { AsymmetricCipherKeyPair keyPair = PaillierUtils.generateKeyPair(); PaillierPublicKeyParameters pubKeyParams = (PaillierPublicKeyParameters) keyPair.getPublic(); @@ -58,13 +58,6 @@ public class PaillierUtilsTest { assertEquals(pInverseConverted, pInverse); assertEquals(muPConverted, muP); assertEquals(muQConverted, muQ); - } - - @Test - public void encryptTest() { - - AsymmetricCipherKeyPair keyPair = PaillierUtils.generateKeyPair(); - PaillierPublicKeyParameters pubKeyParams = (PaillierPublicKeyParameters) keyPair.getPublic(); byte[] pubKeyBytes = PaillierUtils.pubKey2Bytes(pubKeyParams); @@ -77,23 +70,15 @@ public class PaillierUtilsTest { assertEquals(512,ciphertextFromParams.length); assertEquals(512,ciphertextFromBytes.length); - } - @Test - public void decryptTest(){ - AsymmetricCipherKeyPair keyPair = PaillierUtils.generateKeyPair(); - PaillierPublicKeyParameters pubKeyParams = (PaillierPublicKeyParameters) keyPair.getPublic(); - PaillierPrivateKeyParameters privKeyParams = (PaillierPrivateKeyParameters) keyPair.getPrivate(); - - byte[] pubKeyBytes = PaillierUtils.pubKey2Bytes(pubKeyParams); byte[] privKeyBytes = PaillierUtils.privKey2Bytes(privKeyParams); int input = 666; - byte[] data = intToByteArray(input); + byte[] inputBytes = intToByteArray(input); - byte[] ciphertextFromParams = PaillierUtils.encrypt(data,pubKeyParams); - byte[] ciphertextFromBytes = PaillierUtils.encrypt(data,pubKeyBytes); + ciphertextFromParams = PaillierUtils.encrypt(inputBytes,pubKeyParams); + ciphertextFromBytes = PaillierUtils.encrypt(inputBytes,pubKeyBytes); byte[] plaintextFromParams = PaillierUtils.decrypt(ciphertextFromBytes,privKeyParams); byte[] plaintextFromBytes = PaillierUtils.decrypt(ciphertextFromParams,privKeyBytes); @@ -103,16 +88,9 @@ public class PaillierUtilsTest { assertEquals(input,outputFromParams); assertEquals(input,outputFromBytes); - } - @Test - public void addTest() { - AsymmetricCipherKeyPair keyPair = PaillierUtils.generateKeyPair(); - PaillierPublicKeyParameters pubKeyParams = (PaillierPublicKeyParameters) keyPair.getPublic(); - PaillierPrivateKeyParameters privKeyParams = (PaillierPrivateKeyParameters) keyPair.getPrivate(); - - byte[] pubKeyBytes = PaillierUtils.pubKey2Bytes(pubKeyParams); + pubKeyBytes = PaillierUtils.pubKey2Bytes(pubKeyParams); int input1 = 600; int input2 = 60; @@ -139,26 +117,19 @@ public class PaillierUtilsTest { output = byteArrayToInt(plaintext); assertEquals(sum,output); - } - @Test - public void scalarMultiplyTest() { - AsymmetricCipherKeyPair keyPair = PaillierUtils.generateKeyPair(); - PaillierPublicKeyParameters pubKeyParams = (PaillierPublicKeyParameters) keyPair.getPublic(); - PaillierPrivateKeyParameters privKeyParams = (PaillierPrivateKeyParameters) keyPair.getPrivate(); - - byte[] pubKeyBytes = PaillierUtils.pubKey2Bytes(pubKeyParams); + pubKeyBytes = PaillierUtils.pubKey2Bytes(pubKeyParams); - int input = 111; + input = 111; int scalar = 6; - byte[] data = intToByteArray(input); + data = intToByteArray(input); byte[] ciphertext = PaillierUtils.encrypt(data,pubKeyParams); byte[] ciphertextPowered = PaillierUtils.scalarMultiply(pubKeyBytes,ciphertext,scalar); byte[] plaintextMultiplied = PaillierUtils.decrypt(ciphertextPowered,privKeyParams); - int output = byteArrayToInt(plaintextMultiplied); + output = byteArrayToInt(plaintextMultiplied); assertEquals(input * scalar, output); } diff --git a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/SSHKeyParser.java b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/SSHKeyParser.java new file mode 100644 index 00000000..73e5243a --- /dev/null +++ b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/SSHKeyParser.java @@ -0,0 +1,49 @@ +package com.jd.blockchain.crypto.utils.classic; + +import org.bouncycastle.crypto.params.AsymmetricKeyParameter; +import org.bouncycastle.crypto.util.OpenSSHPublicKeyUtil; +import org.bouncycastle.jce.spec.OpenSSHPublicKeySpec; +import org.bouncycastle.util.encoders.Base64; + +/** + * @author zhanglin33 + * @title: SSHKeyParser + * @description: a parser for parsing asymmetric keys in Base64 format + * @date 2019-05-17, 17:52 + */ +public class SSHKeyParser { + + private String pubKeyFormat; + private String pubKeyType; + + public AsymmetricKeyParameter pubKeyParse(String pubKeyStr) { + + byte[] pubKeyBytes; + + if (pubKeyStr.startsWith("ssh") || pubKeyStr.startsWith("ecdsa")) { + String[] algoAndKeyAndLocal = pubKeyStr.split(" "); + pubKeyBytes = Base64.decode(algoAndKeyAndLocal[1]); + } else { + pubKeyBytes = Base64.decode(pubKeyStr); + } + + OpenSSHPublicKeySpec pubKeySpec = new OpenSSHPublicKeySpec(pubKeyBytes); + + pubKeyFormat = pubKeySpec.getFormat(); + pubKeyType = pubKeySpec.getType(); + + return OpenSSHPublicKeyUtil.parsePublicKey(pubKeyBytes); + } + + + + + + public String getPubKeyFormat() { + return pubKeyFormat; + } + + public String getPubKeyType() { + return pubKeyType; + } +} diff --git a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/service/classic/RSACryptoFunctionTest.java b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/service/classic/RSACryptoFunctionTest.java index 55101525..60f4d113 100644 --- a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/service/classic/RSACryptoFunctionTest.java +++ b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/service/classic/RSACryptoFunctionTest.java @@ -42,7 +42,7 @@ public class RSACryptoFunctionTest { } @Test - public void generateKeyPairTest() { + public void test() { CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA"); assertNotNull(algorithm); @@ -72,20 +72,7 @@ public class RSACryptoFunctionTest { byte[] rawPrivKeyBytes = privKey.getRawKeyBytes(); assertArrayEquals(BytesUtils.concat(algoBytes, pubKeyTypeBytes, rawPubKeyBytes), pubKey.toBytes()); assertArrayEquals(BytesUtils.concat(algoBytes, privKeyTypeBytes, rawPrivKeyBytes), privKey.toBytes()); - } - - @Test - public void retrievePubKeyTest() { - - CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA"); - assertNotNull(algorithm); - SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); - - AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); - - PubKey pubKey = keyPair.getPubKey(); - PrivKey privKey = keyPair.getPrivKey(); PubKey retrievedPubKey = signatureFunction.retrievePubKey(privKey); @@ -93,23 +80,12 @@ public class RSACryptoFunctionTest { assertEquals(pubKey.getRawKeyBytes().length, retrievedPubKey.getRawKeyBytes().length); assertEquals(pubKey.getAlgorithm(), retrievedPubKey.getAlgorithm()); assertArrayEquals(pubKey.toBytes(), retrievedPubKey.toBytes()); - } - @Test - public void signTest() { - byte[] data = new byte[1024]; + byte[] data = new byte[128]; Random random = new Random(); random.nextBytes(data); - CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA"); - assertNotNull(algorithm); - - SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); - - AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); - - PrivKey privKey = keyPair.getPrivKey(); SignatureDigest signatureDigest = signatureFunction.sign(privKey, data); byte[] signatureBytes = signatureDigest.toBytes(); @@ -121,48 +97,16 @@ public class RSACryptoFunctionTest { assertEquals((short) (SIGNATURE_ALGORITHM | ENCRYPTION_ALGORITHM | ASYMMETRIC_KEY | ((byte) 23 & 0x00FF)), signatureDigest.getAlgorithm()); - byte[] algoBytes = BytesUtils.toBytes(signatureDigest.getAlgorithm()); byte[] rawSinatureBytes = signatureDigest.getRawDigest(); assertArrayEquals(BytesUtils.concat(algoBytes, rawSinatureBytes), signatureBytes); - } - @Test - public void verifyTest() { - byte[] data = new byte[1024]; - Random random = new Random(); - random.nextBytes(data); - - CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA"); - assertNotNull(algorithm); - - SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); - - AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); - - PubKey pubKey = keyPair.getPubKey(); - PrivKey privKey = keyPair.getPrivKey(); - SignatureDigest signatureDigest = signatureFunction.sign(privKey, data); assertTrue(signatureFunction.verify(signatureDigest, pubKey, data)); - } - - @Test - public void encryptTest() { - - byte[] data = new byte[128]; - Random random = new Random(); - random.nextBytes(data); - CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA"); - assertNotNull(algorithm); AsymmetricEncryptionFunction asymmetricEncryptionFunction = Crypto .getAsymmetricEncryptionFunction(algorithm); - AsymmetricKeypair keyPair = asymmetricEncryptionFunction.generateKeypair(); - - PubKey pubKey = keyPair.getPubKey(); - Ciphertext ciphertext = asymmetricEncryptionFunction.encrypt(pubKey, data); byte[] ciphertextBytes = ciphertext.toBytes(); @@ -172,90 +116,32 @@ public class RSACryptoFunctionTest { assertEquals((short) (SIGNATURE_ALGORITHM | ENCRYPTION_ALGORITHM | ASYMMETRIC_KEY | ((byte) 23 & 0x00FF)), ciphertext.getAlgorithm()); - byte[] algoBytes = BytesUtils.toBytes(ciphertext.getAlgorithm()); byte[] rawCiphertextBytes = ciphertext.getRawCiphertext(); assertArrayEquals(BytesUtils.concat(algoBytes, rawCiphertextBytes), ciphertextBytes); - } - @Test - public void decryptTest() { - - byte[] data = new byte[128]; - Random random = new Random(); - random.nextBytes(data); - - CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA"); - assertNotNull(algorithm); - - AsymmetricEncryptionFunction asymmetricEncryptionFunction = Crypto - .getAsymmetricEncryptionFunction(algorithm); - - AsymmetricKeypair keyPair = asymmetricEncryptionFunction.generateKeypair(); - - PubKey pubKey = keyPair.getPubKey(); - PrivKey privKey = keyPair.getPrivKey(); - - Ciphertext ciphertext = asymmetricEncryptionFunction.encrypt(pubKey, data); byte[] decryptedPlaintext = asymmetricEncryptionFunction.decrypt(privKey, ciphertext); - assertArrayEquals(data, decryptedPlaintext); - } - - @Test - public void supportPrivKeyTest() { - - CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA"); - assertNotNull(algorithm); - SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); - - AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); - PrivKey privKey = keyPair.getPrivKey(); byte[] privKeyBytes = privKey.toBytes(); - assertTrue(signatureFunction.supportPrivKey(privKeyBytes)); - algorithm = Crypto.getAlgorithm("ripemd160"); assertNotNull(algorithm); - byte[] algoBytes = CryptoAlgorithm.getCodeBytes(algorithm); - byte[] pubKeyTypeBytes = new byte[] { PUBLIC.CODE }; byte[] rawKeyBytes = privKey.getRawKeyBytes(); byte[] ripemd160PubKeyBytes = BytesUtils.concat(algoBytes, pubKeyTypeBytes, rawKeyBytes); - assertFalse(signatureFunction.supportPrivKey(ripemd160PubKeyBytes)); - } - @Test - public void resolvePrivKeyTest() { - - CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA"); - assertNotNull(algorithm); - - SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); - - AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); - - PrivKey privKey = keyPair.getPrivKey(); - byte[] privKeyBytes = privKey.toBytes(); PrivKey resolvedPrivKey = signatureFunction.resolvePrivKey(privKeyBytes); - assertEquals(PRIVATE.CODE, resolvedPrivKey.getKeyType().CODE); assertEquals(1155, resolvedPrivKey.getRawKeyBytes().length); assertEquals(ClassicAlgorithm.RSA.code(), resolvedPrivKey.getAlgorithm()); assertEquals((short) (SIGNATURE_ALGORITHM | ENCRYPTION_ALGORITHM | ASYMMETRIC_KEY | ((byte) 23 & 0x00FF)), resolvedPrivKey.getAlgorithm()); assertArrayEquals(privKeyBytes, resolvedPrivKey.toBytes()); - algorithm = Crypto.getAlgorithm("ripemd160"); assertNotNull(algorithm); - byte[] algoBytes = CryptoAlgorithm.getCodeBytes(algorithm); - byte[] pubKeyTypeBytes = new byte[] { PUBLIC.CODE }; - byte[] rawKeyBytes = privKey.getRawKeyBytes(); - byte[] ripemd160PubKeyBytes = BytesUtils.concat(algoBytes, pubKeyTypeBytes, rawKeyBytes); - Class expectedException = CryptoException.class; Exception actualEx = null; try { @@ -265,64 +151,26 @@ public class RSACryptoFunctionTest { } assertNotNull(actualEx); assertTrue(expectedException.isAssignableFrom(actualEx.getClass())); - } - - @Test - public void supportPubKeyTest() { - CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA"); - assertNotNull(algorithm); - SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); - AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); - - PubKey pubKey = keyPair.getPubKey(); byte[] pubKeyBytes = pubKey.toBytes(); - assertTrue(signatureFunction.supportPubKey(pubKeyBytes)); - algorithm = Crypto.getAlgorithm("ripemd160"); assertNotNull(algorithm); - byte[] algoBytes = CryptoAlgorithm.getCodeBytes(algorithm); - byte[] privKeyTypeBytes = new byte[] { PRIVATE.CODE }; - byte[] rawKeyBytes = pubKey.getRawKeyBytes(); byte[] ripemd160PrivKeyBytes = BytesUtils.concat(algoBytes, privKeyTypeBytes, rawKeyBytes); - assertFalse(signatureFunction.supportPubKey(ripemd160PrivKeyBytes)); - } - - @Test - public void resolvePubKeyTest() { - - CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA"); - assertNotNull(algorithm); - - SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); - - AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); - PubKey pubKey = keyPair.getPubKey(); - byte[] pubKeyBytes = pubKey.toBytes(); PubKey resolvedPubKey = signatureFunction.resolvePubKey(pubKeyBytes); - assertEquals(PUBLIC.CODE, resolvedPubKey.getKeyType().CODE); assertEquals(259, resolvedPubKey.getRawKeyBytes().length); assertEquals(ClassicAlgorithm.RSA.code(), resolvedPubKey.getAlgorithm()); assertEquals((short) (SIGNATURE_ALGORITHM | ENCRYPTION_ALGORITHM | ASYMMETRIC_KEY | ((byte) 23 & 0x00FF)), resolvedPubKey.getAlgorithm()); assertArrayEquals(pubKeyBytes, resolvedPubKey.toBytes()); - algorithm = Crypto.getAlgorithm("ripemd160"); assertNotNull(algorithm); - byte[] algoBytes = CryptoAlgorithm.getCodeBytes(algorithm); - byte[] privKeyTypeBytes = new byte[] { PRIVATE.CODE }; - byte[] rawKeyBytes = pubKey.getRawKeyBytes(); - byte[] ripemd160PrivKeyBytes = BytesUtils.concat(algoBytes, privKeyTypeBytes, rawKeyBytes); - - Class expectedException = CryptoException.class; - Exception actualEx = null; try { signatureFunction.resolvePrivKey(ripemd160PrivKeyBytes); } catch (Exception e) { @@ -330,57 +178,18 @@ public class RSACryptoFunctionTest { } assertNotNull(actualEx); assertTrue(expectedException.isAssignableFrom(actualEx.getClass())); - } - - @Test - public void supportDigestTest() { - - byte[] data = new byte[1024]; - Random random = new Random(); - random.nextBytes(data); - - CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA"); - assertNotNull(algorithm); - - SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); - AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); - - PrivKey privKey = keyPair.getPrivKey(); - - SignatureDigest signatureDigest = signatureFunction.sign(privKey, data); byte[] signatureDigestBytes = signatureDigest.toBytes(); assertTrue(signatureFunction.supportDigest(signatureDigestBytes)); algorithm = Crypto.getAlgorithm("ripemd160"); assertNotNull(algorithm); - byte[] algoBytes = CryptoAlgorithm.getCodeBytes(algorithm); byte[] rawDigestBytes = signatureDigest.toBytes(); byte[] ripemd160SignatureBytes = BytesUtils.concat(algoBytes, rawDigestBytes); assertFalse(signatureFunction.supportDigest(ripemd160SignatureBytes)); - } - - @Test - public void resolveDigestTest() { - - byte[] data = new byte[1024]; - Random random = new Random(); - random.nextBytes(data); - - CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA"); - assertNotNull(algorithm); - - SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); - - AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); - - PrivKey privKey = keyPair.getPrivKey(); - SignatureDigest signatureDigest = signatureFunction.sign(privKey, data); - - byte[] signatureDigestBytes = signatureDigest.toBytes(); SignatureDigest resolvedSignatureDigest = signatureFunction.resolveDigest(signatureDigestBytes); @@ -392,12 +201,8 @@ public class RSACryptoFunctionTest { algorithm = Crypto.getAlgorithm("ripemd160"); assertNotNull(algorithm); - byte[] algoBytes = CryptoAlgorithm.getCodeBytes(algorithm); - byte[] rawDigestBytes = signatureDigest.getRawDigest(); byte[] ripemd160SignatureDigestBytes = BytesUtils.concat(algoBytes, rawDigestBytes); - Class expectedException = CryptoException.class; - Exception actualEx = null; try { signatureFunction.resolveDigest(ripemd160SignatureDigestBytes); } catch (Exception e) { @@ -405,77 +210,24 @@ public class RSACryptoFunctionTest { } assertNotNull(actualEx); assertTrue(expectedException.isAssignableFrom(actualEx.getClass())); - } - - @Test - public void supportCiphertextTest() { - - byte[] data = new byte[128]; - Random random = new Random(); - random.nextBytes(data); - - CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA"); - assertNotNull(algorithm); - - AsymmetricEncryptionFunction asymmetricEncryptionFunction = Crypto - .getAsymmetricEncryptionFunction(algorithm); - - AsymmetricKeypair keyPair = asymmetricEncryptionFunction.generateKeypair(); - - PubKey pubKey = keyPair.getPubKey(); - - Ciphertext ciphertext = asymmetricEncryptionFunction.encrypt(pubKey, data); - byte[] ciphertextBytes = ciphertext.toBytes(); assertTrue(asymmetricEncryptionFunction.supportCiphertext(ciphertextBytes)); - algorithm = Crypto.getAlgorithm("ripemd160"); assertNotNull(algorithm); - byte[] algoBytes = CryptoAlgorithm.getCodeBytes(algorithm); - byte[] rawCiphertextBytes = ciphertext.toBytes(); + algoBytes = CryptoAlgorithm.getCodeBytes(algorithm); byte[] ripemd160CiphertextBytes = BytesUtils.concat(algoBytes, rawCiphertextBytes); - assertFalse(asymmetricEncryptionFunction.supportCiphertext(ripemd160CiphertextBytes)); - } - - @Test - public void resolveCiphertextTest() { - - byte[] data = new byte[128]; - Random random = new Random(); - random.nextBytes(data); - - CryptoAlgorithm algorithm = Crypto.getAlgorithm("RSA"); - assertNotNull(algorithm); - - AsymmetricEncryptionFunction asymmetricEncryptionFunction = Crypto - .getAsymmetricEncryptionFunction(algorithm); - - AsymmetricKeypair keyPair = asymmetricEncryptionFunction.generateKeypair(); - PubKey pubKey = keyPair.getPubKey(); - - Ciphertext ciphertext = asymmetricEncryptionFunction.encrypt(pubKey, data); - - byte[] ciphertextBytes = ciphertext.toBytes(); Ciphertext resolvedCiphertext = asymmetricEncryptionFunction.resolveCiphertext(ciphertextBytes); - assertEquals(256, resolvedCiphertext.getRawCiphertext().length); assertEquals(ClassicAlgorithm.RSA.code(), resolvedCiphertext.getAlgorithm()); assertEquals((short) (SIGNATURE_ALGORITHM | ENCRYPTION_ALGORITHM | ASYMMETRIC_KEY | ((byte) 23 & 0x00FF)), resolvedCiphertext.getAlgorithm()); assertArrayEquals(ciphertextBytes, resolvedCiphertext.toBytes()); - algorithm = Crypto.getAlgorithm("ripemd160"); assertNotNull(algorithm); - byte[] algoBytes = CryptoAlgorithm.getCodeBytes(algorithm); - byte[] rawCiphertextBytes = ciphertext.getRawCiphertext(); - byte[] ripemd160CiphertextBytes = BytesUtils.concat(algoBytes, rawCiphertextBytes); - - Class expectedException = CryptoException.class; - Exception actualEx = null; try { asymmetricEncryptionFunction.resolveCiphertext(ripemd160CiphertextBytes); } catch (Exception e) { @@ -484,5 +236,4 @@ public class RSACryptoFunctionTest { assertNotNull(actualEx); assertTrue(expectedException.isAssignableFrom(actualEx.getClass())); } - } diff --git a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RSAUtilsTest.java b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RSAUtilsTest.java index a809da47..a8c82e85 100644 --- a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RSAUtilsTest.java +++ b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/RSAUtilsTest.java @@ -80,7 +80,7 @@ public class RSAUtilsTest { } @Test - public void retrievePublicKeyTest(){ + public void test(){ AsymmetricCipherKeyPair kp = RSAUtils.generateKeyPair(); RSAKeyParameters pubKey = (RSAKeyParameters) kp.getPublic(); @@ -91,38 +91,17 @@ public class RSAUtilsTest { byte[] retrievedPubKeyBytes = RSAUtils.retrievePublicKey(privKeyBytes); assertArrayEquals(pubKeyBytes,retrievedPubKeyBytes); - } - - @Test - public void signTest(){ - byte[] data = new byte[1024]; + byte[] data = new byte[128]; Random random = new Random(); random.nextBytes(data); - AsymmetricCipherKeyPair keyPair = RSAUtils.generateKeyPair(); - AsymmetricKeyParameter privKey = keyPair.getPrivate(); - byte[] privKeyBytes = RSAUtils.privKey2Bytes_RawKey((RSAPrivateCrtKeyParameters) privKey); - byte[] signatureFromPrivKey = RSAUtils.sign(data, privKey); byte[] signatureFromPrivKeyBytes = RSAUtils.sign(data, privKeyBytes); assertNotNull(signatureFromPrivKey); assertEquals(2048 / 8, signatureFromPrivKey.length); assertArrayEquals(signatureFromPrivKeyBytes,signatureFromPrivKey); - } - - @Test - public void verifyTest(){ - - byte[] data = new byte[1024]; - Random random = new Random(); - random.nextBytes(data); - - AsymmetricCipherKeyPair keyPair = RSAUtils.generateKeyPair(); - AsymmetricKeyParameter privKey = keyPair.getPrivate(); - AsymmetricKeyParameter pubKey = keyPair.getPublic(); - byte[] pubKeyBytes = RSAUtils.pubKey2Bytes_RawKey((RSAKeyParameters) pubKey); byte[] signature = RSAUtils.sign(data,privKey); @@ -131,46 +110,23 @@ public class RSAUtilsTest { assertTrue(isValidFromPubKey); assertTrue(isValidFromPubKeyBytes); - } - - @Test - public void encryptTest(){ - - byte[] data = new byte[246]; - Random random = new Random(); - random.nextBytes(data); - - AsymmetricCipherKeyPair keyPair = RSAUtils.generateKeyPair(); - AsymmetricKeyParameter pubKey = keyPair.getPublic(); - byte[] pubKeyBytes = RSAUtils.pubKey2Bytes_RawKey((RSAKeyParameters) pubKey); byte[] ciphertextFromPubKey = RSAUtils.encrypt(data,pubKey); byte[] ciphertextFromPubKeyBytes = RSAUtils.encrypt(data,pubKeyBytes); - assertEquals(512,ciphertextFromPubKey.length); - assertEquals(512,ciphertextFromPubKeyBytes.length); - } - - @Test - public void decryptTest(){ - - AsymmetricCipherKeyPair keyPair = RSAUtils.generateKeyPair(); - AsymmetricKeyParameter pubKey = keyPair.getPublic(); - AsymmetricKeyParameter privKey = keyPair.getPrivate(); - byte[] privKeyBytes = RSAUtils.privKey2Bytes_RawKey((RSAPrivateCrtKeyParameters) privKey); + assertEquals(256,ciphertextFromPubKey.length); + assertEquals(256,ciphertextFromPubKeyBytes.length); - Random random = new Random(); - byte[] data; - data = new byte[1024]; - random.nextBytes(data); - byte[] ciphertext = RSAUtils.encrypt(data, pubKey); + data = new byte[1024]; + random.nextBytes(data); + byte[] ciphertext = RSAUtils.encrypt(data, pubKey); - byte[] plaintextFromPrivKey = RSAUtils.decrypt(ciphertext, privKey); - byte[] plaintextFromPrivKeyBytes = RSAUtils.decrypt(ciphertext, privKeyBytes); + byte[] plaintextFromPrivKey = RSAUtils.decrypt(ciphertext, privKey); + byte[] plaintextFromPrivKeyBytes = RSAUtils.decrypt(ciphertext, privKeyBytes); - assertArrayEquals(data, plaintextFromPrivKey); - assertArrayEquals(data, plaintextFromPrivKeyBytes); + assertArrayEquals(data, plaintextFromPrivKey); + assertArrayEquals(data, plaintextFromPrivKeyBytes); } diff --git a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/SSHKeyUtilsTest.java b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/SSHKeyUtilsTest.java index 5964adc3..a873ed78 100644 --- a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/SSHKeyUtilsTest.java +++ b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/SSHKeyUtilsTest.java @@ -1,5 +1,6 @@ //package test.com.jd.blockchain.crypto.utils.classic; // +//import com.jd.blockchain.crypto.utils.classic.SSHKeyParser; //import org.bouncycastle.asn1.ASN1Sequence; //import org.bouncycastle.crypto.params.RSAKeyParameters; //import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters; @@ -17,6 +18,8 @@ //import java.io.StringReader; //import java.math.BigInteger; // +//import static org.junit.Assert.assertEquals; +// ///** // * @author zhanglin33 // * @title: SSHKeyUtilsTest @@ -34,26 +37,40 @@ // "e/9gMujAtDoolJ181a9P06bvEpIw5cLtUnsm5CtvBuiL7WBXxDJ/IASJrKNGBdK8xib1+Kb8tNLAT6" + // "Dj25BwylqiRNhb5l1Ni4aKrE2FqSEc5Nx5+csQMEl9MBJ3pEsLHBNbohDL+jbwLguRVD6CJ"; // -// byte[] pubKeyBytes = Base64.decode(pubKeyStr); -// System.out.println(Hex.toHexString(pubKeyBytes)); -// OpenSSHPublicKeySpec pubKeySpec = new OpenSSHPublicKeySpec(pubKeyBytes); +// BigInteger exponent = new BigInteger("010001",16); +// BigInteger modulus = new BigInteger("0098c0b378117cbb8345ee82fe2541fa2e8db0118b8f2" + +// "03d2c55ba9b46b12a06aac4b4d1ef6b03bbf4ab314a6bd6619f0d569230a711745800c88200962" + +// "433f98623c99bdea91c74d84659998f9e8a55f83e3a093141d78c9e47d9a3a0e3d7b38a635f7cc" + +// "6bde2b1e4dc7c8ef76815ec1b4c2b5d374c755d64e3353e5b5ea3ffe205e42c4344539b4bb1654" + +// "03aed0c13f35effd80cba302d0e8a25275f356bd3f4e9bbc4a48c3970bb549ec9b90adbc1ba22f" + +// "b5815f10c9fc801226b28d18174af3189bd7e29bf2d34b013e838f6e41c3296a8913616f997536" + +// "2e1a2ab13616a484739371e7e72c40c125f4c049de912c2c704d6e88432fe8dbc0b82e4550fa089",16); +// String pubKeyFormat = "OpenSSH"; +// String pubKeyType = "ssh-rsa"; // -// String pubKeyFormat = pubKeySpec.getFormat(); -// String pubKeyType = pubKeySpec.getType(); -// System.out.println(pubKeyFormat); -// System.out.println(pubKeyType); +// SSHKeyParser parser = new SSHKeyParser(); // -// RSAKeyParameters pubKey = (RSAKeyParameters) OpenSSHPublicKeyUtil.parsePublicKey(pubKeyBytes); +// RSAKeyParameters pubKey = (RSAKeyParameters) parser.pubKeyParse(pubKeyStr); // BigInteger e = pubKey.getExponent(); // BigInteger n = pubKey.getModulus(); -// System.out.println(Hex.toHexString(e.toByteArray())); -// System.out.println(Hex.toHexString(n.toByteArray())); -// -// System.out.println(); -// System.out.println("-------------------------------------------------------"); -// System.out.println(); -// -// +// assertEquals(exponent,e); +// assertEquals(modulus,n); +// assertEquals(pubKeyFormat,parser.getPubKeyFormat()); +// assertEquals(pubKeyType,parser.getPubKeyType()); +// +// String pubKeyStrWithHead = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCYwLN4EXy7g0Xugv4lQfou" + +// "jbARi48gPSxVuptGsSoGqsS00e9rA7v0qzFKa9Zhnw1WkjCnEXRYAMiCAJYkM/mGI8mb3qkcdNhGWZm" + +// "PnopV+D46CTFB14yeR9mjoOPXs4pjX3zGveKx5Nx8jvdoFewbTCtdN0x1XWTjNT5bXqP/4gXkLENEU5" + +// "tLsWVAOu0ME/Ne/9gMujAtDoolJ181a9P06bvEpIw5cLtUnsm5CtvBuiL7WBXxDJ/IASJrKNGBdK8xi" + +// "b1+Kb8tNLAT6Dj25BwylqiRNhb5l1Ni4aKrE2FqSEc5Nx5+csQMEl9MBJ3pEsLHBNbohDL+jbwLguRV" + +// "D6CJ zhanglin33@zhanglin33.local\n"; +// pubKey = (RSAKeyParameters) parser.pubKeyParse(pubKeyStrWithHead); +// e = pubKey.getExponent(); +// n = pubKey.getModulus(); +// assertEquals(exponent,e); +// assertEquals(modulus,n); +// assertEquals(pubKeyFormat,parser.getPubKeyFormat()); +// assertEquals(pubKeyType,parser.getPubKeyType()); // } // // @Test @@ -93,6 +110,7 @@ // } catch (IOException e1) { // e1.printStackTrace(); // } +// assert Bytes2 != null; // System.out.println(Hex.toHexString(Bytes2)); // // String str3 = "-----BEGIN OPENSSH PRIVATE KEY-----\n" + @@ -129,6 +147,7 @@ // } catch (IOException e1) { // e1.printStackTrace(); // } +// assert Bytes3 != null; // System.out.println(Hex.toHexString(Bytes3)); //// System.out.println(Hex.toHexString(Base64.decode("oNE9iA4ZyuZLbpEL7B29NaxGi4puT2Y5RDaMoEkoAKI"))); //// String test = "1ac477fa"; diff --git a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CertParser.java b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CertParser.java index 246c4759..8267d28b 100644 --- a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CertParser.java +++ b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CertParser.java @@ -37,7 +37,7 @@ public class CertParser { try { issuerCert.checkValidity(); } catch (CertificateExpiredException | CertificateNotYetValidException e) { - e.printStackTrace(); + throw new CryptoException(e.getMessage(), e); } PublicKey issuerPubKey = issuerCert.getPublicKey(); X500Principal issuerPrincipal = issuerCert.getSubjectX500Principal(); diff --git a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunctionTest.java b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunctionTest.java index 9b6952be..b7c7d831 100644 --- a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunctionTest.java +++ b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunctionTest.java @@ -41,26 +41,21 @@ public class SHA1WITHRSA2048SignatureFunctionTest { } @Test - public void generateKeyPairTest() { + public void test() { + // generateKeyPairTest CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA2048"); assertNotNull(algorithm); - SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); - AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); - PubKey pubKey = keyPair.getPubKey(); PrivKey privKey = keyPair.getPrivKey(); - assertEquals(PUBLIC.CODE, pubKey.getKeyType().CODE); assertTrue(pubKey.getRawKeyBytes().length > 259); assertEquals(PRIVATE.CODE, privKey.getKeyType().CODE); assertTrue(privKey.getRawKeyBytes().length > 1155); - assertEquals(algorithm.code(), pubKey.getAlgorithm()); assertEquals(algorithm.code(), privKey.getAlgorithm()); - byte[] algoBytes = CryptoAlgorithm.getCodeBytes(algorithm); byte[] pubKeyTypeBytes = new byte[] { PUBLIC.CODE }; byte[] privKeyTypeBytes = new byte[] { PRIVATE.CODE }; @@ -68,200 +63,62 @@ public class SHA1WITHRSA2048SignatureFunctionTest { byte[] rawPrivKeyBytes = privKey.getRawKeyBytes(); assertArrayEquals(BytesUtils.concat(algoBytes, pubKeyTypeBytes, rawPubKeyBytes), pubKey.toBytes()); assertArrayEquals(BytesUtils.concat(algoBytes, privKeyTypeBytes, rawPrivKeyBytes), privKey.toBytes()); - } - - @Test - public void retrievePubKeyTest() { - - CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA2048"); - assertNotNull(algorithm); - - SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); - - AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); - - PubKey pubKey = keyPair.getPubKey(); - PrivKey privKey = keyPair.getPrivKey(); + // retrievePubKeyTest PubKey retrievedPubKey = signatureFunction.retrievePubKey(privKey); - assertEquals(pubKey.getKeyType(), retrievedPubKey.getKeyType()); assertEquals(pubKey.getRawKeyBytes().length, retrievedPubKey.getRawKeyBytes().length); assertEquals(pubKey.getAlgorithm(), retrievedPubKey.getAlgorithm()); assertArrayEquals(pubKey.toBytes(), retrievedPubKey.toBytes()); - } - - @Test - public void signTest() { + // signTest byte[] data = new byte[1024]; Random random = new Random(); random.nextBytes(data); - - CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA2048"); - assertNotNull(algorithm); - - SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); - - AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); - - PrivKey privKey = keyPair.getPrivKey(); SignatureDigest signatureDigest = signatureFunction.sign(privKey, data); - byte[] signatureBytes = signatureDigest.toBytes(); - assertEquals(2 + 256, signatureBytes.length); assertEquals(algorithm.code(), signatureDigest.getAlgorithm()); - assertEquals(PKIAlgorithm.SHA1WITHRSA2048.code(), signatureDigest.getAlgorithm()); assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 31 & 0x00FF)), signatureDigest.getAlgorithm()); - byte[] algoBytes = BytesUtils.toBytes(signatureDigest.getAlgorithm()); byte[] rawSinatureBytes = signatureDigest.getRawDigest(); assertArrayEquals(BytesUtils.concat(algoBytes, rawSinatureBytes), signatureBytes); - } - - @Test - public void verifyTest() { - byte[] data = new byte[1024]; - Random random = new Random(); - random.nextBytes(data); - - CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA2048"); - assertNotNull(algorithm); - - SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); - - AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); - - PubKey pubKey = keyPair.getPubKey(); - PrivKey privKey = keyPair.getPrivKey(); - SignatureDigest signatureDigest = signatureFunction.sign(privKey, data); + // verifyTest assertTrue(signatureFunction.verify(signatureDigest, pubKey, data)); - } - - @Test - public void supportPrivKeyTest() { - CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA2048"); - assertNotNull(algorithm); - - SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); - - AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); - - PrivKey privKey = keyPair.getPrivKey(); + // supportPrivKeyTest byte[] privKeyBytes = privKey.toBytes(); - assertTrue(signatureFunction.supportPrivKey(privKeyBytes)); - } - - @Test - public void resolvePrivKeyTest() { - - CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA2048"); - assertNotNull(algorithm); - - SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); - - AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); - - PrivKey privKey = keyPair.getPrivKey(); - byte[] privKeyBytes = privKey.toBytes(); + // resolvePrivKeyTest PrivKey resolvedPrivKey = signatureFunction.resolvePrivKey(privKeyBytes); - assertEquals(PRIVATE.CODE, resolvedPrivKey.getKeyType().CODE); assertEquals(PKIAlgorithm.SHA1WITHRSA2048.code(), resolvedPrivKey.getAlgorithm()); assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 31 & 0x00FF)), resolvedPrivKey.getAlgorithm()); assertArrayEquals(privKeyBytes, resolvedPrivKey.toBytes()); - } - - @Test - public void supportPubKeyTest() { - CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA2048"); - assertNotNull(algorithm); - - SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); - - AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); - - PubKey pubKey = keyPair.getPubKey(); + // supportPubKeyTest byte[] pubKeyBytes = pubKey.toBytes(); - assertTrue(signatureFunction.supportPubKey(pubKeyBytes)); - } - - @Test - public void resolvePubKeyTest() { - - CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA2048"); - assertNotNull(algorithm); - - SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); - - AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); - - PubKey pubKey = keyPair.getPubKey(); - byte[] pubKeyBytes = pubKey.toBytes(); + // resolvedPubKeyTest PubKey resolvedPubKey = signatureFunction.resolvePubKey(pubKeyBytes); - assertEquals(PUBLIC.CODE, resolvedPubKey.getKeyType().CODE); assertEquals(PKIAlgorithm.SHA1WITHRSA2048.code(), resolvedPubKey.getAlgorithm()); assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 31 & 0x00FF)), resolvedPubKey.getAlgorithm()); assertArrayEquals(pubKeyBytes, resolvedPubKey.toBytes()); - } - - @Test - public void supportDigestTest() { - - byte[] data = new byte[1024]; - Random random = new Random(); - random.nextBytes(data); - - CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA2048"); - assertNotNull(algorithm); - - SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); - - AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); - - PrivKey privKey = keyPair.getPrivKey(); - - SignatureDigest signatureDigest = signatureFunction.sign(privKey, data); + //supportDigestTest byte[] signatureDigestBytes = signatureDigest.toBytes(); assertTrue(signatureFunction.supportDigest(signatureDigestBytes)); - } - - @Test - public void resolveDigestTest() { - - byte[] data = new byte[1024]; - Random random = new Random(); - random.nextBytes(data); - - CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA2048"); - assertNotNull(algorithm); - - SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); - - AsymmetricKeypair keyPair = signatureFunction.generateKeypair(); - - PrivKey privKey = keyPair.getPrivKey(); - - SignatureDigest signatureDigest = signatureFunction.sign(privKey, data); - - byte[] signatureDigestBytes = signatureDigest.toBytes(); + // resolveDigestTest SignatureDigest resolvedSignatureDigest = signatureFunction.resolveDigest(signatureDigestBytes); - assertEquals(256, resolvedSignatureDigest.getRawDigest().length); assertEquals(PKIAlgorithm.SHA1WITHRSA2048.code(), resolvedSignatureDigest.getAlgorithm()); assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 31 & 0x00FF)), diff --git a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunctionTest.java b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunctionTest.java index 5b976c72..9444771b 100644 --- a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunctionTest.java +++ b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunctionTest.java @@ -20,9 +20,6 @@ import static org.junit.Assert.*; */ public class SHA1WITHRSA4096SignatureFunctionTest { - private AsymmetricKeypair keyPair = Crypto.getSignatureFunction(Crypto.getAlgorithm("SHA1WITHRSA4096")). - generateKeypair(); - @Test public void getAlgorithmTest() { @@ -44,12 +41,14 @@ public class SHA1WITHRSA4096SignatureFunctionTest { assertNull(algorithm); } - @Test + //@Test public void generateKeyPairTest() { CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA4096"); assertNotNull(algorithm); + AsymmetricKeypair keyPair = Crypto.getSignatureFunction(algorithm).generateKeypair(); + PubKey pubKey = keyPair.getPubKey(); PrivKey privKey = keyPair.getPrivKey(); @@ -68,125 +67,58 @@ public class SHA1WITHRSA4096SignatureFunctionTest { byte[] rawPrivKeyBytes = privKey.getRawKeyBytes(); assertArrayEquals(BytesUtils.concat(algoBytes, pubKeyTypeBytes, rawPubKeyBytes), pubKey.toBytes()); assertArrayEquals(BytesUtils.concat(algoBytes, privKeyTypeBytes, rawPrivKeyBytes), privKey.toBytes()); - } - - @Test - public void retrievePubKeyTest() { - - CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA4096"); - assertNotNull(algorithm); + // retrievePubKeyTest SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); - - PubKey pubKey = keyPair.getPubKey(); - PrivKey privKey = keyPair.getPrivKey(); - PubKey retrievedPubKey = signatureFunction.retrievePubKey(privKey); - assertEquals(pubKey.getKeyType(), retrievedPubKey.getKeyType()); assertEquals(pubKey.getRawKeyBytes().length, retrievedPubKey.getRawKeyBytes().length); assertEquals(pubKey.getAlgorithm(), retrievedPubKey.getAlgorithm()); assertArrayEquals(pubKey.toBytes(), retrievedPubKey.toBytes()); - } - @Test - public void signAndVerifyTest() { + // signAndVerifyTest byte[] data = new byte[1024]; Random random = new Random(); random.nextBytes(data); - CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA4096"); - assertNotNull(algorithm); - - SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); - - PrivKey privKey = keyPair.getPrivKey(); - PubKey pubKey = keyPair.getPubKey(); - SignatureDigest signatureDigest = signatureFunction.sign(privKey, data); - byte[] signatureBytes = signatureDigest.toBytes(); - assertEquals(2 + 512, signatureBytes.length); assertEquals(algorithm.code(), signatureDigest.getAlgorithm()); - assertEquals(PKIAlgorithm.SHA1WITHRSA4096.code(), signatureDigest.getAlgorithm()); assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 32 & 0x00FF)), signatureDigest.getAlgorithm()); - - byte[] algoBytes = BytesUtils.toBytes(signatureDigest.getAlgorithm()); + algoBytes = BytesUtils.toBytes(signatureDigest.getAlgorithm()); byte[] rawSinatureBytes = signatureDigest.getRawDigest(); assertArrayEquals(BytesUtils.concat(algoBytes, rawSinatureBytes), signatureBytes); - assertTrue(signatureFunction.verify(signatureDigest, pubKey, data)); - } - - @Test - public void supportAndResolvePrivKeyTest() { - - CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA4096"); - assertNotNull(algorithm); - SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); - - PrivKey privKey = keyPair.getPrivKey(); + // supportAndResolvePrivKeyTest byte[] privKeyBytes = privKey.toBytes(); - assertTrue(signatureFunction.supportPrivKey(privKeyBytes)); - PrivKey resolvedPrivKey = signatureFunction.resolvePrivKey(privKeyBytes); - assertEquals(PRIVATE.CODE, resolvedPrivKey.getKeyType().CODE); assertEquals(PKIAlgorithm.SHA1WITHRSA4096.code(), resolvedPrivKey.getAlgorithm()); assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 32 & 0x00FF)), resolvedPrivKey.getAlgorithm()); assertArrayEquals(privKeyBytes, resolvedPrivKey.toBytes()); - } - - @Test - public void supportAndResolvePubKeyTest() { - CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA4096"); - assertNotNull(algorithm); - - SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); - - PubKey pubKey = keyPair.getPubKey(); + // supportAndResolvePubKeyTest byte[] pubKeyBytes = pubKey.toBytes(); - assertTrue(signatureFunction.supportPubKey(pubKeyBytes)); - PubKey resolvedPubKey = signatureFunction.resolvePubKey(pubKeyBytes); - assertEquals(PUBLIC.CODE, resolvedPubKey.getKeyType().CODE); assertEquals(PKIAlgorithm.SHA1WITHRSA4096.code(), resolvedPubKey.getAlgorithm()); assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 32 & 0x00FF)), resolvedPubKey.getAlgorithm()); assertArrayEquals(pubKeyBytes, resolvedPubKey.toBytes()); - } - - @Test - public void supportAndResolveDigestTest() { - byte[] data = new byte[1024]; - Random random = new Random(); - random.nextBytes(data); - - CryptoAlgorithm algorithm = Crypto.getAlgorithm("SHA1WITHRSA4096"); - assertNotNull(algorithm); - - SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); - - PrivKey privKey = keyPair.getPrivKey(); - - SignatureDigest signatureDigest = signatureFunction.sign(privKey, data); + // supportAndResolveDigestTest byte[] signatureDigestBytes = signatureDigest.toBytes(); assertTrue(signatureFunction.supportDigest(signatureDigestBytes)); - SignatureDigest resolvedSignatureDigest = signatureFunction.resolveDigest(signatureDigestBytes); - assertEquals(512, resolvedSignatureDigest.getRawDigest().length); assertEquals(PKIAlgorithm.SHA1WITHRSA4096.code(), resolvedSignatureDigest.getAlgorithm()); assertEquals((short) (SIGNATURE_ALGORITHM | ASYMMETRIC_KEY | ((byte) 32 & 0x00FF)), diff --git a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CSRBuilderTest.java b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CSRBuilderTest.java index f309ff52..62dc4dc2 100644 --- a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CSRBuilderTest.java +++ b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CSRBuilderTest.java @@ -203,7 +203,7 @@ public class CSRBuilderTest { } - @Test +// @Test public void SHA1withRSA4096CSRTest(){ String countryName = "CN"; From 376753b8d2d2f45a73987238ddf1d31ab4347042 Mon Sep 17 00:00:00 2001 From: shaozhuguang Date: Mon, 20 May 2019 15:02:07 +0800 Subject: [PATCH 39/43] Modify the information returned by LedgerSetting, And Adjust Log Printing to LOGGER ! --- .../service/GatewayQueryServiceHandler.java | 20 +- .../jd/blockchain/ledger/ParticipantNode.java | 1 + .../jd/blockchain/peer/web/PeerTimeTasks.java | 22 +- .../jd/blockchain/sdk/LedgerInitSettings.java | 23 +- source/test/pom.xml | 1 - source/test/test-stp-community/pom.xml | 36 --- .../stp/commucation/MyMessageExecutor.java | 37 ---- .../stp/commucation/StpReceiversBoot.java | 75 ------- .../jd/blockchain/StpReceiversBootTest.java | 43 ---- .../java/com/jd/blockchain/StpSenderTest.java | 96 -------- .../test/java/com/jd/blockchain/StpTest.java | 206 ------------------ 11 files changed, 19 insertions(+), 541 deletions(-) delete mode 100644 source/test/test-stp-community/pom.xml delete mode 100644 source/test/test-stp-community/src/main/java/com/jd/blockchain/stp/commucation/MyMessageExecutor.java delete mode 100644 source/test/test-stp-community/src/main/java/com/jd/blockchain/stp/commucation/StpReceiversBoot.java delete mode 100644 source/test/test-stp-community/src/test/java/com/jd/blockchain/StpReceiversBootTest.java delete mode 100644 source/test/test-stp-community/src/test/java/com/jd/blockchain/StpSenderTest.java delete mode 100644 source/test/test-stp-community/src/test/java/com/jd/blockchain/StpTest.java diff --git a/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryServiceHandler.java b/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryServiceHandler.java index 71e34a7c..1a6c0267 100644 --- a/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryServiceHandler.java +++ b/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryServiceHandler.java @@ -81,7 +81,7 @@ public class GatewayQueryServiceHandler implements GatewayQueryService { ledgerInitSettings.setSeed(initSeed(ledgerMetadata.getSeed())); // 设置共识协议 - ledgerInitSettings.setConsensusProtocol(consensusProtocol(ledgerMetadata.getSetting().getConsensusProvider())); + ledgerInitSettings.setConsensusProtocol(ledgerMetadata.getSetting().getConsensusProvider()); return ledgerInitSettings; } @@ -110,24 +110,6 @@ public class GatewayQueryServiceHandler implements GatewayQueryService { return seed.toString(); } - /** - * 生成共识协议 - * - * @param consensusProvider - * 共识协议提提供者 - * @return - */ - private int consensusProtocol(String consensusProvider) { - - if (consensusProvider.equals(BftsmartConsensusProvider.NAME)) { - return LedgerInitSettings.CONSENSUS_PROTOCOL.BFTSMART.code(); - } else if (consensusProvider.equals(MsgQueueConsensusProvider.NAME)) { - return LedgerInitSettings.CONSENSUS_PROTOCOL.MSGQUEUE.code(); - } - - return LedgerInitSettings.CONSENSUS_PROTOCOL.UNKNOWN.code(); - } - /** * 初始化共识配置 * diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantNode.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantNode.java index c8974d1c..dd2c62fa 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantNode.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantNode.java @@ -22,6 +22,7 @@ public interface ParticipantNode {// extends ConsensusNode, ParticipantInfo { * * @return */ + @DataField(order = 0, primitiveType = PrimitiveType.INT32) int getId(); /** diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/web/PeerTimeTasks.java b/source/peer/src/main/java/com/jd/blockchain/peer/web/PeerTimeTasks.java index 8e3d220f..698fb584 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/web/PeerTimeTasks.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/web/PeerTimeTasks.java @@ -15,11 +15,11 @@ import com.jd.blockchain.peer.ConsensusManage; import com.jd.blockchain.peer.LedgerBindingConfigAware; import com.jd.blockchain.peer.PeerServerBooter; import com.jd.blockchain.tools.initializer.LedgerBindingConfig; -import com.jd.blockchain.utils.ArgumentSet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.CommandLineRunner; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.core.io.ClassPathResource; @@ -38,9 +38,11 @@ import java.util.*; * @since 1.0.0 */ @Component -//@EnableScheduling +@EnableScheduling public class PeerTimeTasks implements ApplicationContextAware { + private static Logger LOGGER = LoggerFactory.getLogger(PeerTimeTasks.class); + private ApplicationContext applicationContext; @Autowired @@ -51,7 +53,9 @@ public class PeerTimeTasks implements ApplicationContextAware { //每1分钟执行一次 @Scheduled(cron = "0 */5 * * * * ") public void updateLedger(){ - System.out.println ("Update Ledger Tasks Start " + new Date()); + + LOGGER.debug("Time Task Update Ledger Tasks Start {}", new Date()); + try { LedgerBindingConfig ledgerBindingConfig = loadLedgerBindingConfig(); @@ -78,7 +82,8 @@ public class PeerTimeTasks implements ApplicationContextAware { Map bindingConfigAwares = applicationContext.getBeansOfType(LedgerBindingConfigAware.class); List nodeServers = new ArrayList<>(); for (HashDigest ledgerHash : newAddHashs) { - System.out.printf("newLedger[%s] \r\n", ledgerHash.toBase58()); + + LOGGER.info("New Ledger [{}] Need To Be Init !!!", ledgerHash.toBase58()); for (LedgerBindingConfigAware aware : bindingConfigAwares.values()) { nodeServers.add(aware.setConfig(ledgerBindingConfig, ledgerHash)); } @@ -89,10 +94,10 @@ public class PeerTimeTasks implements ApplicationContextAware { consensusManage.runRealm(nodeServer); } } else { - System.out.println("All Ledgers is newest!!!"); + LOGGER.debug("All Ledgers is newest!!!"); } } catch (Exception e) { - e.printStackTrace(); + LOGGER.error(e.getMessage()); } } @@ -104,7 +109,8 @@ public class PeerTimeTasks implements ApplicationContextAware { private LedgerBindingConfig loadLedgerBindingConfig() throws Exception { LedgerBindingConfig ledgerBindingConfig; ledgerBindConfigFile = PeerServerBooter.ledgerBindConfigFile; - System.out.printf("load ledgerBindConfigFile = %s \r\n", ledgerBindConfigFile); + LOGGER.debug("Load LedgerBindConfigFile path = {}", + ledgerBindConfigFile == null ? "Default" : ledgerBindConfigFile); if (ledgerBindConfigFile == null) { ClassPathResource configResource = new ClassPathResource("ledger-binding.conf"); InputStream in = configResource.getInputStream(); diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/LedgerInitSettings.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/LedgerInitSettings.java index fa3c2cd0..d4f287ab 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/LedgerInitSettings.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/LedgerInitSettings.java @@ -34,7 +34,7 @@ public class LedgerInitSettings { /** * 共识协议 */ - private int consensusProtocol; + private String consensusProtocol; /** * 共识配置 @@ -70,11 +70,11 @@ public class LedgerInitSettings { this.cryptoSetting = cryptoSetting; } - public int getConsensusProtocol() { + public String getConsensusProtocol() { return consensusProtocol; } - public void setConsensusProtocol(int consensusProtocol) { + public void setConsensusProtocol(String consensusProtocol) { this.consensusProtocol = consensusProtocol; } @@ -93,21 +93,4 @@ public class LedgerInitSettings { public void setParticipantNodes(ParticipantNode[] participantNodes) { this.participantNodes = participantNodes; } - - public enum CONSENSUS_PROTOCOL { - UNKNOWN(0), - BFTSMART(1), - MSGQUEUE(2), - ; - - private int code; - - CONSENSUS_PROTOCOL(int code) { - this.code = code; - } - - public int code() { - return code; - } - } } diff --git a/source/test/pom.xml b/source/test/pom.xml index ac3b0562..4df214ad 100644 --- a/source/test/pom.xml +++ b/source/test/pom.xml @@ -15,7 +15,6 @@ test-consensus-node test-ledger-core test-integration - test-stp-community diff --git a/source/test/test-stp-community/pom.xml b/source/test/test-stp-community/pom.xml deleted file mode 100644 index 12d031b1..00000000 --- a/source/test/test-stp-community/pom.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - test - com.jd.blockchain - 0.9.0-SNAPSHOT - - 4.0.0 - - test-stp-community - - test-stp-community - - - UTF-8 - 1.8 - 1.8 - - - - - - com.jd.blockchain - stp-communication - ${project.version} - - - - junit - junit - test - - - diff --git a/source/test/test-stp-community/src/main/java/com/jd/blockchain/stp/commucation/MyMessageExecutor.java b/source/test/test-stp-community/src/main/java/com/jd/blockchain/stp/commucation/MyMessageExecutor.java deleted file mode 100644 index 26656a8b..00000000 --- a/source/test/test-stp-community/src/main/java/com/jd/blockchain/stp/commucation/MyMessageExecutor.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright: Copyright 2016-2020 JD.COM All Right Reserved - * FileName: com.jd.blockchain.stp.commucation.MyMessageExecutor - * Author: shaozhuguang - * Department: Y事业部 - * Date: 2019/4/17 下午3:38 - * Description: - */ -package com.jd.blockchain.stp.commucation; - -import com.jd.blockchain.stp.communication.MessageExecutor; -import com.jd.blockchain.stp.communication.RemoteSession; - -import java.nio.charset.Charset; - -/** - * - * @author shaozhuguang - * @create 2019/4/17 - * @since 1.0.0 - */ - -public class MyMessageExecutor implements MessageExecutor { - - @Override - public byte[] receive(String key, byte[] data, RemoteSession session) { - String receiveMsg = new String(data, Charset.defaultCharset()); - System.out.printf("receive client {%s} request {%s} \r\n", session.remoteNode().toString(), receiveMsg); - String msg = session.localId() + " -> received !!!"; - return msg.getBytes(Charset.defaultCharset()); - } - - @Override - public REPLY replyType() { - return REPLY.AUTO; - } -} \ No newline at end of file diff --git a/source/test/test-stp-community/src/main/java/com/jd/blockchain/stp/commucation/StpReceiversBoot.java b/source/test/test-stp-community/src/main/java/com/jd/blockchain/stp/commucation/StpReceiversBoot.java deleted file mode 100644 index e725d77b..00000000 --- a/source/test/test-stp-community/src/main/java/com/jd/blockchain/stp/commucation/StpReceiversBoot.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Copyright: Copyright 2016-2020 JD.COM All Right Reserved - * FileName: com.jd.blockchain.StpReceiversBoot - * Author: shaozhuguang - * Department: Y事业部 - * Date: 2019/4/18 下午3:44 - * Description: - */ -package com.jd.blockchain.stp.commucation; - -import com.jd.blockchain.stp.communication.MessageExecutor; -import com.jd.blockchain.stp.communication.manager.RemoteSessionManager; -import com.jd.blockchain.stp.communication.node.LocalNode; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -/** - * - * @author shaozhuguang - * @create 2019/4/18 - * @since 1.0.0 - */ - -public class StpReceiversBoot { - - private int[] listenPorts; - - private final String remoteHost = "127.0.0.1"; - - private ExecutorService threadPool; - - public StpReceiversBoot(int... ports) { - listenPorts = ports; - threadPool = Executors.newFixedThreadPool(ports.length + 2); - } - - public RemoteSessionManager[] start(MessageExecutor messageExecutor) { - - final int totalSessionSize = listenPorts.length; - - CountDownLatch countDownLatch = new CountDownLatch(totalSessionSize); - - RemoteSessionManager[] sessionManagers = new RemoteSessionManager[totalSessionSize]; - for (int i = 0; i < totalSessionSize; i++) { - final int port = listenPorts[i], index = i; - threadPool.execute(() -> { - // 创建本地节点 - final LocalNode localNode = new LocalNode(remoteHost, port, messageExecutor); - try { - // 启动当前节点 - RemoteSessionManager sessionManager = new RemoteSessionManager(localNode); - sessionManagers[index] = sessionManager; - System.out.printf("Current Node {%s} start success !!! \r\n", localNode.toString()); - } catch (Exception e) { - e.printStackTrace(); - } finally { - countDownLatch.countDown(); - } - }); - } - - // 等待所有节点启动完成 - try { - countDownLatch.await(); - } catch (Exception e) { - e.printStackTrace(); - } - - return sessionManagers; - } - - -} \ No newline at end of file diff --git a/source/test/test-stp-community/src/test/java/com/jd/blockchain/StpReceiversBootTest.java b/source/test/test-stp-community/src/test/java/com/jd/blockchain/StpReceiversBootTest.java deleted file mode 100644 index 1cd6e985..00000000 --- a/source/test/test-stp-community/src/test/java/com/jd/blockchain/StpReceiversBootTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright: Copyright 2016-2020 JD.COM All Right Reserved - * FileName: com.jd.blockchain.StpReceiversBootTest - * Author: shaozhuguang - * Department: Y事业部 - * Date: 2019/4/18 下午3:53 - * Description: - */ -package com.jd.blockchain; - -import com.jd.blockchain.stp.commucation.MyMessageExecutor; -import com.jd.blockchain.stp.commucation.StpReceiversBoot; -import com.jd.blockchain.stp.communication.manager.RemoteSessionManager; -import org.junit.Test; - -/** - * - * @author shaozhuguang - * @create 2019/4/18 - * @since 1.0.0 - */ - -public class StpReceiversBootTest { - - public static final int[] localPorts = new int[]{9900, 9901}; - - @Test - public void test() { - StpReceiversBoot stpReceiversBoot = new StpReceiversBoot(9900, 9901); - RemoteSessionManager[] sessionManagers = stpReceiversBoot.start(new MyMessageExecutor()); - - try { - Thread.sleep(10000); - - // 关闭所有的监听器 - for (RemoteSessionManager sessionManager : sessionManagers) { - sessionManager.connectionManager().closeReceiver(); - } - } catch (Exception e) { - e.printStackTrace(); - } - } -} \ No newline at end of file diff --git a/source/test/test-stp-community/src/test/java/com/jd/blockchain/StpSenderTest.java b/source/test/test-stp-community/src/test/java/com/jd/blockchain/StpSenderTest.java deleted file mode 100644 index 29741ae0..00000000 --- a/source/test/test-stp-community/src/test/java/com/jd/blockchain/StpSenderTest.java +++ /dev/null @@ -1,96 +0,0 @@ -/** - * Copyright: Copyright 2016-2020 JD.COM All Right Reserved - * FileName: com.jd.blockchain.StpSenderTest - * Author: shaozhuguang - * Department: Y事业部 - * Date: 2019/4/18 下午3:56 - * Description: - */ -package com.jd.blockchain; - -import com.jd.blockchain.stp.commucation.MyMessageExecutor; -import com.jd.blockchain.stp.commucation.StpReceiversBoot; -import com.jd.blockchain.stp.communication.RemoteSession; -import com.jd.blockchain.stp.communication.callback.CallBackBarrier; -import com.jd.blockchain.stp.communication.callback.CallBackDataListener; -import com.jd.blockchain.stp.communication.manager.RemoteSessionManager; -import com.jd.blockchain.stp.communication.message.LoadMessage; -import com.jd.blockchain.stp.communication.node.RemoteNode; -import org.junit.Test; - -import java.util.Iterator; -import java.util.LinkedList; - -/** - * - * @author shaozhuguang - * @create 2019/4/18 - * @since 1.0.0 - */ - -public class StpSenderTest { - - // 本地的端口 - private static final int localPort = 9800; - - // 连接的远端端口集合 - private static final int[] remotePorts = StpReceiversBootTest.localPorts; - - // 本地节点信息 - private static final String localHost = "127.0.0.1"; - - @Test - public void test() { - // 首先启动本地节点 - StpReceiversBoot stpReceiversBoot = new StpReceiversBoot(localPort); - RemoteSessionManager[] sessionManagers = stpReceiversBoot.start(new MyMessageExecutor()); - - // 本地节点启动完成后 - if (sessionManagers != null && sessionManagers.length > 0) { - RemoteSessionManager localSessionManager = sessionManagers[0]; - - // 连接远端的两个节点 - RemoteNode[] remoteNodes = new RemoteNode[]{ - new RemoteNode(localHost, remotePorts[0]), - new RemoteNode(localHost, remotePorts[1]) - }; - - RemoteSession[] remoteSessions = localSessionManager.newSessions(remoteNodes); - - // 生成请求对象 - LoadMessage loadMessage = new StpTest.StpLoadMessage(localHost + ":" + localPort); - - // 异步发送处理过程 - CallBackBarrier callBackBarrier = CallBackBarrier.newCallBackBarrier(remoteSessions.length, 10000); - - // 发送请求至remotes - LinkedList responses = new LinkedList<>(); - for (RemoteSession remoteSession : remoteSessions) { - CallBackDataListener response = remoteSession.asyncRequest(loadMessage, callBackBarrier); - responses.addLast(response); - } - - // 超时判断 - try { - if (callBackBarrier.tryCall()) { - - // 说明结果已经全部返回 - // 打印出所有的结果 - // 通过迭代器遍历链表 - Iterator iterator = responses.iterator(); - while (iterator.hasNext()) { - CallBackDataListener response = iterator.next(); - // 判断是否已完成,对于没有完成的直接放弃(因为已经超时) - if (response.isDone()) { - System.out.printf("Receive Response {%s} {%s} \r\n", - response.remoteNode().toString(), new String(response.getCallBackData())); - } - } - } - Thread.sleep(Integer.MAX_VALUE); - } catch (Exception e) { - e.printStackTrace(); - } - } - } -} \ No newline at end of file diff --git a/source/test/test-stp-community/src/test/java/com/jd/blockchain/StpTest.java b/source/test/test-stp-community/src/test/java/com/jd/blockchain/StpTest.java deleted file mode 100644 index 2e66c8e1..00000000 --- a/source/test/test-stp-community/src/test/java/com/jd/blockchain/StpTest.java +++ /dev/null @@ -1,206 +0,0 @@ -/** - * Copyright: Copyright 2016-2020 JD.COM All Right Reserved - * FileName: com.jd.blockchain.StpTest - * Author: shaozhuguang - * Department: Y事业部 - * Date: 2019/4/11 下午3:31 - * Description: - */ -package com.jd.blockchain; - -import com.jd.blockchain.stp.commucation.MyMessageExecutor; -import com.jd.blockchain.stp.communication.RemoteSession; -import com.jd.blockchain.stp.communication.callback.CallBackBarrier; -import com.jd.blockchain.stp.communication.callback.CallBackDataListener; -import com.jd.blockchain.stp.communication.manager.RemoteSessionManager; -import com.jd.blockchain.stp.communication.message.LoadMessage; -import com.jd.blockchain.stp.communication.node.LocalNode; -import com.jd.blockchain.stp.communication.node.RemoteNode; -import org.junit.Before; -import org.junit.Test; - -import java.nio.charset.Charset; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import static org.junit.Assert.assertNull; - -/** - * - * @author shaozhuguang - * @create 2019/4/11 - * @since 1.0.0 - */ - -public class StpTest { - - private int maxWaitTime = 2000; - - private final String remoteHost = "127.0.0.1"; - - private final int localPort = 9001; - - private final int[] listenPorts = new int[]{9001, 9002, 9003, 9004}; - - private final RemoteSessionManager[] sessionManagers = new RemoteSessionManager[listenPorts.length]; - - private final ExecutorService threadPool = Executors.newFixedThreadPool(6); - - private RemoteSession[] remoteSessions; - - @Before - public void init() { - - System.out.println("---------- listenStart -----------"); - listenStart(); - System.out.println("---------- listenComplete -----------"); - System.out.println("---------- ConnectionStart ----------"); - connectOneOther(); - System.out.println("---------- ConnectionComplete ----------"); - } - - private void listenStart() { - CountDownLatch countDownLatch = new CountDownLatch(listenPorts.length); - - for (int i = 0; i < listenPorts.length; i++) { - final int port = listenPorts[i], index = i; - threadPool.execute(() -> { - // 创建本地节点 - final LocalNode localNode = new LocalNode(remoteHost, port, new MyMessageExecutor()); - try { - // 启动当前节点 - RemoteSessionManager sessionManager = new RemoteSessionManager(localNode); - sessionManagers[index] = sessionManager; - System.out.printf("Current Node {%s} start success !!! \r\n", localNode.toString()); - } catch (Exception e) { - e.printStackTrace(); - } finally { - countDownLatch.countDown(); - } - }); - } - - // 等待所有节点启动完成 - try { - countDownLatch.await(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - private void connectAllOthers() { - // 所有节点完成之后,需要启动 - // 启动一个节点 - RemoteSessionManager starter = sessionManagers[0]; - - // 当前节点需要连接到其他3个节点 - RemoteNode[] remoteNodes = new RemoteNode[listenPorts.length - 1]; - int index = 0; - for (int port : listenPorts) { - if (port != localPort) { - remoteNodes[index++] = new RemoteNode(remoteHost, port); - } - } - - remoteSessions = starter.newSessions(remoteNodes); - } - - private void connectOneOther() { - // 所有节点完成之后,需要启动 - // 启动一个节点 - RemoteSessionManager starter = sessionManagers[0]; - - // 当前节点需要连接到其他3个节点 - RemoteNode[] remoteNodes = new RemoteNode[1]; - int index = 0; - for (int port : listenPorts) { - if (port != localPort && index < 1) { - remoteNodes[index++] = new RemoteNode(remoteHost, port); - } - } - - remoteSessions = starter.newSessions(remoteNodes); - } - - private void connectOneErrorNode() { - // 所有节点完成之后,需要启动 - // 启动一个节点 - RemoteSessionManager starter = sessionManagers[0]; - - // 当前节点需要连接到其他3个节点 - RemoteNode[] remoteNodes = new RemoteNode[1]; - - remoteNodes[0] = new RemoteNode(remoteHost, 10001); - - remoteSessions = starter.newSessions(remoteNodes); - - assertNull(remoteSessions); - } - - - @Test - public void test() { - - try { - Thread.sleep(3000); - - } catch (Exception e) { - e.printStackTrace(); - } - - // 生成请求对象 - LoadMessage loadMessage = new StpLoadMessage(remoteHost + ":" + localPort); - - // 异步发送处理过程 - CallBackBarrier callBackBarrier = CallBackBarrier.newCallBackBarrier(remoteSessions.length, 10000); - - // 发送请求至remotes - LinkedList responses = new LinkedList<>(); - for (RemoteSession remoteSession : remoteSessions) { - CallBackDataListener response = remoteSession.asyncRequest(loadMessage, callBackBarrier); - responses.addLast(response); - } - - // 超时判断 - try { - if (callBackBarrier.tryCall()) { - - // 说明结果已经全部返回 - // 打印出所有的结果 - // 通过迭代器遍历链表 - Iterator iterator = responses.iterator(); - while (iterator.hasNext()) { - CallBackDataListener response = iterator.next(); - // 判断是否已完成,对于没有完成的直接放弃(因为已经超时) - if (response.isDone()) { - System.out.printf("Receive Response {%s} {%s} \r\n", - response.remoteNode().toString(), new String(response.getCallBackData())); - } - } - } - Thread.sleep(Integer.MAX_VALUE); - } catch (Exception e) { - e.printStackTrace(); - } - - - } - - public static class StpLoadMessage implements LoadMessage { - - private String localInfo; - - public StpLoadMessage(String localInfo) { - this.localInfo = localInfo; - } - - @Override - public byte[] toBytes() { - String msg = localInfo + " -> Send !!!"; - return msg.getBytes(Charset.defaultCharset()); - } - } -} \ No newline at end of file From 8288e0cad7d27af877dabb3ecd3081fb3c04e43b Mon Sep 17 00:00:00 2001 From: huanghaiquan Date: Mon, 20 May 2019 17:23:22 +0800 Subject: [PATCH 40/43] Completed development of adding crypto provider setting to LedgerAdminAccount; --- .../java/com/jd/blockchain/crypto/Crypto.java | 6 + .../blockchain/ledger/core/CryptoConfig.java | 12 +- .../ledger/core/impl/LedgerManager.java | 98 +++++++--- .../blockchain/ledger/LedgerManagerTest.java | 1 + .../jd/blockchain/ledger/CryptoSetting.java | 1 + .../peer/LedgerBindingConfigAware.java | 2 - .../peer/web/ManagementController.java | 171 ++---------------- .../initializer/LedgerInitProperties.java | 3 + 8 files changed, 109 insertions(+), 185 deletions(-) diff --git a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/Crypto.java b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/Crypto.java index b6b94603..654e86b4 100644 --- a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/Crypto.java +++ b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/Crypto.java @@ -130,6 +130,12 @@ public final class Crypto { return new CryptoProviderInfo(pd.getFullName(), algorithms); } + /** + * 返回指定名称的密码服务提供者;如果不存在,则返回 null ; + * + * @param providerFullName + * @return + */ public static CryptoProvider getProvider(String providerFullName) { Provider pd = pm.getProvider(CryptoService.class, providerFullName); if (pd == null) { diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/CryptoConfig.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/CryptoConfig.java index 1939e36b..2b905d6b 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/CryptoConfig.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/CryptoConfig.java @@ -13,17 +13,17 @@ public class CryptoConfig implements CryptoSetting { private short hashAlgorithm; private boolean autoVerifyHash; - + HashMap providers; HashMap nameAlgorithms; HashMap codeAlgorithms; - public CryptoConfig() { } public CryptoConfig(CryptoSetting setting) { - this.hashAlgorithm = setting.getHashAlgorithm(); + setSupportedProviders(setting.getSupportedProviders()); + setHashAlgorithm(setting.getHashAlgorithm()); this.autoVerifyHash = setting.getAutoVerifyHash(); } @@ -68,10 +68,10 @@ public class CryptoConfig implements CryptoSetting { providers.put(cryptoProvider.getName(), cryptoProvider); } } - this.providers = providers; + this.providers = providers; this.nameAlgorithms = nameAlgorithms; this.codeAlgorithms = codeAlgorithms; - + this.cryptoProviders = supportedProviders; } @@ -81,7 +81,7 @@ public class CryptoConfig implements CryptoSetting { public void setHashAlgorithm(short hashAlgorithm) { if (codeAlgorithms == null || !codeAlgorithms.containsKey(hashAlgorithm)) { - throw new LedgerException("The specified algorithm has no provider!"); + throw new LedgerException("The specified algorithm[" + hashAlgorithm + "] has no provider!"); } this.hashAlgorithm = hashAlgorithm; } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerManager.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerManager.java index 93842206..4525ed9d 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerManager.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerManager.java @@ -3,10 +3,15 @@ package com.jd.blockchain.ledger.core.impl; import java.util.HashMap; import java.util.Map; +import com.jd.blockchain.crypto.Crypto; +import com.jd.blockchain.crypto.CryptoAlgorithm; +import com.jd.blockchain.crypto.CryptoProvider; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.ledger.CryptoSetting; import com.jd.blockchain.ledger.LedgerInitSetting; import com.jd.blockchain.ledger.core.LedgerConsts; import com.jd.blockchain.ledger.core.LedgerEditor; +import com.jd.blockchain.ledger.core.LedgerException; import com.jd.blockchain.ledger.core.LedgerManage; import com.jd.blockchain.ledger.core.LedgerRepository; import com.jd.blockchain.storage.service.ExPolicyKVStorage; @@ -57,26 +62,83 @@ public class LedgerManager implements LedgerManage { @Override public LedgerRepository register(HashDigest ledgerHash, KVStorageService storageService) { + // 加载账本数据库; VersioningKVStorage ledgerVersioningStorage = storageService.getVersioningKVStorage(); ExPolicyKVStorage ledgerExPolicyStorage = storageService.getExPolicyKVStorage(); LedgerRepository ledgerRepo = new LedgerRepositoryImpl(ledgerHash, LEDGER_PREFIX, ledgerExPolicyStorage, ledgerVersioningStorage); - LedgerRepositoryContext ledgerCtx = new LedgerRepositoryContext(); - ledgerCtx.ledgerRepo = ledgerRepo; - ledgerCtx.storageService = storageService; + // 校验 crypto service provider ; + CryptoSetting cryptoSetting = ledgerRepo.getAdminAccount().getSetting().getCryptoSetting(); + checkCryptoSetting(cryptoSetting, ledgerHash); + + // 创建账本上下文; + LedgerRepositoryContext ledgerCtx = new LedgerRepositoryContext(ledgerRepo, storageService); ledgers.put(ledgerHash, ledgerCtx); return ledgerRepo; } + /** + * 检查账本的密码参数设置与本地节点的运行时环境是否匹配; + * + * @param cryptoSetting + * @param ledgerHash + */ + private void checkCryptoSetting(CryptoSetting cryptoSetting, HashDigest ledgerHash) { + CryptoProvider[] cryptoProviders = cryptoSetting.getSupportedProviders(); + if (cryptoProviders == null || cryptoProviders.length == 0) { + throw new LedgerException("No supported crypto service providers has been setted in the ledger[" + + ledgerHash.toBase58() + "]!"); + } + for (CryptoProvider cp : cryptoProviders) { + CryptoProvider regCp = Crypto.getProvider(cp.getName()); + checkCryptoProviderConsistency(regCp, cp); + } + } + + /** + * 检查密码服务提供者的信息是否匹配; + * + * @param registeredProvider + * @param settingProvider + */ + private void checkCryptoProviderConsistency(CryptoProvider registeredProvider, CryptoProvider settingProvider) { + if (registeredProvider == null) { + throw new LedgerException("Crypto service provider[" + settingProvider.getName() + + "] has not registered in the runtime environment of current peer!"); + } + + CryptoAlgorithm[] runtimeAlgothms = registeredProvider.getAlgorithms(); + CryptoAlgorithm[] settingAlgothms = settingProvider.getAlgorithms(); + if (runtimeAlgothms.length != settingAlgothms.length) { + throw new LedgerException("Crypto service provider[" + settingProvider.getName() + + "] has not registered in runtime of current peer!"); + } + HashMap runtimeAlgothmMap = new HashMap(); + for (CryptoAlgorithm alg : runtimeAlgothms) { + runtimeAlgothmMap.put(alg.code(), alg); + } + for (CryptoAlgorithm alg : settingAlgothms) { + CryptoAlgorithm regAlg = runtimeAlgothmMap.get(alg.code()); + if (regAlg == null) { + throw new LedgerException( + String.format("Crypto algorithm[%s] is not defined by provider[%s] in runtime of current peer!", + alg.toString(), registeredProvider.getName())); + } + if (!regAlg.name().equals(alg.name())) { + throw new LedgerException(String.format( + "Crypto algorithm[%s] do not match the same code algorithm[%s] defined by provider[%s] in runtime of current peer!", + CryptoAlgorithm.getString(alg), CryptoAlgorithm.getString(regAlg), + registeredProvider.getName())); + } + } + } + @Override public void unregister(HashDigest ledgerHash) { - LedgerRepositoryContext ledgerCtx = ledgers.get(ledgerHash); + LedgerRepositoryContext ledgerCtx = ledgers.remove(ledgerHash); if (ledgerCtx != null) { ledgerCtx.ledgerRepo.close(); - ledgers.remove(ledgerHash); - ledgerCtx.ledgerRepo = null; - ledgerCtx.storageService = null; } } @@ -88,18 +150,6 @@ public class LedgerManager implements LedgerManage { */ @Override public LedgerEditor newLedger(LedgerInitSetting initSetting, KVStorageService storageService) { - // GenesisLedgerStorageProxy genesisStorageProxy = new - // GenesisLedgerStorageProxy(); - // BufferedKVStorage bufferedStorage = new - // BufferedKVStorage(genesisStorageProxy, genesisStorageProxy, false); - - // LedgerEditor genesisBlockEditor = - // LedgerTransactionalEditor.createEditor(initSetting, - // bufferedStorage, bufferedStorage); - - // return new LedgerInitializer(genesisBlockEditor, bufferedStorage, - // genesisStorageProxy, storageService, this); - LedgerEditor genesisBlockEditor = LedgerTransactionalEditor.createEditor(initSetting, LEDGER_PREFIX, storageService.getExPolicyKVStorage(), storageService.getVersioningKVStorage()); return genesisBlockEditor; @@ -110,10 +160,16 @@ public class LedgerManager implements LedgerManage { return LEDGER_PREFIX + base58LedgerHash + LedgerConsts.KEY_SEPERATOR; } + private static class LedgerRepositoryContext { - private LedgerRepository ledgerRepo; + public final LedgerRepository ledgerRepo; - private KVStorageService storageService; + public final KVStorageService storageService; + + public LedgerRepositoryContext(LedgerRepository ledgerRepo, KVStorageService storageService) { + this.ledgerRepo = ledgerRepo; + this.storageService = storageService; + } } } diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerManagerTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerManagerTest.java index 066151cd..9819c9b3 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerManagerTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerManagerTest.java @@ -57,6 +57,7 @@ public class LedgerManagerTest { DataContractRegistry.register(UserRegisterOperation.class); DataContractRegistry.register(DataAccountRegisterOperation.class); DataContractRegistry.register(BlockBody.class); + DataContractRegistry.register(CryptoProvider.class); } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/CryptoSetting.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/CryptoSetting.java index 373fd1b3..9f24322c 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/CryptoSetting.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/CryptoSetting.java @@ -20,6 +20,7 @@ public interface CryptoSetting { * * @return */ + @DataField(order = 0, refContract = true, list = true) public CryptoProvider[] getSupportedProviders(); diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/LedgerBindingConfigAware.java b/source/peer/src/main/java/com/jd/blockchain/peer/LedgerBindingConfigAware.java index c0bb263b..e8b244c6 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/LedgerBindingConfigAware.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/LedgerBindingConfigAware.java @@ -4,8 +4,6 @@ import com.jd.blockchain.consensus.service.NodeServer; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.tools.initializer.LedgerBindingConfig; -import java.util.List; - public interface LedgerBindingConfigAware { void setConfig(LedgerBindingConfig config); diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/web/ManagementController.java b/source/peer/src/main/java/com/jd/blockchain/peer/web/ManagementController.java index 0e8c863e..ac95d361 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/web/ManagementController.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/web/ManagementController.java @@ -5,10 +5,6 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; - -import com.jd.blockchain.ledger.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -35,6 +31,21 @@ import com.jd.blockchain.consensus.service.NodeServer; import com.jd.blockchain.consensus.service.ServerSettings; import com.jd.blockchain.consensus.service.StateMachineReplicate; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.ledger.ContractCodeDeployOperation; +import com.jd.blockchain.ledger.ContractEventSendOperation; +import com.jd.blockchain.ledger.CryptoSetting; +import com.jd.blockchain.ledger.DataAccountKVSetOperation; +import com.jd.blockchain.ledger.DataAccountRegisterOperation; +import com.jd.blockchain.ledger.EndpointRequest; +import com.jd.blockchain.ledger.LedgerBlock; +import com.jd.blockchain.ledger.LedgerInitOperation; +import com.jd.blockchain.ledger.NodeRequest; +import com.jd.blockchain.ledger.Operation; +import com.jd.blockchain.ledger.TransactionContent; +import com.jd.blockchain.ledger.TransactionContentBody; +import com.jd.blockchain.ledger.TransactionRequest; +import com.jd.blockchain.ledger.TransactionResponse; +import com.jd.blockchain.ledger.UserRegisterOperation; import com.jd.blockchain.ledger.core.LedgerAdminAccount; import com.jd.blockchain.ledger.core.LedgerManage; import com.jd.blockchain.ledger.core.LedgerRepository; @@ -68,35 +79,17 @@ public class ManagementController implements LedgerBindingConfigAware, PeerManag public static final int MIN_GATEWAY_ID = 10000; - // @Autowired - // private PeerSettings peerSetting; - -// @Autowired -// private ConsensusTransactionService consensusService; - - // private ConsensusPeer consensusReplica; - @Autowired private LedgerManage ledgerManager; @Autowired private DbConnectionFactory connFactory; - // private Map ledgerConns = new - // ConcurrentHashMap<>(); - private Map ledgerTxConverters = new ConcurrentHashMap<>(); private Map ledgerPeers = new ConcurrentHashMap<>(); private Map ledgerCryptoSettings = new ConcurrentHashMap<>(); - // private Map nodeRealms = new - // ConcurrentHashMap<>(); - - // private Map ledgerRealms = new - // ConcurrentHashMap<>(); - // private Map ledgerRealmsNoConflict = new - // ConcurrentHashMap<>(); private LedgerBindingConfig config; @@ -106,9 +99,6 @@ public class ManagementController implements LedgerBindingConfigAware, PeerManag @Autowired private StateMachineReplicate consensusStateManager; - // private static int step = 0; - // private static int temp = 0; - static { DataContractRegistry.register(LedgerInitOperation.class); DataContractRegistry.register(LedgerBlock.class); @@ -134,24 +124,6 @@ public class ManagementController implements LedgerBindingConfigAware, PeerManag } - @PostConstruct - private void init() { - - } - - @PreDestroy - private void destroy() { -// DbConnection[] conns = ledgerConns.values().toArray(new DbConnection[ledgerConns.size()]); -// ledgerConns.clear(); -// for (DbConnection conn : conns) { -// try { -// conn.close(); -// } catch (Exception e) { -// // Ignore; -// } -// } - } - /** * 接入认证; * @@ -234,42 +206,8 @@ public class ManagementController implements LedgerBindingConfigAware, PeerManag HashDigest[] ledgerHashs = config.getLedgerHashs(); for (HashDigest ledgerHash : ledgerHashs) { setConfig(config,ledgerHash); -// LedgerBindingConfig.BindingConfig bindingConfig = config.getLedger(ledgerHash); -// DbConnection dbConnNew = connFactory.connect(bindingConfig.getDbConnection().getUri(), -// bindingConfig.getDbConnection().getPassword()); -// LedgerRepository ledgerRepository = ledgerManager.register(ledgerHash, dbConnNew.getStorageService()); -// -// // load provider; -// LedgerAdminAccount ledgerAdminAccount = ledgerRepository.getAdminAccount(); -// String consensusProvider = ledgerAdminAccount.getSetting().getConsensusProvider(); -// ConsensusProvider provider = ConsensusProviders.getProvider(consensusProvider); -// // find current node; -// Bytes csSettingBytes = ledgerAdminAccount.getSetting().getConsensusSetting(); -// ConsensusSettings csSettings = provider.getSettingsFactory().getConsensusSettingsEncoder() -// .decode(csSettingBytes.toBytes()); -// NodeSettings currentNode = null; -// for (NodeSettings nodeSettings : csSettings.getNodes()) { -// if (nodeSettings.getAddress().equals(bindingConfig.getParticipant().getAddress())) { -// currentNode = nodeSettings; -// } -// } -// if (currentNode == null) { -// throw new IllegalArgumentException( -// "Current node is not found from the consensus settings of ledger[" + ledgerHash.toBase58() -// + "]!"); -// } -// ServerSettings serverSettings = provider.getServerFactory().buildServerSettings(ledgerHash.toBase58(), csSettings, currentNode.getAddress()); -// -// NodeServer server = provider.getServerFactory().setupServer(serverSettings, consensusMessageHandler, -// consensusStateManager); -// ledgerPeers.put(ledgerHash, server); -// ledgerCryptoSettings.put(ledgerHash, ledgerAdminAccount.getSetting().getCryptoSetting()); - } - // remove duplicate consensus realm,and establish consensus peer and consensus - // realm corresponding relationship - // initBindingConfig(config); this.config = config; } catch (Exception e) { @@ -314,46 +252,6 @@ public class ManagementController implements LedgerBindingConfigAware, PeerManag return server; } - // private void initBindingConfig(LedgerBindingConfig config) { - // boolean intersection = false; - // // to remove intersection consensus realm - // for (HashDigest hashDigest : ledgerRealms.keySet()) { - // ConsensusRealm consensusRealm1i = ledgerRealms.get(hashDigest); - // for (ConsensusRealm consensusRealm1j : ledgerRealms.values()) { - // // avoid compare with myself - // if (consensusRealm1i.equals(consensusRealm1j)) { - // continue; - // } - // if (consensusRealm1i.hasIntersection(consensusRealm1j)) { - // intersection = true; - // break; - // } - // } - // // prompt consensus realm conflict info - // if (intersection == true) { - // ConsoleUtils.info("\r\nconsensus realm intersection with other consensus - // realm\r\n"); - // continue; - // } - // if (intersection == false) { - // // add consensus realm without conflict to ledgerRealmsNoConflict - // ledgerRealmsNoConflict.put(hashDigest, consensusRealm1i); - // - // // String consensusSystemFile = - // config.getLedger(hashDigest).getCsConfigFile(); - // int currentId = config.getLedger(hashDigest).getParticipant().getId(); - // // init consensusSystemConfig; - // ConsensusProperties csProps = - // ConsensusProperties.resolve(consensusRealm1i.getSetting()); - // ConsensusPeer consensusPeer = new ConsensusPeer(consensusRealm1i, currentId, - // consensusService, - // csProps.getProperties()); - // ledgerPeers.put(hashDigest, consensusPeer); - // } - // } // END OF FOR:get ledgerRealmsNoConflict and ledgerPeers - // - // } - @Override public ConsensusRealm[] getRealms() { throw new IllegalStateException("Not implemented!"); @@ -364,45 +262,6 @@ public class ManagementController implements LedgerBindingConfigAware, PeerManag for (NodeServer peer : ledgerPeers.values()) { runRealm(peer); } - // try { - // - // // for (ConsensusPeer peer : ledgerPeers.values()) { - // for (Map.Entry entry : ledgerPeers.entrySet()) { - // HashDigest ledgerHash = entry.getKey(); - // ConsensusPeer peer = entry.getValue(); - // // TODO: 多线程启动; - // ConsensusNode[] nodes = peer.getConsensusRealm().getNodes(); - // StringBuilder consensusInfo = new StringBuilder(); - // for (ConsensusNode node : nodes) { - // consensusInfo.append( - // String.format("[%s]-%s; ", node.getAddress(), - // node.getConsensusAddress().toString())); - // } - // LOGGER.debug(String.format("-------- start consensus peer[Id=%s] --Nodes=%s - // -------------", - // peer.getCurrentId(), consensusInfo.toString())); - // peer.start(); - // // 设置消息队列 - // MsgQueueMessageDispatcher messageDispatcher = ledgerTxConverters.get(ledgerHash); - // - // if (messageDispatcher == null) { - // LedgerBindingConfig.BindingConfig bindingConfig = - // this.config.getLedger(ledgerHash); - // MQConnectionConfig mqConnection = bindingConfig.getMqConnection(); - // if (mqConnection != null && mqConnection.getServer() != null) { - // MessageQueueConfig mqConfig = new - // MessageQueueConfig(mqConnection.getServer(), - // mqConnection.getTopic()); - // messageDispatcher = MessageDispatcherFactory.newInstance(mqConfig, peer); - // Executors.newSingleThreadExecutor().execute(messageDispatcher); // 启动监听 - // } - // } - // } - // } catch (Exception e) { - // LOGGER.error("Error occurred on starting all consensus realms! --" + - // e.getMessage(), e); - // throw new IllegalStateException(e.getMessage(), e); - // } } @Override diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProperties.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProperties.java index 66868f66..98dc5523 100644 --- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProperties.java +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProperties.java @@ -45,6 +45,9 @@ public class LedgerInitProperties { // 共识服务提供者;必须; public static final String CONSENSUS_SERVICE_PROVIDER = "consensus.service-provider"; + + // 密码服务提供者列表,以英文逗点“,”分隔;必须; + public static final String CRYPTO_SERVICE_PROVIDER = "crypto.service-providers"; private byte[] ledgerSeed; From e3b9d97f5e071e8a3d6f1c1c4a383eb8acdfe1fe Mon Sep 17 00:00:00 2001 From: huanghaiquan Date: Mon, 20 May 2019 23:16:39 +0800 Subject: [PATCH 41/43] Completed configuring crypto service provider in ledger.init file; --- .../java/com/jd/blockchain/crypto/Crypto.java | 2 +- .../resources/config/init/ledger-init.conf | 67 ------------- .../main/resources/config/init/ledger.init | 97 +++++++++++++++++++ .../src/main/resources/config/init/local.conf | 8 -- .../blockchain/ledger/LedgerManagerTest.java | 5 +- ...est.java => LedgerInitPropertiesTest.java} | 26 ++--- .../src/test/resources/ledger.init | 5 + .../src/test/resources/ledger_init_test.init | 4 + .../test/resources/ledger_init_test_web2.init | 5 + .../initializer/LedgerInitProperties.java | 26 ++++- .../src/main/resources/local.conf | 7 -- 11 files changed, 152 insertions(+), 100 deletions(-) delete mode 100644 source/deployment/deployment-peer/src/main/resources/config/init/ledger-init.conf create mode 100644 source/deployment/deployment-peer/src/main/resources/config/init/ledger.init rename source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/{LedgerInitSettingTest.java => LedgerInitPropertiesTest.java} (72%) diff --git a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/Crypto.java b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/Crypto.java index 654e86b4..2bca057a 100644 --- a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/Crypto.java +++ b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/Crypto.java @@ -139,7 +139,7 @@ public final class Crypto { public static CryptoProvider getProvider(String providerFullName) { Provider pd = pm.getProvider(CryptoService.class, providerFullName); if (pd == null) { - return null; + throw new CryptoException("Crypto service provider named [" + providerFullName + "] does not exist!"); } return getProviderInfo(pd); } diff --git a/source/deployment/deployment-peer/src/main/resources/config/init/ledger-init.conf b/source/deployment/deployment-peer/src/main/resources/config/init/ledger-init.conf deleted file mode 100644 index e6af54f4..00000000 --- a/source/deployment/deployment-peer/src/main/resources/config/init/ledger-init.conf +++ /dev/null @@ -1,67 +0,0 @@ -#账本的种子;一段16进制字符,最长可以包含64个字符;可以用字符“-”分隔,以便更容易读取; -#不同的账本,种子不能相同 -ledger.seed=932dfe23-fe23232f-283f32fa-dd32aa76-8322ca2f-56236cda-7136b322-cb323ffe - -#账本的描述名称;此属性不参与共识,仅仅在当前参与方的本地节点用于描述用途; -#ledger.name= - -#参与方的个数,后续以cons_parti.id分别标识每一个参与方的配置; -cons_parti.count=4 - - -#第0个参与方的名称(不同参与方名称不能相同) -cons_parti.0.name= -#第0个参与方的公钥文件路径 -cons_parti.0.pubkey-path= -#第0个参与方的公钥内容(由keygen工具生成),此参数优先于 pubkey-path 参数 -cons_parti.0.pubkey= -#第0个参与方的账本初始服务的主机 -cons_parti.0.initializer.host=127.0.0.1 -#第0个参与方的账本初始服务的端口 -cons_parti.0.initializer.port=17000 -#第0个参与方的账本初始服务是否开启安全连接 -cons_parti.0.initializer.secure=false - - -#第1个参与方的名称 -cons_parti.1.name= -#第1个参与方的公钥文件路径 -cons_parti.1.pubkey-path= -#第1个参与方的公钥内容(由keygen工具生成),此参数优先于 pubkey-path 参数 -cons_parti.1.pubkey= -#第1个参与方的账本初始服务的主机 -cons_parti.1.initializer.host=127.0.0.1 -#第1个参与方的账本初始服务的端口 -cons_parti.1.initializer.port=17010 -#第1个参与方的账本初始服务是否开启安全连接 -cons_parti.1.initializer.secure=false - - -#第2个参与方的名称 -cons_parti.2.name= -#第2个参与方的公钥文件路径 -cons_parti.2.pubkey-path= -#第2个参与方的公钥内容(由keygen工具生成),此参数优先于 pubkey-path 参数 -cons_parti.2.pubkey= -#第2个参与方的账本初始服务的主机 -cons_parti.2.initializer.host=127.0.0.1 -#第2个参与方的账本初始服务的端口 -cons_parti.2.initializer.port=17020 -#第2个参与方的账本初始服务是否开启安全连接 -cons_parti.2.initializer.secure=false - - -#第3个参与方的名称 -cons_parti.3.name= -#第3个参与方的公钥文件路径 -cons_parti.3.pubkey-path= -#第3个参与方的公钥内容(由keygen工具生成),此参数优先于 pubkey-path 参数 -cons_parti.3.pubkey= -#第3个参与方的账本初始服务的主机 -cons_parti.3.initializer.host=127.0.0.1 -#第3个参与方的账本初始服务的端口 -cons_parti.3.initializer.port=17030 -#第3个参与方的账本初始服务是否开启安全连接 -cons_parti.3.initializer.secure=false - - diff --git a/source/deployment/deployment-peer/src/main/resources/config/init/ledger.init b/source/deployment/deployment-peer/src/main/resources/config/init/ledger.init new file mode 100644 index 00000000..9df38d79 --- /dev/null +++ b/source/deployment/deployment-peer/src/main/resources/config/init/ledger.init @@ -0,0 +1,97 @@ + +#账本的种子;一段16进制字符,最长可以包含64个字符;可以用字符“-”分隔,以便更容易读取; +ledger.seed=932dfe23-fe23232f-283f32fa-dd32aa76-8322ca2f-56236cda-7136b322-cb323ffe + +#账本的描述名称;此属性不参与共识,仅仅在当前参与方的本地节点用于描述用途; +ledger.name= + + +#共识服务提供者;必须; +consensus.service-provider=com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider + +#共识服务的参数配置;必须; +consensus.conf=classpath:bftsmart.config + +#密码服务提供者列表,以英文逗点“,”分隔;必须; +crypto.service-providers=com.jd.blockchain.crypto.service.classic.ClassicCryptoService, \ +com.jd.blockchain.crypto.service.sm.SMCryptoService + + +#参与方的个数,后续以 cons_parti.id 分别标识每一个参与方的配置; +cons_parti.count=4 + +#第0个参与方的名称; +cons_parti.0.name=jd.com +#第0个参与方的公钥文件路径; +cons_parti.0.pubkey-path=keys/jd-com.pub +#第0个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数; +cons_parti.0.pubkey=3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9 +#第0个参与方的共识服务的主机地址; +cons_parti.0.consensus.host=127.0.0.1 +#第0个参与方的共识服务的端口; +cons_parti.0.consensus.port=8900 +#第0个参与方的共识服务是否开启安全连接; +cons_parti.0.consensus.secure=true +#第0个参与方的账本初始服务的主机; +cons_parti.0.initializer.host=127.0.0.1 +#第0个参与方的账本初始服务的端口; +cons_parti.0.initializer.port=8800 +#第0个参与方的账本初始服务是否开启安全连接; +cons_parti.0.initializer.secure=true + +#第1个参与方的名称; +cons_parti.1.name=at.com +#第1个参与方的公钥文件路径; +cons_parti.1.pubkey-path=keys/at-com.pub +#第1个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数; +cons_parti.1.pubkey=3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX +#第1个参与方的共识服务的主机地址; +cons_parti.1.consensus.host=127.0.0.1 +#第1个参与方的共识服务的端口; +cons_parti.1.consensus.port=8910 +#第1个参与方的共识服务是否开启安全连接; +cons_parti.1.consensus.secure=false +#第1个参与方的账本初始服务的主机; +cons_parti.1.initializer.host=127.0.0.1 +#第1个参与方的账本初始服务的端口; +cons_parti.1.initializer.port=8810 +#第1个参与方的账本初始服务是否开启安全连接; +cons_parti.1.initializer.secure=false + +#第2个参与方的名称; +cons_parti.2.name=bt.com +#第2个参与方的公钥文件路径; +cons_parti.2.pubkey-path=classpath:keys/parti2.pub +#第2个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数; +cons_parti.2.pubkey= +#第2个参与方的共识服务的主机地址; +cons_parti.2.consensus.host=127.0.0.1 +#第2个参与方的共识服务的端口; +cons_parti.2.consensus.port=8920 +#第2个参与方的共识服务是否开启安全连接; +cons_parti.2.consensus.secure=false +#第2个参与方的账本初始服务的主机; +cons_parti.2.initializer.host=127.0.0.1 +#第2个参与方的账本初始服务的端口; +cons_parti.2.initializer.port=8820 +#第2个参与方的账本初始服务是否开启安全连接; +cons_parti.2.initializer.secure=true + +#第3个参与方的名称; +cons_parti.3.name=xt.com +#第3个参与方的公钥文件路径; +cons_parti.3.pubkey-path=keys/xt-com.pub +#第3个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数; +cons_parti.3.pubkey=3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk +#第3个参与方的共识服务的主机地址; +cons_parti.3.consensus.host=127.0.0.1 +#第3个参与方的共识服务的端口; +cons_parti.3.consensus.port=8930 +#第3个参与方的共识服务是否开启安全连接; +cons_parti.3.consensus.secure=false +#第3个参与方的账本初始服务的主机; +cons_parti.3.initializer.host=127.0.0.1 +#第3个参与方的账本初始服务的端口; +cons_parti.3.initializer.port=8830 +#第3个参与方的账本初始服务是否开启安全连接; +cons_parti.3.initializer.secure=false diff --git a/source/deployment/deployment-peer/src/main/resources/config/init/local.conf b/source/deployment/deployment-peer/src/main/resources/config/init/local.conf index b182823e..27652184 100644 --- a/source/deployment/deployment-peer/src/main/resources/config/init/local.conf +++ b/source/deployment/deployment-peer/src/main/resources/config/init/local.conf @@ -22,11 +22,3 @@ ledger.db.uri= #账本数据库的连接口令 ledger.db.pwd= -#共识配置文件路径 -#推荐使用绝对路径,相对路径以当前文件(local.conf)所在目录为基准 -consensus.conf=bftsmart.config - -#共识Providers配置 -#BftSmart共识Provider:com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider -#简单消息共识Provider:com.jd.blockchain.consensus.mq.MsgQueueConsensusProvider -consensus.service-provider=com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerManagerTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerManagerTest.java index 9819c9b3..cdbece82 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerManagerTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerManagerTest.java @@ -59,7 +59,6 @@ public class LedgerManagerTest { DataContractRegistry.register(BlockBody.class); DataContractRegistry.register(CryptoProvider.class); } - public static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(), SMCryptoService.class.getName() }; @@ -185,9 +184,9 @@ public class LedgerManagerTest { } CryptoConfig defCryptoSetting = new CryptoConfig(); - + defCryptoSetting.setSupportedProviders(supportedProviders); - + defCryptoSetting.setAutoVerifyHash(true); defCryptoSetting.setHashAlgorithm(ClassicAlgorithm.SHA256); diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitSettingTest.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitPropertiesTest.java similarity index 72% rename from source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitSettingTest.java rename to source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitPropertiesTest.java index 02e4ca0a..3f926073 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitSettingTest.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitPropertiesTest.java @@ -16,38 +16,42 @@ import com.jd.blockchain.tools.keygen.KeyGenCommand; import com.jd.blockchain.utils.codec.HexUtils; import test.com.jd.blockchain.intgr.IntegrationBase; -public class LedgerInitSettingTest { +public class LedgerInitPropertiesTest { @Test public void test() throws IOException { ClassPathResource ledgerInitSettingResource = new ClassPathResource("ledger.init"); InputStream in = ledgerInitSettingResource.getInputStream(); try { - LedgerInitProperties setting = LedgerInitProperties.resolve(in); - assertEquals(4, setting.getConsensusParticipantCount()); + LedgerInitProperties initProps = LedgerInitProperties.resolve(in); + assertEquals(4, initProps.getConsensusParticipantCount()); String expectedLedgerSeed = "932dfe23-fe23232f-283f32fa-dd32aa76-8322ca2f-56236cda-7136b322-cb323ffe" .replace("-", ""); - String actualLedgerSeed = HexUtils.encode(setting.getLedgerSeed()); + String actualLedgerSeed = HexUtils.encode(initProps.getLedgerSeed()); assertEquals(expectedLedgerSeed, actualLedgerSeed); - ConsensusParticipantConfig part0 = setting.getConsensusParticipant(0); + assertEquals("com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider", + initProps.getConsensusProvider()); + + String[] cryptoProviders = initProps.getCryptoProviders(); + assertEquals(2, cryptoProviders.length); + assertEquals("com.jd.blockchain.crypto.service.classic.ClassicCryptoService", cryptoProviders[0]); + assertEquals("com.jd.blockchain.crypto.service.sm.SMCryptoService", cryptoProviders[1]); + + ConsensusParticipantConfig part0 = initProps.getConsensusParticipant(0); assertEquals("jd.com", part0.getName()); -// assertEquals("keys/jd-com.pub", part0.getPubKeyPath()); PubKey pubKey0 = KeyGenCommand.decodePubKey("3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9"); assertEquals(pubKey0, part0.getPubKey()); -// assertEquals("127.0.0.1", part0.getConsensusAddress().getHost()); -// assertEquals(8900, part0.getConsensusAddress().getPort()); -// assertEquals(true, part0.getConsensusAddress().isSecure()); assertEquals("127.0.0.1", part0.getInitializerAddress().getHost()); assertEquals(8800, part0.getInitializerAddress().getPort()); assertEquals(true, part0.getInitializerAddress().isSecure()); - ConsensusParticipantConfig part1 = setting.getConsensusParticipant(1); + ConsensusParticipantConfig part1 = initProps.getConsensusParticipant(1); assertEquals(false, part1.getInitializerAddress().isSecure()); PubKey pubKey1 = KeyGenCommand.decodePubKey("3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX"); assertEquals(pubKey1, part1.getPubKey()); - ConsensusParticipantConfig part2 = setting.getConsensusParticipant(2); + ConsensusParticipantConfig part2 = initProps.getConsensusParticipant(2); assertEquals("7VeRAr3dSbi1xatq11ZcF7sEPkaMmtZhV9shonGJWk9T4pLe", part2.getPubKey().toBase58()); } finally { diff --git a/source/test/test-integration/src/test/resources/ledger.init b/source/test/test-integration/src/test/resources/ledger.init index 74dd2585..9df38d79 100644 --- a/source/test/test-integration/src/test/resources/ledger.init +++ b/source/test/test-integration/src/test/resources/ledger.init @@ -12,6 +12,11 @@ consensus.service-provider=com.jd.blockchain.consensus.bftsmart.BftsmartConsensu #共识服务的参数配置;必须; consensus.conf=classpath:bftsmart.config +#密码服务提供者列表,以英文逗点“,”分隔;必须; +crypto.service-providers=com.jd.blockchain.crypto.service.classic.ClassicCryptoService, \ +com.jd.blockchain.crypto.service.sm.SMCryptoService + + #参与方的个数,后续以 cons_parti.id 分别标识每一个参与方的配置; cons_parti.count=4 diff --git a/source/test/test-integration/src/test/resources/ledger_init_test.init b/source/test/test-integration/src/test/resources/ledger_init_test.init index 2f4427ba..518d88c1 100644 --- a/source/test/test-integration/src/test/resources/ledger_init_test.init +++ b/source/test/test-integration/src/test/resources/ledger_init_test.init @@ -11,6 +11,10 @@ consensus.service-provider=com.jd.blockchain.consensus.bftsmart.BftsmartConsensu #共识服务的参数配置;必须; consensus.conf=classpath:bftsmart.config +#密码服务提供者列表,以英文逗点“,”分隔;必须; +crypto.service-providers=com.jd.blockchain.crypto.service.classic.ClassicCryptoService, \ +com.jd.blockchain.crypto.service.sm.SMCryptoService + #参与方的个数,后续以 cons_parti.id 分别标识每一个参与方的配置; cons_parti.count=4 diff --git a/source/test/test-integration/src/test/resources/ledger_init_test_web2.init b/source/test/test-integration/src/test/resources/ledger_init_test_web2.init index f661bd0e..73626947 100644 --- a/source/test/test-integration/src/test/resources/ledger_init_test_web2.init +++ b/source/test/test-integration/src/test/resources/ledger_init_test_web2.init @@ -11,6 +11,11 @@ consensus.service-provider=com.jd.blockchain.consensus.bftsmart.BftsmartConsensu #共识服务的参数配置;必须; consensus.conf=classpath:bftsmart.config +#密码服务提供者列表,以英文逗点“,”分隔;必须; +crypto.service-providers=com.jd.blockchain.crypto.service.classic.ClassicCryptoService, \ +com.jd.blockchain.crypto.service.sm.SMCryptoService + + #参与方的个数,后续以 cons_parti.id 分别标识每一个参与方的配置; cons_parti.count=4 diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProperties.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProperties.java index 98dc5523..2ee028b2 100644 --- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProperties.java +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProperties.java @@ -45,9 +45,11 @@ public class LedgerInitProperties { // 共识服务提供者;必须; public static final String CONSENSUS_SERVICE_PROVIDER = "consensus.service-provider"; - + // 密码服务提供者列表,以英文逗点“,”分隔;必须; - public static final String CRYPTO_SERVICE_PROVIDER = "crypto.service-providers"; + public static final String CRYPTO_SERVICE_PROVIDERS = "crypto.service-providers"; + + public static final String CRYPTO_SERVICE_PROVIDERS_SPLITTER = ","; private byte[] ledgerSeed; @@ -57,8 +59,10 @@ public class LedgerInitProperties { private Properties consensusConfig; + private String[] cryptoProviders; + public byte[] getLedgerSeed() { - return ledgerSeed; + return ledgerSeed.clone(); } public Properties getConsensusConfig() { @@ -76,6 +80,14 @@ public class LedgerInitProperties { public List getConsensusParticipants() { return consensusParticipants; } + + public String[] getCryptoProviders() { + return cryptoProviders.clone(); + } + + public void setCryptoProviders(String[] cryptoProviders) { + this.cryptoProviders = cryptoProviders; + } /** * 返回参与者; @@ -131,6 +143,14 @@ public class LedgerInitProperties { String.format("Consensus config file[%s] doesn't exist! ", consensusConfigFilePath), e); } + // 解析密码提供者列表; + String cryptoProviderNames = PropertiesUtils.getProperty(props, CRYPTO_SERVICE_PROVIDERS, true); + String[] cryptoProviders = cryptoProviderNames.split(CRYPTO_SERVICE_PROVIDERS_SPLITTER); + for (int i = 0; i < cryptoProviders.length; i++) { + cryptoProviders[i] = cryptoProviders[i].trim(); + } + initProps.cryptoProviders = cryptoProviders; + // 解析参与方节点列表; int partCount = getInt(PropertiesUtils.getRequiredProperty(props, PART_COUNT)); if (partCount < 0) { diff --git a/source/tools/tools-initializer/src/main/resources/local.conf b/source/tools/tools-initializer/src/main/resources/local.conf index 9df0303c..dc7c7347 100644 --- a/source/tools/tools-initializer/src/main/resources/local.conf +++ b/source/tools/tools-initializer/src/main/resources/local.conf @@ -16,10 +16,3 @@ ledger.db.uri=redis://127.0.0.1/0 #账本数据库的连接口令; ledger.db.pwd= - -#共识协议的参数配置;必须参数; -consensus.conf=mq.config - -#共识协议的实现类型;必须参数; -consensus.service-provider=com.jd.blockchain.consensus.mq.MsgQueueConsensusProvider - From 611e12714abc911739f37fe57c6d7d8801bd5482 Mon Sep 17 00:00:00 2001 From: huanghaiquan Date: Mon, 20 May 2019 23:27:13 +0800 Subject: [PATCH 42/43] Fixed compilation error; --- source/peer/pom.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/source/peer/pom.xml b/source/peer/pom.xml index 51746e7d..01311d5c 100644 --- a/source/peer/pom.xml +++ b/source/peer/pom.xml @@ -20,11 +20,6 @@ consensus-framework ${project.version} - - com.jd.blockchain - state-transfer - ${project.version} - com.jd.blockchain ledger-rpc From fa99325a93a38be04cd80a1db7c0077d6dbfc374 Mon Sep 17 00:00:00 2001 From: huanghaiquan Date: Tue, 21 May 2019 02:08:54 +0800 Subject: [PATCH 43/43] Refactored the timestamp generation mechanism of ContractEventSendOperation; --- .../ledger/ContractEventSendOperation.java | 42 +++++++++++++------ .../ContractEventSendOpTemplate.java | 13 +++--- ...ContractEventSendOperationBuilderImpl.java | 7 ++-- 3 files changed, 42 insertions(+), 20 deletions(-) diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractEventSendOperation.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractEventSendOperation.java index 59cb3111..b5ee3b5a 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractEventSendOperation.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractEventSendOperation.java @@ -10,21 +10,39 @@ import com.jd.blockchain.utils.Bytes; * @author huanghaiquan * */ -@DataContract(code= DataCodes.TX_OP_CONTRACT_EVENT_SEND) +@DataContract(code = DataCodes.TX_OP_CONTRACT_EVENT_SEND) public interface ContractEventSendOperation extends Operation { - - @DataField(order=2, primitiveType=PrimitiveType.BYTES) + + /** + * 响应事件的合约地址; + * + * @return + */ + @DataField(order = 2, primitiveType = PrimitiveType.BYTES) Bytes getContractAddress(); - - @DataField(order=3, primitiveType=PrimitiveType.TEXT) + + /** + * 事件名; + * + * @return + */ + @DataField(order = 3, primitiveType = PrimitiveType.TEXT) String getEvent(); - - - @DataField(order=4, primitiveType=PrimitiveType.BYTES) + + /** + * 事件参数; + * + * @return + */ + @DataField(order = 4, primitiveType = PrimitiveType.BYTES) byte[] getArgs(); - //获得交易操作时间; - @DataField(order=5, primitiveType=PrimitiveType.INT64) - Long getTxOpTime(); - + /** + * 时间戳; + * + * @return + */ + @DataField(order = 5, primitiveType = PrimitiveType.INT64) + long getTs(); + } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractEventSendOpTemplate.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractEventSendOpTemplate.java index c5ad6db2..aa3a7b6a 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractEventSendOpTemplate.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractEventSendOpTemplate.java @@ -12,8 +12,8 @@ public class ContractEventSendOpTemplate implements ContractEventSendOperation { private Bytes contractAddress; private byte[] args; private String event; - //交易操作时间; - private Long txOpTime; + + private long ts; public ContractEventSendOpTemplate() { } @@ -22,7 +22,6 @@ public class ContractEventSendOpTemplate implements ContractEventSendOperation { this.contractAddress = contractAddress; this.event = event; this.args = args; - this.txOpTime = System.currentTimeMillis(); } @Override @@ -41,7 +40,11 @@ public class ContractEventSendOpTemplate implements ContractEventSendOperation { } @Override - public Long getTxOpTime() { - return txOpTime; + public long getTs() { + return ts; + } + + public void setTs(long ts) { + this.ts = ts; } } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractEventSendOperationBuilderImpl.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractEventSendOperationBuilderImpl.java index 7c54e4e8..b60153fc 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractEventSendOperationBuilderImpl.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractEventSendOperationBuilderImpl.java @@ -4,18 +4,19 @@ import com.jd.blockchain.ledger.ContractEventSendOperation; import com.jd.blockchain.utils.Bytes; @Deprecated -class ContractEventSendOperationBuilderImpl implements ContractEventSendOperationBuilder{ - +class ContractEventSendOperationBuilderImpl implements ContractEventSendOperationBuilder { @Override public ContractEventSendOperation send(String address, String event, byte[] args) { ContractEventSendOpTemplate op = new ContractEventSendOpTemplate(Bytes.fromBase58(address), event, args); + op.setTs(System.currentTimeMillis()); return op; } - + @Override public ContractEventSendOperation send(Bytes address, String event, byte[] args) { ContractEventSendOpTemplate op = new ContractEventSendOpTemplate(address, event, args); + op.setTs(System.currentTimeMillis()); return op; }