diff --git a/source/manager/ump-booter/pom.xml b/source/manager/ump-booter/pom.xml
new file mode 100644
index 00000000..63461b0f
--- /dev/null
+++ b/source/manager/ump-booter/pom.xml
@@ -0,0 +1,60 @@
+
+
+
+
+ manager
+ com.jd.blockchain
+ 1.1.0-SNAPSHOT
+
+ 4.0.0
+
+ ump-booter
+
+ ump-booter
+
+
+ UTF-8
+ 1.8
+ 1.8
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-logging
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-log4j2
+
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ true
+
+
+ junit
+ junit
+ test
+
+
+
diff --git a/source/manager/ump-booter/src/main/java/com/jd/blockchain/ump/UmpBooter.java b/source/manager/ump-booter/src/main/java/com/jd/blockchain/ump/UmpBooter.java
new file mode 100644
index 00000000..97656b03
--- /dev/null
+++ b/source/manager/ump-booter/src/main/java/com/jd/blockchain/ump/UmpBooter.java
@@ -0,0 +1,138 @@
+package com.jd.blockchain.ump;
+
+import org.springframework.boot.SpringApplication;
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+
+public class UmpBooter {
+
+ private static final String ARG_PORT = "-p";
+
+ private static final String ARG_HOST = "-h";
+
+ private static final String CONFIG = "BOOT-INF" + File.separator + "classes" + File.separator + "config.properties";
+
+ private static final String CONFIG_PROP_HOST = "server.host";
+
+ private static final String CONFIG_PROP_HOST_DEFAULT = "0.0.0.0";
+
+ private static final String CONFIG_PROP_PORT = "server.port";
+
+ private static final String CONFIG_PROP_PORT_DEFAULT = "8080";
+
+ private static final String CONFIG_PROP_DB_URL = "db.url";
+
+ private static final String CONFIG_PROP_DB_URL_DEFAULT = "rocksdb://#project#/jumpdb";
+
+ public static void main(String[] args) {
+ try {
+ startServer(server(args));
+ System.out.println("Server Start SUCCESS !!!");
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.err.printf("Server Start FAIL -> %s, Exit JVM !!!", e.toString());
+ // 正常退出
+ System.exit(0);
+ }
+ }
+
+ private static void startServer(Server server) {
+
+ System.out.printf("server.address = %s, server.port = %s, db.url = %s \r\n",
+ server.host, server.port, server.dbUrl);
+
+ List argList = new ArrayList<>();
+ argList.add(String.format("--server.address=%s", server.host));
+ argList.add(String.format("--server.port=%s", server.port));
+ argList.add(String.format("--db.url=%s", server.dbUrl));
+
+ String[] args = argList.toArray(new String[argList.size()]);
+
+ // 启动服务器;
+ SpringApplication.run(UmpConfiguration.class, args);
+ }
+
+ private static Server server(String[] args) {
+ Server defaultServer = serverFromConfig();
+ if (args == null || args.length == 0) {
+ return defaultServer;
+ }
+ String host = null;
+
+ int port = 0;
+
+ // 读取参数列表
+ for (int i = 0; i < args.length; i++) {
+ String arg = args[i];
+ if (arg.equals(ARG_HOST)) {
+ host = args[i + 1];
+ } else if (arg.equals(ARG_PORT)) {
+ port = Integer.parseInt(args[i + 1]);
+ }
+ }
+
+ // 参数列表中的数据不完整,则剩余部分数据从配置文件中获取
+ if (host == null) {
+ host = defaultServer.host;
+ }
+ if (port == 0) {
+ port = defaultServer.port;
+ }
+
+ return new Server(host, port, defaultServer.dbUrl);
+ }
+
+ private static Server serverFromConfig() {
+ try {
+ InputStream inputStream = UmpBooter.class.getResourceAsStream(File.separator + CONFIG);
+ if (inputStream == null) {
+ System.err.println("InputStream is NULL !!!");
+ }
+ Properties props = new Properties();
+ props.load(inputStream);
+ String host = props.getProperty(CONFIG_PROP_HOST, CONFIG_PROP_HOST_DEFAULT);
+ int port = Integer.parseInt(
+ props.getProperty(CONFIG_PROP_PORT, CONFIG_PROP_PORT_DEFAULT));
+ String dbUrl = props.getProperty(CONFIG_PROP_DB_URL, CONFIG_PROP_DB_URL_DEFAULT);
+ return new Server(host, port, dbUrl);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ private static class Server {
+
+ private String host;
+
+ private int port;
+
+ private String dbUrl;
+
+ public Server(String host, int port, String dbUrl) {
+ this.host = host;
+ this.port = port;
+ this.dbUrl = dbUrl;
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+ }
+}
diff --git a/source/manager/ump-booter/src/main/java/com/jd/blockchain/ump/UmpConfiguration.java b/source/manager/ump-booter/src/main/java/com/jd/blockchain/ump/UmpConfiguration.java
new file mode 100644
index 00000000..f1e86f12
--- /dev/null
+++ b/source/manager/ump-booter/src/main/java/com/jd/blockchain/ump/UmpConfiguration.java
@@ -0,0 +1,12 @@
+package com.jd.blockchain.ump;
+
+
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+
+@EnableConfigurationProperties
+@SpringBootApplication(exclude = {
+ org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class}
+ )
+public class UmpConfiguration {
+}
diff --git a/source/manager/ump-booter/src/main/resources/application.properties b/source/manager/ump-booter/src/main/resources/application.properties
new file mode 100644
index 00000000..b5ef6943
--- /dev/null
+++ b/source/manager/ump-booter/src/main/resources/application.properties
@@ -0,0 +1,5 @@
+server.tomcat.uri-encoding=utf-8
+
+spring.mvc.favicon.enabled=false
+
+logging.config=classpath:log4j2-jump.xml
\ No newline at end of file
diff --git a/source/manager/ump-booter/src/main/resources/assembly.xml b/source/manager/ump-booter/src/main/resources/assembly.xml
new file mode 100644
index 00000000..8fd114ba
--- /dev/null
+++ b/source/manager/ump-booter/src/main/resources/assembly.xml
@@ -0,0 +1,27 @@
+
+
+ ${project.version}
+
+ zip
+
+ false
+
+
+ src/main/resources/scripts
+ bin
+
+
+
+
+ false
+ true
+ ext
+
+ com.jd.blockchain:ump-booter
+
+
+
+
\ No newline at end of file
diff --git a/source/manager/ump-booter/src/main/resources/banner.txt b/source/manager/ump-booter/src/main/resources/banner.txt
new file mode 100644
index 00000000..c39618bd
--- /dev/null
+++ b/source/manager/ump-booter/src/main/resources/banner.txt
@@ -0,0 +1,13 @@
+
+ ▄▄▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄▄ ▄ ▄▄▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄▄▄ ▄ ▄ ▄▄▄▄▄▄▄▄▄▄▄ ▄ ▄ ▄▄▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄▄▄ ▄▄ ▄
+▐░░░░░░░░░░░▌▐░░░░░░░░░░▌ ▐░░░░░░░░░░▌ ▐░▌ ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░▌ ▐░▌ ▐░░░░░░░░░░░▌▐░▌ ▐░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░▌ ▐░▌
+ ▀▀▀▀▀█░█▀▀▀ ▐░█▀▀▀▀▀▀▀█░▌ ▐░█▀▀▀▀▀▀▀█░▌▐░▌ ▐░█▀▀▀▀▀▀▀█░▌▐░█▀▀▀▀▀▀▀▀▀ ▐░▌ ▐░▌ ▐░█▀▀▀▀▀▀▀▀▀ ▐░▌ ▐░▌▐░█▀▀▀▀▀▀▀█░▌ ▀▀▀▀█░█▀▀▀▀ ▐░▌░▌ ▐░▌
+ ▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌▐░▌ ▐░▌ ▐░▌▐░▌ ▐░▌▐░▌ ▐░▌ ▐░▌ ▐░▌▐░▌ ▐░▌ ▐░▌ ▐░▌▐░▌ ▐░▌
+ ▐░▌ ▐░▌ ▐░▌ ▐░█▄▄▄▄▄▄▄█░▌▐░▌ ▐░▌ ▐░▌▐░▌ ▐░▌░▌ ▐░▌ ▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄█░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌
+ ▐░▌ ▐░▌ ▐░▌ ▐░░░░░░░░░░▌ ▐░▌ ▐░▌ ▐░▌▐░▌ ▐░░▌ ▐░▌ ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌
+ ▐░▌ ▐░▌ ▐░▌ ▐░█▀▀▀▀▀▀▀█░▌▐░▌ ▐░▌ ▐░▌▐░▌ ▐░▌░▌ ▐░▌ ▐░█▀▀▀▀▀▀▀█░▌▐░█▀▀▀▀▀▀▀█░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌
+ ▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌▐░▌ ▐░▌ ▐░▌▐░▌ ▐░▌▐░▌ ▐░▌ ▐░▌ ▐░▌▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌▐░▌
+ ▄▄▄▄▄█░▌ ▐░█▄▄▄▄▄▄▄█░▌ ▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄▄▄ ▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄▄▄ ▐░▌ ▐░▌ ▐░█▄▄▄▄▄▄▄▄▄ ▐░▌ ▐░▌▐░▌ ▐░▌ ▄▄▄▄█░█▄▄▄▄ ▐░▌ ▐░▐░▌
+▐░░░░░░░▌ ▐░░░░░░░░░░▌ ▐░░░░░░░░░░▌ ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░▌ ▐░▌ ▐░░░░░░░░░░░▌▐░▌ ▐░▌▐░▌ ▐░▌▐░░░░░░░░░░░▌▐░▌ ▐░░▌
+ ▀▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀▀ ▀ ▀ ▀▀▀▀▀▀▀▀▀▀▀ ▀ ▀ ▀ ▀ ▀▀▀▀▀▀▀▀▀▀▀ ▀ ▀▀
+
diff --git a/source/manager/ump-booter/src/main/resources/config.properties b/source/manager/ump-booter/src/main/resources/config.properties
new file mode 100644
index 00000000..deaf015e
--- /dev/null
+++ b/source/manager/ump-booter/src/main/resources/config.properties
@@ -0,0 +1,8 @@
+# Tomcat启动的HOST,默认为0.0.0.0
+server.host=0.0.0.0
+
+# Tomcat启动监听端口号
+server.port=8080
+
+# 本地数据库存储位置
+db.url=rocksdb://#project#/jumpdb
\ No newline at end of file
diff --git a/source/manager/ump-booter/src/main/resources/log4j2-jump.xml b/source/manager/ump-booter/src/main/resources/log4j2-jump.xml
new file mode 100644
index 00000000..6b19f527
--- /dev/null
+++ b/source/manager/ump-booter/src/main/resources/log4j2-jump.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/source/manager/ump-booter/src/main/resources/scripts/jump-start.sh b/source/manager/ump-booter/src/main/resources/scripts/jump-start.sh
new file mode 100644
index 00000000..a31a5b28
--- /dev/null
+++ b/source/manager/ump-booter/src/main/resources/scripts/jump-start.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+HOME=$(cd `dirname $0`;cd ../; pwd)
+UMP=$(ls $HOME/ext | grep ump-booter-)
+if [ ! -n "UMP" ]; then
+ echo "Unified Management Platform Is Null !!!"
+else
+ nohup java -jar -server -Djump.log=$HOME $HOME/ext/$UMP $* >$HOME/bin/jump.out 2>&1 &
+fi
\ No newline at end of file
diff --git a/source/manager/ump-booter/src/main/resources/scripts/jump-stop.sh b/source/manager/ump-booter/src/main/resources/scripts/jump-stop.sh
new file mode 100644
index 00000000..b7155c88
--- /dev/null
+++ b/source/manager/ump-booter/src/main/resources/scripts/jump-stop.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+#启动Home路径
+BOOT_HOME=$(cd `dirname $0`;cd ../; pwd)
+
+#获取进程PID
+PID=`ps -ef | grep $BOOT_HOME/ext/ump-booter | grep -v grep | awk '{print $2}'`
+
+#通过Kill命令将进程杀死
+if [ -z "$PID" ]; then
+ echo "Unable to find UMP PID. stop aborted."
+else
+ echo "Start to kill PID = $PID ..."
+ kill -9 $PID
+ echo "Unified Management Platform has been stopped ..."
+fi
\ No newline at end of file
diff --git a/source/manager/ump-model/pom.xml b/source/manager/ump-model/pom.xml
new file mode 100644
index 00000000..67436cc0
--- /dev/null
+++ b/source/manager/ump-model/pom.xml
@@ -0,0 +1,81 @@
+
+
+
+
+ manager
+ com.jd.blockchain
+ 1.1.0-SNAPSHOT
+
+ 4.0.0
+
+ ump-model
+
+ ump-model
+
+
+ UTF-8
+ 1.8
+ 1.8
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-logging
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-log4j2
+
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ true
+
+
+
+ com.alibaba
+ fastjson
+
+
+
+ org.reflections
+ reflections
+
+
+
+ org.rocksdb
+ rocksdbjni
+
+
+
+ commons-io
+ commons-io
+
+
+
+ junit
+ junit
+ test
+
+
+
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/dao/DBConnection.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/dao/DBConnection.java
new file mode 100644
index 00000000..eea65d3f
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/dao/DBConnection.java
@@ -0,0 +1,16 @@
+package com.jd.blockchain.ump.dao;
+
+public interface DBConnection {
+
+ String dbSchema();
+
+ DBConnection initDbUrl(String dbUrl);
+
+ void put(String key, String value);
+
+ void put(String key, Object value, Class> type);
+
+ String get(String key);
+
+ boolean exist(String dbUrl);
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/dao/DBConnectionProvider.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/dao/DBConnectionProvider.java
new file mode 100644
index 00000000..d029a411
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/dao/DBConnectionProvider.java
@@ -0,0 +1,58 @@
+package com.jd.blockchain.ump.dao;
+
+import org.reflections.Reflections;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class DBConnectionProvider {
+
+ private static final Map dbConnections = new ConcurrentHashMap<>();
+
+ static {
+ init();
+ }
+
+ public static DBConnection dbConnection(String dbUrl) {
+ String dbSchema = dbSchema(dbUrl);
+ if (!dbConnections.containsKey(dbSchema)) {
+ throw new IllegalStateException(
+ String.format("Can not find DBConnection by {%s} !", dbUrl));
+ }
+
+ DBConnection dbConnection = dbConnections.get(dbSchema);
+ return dbConnection.initDbUrl(dbUrl);
+ }
+
+
+ private static String dbSchema(String dbUrl) {
+ // rocksdb:///home/xxx -> rocksdb
+ return dbUrl.split("://")[0];
+
+ }
+
+ private static void init() {
+ // 初始化所有实现类
+ Reflections reflections = new Reflections("com.jd.blockchain.ump.dao");
+
+ Set> dbConnectionSet =
+ reflections.getSubTypesOf(DBConnection.class);
+
+ for (Class extends DBConnection> clazz : dbConnectionSet) {
+
+ if (!clazz.isInterface() && !clazz.equals(UmpDaoHandler.class)) {
+ try {
+ // 根据class生成对象
+ DBConnection dbConnection = clazz.newInstance();
+ String dbSchema = dbConnection.dbSchema();
+ if (dbSchema != null && dbSchema.length() > 0) {
+ dbConnections.put(dbSchema, dbConnection);
+ }
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+ }
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/dao/MemoryDBConnection.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/dao/MemoryDBConnection.java
new file mode 100644
index 00000000..ac9e5755
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/dao/MemoryDBConnection.java
@@ -0,0 +1,47 @@
+package com.jd.blockchain.ump.dao;
+
+import com.alibaba.fastjson.JSON;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class MemoryDBConnection implements DBConnection {
+
+ private static final String MEMORY_SCHEMA = "memory";
+
+ private final Map memory = new ConcurrentHashMap<>();
+
+ @Override
+ public String dbSchema() {
+ return MEMORY_SCHEMA;
+ }
+
+ @Override
+ public DBConnection initDbUrl(String dbUrl) {
+ return this;
+ }
+
+ @Override
+ public void put(String key, String value) {
+ memory.put(key, value);
+ }
+
+ @Override
+ public void put(String key, Object value, Class> type) {
+ String json = JSON.toJSONString(value);
+ put(key, json);
+ }
+
+ @Override
+ public String get(String key) {
+ return memory.get(key);
+ }
+
+ @Override
+ public boolean exist(String dbUrl) {
+ if (dbUrl.startsWith(MEMORY_SCHEMA)) {
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/dao/RocksDBConnection.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/dao/RocksDBConnection.java
new file mode 100644
index 00000000..ed32c519
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/dao/RocksDBConnection.java
@@ -0,0 +1,145 @@
+package com.jd.blockchain.ump.dao;
+
+
+import com.alibaba.fastjson.JSON;
+import org.apache.commons.io.FileUtils;
+import org.rocksdb.*;
+import org.rocksdb.util.SizeUnit;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+public class RocksDBConnection implements DBConnection {
+
+ public static final String SCHEMA = "rocksdb";
+
+ public static final String PROTOCOL_SPLIT = "://";
+
+ public static final String ROCKSDB_PROTOCOL = SCHEMA + PROTOCOL_SPLIT;
+
+ static {
+ RocksDB.loadLibrary();
+ }
+
+ private RocksDB rocksDB;
+
+ @Override
+ public String dbSchema() {
+ return SCHEMA;
+ }
+
+ @Override
+ public DBConnection initDbUrl(String dbUrl) {
+ if (!dbUrl.startsWith(dbSchema())) {
+ throw new IllegalStateException(String.format("Unsupport DBConnection by URL {%s} !!!", dbUrl));
+ }
+ String dbSavePath = dbUrl.split(PROTOCOL_SPLIT)[1];
+ initDBConnection(dbSavePath);
+ return this;
+ }
+
+ @Override
+ public void put(String key, String value) {
+ if (this.rocksDB == null) {
+ throw new IllegalStateException("Rocksdb is NULL, Please initDbUrl first !!!");
+ }
+ try {
+ this.rocksDB.put(key.getBytes(UTF_8), value.getBytes(UTF_8));
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @Override
+ public void put(String key, Object value, Class> type) {
+ // 使用JSON序列化
+ String json = JSON.toJSONString(value);
+ put(key, json);
+ }
+
+ @Override
+ public String get(String key) {
+ try {
+ byte[] value = this.rocksDB.get(key.getBytes(UTF_8));
+ if (value != null && value.length > 0) {
+ return new String(value, UTF_8);
+ }
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ return null;
+ }
+
+ @Override
+ public boolean exist(String dbUrl) {
+ // 首先该dbUrl是Rocksdb
+ if (dbUrl.startsWith(ROCKSDB_PROTOCOL)) {
+ // 判断File是否存在,并且是文件夹
+ File dbPath = new File(dbUrl.substring(ROCKSDB_PROTOCOL.length()));
+ if (dbPath.exists() && dbPath.isDirectory()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void initDBConnection(String dbUrl) {
+ try {
+ File dbPath = new File(dbUrl);
+ File dbParentPath = dbPath.getParentFile();
+ if (!dbParentPath.exists()) {
+ FileUtils.forceMkdir(dbParentPath);
+ }
+ this.rocksDB = RocksDB.open(initOptions(), dbUrl);
+ } catch (Exception e) {
+ throw new IllegalStateException(e.getMessage(), e);
+ }
+ }
+
+ private Options initOptions() {
+ final Filter bloomFilter = new BloomFilter(32);
+ final BlockBasedTableConfig tableOptions = new BlockBasedTableConfig()
+ .setFilter(bloomFilter)
+ .setBlockSize(4 * SizeUnit.KB)
+ .setBlockSizeDeviation(10)
+ .setBlockCacheSize(64 * SizeUnit.GB)
+ .setNoBlockCache(false)
+ .setCacheIndexAndFilterBlocks(true)
+ .setBlockRestartInterval(16)
+ ;
+ final List compressionLevels = new ArrayList<>();
+ compressionLevels.add(CompressionType.NO_COMPRESSION); // 0-1
+ compressionLevels.add(CompressionType.SNAPPY_COMPRESSION); // 1-2
+ compressionLevels.add(CompressionType.SNAPPY_COMPRESSION); // 2-3
+ compressionLevels.add(CompressionType.SNAPPY_COMPRESSION); // 3-4
+ compressionLevels.add(CompressionType.SNAPPY_COMPRESSION); // 4-5
+ compressionLevels.add(CompressionType.SNAPPY_COMPRESSION); // 5-6
+ compressionLevels.add(CompressionType.SNAPPY_COMPRESSION); // 6-7
+
+ Options options = new Options()
+ .setAllowConcurrentMemtableWrite(true)
+ .setEnableWriteThreadAdaptiveYield(true)
+ .setCreateIfMissing(true)
+ .setMaxWriteBufferNumber(3)
+ .setTableFormatConfig(tableOptions)
+ .setMaxBackgroundCompactions(10)
+ .setMaxBackgroundFlushes(4)
+ .setBloomLocality(10)
+ .setMinWriteBufferNumberToMerge(4)
+ .setCompressionPerLevel(compressionLevels)
+ .setNumLevels(7)
+ .setCompressionType(CompressionType.SNAPPY_COMPRESSION)
+ .setCompactionStyle(CompactionStyle.UNIVERSAL)
+ .setMemTableConfig(new SkipListMemTableConfig())
+ ;
+ return options;
+ }
+
+ public static void main(String[] args) {
+ String path = "rocksdb:///zhangsan/lisi";
+ System.out.println(path.substring(ROCKSDB_PROTOCOL.length()));
+ }
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/dao/UmpDao.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/dao/UmpDao.java
new file mode 100644
index 00000000..1da5d48b
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/dao/UmpDao.java
@@ -0,0 +1,4 @@
+package com.jd.blockchain.ump.dao;
+
+public interface UmpDao {
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/dao/UmpDaoHandler.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/dao/UmpDaoHandler.java
new file mode 100644
index 00000000..62cce01d
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/dao/UmpDaoHandler.java
@@ -0,0 +1,115 @@
+package com.jd.blockchain.ump.dao;
+
+import com.jd.blockchain.ump.model.UmpConstant;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.stereotype.Repository;
+
+import java.io.File;
+
+@Repository
+public class UmpDaoHandler implements UmpDao, CommandLineRunner, DBConnection {
+
+ public final String PROJECT_FLAG = "#project#";
+
+ private static final String PROTOCOL_FILE = "file:";
+
+ private static final String INNER_FILE_SEPARATOR = "!";
+
+ private static final String PROTOCOL_SEPARATOR = "://";
+
+ private DBConnection dbConnection;
+
+ @Override
+ public void run(String... args) {
+
+ String dbUrl = RocksDBConnection.SCHEMA + PROTOCOL_SEPARATOR +
+ PROJECT_FLAG + File.separator + UmpConstant.DB_NAME;
+
+ if (args != null && args.length > 0) {
+ for (String arg : args) {
+ if (arg.startsWith("--db.url")) {
+ dbUrl = arg.split("=")[1];
+ }
+ }
+ }
+
+ dbConnection = DBConnectionProvider.dbConnection(realPath(dbUrl));
+
+ initProjectPath();
+ }
+
+ private void initProjectPath() {
+ UmpConstant.PROJECT_PATH = projectPath();
+ System.out.printf("Init Project Path = %s \r\n", UmpConstant.PROJECT_PATH);
+ }
+
+ @Override
+ public String dbSchema() {
+ return null;
+ }
+
+ @Override
+ public DBConnection initDbUrl(String dbUrl) {
+ return dbConnection;
+ }
+
+ @Override
+ public void put(String key, String value) {
+ dbConnection.put(key, value);
+ }
+
+ @Override
+ public void put(String key, Object value, Class> type) {
+ dbConnection.put(key, value, type);
+ }
+
+ @Override
+ public String get(String key) {
+ return dbConnection.get(key);
+ }
+
+ @Override
+ public boolean exist(String dbUrl) {
+ try {
+ return dbConnection.exist(dbUrl);
+ } catch (Exception e) {
+ // 不关心异常
+ System.err.println(e);
+ return false;
+ }
+ }
+
+ private String realPath(String dbUrl) {
+ if (dbUrl.contains(PROJECT_FLAG)) {
+ // 获取当前jar包路径
+ try {
+ String projectPath = projectPath();
+ return dbUrl.replaceAll(PROJECT_FLAG, projectPath);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ return dbUrl;
+ }
+
+ private String projectPath() {
+ File jarDirectory = new File(jarRootPath());
+ return jarDirectory.getParentFile().getParentFile().getPath();
+ }
+
+ private String jarRootPath() {
+ // 获取Jar包所在路径
+ String jarRootPath = UmpDaoHandler.class.getProtectionDomain().getCodeSource().getLocation().getPath();
+
+ // 处理打包到SpringBoot后路径问题:file:
+ if (jarRootPath.startsWith(PROTOCOL_FILE)) {
+ jarRootPath = jarRootPath.substring(PROTOCOL_FILE.length());
+ }
+ // 处理打包到SpringBoot后内部分隔符问题:!
+ if (jarRootPath.contains(INNER_FILE_SEPARATOR)) {
+ jarRootPath = jarRootPath.substring(0, jarRootPath.indexOf(INNER_FILE_SEPARATOR));
+ }
+
+ return jarRootPath;
+ }
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/MasterAddr.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/MasterAddr.java
new file mode 100644
index 00000000..700cef0b
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/MasterAddr.java
@@ -0,0 +1,47 @@
+package com.jd.blockchain.ump.model;
+
+public class MasterAddr {
+
+ private String ipAddr;
+
+ private int port;
+
+ public MasterAddr() {
+ }
+
+ public MasterAddr(String ipAddr, int port) {
+ this.ipAddr = ipAddr;
+ this.port = port;
+ }
+
+ public String getIpAddr() {
+ return ipAddr;
+ }
+
+ public void setIpAddr(String ipAddr) {
+ this.ipAddr = ipAddr;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public static MasterAddr newInstance(String ipAddr, int port) {
+ return new MasterAddr(ipAddr, port);
+ }
+
+ public String toHttpUrl() {
+ return "http://" + ipAddr + ":" + port;
+ }
+
+ public boolean legal() {
+ if (this.ipAddr == null || this.ipAddr.length() == 0 || this.port == 0) {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/PartiNode.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/PartiNode.java
new file mode 100644
index 00000000..9281d408
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/PartiNode.java
@@ -0,0 +1,88 @@
+package com.jd.blockchain.ump.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PartiNode {
+
+ private int id;
+
+ private String name;
+
+ private String pubKey;
+
+ private String initHost;
+
+ private int initPort;
+
+ private boolean isSecure;
+
+ public List toConfigChars() {
+
+ List configCharList = new ArrayList<>();
+
+ configCharList.add(formatConfig(UmpConstant.PARTINODE_NAME_FORMAT, name));
+
+ configCharList.add(formatConfig(UmpConstant.PARTINODE_PUBKEY_FORMAT, pubKey));
+
+ configCharList.add(formatConfig(UmpConstant.PARTINODE_INIT_HOST_FORMAT, initHost));
+
+ configCharList.add(formatConfig(UmpConstant.PARTINODE_INIT_PORT_FORMAT, initPort));
+
+ configCharList.add(formatConfig(UmpConstant.PARTINODE_INIT_SECURE_FORMAT, isSecure));
+
+ return configCharList;
+ }
+
+ private String formatConfig(String formatter, Object value) {
+ return String.format(formatter, id) + "=" + value;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getPubKey() {
+ return pubKey;
+ }
+
+ public void setPubKey(String pubKey) {
+ this.pubKey = pubKey;
+ }
+
+ public String getInitHost() {
+ return initHost;
+ }
+
+ public void setInitHost(String initHost) {
+ this.initHost = initHost;
+ }
+
+ public int getInitPort() {
+ return initPort;
+ }
+
+ public void setInitPort(int initPort) {
+ this.initPort = initPort;
+ }
+
+ public boolean isSecure() {
+ return isSecure;
+ }
+
+ public void setSecure(boolean secure) {
+ isSecure = secure;
+ }
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/PeerSharedConfigs.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/PeerSharedConfigs.java
new file mode 100644
index 00000000..63251967
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/PeerSharedConfigs.java
@@ -0,0 +1,217 @@
+package com.jd.blockchain.ump.model;
+
+import com.jd.blockchain.ump.model.config.LedgerInitConfig;
+import com.jd.blockchain.ump.model.config.MasterConfig;
+import com.jd.blockchain.ump.model.config.PeerLocalConfig;
+import com.jd.blockchain.ump.model.config.PeerSharedConfig;
+import com.jd.blockchain.ump.model.state.LedgerMasterInstall;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+public class PeerSharedConfigs {
+
+ /**
+ * 默认的一次邀请码最长等待时间,单位分钟,默认30分钟
+ */
+ private static final int MAX_WAIT_MINUTE = 30;
+
+ private CountDownLatch latch = null;
+
+ private Lock lock = new ReentrantLock();
+
+ private Lock waitLock = new ReentrantLock();
+
+ private Condition sizeCondition = waitLock.newCondition();
+
+ private List sharedConfigs = new ArrayList<>();
+
+ private int waitNodeSize;
+
+ private String consensusProvider;
+
+ private String sharedKey;
+
+ private String ledgerName;
+
+ private LedgerInitConfig ledgerInitConfig;
+
+ public synchronized PeerSharedConfigs addConfig(PeerLocalConfig sharedConfig) {
+
+ // 判断内容是否存在重复
+ for (PeerSharedConfig innerSharedConfig : sharedConfigs) {
+ if (innerSharedConfig.getName().equals(sharedConfig.getName())
+ || innerSharedConfig.getPubKey().equals(sharedConfig.getPubKey())) {
+ return null;
+ }
+ }
+
+ if (sharedConfig.getMasterConfig().isMaster()) {
+ initDataByMaster(sharedConfig);
+ }
+
+ sharedConfigs.add(sharedConfig);
+
+ if (latch != null) {
+ // 不管是Master还是普通用户都需要-1
+ latch.countDown();
+ }
+ return this;
+ }
+
+ /**
+ * 由Master节点传入的信息对数据进行初始化
+ *
+ * @param sharedConfig
+ */
+ private void initDataByMaster(PeerLocalConfig sharedConfig) {
+
+ MasterConfig masterConfig = sharedConfig.getMasterConfig();
+
+ // master需要对数据进行组织
+ if (latch == null) {
+ latch = new CountDownLatch(masterConfig.getNodeSize() - sharedConfigs.size());
+ }
+ if (consensusProvider == null) {
+ consensusProvider = sharedConfig.getConsensusProvider();
+ }
+ if (sharedKey == null) {
+ sharedKey = sharedConfig.getSharedKey();
+ }
+ if (ledgerName == null) {
+ ledgerName = masterConfig.getLedgerName();
+ }
+ waitNodeSize = masterConfig.getNodeSize();
+ }
+
+ /**
+ * 线程等待
+ * 一直处于等待状态(30分钟),直到有线程调用single方法
+ *
+ */
+ public void await() {
+ waitLock.lock();
+ try {
+ sizeCondition.await(MAX_WAIT_MINUTE, TimeUnit.MINUTES);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ } finally {
+ waitLock.unlock();
+ }
+ }
+
+ /**
+ * 通知其他线程等待状态结束
+ *
+ */
+ public void single() {
+ waitLock.lock();
+ try {
+ sizeCondition.signalAll();
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ } finally {
+ waitLock.unlock();
+ }
+ }
+
+ /**
+ * Master线程调用,等待数据满足后通知其他线程
+ *
+ */
+ public void waitAndNotify() {
+ if (this.latch == null) {
+ throw new IllegalStateException("Please init MasterConfig first !!!");
+ }
+ try {
+ latch.await(MAX_WAIT_MINUTE, TimeUnit.MINUTES);
+ single(); // 通知其他线程释放
+ } catch (Exception e) {
+ if (sharedConfigs.size() >= waitNodeSize) {
+ // 成功
+ single();
+ }
+ }
+ }
+
+ public synchronized LedgerInitConfig ledgerInitConfig(String seed, String createTime) {
+ if (ledgerInitConfig != null) {
+ return ledgerInitConfig;
+ }
+
+ // 处理该ledgerInitConfig
+ ledgerInitConfig = new LedgerInitConfig(seed, ledgerName, createTime, consensusProvider, waitNodeSize);
+
+ // 添加参与方
+ for (int i = 0; i < sharedConfigs.size(); i++) {
+ PeerLocalConfig sharedConfig = sharedConfigs.get(i);
+ ledgerInitConfig.addPartiNode(sharedConfig.toPartiNode(i));
+ }
+
+ return ledgerInitConfig;
+ }
+
+ public String getConsensusProvider() {
+ return consensusProvider;
+ }
+
+ public void setConsensusProvider(String consensusProvider) {
+ this.consensusProvider = consensusProvider;
+ }
+
+ public String getSharedKey() {
+ return sharedKey;
+ }
+
+ public void setSharedKey(String sharedKey) {
+ this.sharedKey = sharedKey;
+ }
+
+ public Lock getLock() {
+ return lock;
+ }
+
+ public String getLedgerName() {
+ return ledgerName;
+ }
+
+ public void setLedgerName(String ledgerName) {
+ this.ledgerName = ledgerName;
+ }
+
+ public List getSharedConfigs() {
+ return sharedConfigs;
+ }
+
+ public void setSharedConfigs(List sharedConfigs) {
+ this.sharedConfigs = sharedConfigs;
+ }
+
+ public LedgerInitConfig getLedgerInitConfig() {
+ return ledgerInitConfig;
+ }
+
+ public void setLedgerInitConfig(LedgerInitConfig ledgerInitConfig) {
+ this.ledgerInitConfig = ledgerInitConfig;
+ }
+
+ public LedgerMasterInstall toLedgerMasterInstall() {
+
+ // String ledgerKey, String sharedKey, int totalNodeSize
+ LedgerMasterInstall masterInstall = new LedgerMasterInstall(
+ ledgerInitConfig.ledgerKey(), sharedConfigs.size())
+ .initCreateTime(ledgerInitConfig.getCreateTime());
+
+ for (PeerLocalConfig sharedConfig : sharedConfigs) {
+
+ masterInstall.add(sharedConfig.toPeerInstall());
+ }
+
+ return masterInstall;
+ }
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/UmpConstant.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/UmpConstant.java
new file mode 100644
index 00000000..5f383e02
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/UmpConstant.java
@@ -0,0 +1,104 @@
+package com.jd.blockchain.ump.model;
+
+import java.io.File;
+
+public class UmpConstant {
+
+ public static String PROJECT_PATH = "";
+
+ public static final String DB_NAME = "jumpdb";
+
+ public static final String URL_SEPARATOR = "/";
+
+ public static final String URL_MASTER = "/master";
+
+ public static final String URL_PEER = "/peer";
+
+ public static final String PRIVATE_KEY_SUFFIX = ".priv";
+
+ public static final String PUBLIC_KEY_SUFFIX = ".priv";
+
+ public static final String PWD_SUFFIX = ".pwd";
+
+ public static final String REQUEST_SHARED_URL = URL_MASTER + URL_SEPARATOR + "share";
+
+ public static final String REQUEST_STATE_URL = URL_MASTER + URL_SEPARATOR + "receive";
+
+ public static final String PARTINODE_COUNT = "cons_parti.count";
+
+ public static final String PARTINODE_FORMAT = "cons_parti.%s";
+
+ public static final String PARTINODE_NAME_FORMAT = PARTINODE_FORMAT + ".name";
+
+ public static final String PARTINODE_PUBKEY_FORMAT = PARTINODE_FORMAT + ".pubkey";
+
+ public static final String PARTINODE_INIT_FORMAT = PARTINODE_FORMAT + ".initializer";
+
+ public static final String PARTINODE_INIT_HOST_FORMAT = PARTINODE_INIT_FORMAT + ".host";
+
+ public static final String PARTINODE_INIT_PORT_FORMAT = PARTINODE_INIT_FORMAT + ".port";
+
+ public static final String PARTINODE_INIT_SECURE_FORMAT = PARTINODE_INIT_FORMAT + ".secure";
+
+ public static final String LEDGER_PREFIX = "ledger";
+
+ public static final String LEDGER_SEED_PREFIX = LEDGER_PREFIX + ".seed";
+
+ public static final String LEDGER_NAME_PREFIX = LEDGER_PREFIX + ".name";
+
+ public static final String CREATE_TIME_PREFIX = "created-time";
+
+ public static final String CONSENSUS_PREFIX = "consensus";
+
+ public static final String CONSENSUS_PROVIDER_PREFIX = CONSENSUS_PREFIX + ".service-provider";
+
+ public static final String CONSENSUS_CONF_PREFIX = CONSENSUS_PREFIX + ".conf";
+
+ public static final String CRYPTO_PREFIX = "crypto";
+
+ public static final String CRYPTO_PROVIDERS_PREFIX = CRYPTO_PREFIX + ".service-providers";
+
+ public static final String LOCAL_PREFIX = "local";
+
+ public static final String LOCAL_PARTI_PREFIX = LOCAL_PREFIX + ".parti";
+
+ public static final String LOCAL_PARTI_ID_PREFIX = LOCAL_PARTI_PREFIX + ".id";
+
+ public static final String LOCAL_PARTI_PUBKEY_PREFIX = LOCAL_PARTI_PREFIX + ".pubkey";
+
+ public static final String LOCAL_PARTI_PRIVKEY_PREFIX = LOCAL_PARTI_PREFIX + ".privkey";
+
+ public static final String LOCAL_PARTI_PWD_PREFIX = LOCAL_PARTI_PREFIX + ".pwd";
+
+ public static final String LEDGER_BINDING_OUT_PREFIX = LEDGER_PREFIX + ".binding.out";
+
+ public static final String LEDGER_DB_URI_PREFIX = LEDGER_PREFIX + ".db.uri";
+
+ public static final String LEDGER_DB_PWD_PREFIX = LEDGER_PREFIX + ".db.pwd";
+
+ public static final String CMD_LEDGER_INIT = "/bin/bash %s -monitor";
+
+ public static final String CMD_START_UP_FORMAT = "/bin/bash %s";
+
+ public static final String PATH_BIN = File.separator + "bin";
+
+ public static final String PATH_LEDGER_INIT_BIN = PATH_BIN + File.separator + "ledger-init.sh";
+
+ public static final String PATH_STARTUP_BIN = PATH_BIN + File.separator + "startup.sh";
+
+ public static final String PATH_LIBS = File.separator + "libs";
+
+ public static final String PATH_SYSTEM = File.separator + "system";
+
+ public static final String PATH_CONFIG = File.separator + "config";
+
+ public static final String PATH_CONFIG_KEYS = PATH_CONFIG + File.separator + "keys";
+
+ public static final String PATH_LEDGER_BINDING_CONFIG = PATH_CONFIG + File.separator + "ledger-binding.conf";
+
+ public static final String PATH_CONFIG_INIT = PATH_CONFIG + File.separator + "init";
+
+ public static final String PATH_LOCAL_CONFIG = PATH_CONFIG_INIT + File.separator + "local.conf";
+
+ public static final String PATH_LEDGER_INIT_CONFIG = PATH_CONFIG_INIT + File.separator + "ledger.init";
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/UmpQueue.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/UmpQueue.java
new file mode 100644
index 00000000..509fb4a5
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/UmpQueue.java
@@ -0,0 +1,50 @@
+package com.jd.blockchain.ump.model;
+
+import com.jd.blockchain.ump.model.state.InstallSchedule;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+public class UmpQueue {
+
+ private final BlockingQueue QUEUE_INSTALL_SCHEDULE = new LinkedBlockingQueue<>();
+
+ public void put(InstallSchedule installSchedule, MasterAddr masterAddr) throws InterruptedException {
+ QUEUE_INSTALL_SCHEDULE.put(new InstallScheduleRequest(installSchedule, masterAddr));
+ }
+
+ public InstallScheduleRequest take() throws InterruptedException {
+ return QUEUE_INSTALL_SCHEDULE.take();
+ }
+
+ public static class InstallScheduleRequest {
+
+ private InstallSchedule installSchedule;
+
+ private MasterAddr masterAddr;
+
+ public InstallScheduleRequest() {
+ }
+
+ public InstallScheduleRequest(InstallSchedule installSchedule, MasterAddr masterAddr) {
+ this.installSchedule = installSchedule;
+ this.masterAddr = masterAddr;
+ }
+
+ public InstallSchedule getInstallSchedule() {
+ return installSchedule;
+ }
+
+ public void setInstallSchedule(InstallSchedule installSchedule) {
+ this.installSchedule = installSchedule;
+ }
+
+ public MasterAddr getMasterAddr() {
+ return masterAddr;
+ }
+
+ public void setMasterAddr(MasterAddr masterAddr) {
+ this.masterAddr = masterAddr;
+ }
+ }
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/config/ConsensusConfig.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/config/ConsensusConfig.java
new file mode 100644
index 00000000..e6963c2f
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/config/ConsensusConfig.java
@@ -0,0 +1,24 @@
+package com.jd.blockchain.ump.model.config;
+
+public class ConsensusConfig {
+
+ private String confPath;
+
+ private byte[] content;
+
+ public String getConfPath() {
+ return confPath;
+ }
+
+ public void setConfPath(String confPath) {
+ this.confPath = confPath;
+ }
+
+ public byte[] getContent() {
+ return content;
+ }
+
+ public void setContent(byte[] content) {
+ this.content = content;
+ }
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/config/LedgerConfig.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/config/LedgerConfig.java
new file mode 100644
index 00000000..2b435f93
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/config/LedgerConfig.java
@@ -0,0 +1,46 @@
+package com.jd.blockchain.ump.model.config;
+
+public class LedgerConfig {
+
+ private LedgerInitConfig initConfig;
+
+ /**
+ * 共识文件配置信息,Base58格式
+ */
+ private String consensusConfig;
+
+
+ public LedgerConfig() {
+ }
+
+ /**
+ * 包装一下,使用JSON处理过程
+ *
+ * @param ledgerConfig
+ */
+ public LedgerConfig(LedgerConfig ledgerConfig) {
+ this.consensusConfig = ledgerConfig.getConsensusConfig();
+
+ }
+
+ public LedgerConfig(LedgerInitConfig initConfig, String consensusConfig) {
+ this.initConfig = initConfig;
+ this.consensusConfig = consensusConfig;
+ }
+
+ public LedgerInitConfig getInitConfig() {
+ return initConfig;
+ }
+
+ public void setInitConfig(LedgerInitConfig initConfig) {
+ this.initConfig = initConfig;
+ }
+
+ public String getConsensusConfig() {
+ return consensusConfig;
+ }
+
+ public void setConsensusConfig(String consensusConfig) {
+ this.consensusConfig = consensusConfig;
+ }
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/config/LedgerIdentification.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/config/LedgerIdentification.java
new file mode 100644
index 00000000..1b724dc7
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/config/LedgerIdentification.java
@@ -0,0 +1,92 @@
+package com.jd.blockchain.ump.model.config;
+
+import com.jd.blockchain.ump.model.MasterAddr;
+
+public class LedgerIdentification {
+
+ private String ledgerKey;
+
+ private String ledgerAndNodeKey;
+
+ private MasterAddr masterAddr;
+
+ private int nodeId;
+
+ private PeerLocalConfig localConfig;
+
+ private LedgerInitConfig initConfig;
+
+ public LedgerIdentification() {
+ }
+
+ public LedgerIdentification(int nodeId, PeerLocalConfig localConfig, MasterAddr masterAddr, String ledgerAndNodeKey, LedgerInitConfig initConfig) {
+ this.nodeId = nodeId;
+ this.localConfig = localConfig;
+ this.masterAddr = masterAddr;
+ this.ledgerKey = initConfig.ledgerKey();
+ this.ledgerAndNodeKey = ledgerAndNodeKey;
+ this.initConfig = initConfig;
+ init();
+ }
+
+ private void init() {
+ // 初始化部分配置信息
+ MasterConfig masterConfig = localConfig.getMasterConfig();
+ // 设置账本名称
+ if (masterConfig.getLedgerName() == null || masterConfig.getLedgerName().length() == 0) {
+ masterConfig.setLedgerName(initConfig.getName());
+ }
+ // 设置NodeSize
+ if (masterConfig.getNodeSize() == 0) {
+ masterConfig.setNodeSize(initConfig.getNodeSize());
+ }
+ }
+
+ public String getLedgerKey() {
+ return ledgerKey;
+ }
+
+ public void setLedgerKey(String ledgerKey) {
+ this.ledgerKey = ledgerKey;
+ }
+
+ public String getLedgerAndNodeKey() {
+ return ledgerAndNodeKey;
+ }
+
+ public void setLedgerAndNodeKey(String ledgerAndNodeKey) {
+ this.ledgerAndNodeKey = ledgerAndNodeKey;
+ }
+
+ public MasterAddr getMasterAddr() {
+ return masterAddr;
+ }
+
+ public void setMasterAddr(MasterAddr masterAddr) {
+ this.masterAddr = masterAddr;
+ }
+
+ public int getNodeId() {
+ return nodeId;
+ }
+
+ public void setNodeId(int nodeId) {
+ this.nodeId = nodeId;
+ }
+
+ public PeerLocalConfig getLocalConfig() {
+ return localConfig;
+ }
+
+ public void setLocalConfig(PeerLocalConfig localConfig) {
+ this.localConfig = localConfig;
+ }
+
+ public LedgerInitConfig getInitConfig() {
+ return initConfig;
+ }
+
+ public void setInitConfig(LedgerInitConfig initConfig) {
+ this.initConfig = initConfig;
+ }
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/config/LedgerInitConfig.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/config/LedgerInitConfig.java
new file mode 100644
index 00000000..f31d84fe
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/config/LedgerInitConfig.java
@@ -0,0 +1,141 @@
+package com.jd.blockchain.ump.model.config;
+
+import com.jd.blockchain.ump.model.PartiNode;
+import com.jd.blockchain.ump.model.UmpConstant;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class LedgerInitConfig {
+
+ private String seed;
+
+ private String name;
+
+ private String createTime;
+
+ private String consensusProvider;
+
+ private int nodeSize;
+
+ private String cryptoProviders =
+ "com.jd.blockchain.crypto.service.classic.ClassicCryptoService, " +
+ "com.jd.blockchain.crypto.service.sm.SMCryptoService";
+
+
+ private List partiNodes = new ArrayList<>();
+
+ public LedgerInitConfig() {
+ }
+
+ public LedgerInitConfig(String seed, String name, String createTime, String consensusProvider, int nodeSize) {
+ this.seed = seed;
+ this.name = name;
+ this.createTime = createTime;
+ this.consensusProvider = consensusProvider;
+ this.nodeSize = nodeSize;
+ }
+
+ public List toConfigChars(String consensusConf) {
+
+ List configChars = new ArrayList<>();
+
+ configChars.add(toConfigChars(UmpConstant.LEDGER_SEED_PREFIX, seed));
+
+ configChars.add(toConfigChars(UmpConstant.LEDGER_NAME_PREFIX, name));
+
+ configChars.add(toConfigChars(UmpConstant.CREATE_TIME_PREFIX, createTime));
+
+ configChars.add(toConfigChars(UmpConstant.CONSENSUS_PROVIDER_PREFIX, consensusProvider));
+
+ configChars.add(toConfigChars(UmpConstant.CONSENSUS_CONF_PREFIX, consensusConf));
+
+ configChars.add(toConfigChars(UmpConstant.CRYPTO_PROVIDERS_PREFIX, cryptoProviders));
+
+ configChars.add(toConfigChars(UmpConstant.PARTINODE_COUNT, partiNodes.size()));
+
+ for (PartiNode partiNode : partiNodes) {
+ configChars.addAll(partiNode.toConfigChars());
+ }
+
+ return configChars;
+ }
+
+ public String ledgerKey() {
+ return seed + "-" + name;
+ }
+
+ public int nodeId(String pubKey) {
+ for (int i = 0; i < partiNodes.size(); i++) {
+ PartiNode partiNode = partiNodes.get(i);
+ if (partiNode.getPubKey().equals(pubKey)) {
+ return i;
+ }
+ }
+ throw new IllegalStateException(String.format("Can not find PubKey = %s !", pubKey));
+ }
+
+ private String toConfigChars(String prefix, Object value) {
+ return prefix + "=" + value;
+ }
+
+ public String getSeed() {
+ return seed;
+ }
+
+ public void setSeed(String seed) {
+ this.seed = seed;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getCreateTime() {
+ return createTime;
+ }
+
+ public void setCreateTime(String createTime) {
+ this.createTime = createTime;
+ }
+
+ public String getConsensusProvider() {
+ return consensusProvider;
+ }
+
+ public void setConsensusProvider(String consensusProvider) {
+ this.consensusProvider = consensusProvider;
+ }
+
+ public int getNodeSize() {
+ return nodeSize;
+ }
+
+ public void setNodeSize(int nodeSize) {
+ this.nodeSize = nodeSize;
+ }
+
+ public String getCryptoProviders() {
+ return cryptoProviders;
+ }
+
+ public void setCryptoProviders(String cryptoProviders) {
+ this.cryptoProviders = cryptoProviders;
+ }
+
+ public List getPartiNodes() {
+ return partiNodes;
+ }
+
+ public void setPartiNodes(List partiNodes) {
+ this.partiNodes = partiNodes;
+ }
+
+ public void addPartiNode(PartiNode partiNode) {
+ this.partiNodes.add(partiNode);
+ }
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/config/MasterConfig.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/config/MasterConfig.java
new file mode 100644
index 00000000..f3807773
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/config/MasterConfig.java
@@ -0,0 +1,89 @@
+package com.jd.blockchain.ump.model.config;
+
+import com.jd.blockchain.ump.model.MasterAddr;
+
+public class MasterConfig {
+
+ private String masterAddr;
+
+ private int masterPort;
+
+ private String ledgerName;
+
+ private int nodeSize;
+
+ private boolean isMaster = false;
+
+ public MasterConfig() {
+ }
+
+ public String getMasterAddr() {
+ return masterAddr;
+ }
+
+ public void setMasterAddr(String masterAddr) {
+ this.masterAddr = masterAddr;
+ }
+
+ public int getMasterPort() {
+ return masterPort;
+ }
+
+ public void setMasterPort(int masterPort) {
+ this.masterPort = masterPort;
+ }
+
+ public String getLedgerName() {
+ return ledgerName;
+ }
+
+ public void setLedgerName(String ledgerName) {
+ this.ledgerName = ledgerName;
+ }
+
+ public int getNodeSize() {
+ return nodeSize;
+ }
+
+ public void setNodeSize(int nodeSize) {
+ this.nodeSize = nodeSize;
+ }
+
+ public boolean isMaster() {
+ return isMaster;
+ }
+
+ public void setMaster(boolean master) {
+ isMaster = master;
+ }
+
+ public MasterConfig buildIsMaster(boolean isMaster) {
+ setMaster(isMaster);
+ return this;
+ }
+
+ public MasterConfig buildNodeSize(int nodeSize) {
+ setNodeSize(nodeSize);
+ return this;
+ }
+
+ public MasterConfig buildLedgerName(String ledgerName) {
+ setLedgerName(ledgerName);
+ return this;
+ }
+
+ public MasterConfig buildMasterAddr(String masterAddr) {
+ setMasterAddr(masterAddr);
+ return this;
+ }
+
+ public MasterConfig buildMasterPort(int masterPort) {
+ setMasterPort(masterPort);
+ return this;
+ }
+
+
+ public MasterAddr toMasterAddr() {
+ return MasterAddr.newInstance(masterAddr, masterPort);
+ }
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/config/PeerLocalConfig.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/config/PeerLocalConfig.java
new file mode 100644
index 00000000..21ba3220
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/config/PeerLocalConfig.java
@@ -0,0 +1,160 @@
+package com.jd.blockchain.ump.model.config;
+
+
+import com.jd.blockchain.ump.model.MasterAddr;
+import com.jd.blockchain.ump.model.PartiNode;
+import com.jd.blockchain.ump.model.UmpConstant;
+import com.jd.blockchain.ump.model.state.LedgerMasterInstall;
+import com.jd.blockchain.ump.model.state.LedgerPeerInstall;
+
+import java.io.File;
+
+/**
+ * Peer本地配置信息
+ */
+public class PeerLocalConfig extends PeerSharedConfig {
+
+ private String peerPath;
+
+ private String consensusConf = "bftsmart.config"; // 默认为bftsmart配置
+
+ private String privKey;
+
+ private String encodePwd;
+
+ private String dbName;
+
+ private MasterConfig masterConfig;
+
+ public String bindingOutPath() {
+ return peerPath + UmpConstant.PATH_CONFIG;
+ }
+
+ public String localConfPath() {
+ return peerPath + UmpConstant.PATH_LOCAL_CONFIG;
+ }
+
+ public String ledgerInitConfPath() {
+ return peerPath + UmpConstant.PATH_LEDGER_INIT_CONFIG;
+ }
+
+ public String consensusConfPath() {
+ return peerPath + UmpConstant.PATH_CONFIG_INIT + File.separator + consensusConf;
+ }
+
+ public String libsDirectory() {
+ return peerPath + UmpConstant.PATH_LIBS;
+ }
+
+ public String getPeerPath() {
+ return peerPath;
+ }
+
+ public void setPeerPath(String peerPath) {
+ this.peerPath = peerPath;
+ }
+
+ public String getConsensusConf() {
+ return consensusConf;
+ }
+
+ public void setConsensusConf(String consensusConf) {
+ this.consensusConf = consensusConf;
+ }
+
+ public String getPrivKey() {
+ return privKey;
+ }
+
+ public void setPrivKey(String privKey) {
+ this.privKey = privKey;
+ }
+
+ public String getEncodePwd() {
+ return encodePwd;
+ }
+
+ public void setEncodePwd(String encodePwd) {
+ this.encodePwd = encodePwd;
+ }
+
+ public String getDbName() {
+ return dbName;
+ }
+
+ public void setDbName(String dbName) {
+ this.dbName = dbName;
+ }
+
+ public MasterConfig getMasterConfig() {
+ return masterConfig;
+ }
+
+ public void setMasterConfig(MasterConfig masterConfig) {
+ this.masterConfig = masterConfig;
+ }
+
+ public synchronized PartiNode toPartiNode(int nodeId) {
+ if (this.partiNode != null) {
+ return partiNode;
+ }
+ partiNode = new PartiNode();
+ partiNode.setId(nodeId);
+ partiNode.setName(name);
+ partiNode.setInitHost(initAddr);
+ partiNode.setInitPort(initPort);
+ partiNode.setPubKey(pubKey);
+ partiNode.setSecure(false);
+ return partiNode;
+ }
+
+ public LedgerPeerInstall toLedgerPeerInstall(int totalNodeSize) {
+ return new LedgerPeerInstall(name, sharedKey, peerPath, totalNodeSize);
+ }
+
+ public LedgerMasterInstall.PeerInstall toPeerInstall() {
+ return new LedgerMasterInstall.PeerInstall(name, pubKey, initAddr, initPort, consensusNode, consensusProvider);
+ }
+
+ public void verify() {
+
+ // 主要校验dbName地址是否存在
+ String dbPath = peerPath + File.separator + dbName;
+ File dbDir = new File(dbPath);
+ if (dbDir.exists()) {
+ throw new IllegalStateException(String.format("DB name = %s, path = %s is exist !!!", dbName, dbPath));
+ }
+
+ // 其他配置信息是否正确
+ if (masterConfig == null) {
+ // Master不能为空
+ throw new IllegalStateException("Master Config can not be NULL !!!");
+ }
+ if (masterConfig.isMaster()) {
+ // 账本名字及NodeSize不能为空
+ if (masterConfig.getLedgerName() == null || masterConfig.getLedgerName().length() == 0) {
+ throw new IllegalStateException("Master 's LedgerName can not be empty !!!");
+ }
+ if (masterConfig.getNodeSize() == 0) {
+ throw new IllegalStateException("Master 's NodeSize can not be Zero !!!");
+ }
+ } else {
+ // 普通Peer需要检查Master的IP地址及端口
+ if (masterConfig.getMasterAddr() == null || masterConfig.getMasterAddr().length() == 0) {
+ throw new IllegalStateException("Master 's IP Address can not be empty !!!");
+ }
+
+ if (masterConfig.getMasterPort() == 0) {
+ throw new IllegalStateException("Master 's Port must be Set !!!");
+ }
+ }
+ }
+
+ public boolean master() {
+ return masterConfig.isMaster();
+ }
+
+ public MasterAddr masterAddr() {
+ return masterConfig.toMasterAddr();
+ }
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/config/PeerSharedConfig.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/config/PeerSharedConfig.java
new file mode 100644
index 00000000..cf5d71ef
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/config/PeerSharedConfig.java
@@ -0,0 +1,86 @@
+package com.jd.blockchain.ump.model.config;
+
+import com.jd.blockchain.ump.model.PartiNode;
+
+public class PeerSharedConfig {
+
+ public static final String DB_ROCKSDB_SUFFIX = "rocksdb_";
+
+ protected String sharedKey;
+
+ protected String name;
+
+ protected String initAddr;
+
+ protected String pubKey;
+
+ protected int initPort;
+
+ protected String consensusNode;
+
+ protected String consensusProvider = "com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider";
+
+ protected PartiNode partiNode;
+
+ public String getSharedKey() {
+ return sharedKey;
+ }
+
+ public void setSharedKey(String sharedKey) {
+ this.sharedKey = sharedKey;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getInitAddr() {
+ return initAddr;
+ }
+
+ public void setInitAddr(String initAddr) {
+ this.initAddr = initAddr;
+ }
+
+ public String getPubKey() {
+ return pubKey;
+ }
+
+ public void setPubKey(String pubKey) {
+ this.pubKey = pubKey;
+ }
+
+ public int getInitPort() {
+ return initPort;
+ }
+
+ public void setInitPort(int initPort) {
+ this.initPort = initPort;
+ }
+
+ public String addr() {
+ return initAddr + "-" + initPort;
+ }
+
+ public String getConsensusNode() {
+ return consensusNode;
+ }
+
+ public void setConsensusNode(String consensusNode) {
+ this.consensusNode = consensusNode;
+ }
+
+ public String getConsensusProvider() {
+ return consensusProvider;
+ }
+
+ public void setConsensusProvider(String consensusProvider) {
+ this.consensusProvider = consensusProvider;
+ }
+
+
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/config/PeerSharedConfigVv.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/config/PeerSharedConfigVv.java
new file mode 100644
index 00000000..6e536b32
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/config/PeerSharedConfigVv.java
@@ -0,0 +1,180 @@
+package com.jd.blockchain.ump.model.config;
+
+
+import com.jd.blockchain.ump.model.UmpConstant;
+import com.jd.blockchain.ump.model.user.UserKeys;
+
+/**
+ *
+ */
+public class PeerSharedConfigVv {
+
+ private String sharedKey;
+
+ private String name;
+
+ private int userId;
+
+ private String pubKey;
+
+ private String initAddr;
+
+ private int initPort;
+
+ private String consensusNode;
+
+ private String peerPath = UmpConstant.PROJECT_PATH;
+
+ private String dbName;
+
+ private int nodeSize;
+
+ private String masterAddr;
+
+ private int masterPort;
+
+ private String ledgerName;
+
+ public String getSharedKey() {
+ return sharedKey;
+ }
+
+ public void setSharedKey(String sharedKey) {
+ this.sharedKey = sharedKey;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getUserId() {
+ return userId;
+ }
+
+ public void setUserId(int userId) {
+ this.userId = userId;
+ }
+
+ public String getInitAddr() {
+ return initAddr;
+ }
+
+ public String getPubKey() {
+ return pubKey;
+ }
+
+ public void setPubKey(String pubKey) {
+ this.pubKey = pubKey;
+ }
+
+ public void setInitAddr(String initAddr) {
+ this.initAddr = initAddr;
+ }
+
+ public int getInitPort() {
+ return initPort;
+ }
+
+ public void setInitPort(int initPort) {
+ this.initPort = initPort;
+ }
+
+ public String getConsensusNode() {
+ return consensusNode;
+ }
+
+ public void setConsensusNode(String consensusNode) {
+ this.consensusNode = consensusNode;
+ }
+
+ public String getPeerPath() {
+ return peerPath;
+ }
+
+ public void setPeerPath(String peerPath) {
+ this.peerPath = peerPath;
+ }
+
+ public String getDbName() {
+ return dbName;
+ }
+
+ public void setDbName(String dbName) {
+ this.dbName = dbName;
+ }
+
+ public int getNodeSize() {
+ return nodeSize;
+ }
+
+ public void setNodeSize(Integer nodeSize) {
+ this.nodeSize = nodeSize;
+ }
+
+ public String getMasterAddr() {
+ return masterAddr;
+ }
+
+ public void setMasterAddr(String masterAddr) {
+ this.masterAddr = masterAddr;
+ }
+
+ public int getMasterPort() {
+ return masterPort;
+ }
+
+ public void setMasterPort(Integer masterPort) {
+ this.masterPort = masterPort;
+ }
+
+ public String getLedgerName() {
+ return ledgerName;
+ }
+
+ public void setLedgerName(String ledgerName) {
+ this.ledgerName = ledgerName;
+ }
+
+ public PeerLocalConfig toPeerLocalConfig(UserKeys userKeys) {
+
+ PeerLocalConfig localConfig = new PeerLocalConfig();
+
+ localConfig.setSharedKey(sharedKey);
+ localConfig.setName(name);
+ localConfig.setInitAddr(initAddr);
+ localConfig.setInitPort(initPort);
+ localConfig.setConsensusNode(consensusNode);
+ localConfig.setPubKey(userKeys.getPubKey());
+ localConfig.setPrivKey(userKeys.getPrivKey());
+ localConfig.setEncodePwd(userKeys.getEncodePwd());
+ localConfig.setPeerPath(peerPath);
+ localConfig.setDbName(dbName);
+
+ MasterConfig masterConfig = new MasterConfig();
+
+ if (master()) {
+ masterConfig.buildIsMaster(true)
+ .buildLedgerName(ledgerName)
+ .buildNodeSize(nodeSize);
+ } else {
+ masterConfig.buildIsMaster(false)
+ .buildMasterAddr(masterAddr)
+ .buildMasterPort(masterPort);
+ }
+
+ localConfig.setMasterConfig(masterConfig);
+
+ return localConfig;
+ }
+
+ private boolean master() {
+ if (masterAddr == null || masterAddr.length() == 0) {
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/InstallProcess.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/InstallProcess.java
new file mode 100644
index 00000000..a373f5be
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/InstallProcess.java
@@ -0,0 +1,21 @@
+package com.jd.blockchain.ump.model.state;
+
+public class InstallProcess {
+
+ private String content;
+
+ public InstallProcess() {
+ }
+
+ public InstallProcess(String content) {
+ this.content = content;
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+ public void setContent(String content) {
+ this.content = content;
+ }
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/InstallSchedule.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/InstallSchedule.java
new file mode 100644
index 00000000..66f26ebb
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/InstallSchedule.java
@@ -0,0 +1,54 @@
+package com.jd.blockchain.ump.model.state;
+
+public class InstallSchedule {
+
+ private String ledgerKey;
+
+ private String ledgerAndNodeKey;
+
+ private InstallProcess process;
+
+ private ScheduleState state;
+
+ public InstallSchedule() {
+ }
+
+ public InstallSchedule(String ledgerKey, String ledgerAndNodeKey, InstallProcess process, ScheduleState state) {
+ this.ledgerKey = ledgerKey;
+ this.ledgerAndNodeKey = ledgerAndNodeKey;
+ this.process = process;
+ this.state = state;
+ }
+
+ public String getLedgerKey() {
+ return ledgerKey;
+ }
+
+ public void setLedgerKey(String ledgerKey) {
+ this.ledgerKey = ledgerKey;
+ }
+
+ public String getLedgerAndNodeKey() {
+ return ledgerAndNodeKey;
+ }
+
+ public void setLedgerAndNodeKey(String ledgerAndNodeKey) {
+ this.ledgerAndNodeKey = ledgerAndNodeKey;
+ }
+
+ public InstallProcess getProcess() {
+ return process;
+ }
+
+ public void setProcess(InstallProcess process) {
+ this.process = process;
+ }
+
+ public ScheduleState getState() {
+ return state;
+ }
+
+ public void setState(ScheduleState state) {
+ this.state = state;
+ }
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/LedgerBindingConf.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/LedgerBindingConf.java
new file mode 100644
index 00000000..7843dade
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/LedgerBindingConf.java
@@ -0,0 +1,33 @@
+package com.jd.blockchain.ump.model.state;
+
+import java.util.Set;
+
+public class LedgerBindingConf {
+
+ private Set ledgerHashs;
+
+ private long lastTime;
+
+ public LedgerBindingConf() {
+ }
+
+ public LedgerBindingConf(long lastTime) {
+ this.lastTime = lastTime;
+ }
+
+ public Set getLedgerHashs() {
+ return ledgerHashs;
+ }
+
+ public void setLedgerHashs(Set ledgerHashs) {
+ this.ledgerHashs = ledgerHashs;
+ }
+
+ public long getLastTime() {
+ return lastTime;
+ }
+
+ public void setLastTime(long lastTime) {
+ this.lastTime = lastTime;
+ }
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/LedgerInited.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/LedgerInited.java
new file mode 100644
index 00000000..64445781
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/LedgerInited.java
@@ -0,0 +1,101 @@
+package com.jd.blockchain.ump.model.state;
+
+public class LedgerInited {
+
+ private String ledgerHash;
+
+ private String ledgerName;
+
+ private String partiName;
+
+ private String partiAddress;
+
+ private String dbUri;
+
+ private StartupState startupState = StartupState.UNKNOWN;
+
+ public LedgerInited() {
+ }
+
+ public LedgerInited(String ledgerHash) {
+ this.ledgerHash = ledgerHash;
+ }
+
+ public String getLedgerHash() {
+ return ledgerHash;
+ }
+
+ public void setLedgerHash(String ledgerHash) {
+ this.ledgerHash = ledgerHash;
+ }
+
+ public String getLedgerName() {
+ return ledgerName;
+ }
+
+ public void setLedgerName(String ledgerName) {
+ this.ledgerName = ledgerName;
+ }
+
+ public String getPartiName() {
+ return partiName;
+ }
+
+ public void setPartiName(String partiName) {
+ this.partiName = partiName;
+ }
+
+ public String getPartiAddress() {
+ return partiAddress;
+ }
+
+ public void setPartiAddress(String partiAddress) {
+ this.partiAddress = partiAddress;
+ }
+
+ public String getDbUri() {
+ return dbUri;
+ }
+
+ public void setDbUri(String dbUri) {
+ this.dbUri = dbUri;
+ }
+
+ public StartupState getStartupState() {
+ return startupState;
+ }
+
+ public void setStartupState(StartupState startupState) {
+ this.startupState = startupState;
+ }
+
+ public LedgerInited buildLedgerHash(String ledgerHash) {
+ setLedgerHash(ledgerHash);
+ return this;
+ }
+
+ public LedgerInited buildLedgerName(String ledgerName) {
+ setLedgerName(ledgerName);
+ return this;
+ }
+
+ public LedgerInited buildPartiName(String partiName) {
+ setPartiName(partiName);
+ return this;
+ }
+
+ public LedgerInited buildPartiAddress(String partiAddress) {
+ setPartiAddress(partiAddress);
+ return this;
+ }
+
+ public LedgerInited buildDbUri(String dbUri) {
+ setDbUri(dbUri);
+ return this;
+ }
+
+ public LedgerInited buildStartupState(StartupState startupState) {
+ setStartupState(startupState);
+ return this;
+ }
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/LedgerMasterInstall.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/LedgerMasterInstall.java
new file mode 100644
index 00000000..76ca3d41
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/LedgerMasterInstall.java
@@ -0,0 +1,156 @@
+package com.jd.blockchain.ump.model.state;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+public class LedgerMasterInstall {
+
+ private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
+ private String ledgerKey;
+
+ private int totalNodeSize;
+
+ private String createTime;
+
+ private List peerInstalls = new ArrayList<>();
+
+ public LedgerMasterInstall() {
+ }
+
+ public LedgerMasterInstall(String ledgerKey, int totalNodeSize) {
+ this.ledgerKey = ledgerKey;
+ this.totalNodeSize = totalNodeSize;
+ }
+
+ public LedgerMasterInstall initCreateTime(String createTime) {
+ this.createTime = createTime;
+ return this;
+ }
+
+ public LedgerMasterInstall initCreateTime(Date date) {
+ this.createTime = SDF.format(date);
+ return this;
+ }
+
+ public LedgerMasterInstall add(PeerInstall peerInstall) {
+ peerInstalls.add(peerInstall);
+ return this;
+ }
+
+ public LedgerMasterInstall add(String name, String pubKey, String ipAddr, int initPort,
+ String consensusNode, String consensusProvider) {
+ PeerInstall peerInstall = new PeerInstall(
+ name, pubKey, ipAddr, initPort, consensusNode, consensusProvider);
+ return add(peerInstall);
+ }
+
+ public String getLedgerKey() {
+ return ledgerKey;
+ }
+
+ public void setLedgerKey(String ledgerKey) {
+ this.ledgerKey = ledgerKey;
+ }
+
+ public int getTotalNodeSize() {
+ return totalNodeSize;
+ }
+
+ public void setTotalNodeSize(int totalNodeSize) {
+ this.totalNodeSize = totalNodeSize;
+ }
+
+ public String getCreateTime() {
+ return createTime;
+ }
+
+ public void setCreateTime(String createTime) {
+ this.createTime = createTime;
+ }
+
+ public List getPeerInstalls() {
+ return peerInstalls;
+ }
+
+ public void setPeerInstalls(List peerInstalls) {
+ this.peerInstalls = peerInstalls;
+ }
+
+ public static class PeerInstall {
+
+ private String name;
+
+ private String pubKey;
+
+ private String ipAddr;
+
+ private int initPort;
+
+ private String consensusNode;
+
+ private String consensusProvider;
+
+ public PeerInstall() {
+ }
+
+ public PeerInstall(String name, String pubKey, String ipAddr, int initPort, String consensusNode, String consensusProvider) {
+ this.name = name;
+ this.pubKey = pubKey;
+ this.ipAddr = ipAddr;
+ this.initPort = initPort;
+ this.consensusNode = consensusNode;
+ this.consensusProvider = consensusProvider;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getPubKey() {
+ return pubKey;
+ }
+
+ public void setPubKey(String pubKey) {
+ this.pubKey = pubKey;
+ }
+
+ public String getIpAddr() {
+ return ipAddr;
+ }
+
+ public void setIpAddr(String ipAddr) {
+ this.ipAddr = ipAddr;
+ }
+
+ public int getInitPort() {
+ return initPort;
+ }
+
+ public void setInitPort(int initPort) {
+ this.initPort = initPort;
+ }
+
+ public String getConsensusNode() {
+ return consensusNode;
+ }
+
+ public void setConsensusNode(String consensusNode) {
+ this.consensusNode = consensusNode;
+ }
+
+ public String getConsensusProvider() {
+ return consensusProvider;
+ }
+
+ public void setConsensusProvider(String consensusProvider) {
+ this.consensusProvider = consensusProvider;
+ }
+ }
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/LedgerPeerInited.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/LedgerPeerInited.java
new file mode 100644
index 00000000..7026aa57
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/LedgerPeerInited.java
@@ -0,0 +1,42 @@
+package com.jd.blockchain.ump.model.state;
+
+public class LedgerPeerInited {
+
+ private String ledgerHash;
+
+ private LedgerPeerInstall peerInstall;
+
+ private StartupState startupState;
+
+ public LedgerPeerInited() {
+ }
+
+ public LedgerPeerInited(String ledgerHash, LedgerPeerInstall peerInstall) {
+ this.ledgerHash = ledgerHash;
+ this.peerInstall = peerInstall;
+ }
+
+ public String getLedgerHash() {
+ return ledgerHash;
+ }
+
+ public void setLedgerHash(String ledgerHash) {
+ this.ledgerHash = ledgerHash;
+ }
+
+ public LedgerPeerInstall getPeerInstall() {
+ return peerInstall;
+ }
+
+ public void setPeerInstall(LedgerPeerInstall peerInstall) {
+ this.peerInstall = peerInstall;
+ }
+
+ public StartupState getStartupState() {
+ return startupState;
+ }
+
+ public void setStartupState(StartupState startupState) {
+ this.startupState = startupState;
+ }
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/LedgerPeerInstall.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/LedgerPeerInstall.java
new file mode 100644
index 00000000..932d621c
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/LedgerPeerInstall.java
@@ -0,0 +1,117 @@
+package com.jd.blockchain.ump.model.state;
+
+import com.jd.blockchain.ump.model.MasterAddr;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class LedgerPeerInstall {
+
+ private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
+ private String ledgerKey;
+
+ private String ledgerAndNodeKey;
+
+ private String nodeName;
+
+ private String sharedKey;
+
+ private String peerPath;
+
+ private int totalNodeSize;
+
+ private MasterAddr masterAddr;
+
+ private String createTime;
+
+ public LedgerPeerInstall() {
+ }
+
+ public LedgerPeerInstall(String nodeName, String sharedKey, String peerPath, int totalNodeSize) {
+ this.nodeName = nodeName;
+ this.sharedKey = sharedKey;
+ this.peerPath = peerPath;
+ this.totalNodeSize = totalNodeSize;
+ }
+
+ public LedgerPeerInstall initKey(String ledgerKey, String ledgerAndNodeKey) {
+ this.ledgerKey = ledgerKey;
+ this.ledgerAndNodeKey = ledgerAndNodeKey;
+ return this;
+ }
+
+ public LedgerPeerInstall initMasterAddr(MasterAddr masterAddr) {
+ this.masterAddr = masterAddr;
+ return this;
+ }
+
+ public LedgerPeerInstall initCreateTime(Date date) {
+ createTime = SDF.format(date);
+ return this;
+ }
+
+ public String getLedgerKey() {
+ return ledgerKey;
+ }
+
+ public void setLedgerKey(String ledgerKey) {
+ this.ledgerKey = ledgerKey;
+ }
+
+ public String getLedgerAndNodeKey() {
+ return ledgerAndNodeKey;
+ }
+
+ public void setLedgerAndNodeKey(String ledgerAndNodeKey) {
+ this.ledgerAndNodeKey = ledgerAndNodeKey;
+ }
+
+ public String getNodeName() {
+ return nodeName;
+ }
+
+ public void setNodeName(String nodeName) {
+ this.nodeName = nodeName;
+ }
+
+ public String getSharedKey() {
+ return sharedKey;
+ }
+
+ public void setSharedKey(String sharedKey) {
+ this.sharedKey = sharedKey;
+ }
+
+ public String getPeerPath() {
+ return peerPath;
+ }
+
+ public void setPeerPath(String peerPath) {
+ this.peerPath = peerPath;
+ }
+
+ public int getTotalNodeSize() {
+ return totalNodeSize;
+ }
+
+ public void setTotalNodeSize(int totalNodeSize) {
+ this.totalNodeSize = totalNodeSize;
+ }
+
+ public String getCreateTime() {
+ return createTime;
+ }
+
+ public void setCreateTime(String createTime) {
+ this.createTime = createTime;
+ }
+
+ public MasterAddr getMasterAddr() {
+ return masterAddr;
+ }
+
+ public void setMasterAddr(MasterAddr masterAddr) {
+ this.masterAddr = masterAddr;
+ }
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/PeerInstallSchedule.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/PeerInstallSchedule.java
new file mode 100644
index 00000000..dc85343a
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/PeerInstallSchedule.java
@@ -0,0 +1,32 @@
+package com.jd.blockchain.ump.model.state;
+
+public class PeerInstallSchedule {
+
+ private InstallProcess process;
+
+ private ScheduleState state;
+
+ public PeerInstallSchedule() {
+ }
+
+ public PeerInstallSchedule(InstallProcess process, ScheduleState state) {
+ this.process = process;
+ this.state = state;
+ }
+
+ public InstallProcess getProcess() {
+ return process;
+ }
+
+ public void setProcess(InstallProcess process) {
+ this.process = process;
+ }
+
+ public ScheduleState getState() {
+ return state;
+ }
+
+ public void setState(ScheduleState state) {
+ this.state = state;
+ }
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/PeerInstallSchedules.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/PeerInstallSchedules.java
new file mode 100644
index 00000000..d6aaa7b1
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/PeerInstallSchedules.java
@@ -0,0 +1,61 @@
+package com.jd.blockchain.ump.model.state;
+
+import com.jd.blockchain.ump.model.config.LedgerIdentification;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PeerInstallSchedules {
+
+ private String ledgerHash;
+
+ private LedgerIdentification identification;
+
+ private List installSchedules = new ArrayList<>();
+
+ public PeerInstallSchedules() {
+ }
+
+ public PeerInstallSchedules(LedgerIdentification identification) {
+ this.identification = identification;
+ }
+
+ public PeerInstallSchedules(LedgerIdentification identification, String ledgerHash) {
+ this.identification = identification;
+ this.ledgerHash = ledgerHash;
+ }
+
+ public PeerInstallSchedules addInstallSchedule(PeerInstallSchedule installSchedule) {
+ this.installSchedules.add(installSchedule);
+ return this;
+ }
+
+ public PeerInstallSchedules initLedgerHash(String ledgerHash) {
+ setLedgerHash(ledgerHash);
+ return this;
+ }
+
+ public String getLedgerHash() {
+ return ledgerHash;
+ }
+
+ public void setLedgerHash(String ledgerHash) {
+ this.ledgerHash = ledgerHash;
+ }
+
+ public LedgerIdentification getIdentification() {
+ return identification;
+ }
+
+ public void setIdentification(LedgerIdentification identification) {
+ this.identification = identification;
+ }
+
+ public List getInstallSchedules() {
+ return installSchedules;
+ }
+
+ public void setInstallSchedules(List installSchedules) {
+ this.installSchedules = installSchedules;
+ }
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/PeerStartupSchedules.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/PeerStartupSchedules.java
new file mode 100644
index 00000000..ba9ac9da
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/PeerStartupSchedules.java
@@ -0,0 +1,40 @@
+package com.jd.blockchain.ump.model.state;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PeerStartupSchedules {
+
+ private String peerPath;
+
+ private List installSchedules = new ArrayList<>();
+
+ public PeerStartupSchedules() {
+ }
+
+ public PeerStartupSchedules(String peerPath) {
+ this.peerPath = peerPath;
+ }
+
+
+ public PeerStartupSchedules addInstallSchedule(PeerInstallSchedule installSchedule) {
+ this.installSchedules.add(installSchedule);
+ return this;
+ }
+
+ public List getInstallSchedules() {
+ return installSchedules;
+ }
+
+ public void setInstallSchedules(List installSchedules) {
+ this.installSchedules = installSchedules;
+ }
+
+ public String getPeerPath() {
+ return peerPath;
+ }
+
+ public void setPeerPath(String peerPath) {
+ this.peerPath = peerPath;
+ }
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/ScheduleState.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/ScheduleState.java
new file mode 100644
index 00000000..6307e498
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/ScheduleState.java
@@ -0,0 +1,43 @@
+package com.jd.blockchain.ump.model.state;
+
+public enum ScheduleState {
+
+ /**
+ * 加载内容,包括获取各种数据列表
+ */
+ LOAD,
+ LOAD_SUCCESS, // 加载成功
+ LOAD_FAIL, // 加载失败
+
+ /**
+ * 将获取的数据写入文件
+ *
+ */
+ WRITE,
+ WRITE_SUCCESS, // 写入文件成功
+ WRITE_FAIL, // 写入文件失败
+
+ /**
+ * Ledger_INIT:账本初始化过程
+ * 主要是调用SHELL
+ *
+ */
+ INIT,
+ INIT_SUCCESS, // 账本初始化成功
+ INIT_FAIL, // 账本初始化失败
+
+ /**
+ * 无须启动PEER,等待PEER自动更新账本信息
+ */
+ NO_STARTUP,
+
+ /**
+ * 启动Peer节点
+ */
+ STARTUP_START,
+ STARTUP_OVER,
+ STARTUP_SUCCESS, // Peer节点启动成功
+ STARTUP_FAIL, // Peer节点启动失败
+ ;
+
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/StartupState.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/StartupState.java
new file mode 100644
index 00000000..d605ccd8
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/state/StartupState.java
@@ -0,0 +1,48 @@
+package com.jd.blockchain.ump.model.state;
+
+public enum StartupState {
+
+ /**
+ * UNEXIST
+ * 不存在,描述该账本Hash曾经创建,但目前在LedgerBinding.conf文件中不存在
+ * 此状态不支持任何其他操作
+ */
+ UNEXIST,
+
+ /**
+ * UNLOAD
+ * 账本存在,但未加载
+ * 此状态可以启动,不能停止
+ */
+ UNLOAD,
+
+ /**
+ * LOADING
+ * 账本加载中,说明程序已经启动,但尚未加载该程序
+ * 此状态不可以启动,不建议停止
+ */
+ LOADING,
+
+ /**
+ * LOADED
+ * 账本已加载
+ * 此状态不可以启动,后续可以支持停止操作
+ */
+ LOADED,
+
+ /**
+ * UNKNOWN
+ * 未知,常见于命令检测执行错误或程序启动,但账本尚未加载完成
+ * 此状态不支持任何其他操作
+ */
+ UNKNOWN,
+
+ /**
+ * DB_UNEXIST
+ * 该账本对应的数据库不存在
+ * 此状态不支持任何其他操作
+ */
+ DB_UNEXIST,
+
+ ;
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/user/UserKeyBuilder.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/user/UserKeyBuilder.java
new file mode 100644
index 00000000..e3967c01
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/user/UserKeyBuilder.java
@@ -0,0 +1,34 @@
+package com.jd.blockchain.ump.model.user;
+
+public class UserKeyBuilder {
+
+ private String name;
+
+ private String seed;
+
+ private String pwd;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getSeed() {
+ return seed;
+ }
+
+ public void setSeed(String seed) {
+ this.seed = seed;
+ }
+
+ public String getPwd() {
+ return pwd;
+ }
+
+ public void setPwd(String pwd) {
+ this.pwd = pwd;
+ }
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/user/UserKeys.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/user/UserKeys.java
new file mode 100644
index 00000000..121d3ed7
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/user/UserKeys.java
@@ -0,0 +1,68 @@
+package com.jd.blockchain.ump.model.user;
+
+public class UserKeys {
+
+ private int id;
+
+ private String name;
+
+ private String privKey;
+
+ private String pubKey;
+
+ private String encodePwd;
+
+ public UserKeys() {
+ }
+
+ public UserKeys(String name, String privKey, String pubKey, String encodePwd) {
+ this.name = name;
+ this.privKey = privKey;
+ this.pubKey = pubKey;
+ this.encodePwd = encodePwd;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getPrivKey() {
+ return privKey;
+ }
+
+ public void setPrivKey(String privKey) {
+ this.privKey = privKey;
+ }
+
+ public String getPubKey() {
+ return pubKey;
+ }
+
+ public void setPubKey(String pubKey) {
+ this.pubKey = pubKey;
+ }
+
+ public String getEncodePwd() {
+ return encodePwd;
+ }
+
+ public void setEncodePwd(String encodePwd) {
+ this.encodePwd = encodePwd;
+ }
+
+ public UserKeysVv toUserKeysVv() {
+ return new UserKeysVv(id, name, privKey, pubKey);
+ }
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/user/UserKeysVv.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/user/UserKeysVv.java
new file mode 100644
index 00000000..90eaae9c
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/user/UserKeysVv.java
@@ -0,0 +1,69 @@
+package com.jd.blockchain.ump.model.user;
+
+public class UserKeysVv {
+
+ public static final int PRIVKEY_HEADER_LENGTH = 4;
+
+ public static final int PRIVKEY_TAIL_LENGTH = 8;
+
+ public static final String PRIVKEY_HIDE_CONTENT = "******";
+
+ private int id;
+
+ private String name;
+
+ private String privKey;
+
+ private String pubKey;
+
+ public UserKeysVv() {
+ }
+
+ public UserKeysVv(int id, String name, String privKey, String pubKey) {
+ this.id = id;
+ this.name = name;
+ this.privKey = encodePrivKey(privKey);
+ this.pubKey = pubKey;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getPrivKey() {
+ return privKey;
+ }
+
+ public void setPrivKey(String privKey) {
+ this.privKey = privKey;
+ }
+
+ public String getPubKey() {
+ return pubKey;
+ }
+
+ public void setPubKey(String pubKey) {
+ this.pubKey = pubKey;
+ }
+
+ private String encodePrivKey(final String privKey) {
+ if (privKey != null && privKey.length() > (PRIVKEY_HEADER_LENGTH + PRIVKEY_TAIL_LENGTH)) {
+ return privKey.substring(0, PRIVKEY_HEADER_LENGTH) +
+ PRIVKEY_HIDE_CONTENT +
+ privKey.substring(privKey.length() - PRIVKEY_TAIL_LENGTH);
+ }
+ return privKey;
+ }
+}
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/web/ErrorCode.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/web/ErrorCode.java
new file mode 100644
index 00000000..ca023e05
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/web/ErrorCode.java
@@ -0,0 +1,20 @@
+package com.jd.blockchain.ump.model.web;
+
+/**
+ * 错误代码;
+ */
+public enum ErrorCode {
+
+ UNEXPECTED(5000),
+ ;
+
+ private int value;
+
+ ErrorCode(int value) {
+ this.value = value;
+ }
+
+ public int getValue() {
+ return value;
+ }
+}
\ No newline at end of file
diff --git a/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/web/WebResponse.java b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/web/WebResponse.java
new file mode 100644
index 00000000..29890518
--- /dev/null
+++ b/source/manager/ump-model/src/main/java/com/jd/blockchain/ump/model/web/WebResponse.java
@@ -0,0 +1,97 @@
+package com.jd.blockchain.ump.model.web;
+
+public class WebResponse {
+
+ private boolean success;
+
+ private T data;
+
+ private ErrorMessage error;
+
+ private WebResponse(){
+
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public T getData() {
+ return data;
+ }
+
+ public void setData(T data) {
+ this.data = data;
+ }
+
+ public ErrorMessage getError() {
+ return error;
+ }
+
+ public void setError(ErrorMessage error) {
+ this.error = error;
+ }
+
+ public static WebResponse createSuccessResult(Object data){
+ WebResponse responseResult = new WebResponse();
+ responseResult.setSuccess(true);
+ responseResult.setData(data);
+ return responseResult;
+ }
+
+ public static WebResponse createFailureResult(int code, String message){
+ ErrorMessage errorMessage = new ErrorMessage(code, message);
+ return createFailureResult(errorMessage);
+ }
+
+ public static WebResponse createFailureResult(ErrorMessage errorMessage){
+ WebResponse responseResult = new WebResponse();
+ responseResult.setSuccess(false);
+ responseResult.setError(errorMessage);
+ return responseResult;
+ }
+
+
+
+ /**
+ * 错误消息实体
+ *
+ * @author liuxrb
+ *
+ */
+ public static class ErrorMessage {
+
+ private int errorCode;
+
+ private String errorMessage;
+
+ public ErrorMessage() {
+
+ }
+
+ public ErrorMessage(int errorCode, String errorMessage) {
+ this.errorCode = errorCode;
+ this.errorMessage = errorMessage;
+ }
+
+ public int getErrorCode() {
+ return errorCode;
+ }
+
+ public void setErrorCode(int errorCode) {
+ this.errorCode = errorCode;
+ }
+
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ public void setErrorMessage(String errorMessage) {
+ this.errorMessage = errorMessage;
+ }
+ }
+}
diff --git a/source/manager/ump-service/pom.xml b/source/manager/ump-service/pom.xml
new file mode 100644
index 00000000..99b5f2c4
--- /dev/null
+++ b/source/manager/ump-service/pom.xml
@@ -0,0 +1,114 @@
+
+
+
+
+ manager
+ com.jd.blockchain
+ 1.1.0-SNAPSHOT
+
+ 4.0.0
+
+ ump-service
+
+ ump-service
+
+
+ UTF-8
+ 1.8
+ 1.8
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-logging
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-log4j2
+
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ true
+
+
+
+ com.jd.blockchain
+ crypto-classic
+ ${project.version}
+
+
+
+ com.jd.blockchain
+ crypto-sm
+ ${project.version}
+
+
+
+ com.jd.blockchain
+ tools-keygen
+ ${project.version}
+
+
+
+ com.alibaba
+ fastjson
+
+
+
+ commons-io
+ commons-io
+
+
+
+ commons-codec
+ commons-codec
+
+
+
+ com.jd.blockchain
+ ump-model
+ ${project.version}
+
+
+
+ org.reflections
+ reflections
+
+
+
+ org.apache.httpcomponents
+ httpclient
+
+
+
+ com.sun
+ tools
+ 1.8
+ system
+ ${project.basedir}/../ump-booter/libs/tools.jar
+
+
+
+ junit
+ junit
+ test
+
+
+
diff --git a/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/LedgerService.java b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/LedgerService.java
new file mode 100644
index 00000000..77c11016
--- /dev/null
+++ b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/LedgerService.java
@@ -0,0 +1,31 @@
+package com.jd.blockchain.ump.service;
+
+import com.jd.blockchain.ump.model.state.LedgerBindingConf;
+import com.jd.blockchain.ump.model.state.LedgerInited;
+
+import java.util.List;
+
+public interface LedgerService {
+
+ String randomSeed();
+
+ String currentCreateTime();
+
+ String ledgerInitCommand(String peerPath);
+
+ String peerStartCommand(String peerPath);
+
+ LedgerBindingConf allLedgerHashs(String peerPath);
+
+ LedgerBindingConf allLedgerHashs(long lastTime, String peerPath);
+
+ List allLedgerIniteds(String peerPath);
+
+ boolean dbExist(String peerPath, String ledgerHash);
+
+ String peerVerifyKey(String peerPath);
+
+ void save(String ledgerAndNodeKey, String ledgerHash);
+
+ String readLedgerHash(String ledgerAndNodeKey);
+}
diff --git a/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/LedgerServiceHandler.java b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/LedgerServiceHandler.java
new file mode 100644
index 00000000..f78aef42
--- /dev/null
+++ b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/LedgerServiceHandler.java
@@ -0,0 +1,310 @@
+package com.jd.blockchain.ump.service;
+
+
+import com.jd.blockchain.ump.dao.DBConnection;
+import com.jd.blockchain.ump.model.UmpConstant;
+import com.jd.blockchain.ump.model.state.LedgerBindingConf;
+import com.jd.blockchain.ump.model.state.LedgerInited;
+import org.apache.commons.codec.binary.Hex;
+import org.apache.commons.io.FileUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+@Service
+public class LedgerServiceHandler implements LedgerService {
+
+ private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ");
+
+ private static final String LEDGER_HASHS_FLAG = "ledger.bindings";
+
+ private static final String LEDGER_NAME_FORMAT = "binding.%s.name";
+
+ private static final String LEDGER_PARTI_ADDRESS_FORMAT = "binding.%s.parti.address";
+
+ private static final String LEDGER_PARTI_NAME_FORMAT = "binding.%s.parti.name";
+
+ private static final String LEDGER_DB_FORMAT = "binding.%s.db.uri";
+
+ private static final String FILE_PEER_FLAG = "deployment-peer";
+
+ private static final String JAR_SUFFIX = "jar";
+
+ private static final int SEED_BYTES_LENGTH = 32;
+
+ private static final int NAME_BYTES_LENGTH = 8;
+
+ private static final int SEED_PART_LENGTH = 8;
+
+ private static final Random LEDGER_RANDOM = new Random();
+
+ @Autowired
+ private UmpStateService umpStateService;
+
+ @Autowired
+ private DBConnection dbConnection;
+
+ @Override
+ public String randomSeed() {
+ byte[] seedBytes = new byte[SEED_BYTES_LENGTH];
+
+ LEDGER_RANDOM.nextBytes(seedBytes);
+
+ char[] seedChars = Hex.encodeHex(seedBytes);
+
+ StringBuilder sBuilder = new StringBuilder();
+
+ for (int i = 0; i < seedChars.length; i++) {
+ if (i != 0 && i % SEED_PART_LENGTH == 0) {
+ sBuilder.append("-");
+ }
+ sBuilder.append(seedChars[i]);
+ }
+
+ return sBuilder.toString();
+ }
+
+ @Override
+ public String currentCreateTime() {
+ return SDF.format(new Date());
+ }
+
+ @Override
+ public String ledgerInitCommand(String peerPath) {
+
+ return String.format(UmpConstant.CMD_LEDGER_INIT,
+ peerPath + UmpConstant.PATH_LEDGER_INIT_BIN);
+ }
+
+ @Override
+ public String peerStartCommand(String peerPath) {
+ return String.format(UmpConstant.CMD_START_UP_FORMAT,
+ peerPath + UmpConstant.PATH_STARTUP_BIN);
+ }
+
+ @Override
+ public LedgerBindingConf allLedgerHashs(String peerPath) {
+
+ return allLedgerHashs(0L, peerPath);
+ }
+
+ @Override
+ public LedgerBindingConf allLedgerHashs(long lastTime, String peerPath) {
+
+ // 读取LedgerBingConf文件,假设该文件不存在则返回空值
+ Set allLedgerHashs = new HashSet<>();
+
+ PropAndTime propAndTime = loadLedgerBindingConf(lastTime, peerPath);
+
+ Properties props = propAndTime.getProp();
+
+ if (props != null) {
+
+ String ledgerHashChars = props.getProperty(LEDGER_HASHS_FLAG);
+
+ if (ledgerHashChars != null && ledgerHashChars.length() > 0) {
+ String[] ledgerHashArray = ledgerHashChars.split(",");
+ if (ledgerHashArray.length > 0) {
+ for (String ledgerHash : ledgerHashArray) {
+ allLedgerHashs.add(ledgerHash.trim());
+ }
+ }
+ }
+ }
+
+ LedgerBindingConf ledgerBindingConf = new LedgerBindingConf(propAndTime.getLastTime());
+
+ ledgerBindingConf.setLedgerHashs(allLedgerHashs);
+
+ return ledgerBindingConf;
+ }
+
+ @Override
+ public List allLedgerIniteds(String peerPath) {
+
+ List ledgerIniteds = new ArrayList<>();
+
+ PropAndTime propAndTime = loadLedgerBindingConf(0L, peerPath);
+
+ Properties props = propAndTime.getProp();
+
+ if (props != null) {
+
+ String ledgerHashChars = props.getProperty(LEDGER_HASHS_FLAG);
+
+ Set ledgerHashSet = new HashSet<>();
+
+ if (ledgerHashChars != null && ledgerHashChars.length() > 0) {
+ String[] ledgerHashArray = ledgerHashChars.split(",");
+ if (ledgerHashArray.length > 0) {
+ for (String ledgerHash : ledgerHashArray) {
+ ledgerHashSet.add(ledgerHash.trim());
+ }
+ }
+ }
+
+ // 根据Hash值,遍历Prop
+ for (String hash : ledgerHashSet) {
+
+ LedgerInited ledgerInited = new LedgerInited(hash);
+
+ String ledgerName = props.getProperty(String.format(LEDGER_NAME_FORMAT, hash));
+
+ String partiAddress = props.getProperty(String.format(LEDGER_PARTI_ADDRESS_FORMAT, hash));
+
+ String partiName = props.getProperty(String.format(LEDGER_PARTI_NAME_FORMAT, hash));
+
+ String dbUri = props.getProperty(String.format(LEDGER_DB_FORMAT, hash));
+
+ ledgerIniteds.add(
+ ledgerInited
+ .buildLedgerName(ledgerName)
+ .buildPartiAddress(partiAddress)
+ .buildPartiName(partiName)
+ .buildDbUri(dbUri));
+ }
+ }
+ return ledgerIniteds;
+ }
+
+ @Override
+ public synchronized boolean dbExist(String peerPath, String ledgerHash) {
+ // 检查该账本对应的数据库是否存在
+
+ PropAndTime propAndTime = loadLedgerBindingConf(0L, peerPath);
+
+ // binding.j5faRYSqSqSRmSVgdmPsgq7Hzd1yP7yAGPWkTihekWms94.db.uri=rocksdb:///Users/shaozhuguang/Documents/ideaProjects/jdchain-patch/source/test/test-integration/rocks.db/rocksdb4.db
+ Properties props = propAndTime.getProp();
+
+ if (props != null) {
+ String dbKey = String.format(LEDGER_DB_FORMAT, ledgerHash);
+
+ String dbUri = props.getProperty(dbKey);
+
+ if (dbUri != null && dbUri.length() > 0) {
+
+ return dbConnection.exist(dbUri);
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public String peerVerifyKey(String peerPath) {
+ // 从libs中读取对应的Peer.jar的文件名称,配合全路径
+ File libsDirectory = new File(peerPath + UmpConstant.PATH_SYSTEM);
+
+ Collection jars = FileUtils.listFiles(libsDirectory, new String[]{JAR_SUFFIX}, false);
+
+ String peerVerifyKey = null;
+
+ if (!jars.isEmpty()) {
+ for (File jar : jars) {
+ String jarName = jar.getName();
+ if (jarName.startsWith(FILE_PEER_FLAG)) {
+ peerVerifyKey = jar.getPath();
+ break;
+ }
+ }
+ }
+
+ return peerVerifyKey;
+ }
+
+ @Override
+ public void save(String ledgerAndNodeKey, String ledgerHash) {
+ // 保存LedgerAndNodeKey与账本关系
+ umpStateService.saveLedgerHash(ledgerAndNodeKey, ledgerHash);
+ }
+
+ @Override
+ public String readLedgerHash(String ledgerAndNodeKey) {
+
+ return umpStateService.readLedgerHash(ledgerAndNodeKey);
+ }
+
+ private PropAndTime loadLedgerBindingConf(long lastTime, String peerPath) {
+
+ File ledgerBindingConf = new File(peerPath + UmpConstant.PATH_LEDGER_BINDING_CONFIG);
+
+ PropAndTime propAndTime = new PropAndTime(lastTime);
+
+ // 说明被修改过
+ if (ledgerBindingConf.exists() && ledgerBindingConf.lastModified() > lastTime) {
+
+ propAndTime.lastTime = ledgerBindingConf.lastModified();
+
+ try (InputStream inputStream = new FileInputStream(ledgerBindingConf)) {
+
+ Properties props = new Properties();
+
+ props.load(inputStream);
+
+ propAndTime.prop = props;
+
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ return propAndTime;
+ }
+
+ private static class PropAndTime {
+
+ private Properties prop;
+
+ private long lastTime;
+
+ public PropAndTime() {
+ }
+
+ public PropAndTime(long lastTime) {
+ this.lastTime = lastTime;
+ }
+
+ public Properties getProp() {
+ return prop;
+ }
+
+ public void setProp(Properties prop) {
+ this.prop = prop;
+ }
+
+ public long getLastTime() {
+ return lastTime;
+ }
+
+ public void setLastTime(long lastTime) {
+ this.lastTime = lastTime;
+ }
+ }
+
+// private Properties loadLedgerBindingConf(String peerPath) {
+//
+// File ledgerBindingConf = new File(peerPath + UmpConstant.PATH_LEDGER_BINDING_CONFIG);
+//
+// if (ledgerBindingConf.exists()) {
+//
+// try (InputStream inputStream = new FileInputStream(ledgerBindingConf)) {
+//
+// Properties props = new Properties();
+//
+// props.load(inputStream);
+//
+// return props;
+//
+// } catch (Exception e) {
+// throw new IllegalStateException(e);
+// }
+// }
+//
+// return null;
+// }
+}
diff --git a/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UmpService.java b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UmpService.java
new file mode 100644
index 00000000..08e1ee4a
--- /dev/null
+++ b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UmpService.java
@@ -0,0 +1,36 @@
+package com.jd.blockchain.ump.service;
+
+import com.jd.blockchain.ump.model.MasterAddr;
+import com.jd.blockchain.ump.model.PeerSharedConfigs;
+import com.jd.blockchain.ump.model.config.*;
+import com.jd.blockchain.ump.model.state.PeerInstallSchedules;
+import com.jd.blockchain.ump.model.state.PeerStartupSchedules;
+
+
+public interface UmpService {
+
+ PeerSharedConfigs loadPeerSharedConfigs(PeerLocalConfig sharedConfig);
+
+ LedgerConfig response(PeerSharedConfigs peerSharedConfigs, PeerLocalConfig localConfig);
+
+ String save(MasterAddr masterAddr, LedgerConfig ledgerConfig, PeerLocalConfig localConfig);
+
+ String ledgerAndNodeKey(LedgerConfig ledgerConfig, PeerSharedConfig sharedConfig);
+
+ PeerInstallSchedules install(LedgerIdentification identification, PeerLocalConfig localConfig, String ledgerAndNodeKey);
+
+ PeerInstallSchedules install(String ledgerAndNodeKey);
+
+ PeerInstallSchedules init(String ledgerAndNodeKey);
+
+ PeerInstallSchedules init(LedgerIdentification identification, PeerLocalConfig localConfig, String ledgerAndNodeKey);
+
+// PeerInstallSchedules startup(String ledgerAndNodeKey);
+
+ PeerStartupSchedules startup();
+
+ boolean stop(String ledgerAndNodeKey);
+
+ boolean stop();
+
+}
diff --git a/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UmpServiceHandler.java b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UmpServiceHandler.java
new file mode 100644
index 00000000..c17cc309
--- /dev/null
+++ b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UmpServiceHandler.java
@@ -0,0 +1,925 @@
+package com.jd.blockchain.ump.service;
+
+
+import com.jd.blockchain.ump.dao.DBConnection;
+import com.jd.blockchain.ump.dao.RocksDBConnection;
+import com.jd.blockchain.ump.model.MasterAddr;
+import com.jd.blockchain.ump.model.PeerSharedConfigs;
+import com.jd.blockchain.ump.model.UmpConstant;
+import com.jd.blockchain.ump.model.config.*;
+import com.jd.blockchain.ump.model.state.*;
+import com.jd.blockchain.ump.service.consensus.ConsensusService;
+import com.jd.blockchain.ump.util.Base58Utils;
+import com.jd.blockchain.ump.util.CommandUtils;
+import org.apache.commons.io.FileUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.Lock;
+
+@Service
+public class UmpServiceHandler implements UmpService {
+
+ private final Logger LOGGER = LoggerFactory.getLogger(getClass());
+
+ private static final String SUCCESS = "SUCCESS";
+
+ private static final String ROCKSDB_PROTOCOL = RocksDBConnection.ROCKSDB_PROTOCOL;
+
+ private static final int DB_SUFFIX_LENGTH = 4;
+
+ private static final Random DB_RANDOM = new Random();
+
+ private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyyMMddHHmmssSSS");//yyyy-MM-dd HH:mm:ss为目标的样式
+
+ private final Map ledgerConfigs = new ConcurrentHashMap<>();
+
+ private final Map masterConfigs = new ConcurrentHashMap<>();
+
+ private final Map peerShareds = new ConcurrentHashMap<>();
+
+ private final Map ledgerConfigMemory = new ConcurrentHashMap<>();
+
+ @Autowired
+ private ConsensusService consensusService;
+
+ @Autowired
+ private LedgerService ledgerService;
+
+ @Autowired
+ private DBConnection dbConnection;
+
+ @Autowired
+ private UmpStateService umpStateService;
+
+ @Override
+ public synchronized PeerSharedConfigs loadPeerSharedConfigs(PeerLocalConfig sharedConfig) {
+
+ String sharedKey = sharedConfig.getSharedKey();
+
+ PeerSharedConfigs peerSharedConfigs = peerShareds.get(sharedKey);
+
+ if (peerSharedConfigs == null) {
+ peerSharedConfigs = new PeerSharedConfigs();
+ peerShareds.put(sharedKey, peerSharedConfigs);
+ }
+
+ return peerSharedConfigs.addConfig(sharedConfig);
+ }
+
+ @Override
+ public LedgerConfig response(PeerSharedConfigs sharedConfigs, PeerLocalConfig localConfig) {
+ try {
+ // 对于Master和Peer处理方式不同
+ if (localConfig.getMasterConfig().isMaster()) {
+
+ // Master节点需要等待完成后通知其他线程
+ sharedConfigs.waitAndNotify();
+ } else {
+
+ // 等待Master节点通知
+ sharedConfigs.await();
+ }
+
+ // 此处需要防止并发
+ final String sharedKey = sharedConfigs.getSharedKey();
+
+ LedgerConfig savedLedgerConfig = ledgerConfigMemory.get(sharedKey);
+
+ if (savedLedgerConfig != null) {
+ return savedLedgerConfig;
+ }
+
+ // 获取当前对象锁(所有节点请求使用同一个对象)
+ final Lock lock = sharedConfigs.getLock();
+
+ lock.lock();
+
+ try {
+ // 执行到此表示获取到锁,此时需要判断是否有数据
+ // Double Check !!!
+ savedLedgerConfig = ledgerConfigMemory.get(sharedKey);
+
+ if (savedLedgerConfig != null) {
+ return savedLedgerConfig;
+ }
+
+ // 校验
+ verify(sharedConfigs);
+
+ // 所有数据到达之后生成返回的应答
+ LedgerInitConfig initConfig = sharedConfigs.ledgerInitConfig(
+ ledgerService.randomSeed(), ledgerService.currentCreateTime());
+
+ // 生成共识文件
+ String consensusConfig = consensusService.initConsensusConf(
+ sharedConfigs.getConsensusProvider(), sharedConfigs.getSharedConfigs());
+
+ LedgerConfig ledgerConfig = new LedgerConfig(initConfig, consensusConfig);
+
+ // 将本次LedgerKey信息写入数据库
+ String ledgerKey = initConfig.ledgerKey();
+
+ dbConnection.put(ledgerKey, ledgerConfig, LedgerConfig.class);
+
+ // 将节点的Key信息写入数据库
+ umpStateService.save(ledgerKey, sharedConfigKeys(ledgerKey, sharedConfigs));
+
+ // 将本地生成数据的信息写入数据库
+ LedgerMasterInstall masterInstall = sharedConfigs.toLedgerMasterInstall();
+
+ umpStateService.save(masterInstall);
+
+ // 将数据放入内存
+ ledgerConfigMemory.put(sharedKey, ledgerConfig);
+
+ return ledgerConfig;
+ } finally {
+ lock.unlock();
+ }
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @Override
+ public String save(MasterAddr masterAddr, LedgerConfig ledgerConfig, PeerLocalConfig localConfig) {
+
+ String ledgerAndNodeKey = ledgerAndNodeKey(ledgerConfig, localConfig);
+
+ ledgerConfigs.put(ledgerAndNodeKey, ledgerConfig);
+
+ // 保存本次需要发送的Master地址
+ masterConfigs.put(ledgerAndNodeKey, localConfig.getMasterConfig());
+
+ // 保存所有的信息至本地
+ umpStateService.save(ledgerAndNodeKey, localConfig);
+
+ // 保存当前同步信息至数据库
+ LedgerPeerInstall peerInstall = localConfig.toLedgerPeerInstall(ledgerConfig.getInitConfig().getNodeSize());
+
+ // init相关配置信息
+ peerInstall
+ .initKey(ledgerConfig.getInitConfig().ledgerKey(), ledgerAndNodeKey)
+ .initCreateTime(new Date())
+ .initMasterAddr(masterAddr);
+
+ // 写入数据库
+ umpStateService.save(peerInstall);
+
+ return ledgerAndNodeKey;
+ }
+
+ @Override
+ public String ledgerAndNodeKey(LedgerConfig ledgerConfig, PeerSharedConfig sharedConfig) {
+
+ return ledgerAndNodeKey(ledgerConfig.getInitConfig().ledgerKey(), sharedConfig);
+ }
+
+ @Override
+ public PeerInstallSchedules install(LedgerIdentification identification, PeerLocalConfig localConfig, String ledgerAndNodeKey) {
+
+ // 初始化Peer节点数据
+ PeerInstallSchedules installSchedules = init(identification, localConfig, ledgerAndNodeKey);
+
+ // Peer节点启动
+ peerStart(localConfig.getPeerPath(), installSchedules);
+
+ return installSchedules;
+ }
+
+ @Override
+ public PeerInstallSchedules install(String ledgerAndNodeKey) {
+
+ PeerLocalConfig localConfig = umpStateService.readConfig(ledgerAndNodeKey);
+
+ if (localConfig != null) {
+
+ // 获取LedgerIdentification
+ LedgerIdentification identification = umpStateService.readIdentification(ledgerAndNodeKey);
+
+ return install(identification, localConfig, ledgerAndNodeKey);
+ }
+ throw new IllegalStateException("Can not find LocalConfig from DataBase !!!");
+ }
+
+ @Override
+ public PeerInstallSchedules init(LedgerIdentification identification, PeerLocalConfig localConfig, String ledgerAndNodeKey) {
+
+ PeerInstallSchedules installSchedules = new PeerInstallSchedules(identification);
+
+ MasterAddr masterAddr = loadMaster(localConfig);
+
+ LedgerConfig ledgerConfig = ledgerConfigs.get(ledgerAndNodeKey);
+
+ if (ledgerConfig == null || ledgerConfig.getInitConfig() == null) {
+ saveInstallSchedule(installSchedules, masterAddr, "", ledgerAndNodeKey,
+ String.format("Ledger Key = [%s] can not find Ledger-Config !!!", ledgerAndNodeKey),
+ ScheduleState.LOAD_FAIL);
+ throw new IllegalStateException(String.format("Ledger Key = [%s] can not find Ledger-Config !!!", ledgerAndNodeKey));
+ }
+
+ LedgerInitConfig initConfig = ledgerConfig.getInitConfig();
+
+ String ledgerKey = initConfig.ledgerKey();
+
+ List localConfContents, ledgerInitContents;
+
+ try {
+ saveInstallSchedule(installSchedules, masterAddr, ledgerKey, ledgerAndNodeKey,
+ String.format("Find LedgerConfig from Memory for Key [%s] -> %s", ledgerAndNodeKey, SUCCESS),
+ ScheduleState.LOAD);
+
+ // 首先获取当前节点的ID
+ int nodeId = initConfig.nodeId(localConfig.getPubKey());
+
+ // 生成local.conf文件内容
+ localConfContents = localConfContents(localConfig, nodeId);
+
+ saveInstallSchedule(installSchedules, masterAddr, ledgerKey, ledgerAndNodeKey,
+ String.format("Init Local.Conf's Content -> %s", SUCCESS),
+ ScheduleState.LOAD);
+
+ // 生成LedgerInit内容
+ ledgerInitContents = initConfig.toConfigChars(localConfig.consensusConfPath());
+
+ saveInstallSchedule(installSchedules, masterAddr, ledgerKey, ledgerAndNodeKey,
+ String.format("Init Ledger.Init's Content -> %s", SUCCESS),
+ ScheduleState.LOAD);
+ } catch (Exception e) {
+ saveInstallSchedule(installSchedules, masterAddr, ledgerKey, ledgerAndNodeKey,
+ "Load Config's Content !!!",
+ ScheduleState.LOAD_FAIL);
+ throw new IllegalStateException(e);
+ }
+
+ saveInstallSchedule(installSchedules, masterAddr, ledgerKey, ledgerAndNodeKey,
+ "Load Config's Content !!!",
+ ScheduleState.LOAD_SUCCESS);
+
+ try {
+ // 将该文件内容写入Local.Conf
+ forceWrite(localConfContents, new File(localConfig.localConfPath()));
+
+ saveInstallSchedule(installSchedules, masterAddr, ledgerKey, ledgerAndNodeKey,
+ String.format("Write And Backup File local.conf -> %s", SUCCESS),
+ ScheduleState.WRITE);
+
+ // 将文件内容写入Ledger-Init
+ forceWrite(ledgerInitContents, new File(localConfig.ledgerInitConfPath()));
+
+ saveInstallSchedule(installSchedules, masterAddr, ledgerKey, ledgerAndNodeKey,
+ String.format("Write And Backup File ledger.init -> %s", SUCCESS),
+ ScheduleState.WRITE);
+
+ // 将共识内容写入文件,例如bftsmart.conf
+ String consensusFileName = writeConsensusContent(ledgerConfig.getConsensusConfig(),
+ new File(localConfig.consensusConfPath()));
+
+ saveInstallSchedule(installSchedules, masterAddr, ledgerKey, ledgerAndNodeKey,
+ String.format("Write And Backup Consensus File %s -> %s", consensusFileName, SUCCESS),
+ ScheduleState.WRITE);
+
+ } catch (Exception e) {
+ saveInstallSchedule(installSchedules, masterAddr, ledgerKey, ledgerAndNodeKey,
+ "Write Config's Content to Config File !!!",
+ ScheduleState.WRITE_FAIL);
+ throw new IllegalStateException(e);
+ }
+
+ saveInstallSchedule(installSchedules, masterAddr, ledgerKey, ledgerAndNodeKey,
+ "Write Config's Content to Config File !!!",
+ ScheduleState.WRITE_SUCCESS);
+
+ // 账本初始化
+ String ledgerHash = ledgerInit(localConfig.getPeerPath(), installSchedules, masterAddr, ledgerKey, ledgerAndNodeKey);
+
+ // 设置账本Hash
+ installSchedules.setLedgerHash(ledgerHash);
+
+ return installSchedules;
+ }
+
+ @Override
+ public PeerInstallSchedules init(String ledgerAndNodeKey) {
+
+ PeerLocalConfig localConfig = umpStateService.readConfig(ledgerAndNodeKey);
+
+ if (localConfig != null) {
+
+ // 获取LedgerIdentification
+ LedgerIdentification identification = umpStateService.readIdentification(ledgerAndNodeKey);
+
+ return init(identification, localConfig, ledgerAndNodeKey);
+ }
+ throw new IllegalStateException("Can not find LocalConfig from DataBase !!!");
+ }
+
+
+// @Override
+// public PeerInstallSchedules startup(String ledgerAndNodeKey) {
+//
+// PeerLocalConfig localConfig = umpStateService.readConfig(ledgerAndNodeKey);
+//
+// if (localConfig != null) {
+//
+// PeerInstallSchedules installSchedules = umpStateService.loadState(ledgerAndNodeKey);
+//
+// // Peer节点启动
+// return peerStart(localConfig.getPeerPath(), installSchedules);
+//
+// }
+// throw new IllegalStateException("Can not find LocalConfig from DataBase !!!");
+// }
+
+ @Override
+ public PeerStartupSchedules startup() {
+
+ PeerStartupSchedules startupSchedules = new PeerStartupSchedules(UmpConstant.PROJECT_PATH);
+
+ return peerStart(startupSchedules);
+ }
+
+ @Override
+ public boolean stop(String ledgerAndNodeKey) {
+ PeerLocalConfig localConfig = umpStateService.readConfig(ledgerAndNodeKey);
+
+ if (localConfig != null) {
+
+ // Peer节点停止
+ return peerStop(localConfig.getPeerPath());
+ }
+ throw new IllegalStateException("Can not find LocalConfig from DataBase !!!");
+ }
+
+ @Override
+ public boolean stop() {
+
+ return peerStop(UmpConstant.PROJECT_PATH);
+ }
+
+ private MasterAddr loadMaster(PeerLocalConfig localConfig) {
+
+ // 开始安装之后则可以将内存中的数据释放
+ String sharedKey = localConfig.getSharedKey();
+
+ if (sharedKey != null) {
+ ledgerConfigMemory.remove(sharedKey);
+ }
+
+ if (localConfig.master()) {
+ return null;
+ }
+
+ return localConfig.masterAddr();
+ }
+
+ private List sharedConfigKeys(String ledgerKey, PeerSharedConfigs sharedConfigs) {
+
+ List sharedConfigKeys = new ArrayList<>();
+
+ List pscs = sharedConfigs.getSharedConfigs();
+
+ for(PeerSharedConfig psc : pscs) {
+ sharedConfigKeys.add(ledgerAndNodeKey(ledgerKey, psc));
+ }
+
+ return sharedConfigKeys;
+ }
+
+ private String ledgerAndNodeKey(String ledgerKey, PeerSharedConfig sharedConfig) {
+
+ return ledgerKey + "-" + sharedConfig.getName();
+ }
+
+ private String ledgerInit(String peerPath, PeerInstallSchedules installSchedules, MasterAddr masterAddr, String ledgerKey, String ledgerAndNodeKey) {
+
+ String newLedgerHash = "";
+
+ saveInstallSchedule(installSchedules, masterAddr, ledgerKey, ledgerAndNodeKey,
+ "Steps to start processing LedgerInit !!!",
+ ScheduleState.INIT);
+
+ // 获取当前已经存在的Ledger列表
+ LedgerBindingConf ledgerBindingConf = ledgerService.allLedgerHashs(peerPath);
+
+ Set currentLedgerHashs = ledgerBindingConf.getLedgerHashs();
+
+ long lastTime = ledgerBindingConf.getLastTime();
+
+ saveInstallSchedule(installSchedules, masterAddr, ledgerKey, ledgerAndNodeKey,
+ String.format("Find History Ledger's Size = %s", currentLedgerHashs.size()),
+ ScheduleState.INIT);
+
+ String ledgerInitCommand = ledgerService.ledgerInitCommand(peerPath);
+
+ try {
+
+ LOGGER.info("Execute Ledger-Init's Shell {}", ledgerInitCommand);
+
+ Process ledgerInitProcess;
+
+ try {
+ // 调用ledgerInit初始化脚本
+ ledgerInitProcess = CommandUtils.execute(CommandUtils.toCommandList(ledgerInitCommand));
+
+ saveInstallSchedule(installSchedules, masterAddr, ledgerKey, ledgerAndNodeKey,
+ String.format("Execute LedgerInit's Command -> %s", SUCCESS),
+ ScheduleState.INIT);
+ } catch (Exception e) {
+ LOGGER.error("Execute Ledger-Init's Shell !!!", e);
+ throw new IllegalStateException(e);
+ }
+
+ int maxSize = 512;
+
+ boolean isInitSuccess = false;
+
+ int checkIndex = 1;
+
+ while (maxSize > 0) {
+ // 时延
+ Thread.sleep(6000);
+
+ saveInstallSchedule(installSchedules, masterAddr, ledgerKey, ledgerAndNodeKey,
+ String.format("%s Check LedgerInit's Status ...... ", checkIndex++),
+ ScheduleState.INIT);
+
+ // 检查账本是否增加
+ CurrentLedger currentLedger = checkNewLedger(lastTime, peerPath, currentLedgerHashs);
+
+ lastTime = currentLedger.getLastTime();
+
+ newLedgerHash = currentLedger.getLedgerHash();
+
+ if (newLedgerHash != null && newLedgerHash.length() > 0) {
+ isInitSuccess = true;
+ saveInstallSchedule(installSchedules, masterAddr, ledgerKey, ledgerAndNodeKey,
+ String.format("Find New Ledger = %s", newLedgerHash),
+ ScheduleState.INIT);
+ break;
+ }
+ maxSize --;
+ }
+
+ // 完成后,不管是否处理完,都将命令停止
+ // 为防止其他应用仍在访问,延时6秒停止
+ try {
+ Thread.sleep(6000);
+ ledgerInitProcess = ledgerInitProcess.destroyForcibly();
+ if (ledgerInitProcess.isAlive()) {
+ // 再尝试一次
+ ledgerInitProcess.destroyForcibly();
+ }
+ } catch (Exception e) {
+ // 暂时打印日志
+ LOGGER.error("Stop Ledger Init Command !!!", e);
+ }
+
+ // 再次判断是否初始化账本成功
+ if (newLedgerHash == null) {
+
+ CurrentLedger currentLedger = checkNewLedger(lastTime, peerPath, currentLedgerHashs);
+
+ newLedgerHash = currentLedger.getLedgerHash();
+
+ if (newLedgerHash != null && newLedgerHash.length() > 0) {
+ isInitSuccess = true;
+ saveInstallSchedule(installSchedules, masterAddr, ledgerKey, ledgerAndNodeKey,
+ String.format("Final Find New Ledger = %s", newLedgerHash),
+ ScheduleState.INIT);
+ }
+ }
+
+ if (!isInitSuccess) {
+ // 失败则抛出异常
+ throw new IllegalStateException("Can Not Find New Ledger !!!");
+ }
+ } catch (Exception e) {
+ saveInstallSchedule(installSchedules, masterAddr, ledgerKey, ledgerAndNodeKey,
+ "Execute Ledger-Init Command Fail !!!",
+ ScheduleState.INIT_FAIL);
+ LOGGER.error("Execute Ledger-Init Command Fail !!!", e);
+ throw new IllegalStateException(e);
+ }
+
+ saveInstallSchedule(installSchedules, masterAddr, ledgerKey, ledgerAndNodeKey,
+ String.format("Steps to processing LedgerInit -> %s", SUCCESS),
+ ScheduleState.INIT_SUCCESS);
+
+ // 将账本Hash写入数据库
+ ledgerService.save(ledgerAndNodeKey, newLedgerHash);
+
+ return newLedgerHash;
+ }
+
+ private CurrentLedger checkNewLedger(long lastTime, String peerPath, Set currentLedgerHashs) {
+ // 再次判断是否初始化账本成功
+ LedgerBindingConf ledgerBindingConf = ledgerService.allLedgerHashs(lastTime, peerPath);
+
+ Set newLedgerHashs = ledgerBindingConf.getLedgerHashs();
+
+ CurrentLedger currentLedger = new CurrentLedger(ledgerBindingConf.getLastTime());
+
+ if (newLedgerHashs.size() > currentLedgerHashs.size()) {
+ // 获取其新安装的LedgerHash
+ for (String ledgerHash : newLedgerHashs) {
+ if (!currentLedgerHashs.contains(ledgerHash)) {
+ // 新获取的LedgerHash为当前值
+ currentLedger.ledgerHash = ledgerHash;
+ break;
+ }
+ }
+ }
+ return currentLedger;
+ }
+
+
+ private PeerInstallSchedules peerStart(String peerPath, PeerInstallSchedules installSchedules) {
+
+ saveInstallSchedule(installSchedules,
+ "Steps to start processing PeerNodeStart !!!",
+ ScheduleState.STARTUP_START);
+ // 启动Peer
+ // 说明初始化成功
+ // 判断是否需要启动Peer
+ String peerVerify = ledgerService.peerVerifyKey(peerPath);
+
+ try {
+ if (!CommandUtils.isActive(peerVerify)) {
+ // 不存在,则需要再启动
+ String peerStartCmd = ledgerService.peerStartCommand(peerPath);
+
+ LOGGER.info("Execute Peer-Startup's Shell {}", peerStartCmd);
+
+ if (!CommandUtils.executeAndVerify(CommandUtils.toCommandList(peerStartCmd), peerVerify)) {
+ // Peer节点启动失败
+ throw new IllegalStateException("Peer Node Start UP Fail !!!");
+ }
+ saveInstallSchedule(installSchedules,
+ String.format("Peer's process %s start -> %s", peerVerify, SUCCESS),
+ ScheduleState.STARTUP_SUCCESS);
+ } else {
+ // 命令已经存在
+ saveInstallSchedule(installSchedules,
+ String.format("Peer's process is exist -> %s", peerVerify),
+ ScheduleState.NO_STARTUP);
+ }
+ } catch (Exception e) {
+ saveInstallSchedule(installSchedules,
+ e.getMessage(),
+ ScheduleState.STARTUP_FAIL);
+ throw new IllegalStateException(e);
+ }
+
+ saveInstallSchedule(installSchedules,
+ "Steps to start processing PeerNodeStart over !!!",
+ ScheduleState.STARTUP_OVER);
+
+ return installSchedules;
+ }
+
+ private PeerStartupSchedules peerStart(PeerStartupSchedules startupSchedules) {
+
+ String peerPath = startupSchedules.getPeerPath();
+
+ saveStartupSchedules(startupSchedules,
+ "Steps to start processing PeerNodeStart !!!",
+ ScheduleState.STARTUP_START);
+ // 启动Peer
+ // 说明初始化成功
+ // 判断是否需要启动Peer
+ String peerVerify = ledgerService.peerVerifyKey(peerPath);
+
+ try {
+ if (!CommandUtils.isActive(peerVerify)) {
+ // 不存在,则需要再启动
+ String peerStartCmd = ledgerService.peerStartCommand(peerPath);
+
+ LOGGER.info("Execute Peer-Startup's Shell {}", peerStartCmd);
+
+ if (!CommandUtils.executeAndVerify(CommandUtils.toCommandList(peerStartCmd), peerVerify)) {
+ // Peer节点启动失败
+ throw new IllegalStateException("Peer Node Start UP Fail !!!");
+ }
+ saveStartupSchedules(startupSchedules,
+ String.format("Peer's process %s start -> %s", peerVerify, SUCCESS),
+ ScheduleState.STARTUP_SUCCESS);
+ } else {
+ // 命令已经存在
+ saveStartupSchedules(startupSchedules,
+ String.format("Peer's process is exist -> %s", peerVerify),
+ ScheduleState.NO_STARTUP);
+ }
+ } catch (Exception e) {
+ saveStartupSchedules(startupSchedules,
+ e.getMessage(),
+ ScheduleState.STARTUP_FAIL);
+ throw new IllegalStateException(e);
+ }
+
+ saveStartupSchedules(startupSchedules,
+ "Steps to start processing PeerNodeStart over !!!",
+ ScheduleState.STARTUP_OVER);
+
+ return startupSchedules;
+ }
+
+// private PeerInstallSchedules peerStart(String peerPath, PeerInstallSchedules installSchedules) {
+//
+// MasterAddr masterAddr = installSchedules.getIdentification().getMasterAddr();
+//
+// String ledgerKey = installSchedules.getIdentification().getLedgerKey();
+//
+// String ledgerAndNodeKey = installSchedules.getIdentification().getLedgerAndNodeKey();
+//
+// saveInstallSchedule(installSchedules, masterAddr, ledgerKey, ledgerAndNodeKey,
+// "Steps to start processing PeerNodeStart !!!",
+// ScheduleState.STARTUP_START);
+// // 启动Peer
+// // 说明初始化成功
+// // 判断是否需要启动Peer
+// String peerVerify = ledgerService.peerVerifyKey(peerPath);
+//
+// try {
+// if (!CommandUtils.isActive(peerVerify)) {
+// // 不存在,则需要再启动
+// String peerStartCmd = ledgerService.peerStartCommand(peerPath);
+//
+// LOGGER.info("Execute Peer-Startup's Shell {}", peerStartCmd);
+//
+// if (!CommandUtils.executeAndVerify(CommandUtils.toCommandList(peerStartCmd), peerVerify)) {
+// // Peer节点启动失败
+// throw new IllegalStateException("Peer Node Start UP Fail !!!");
+// }
+// saveInstallSchedule(installSchedules, masterAddr, ledgerKey, ledgerAndNodeKey,
+// String.format("Peer's process %s start -> %s", peerVerify, SUCCESS),
+// ScheduleState.STARTUP_SUCCESS);
+// } else {
+// // 命令已经存在
+// saveInstallSchedule(installSchedules, masterAddr, ledgerKey, ledgerAndNodeKey,
+// String.format("Peer's process is exist -> %s", peerVerify),
+// ScheduleState.NO_STARTUP);
+// }
+// } catch (Exception e) {
+// saveInstallSchedule(installSchedules, masterAddr, ledgerKey, ledgerAndNodeKey,
+// e.getMessage(),
+// ScheduleState.STARTUP_FAIL);
+// throw new IllegalStateException(e);
+// }
+//
+// saveInstallSchedule(installSchedules, masterAddr, ledgerKey, ledgerAndNodeKey,
+// "Steps to start processing PeerNodeStart over !!!",
+// ScheduleState.STARTUP_OVER);
+//
+// return installSchedules;
+// }
+
+ private boolean peerStop(String peerPath) {
+
+ // 判断是否需要停止Peer
+ String peerVerify = ledgerService.peerVerifyKey(peerPath);
+
+ try {
+ if (CommandUtils.isActive(peerVerify)) {
+
+ LOGGER.info("We need stop peer {}", peerVerify);
+ // 需要停止Peer节点
+ CommandUtils.killVm(peerVerify);
+
+ // 最多循环5次进行判断
+ int maxSize = 5;
+
+ while (maxSize > 0) {
+ try {
+ Thread.sleep(3000);
+ if (!CommandUtils.isActive(peerVerify)) {
+ return true;
+ }
+ } catch (Exception e) {
+ LOGGER.error("Check Peer Stop State !!!", e);
+ } finally {
+ maxSize--;
+ }
+ }
+ } else {
+ LOGGER.info("We do not need stop peer {}", peerVerify);
+ return false;
+ }
+ } catch (Exception e) {
+ LOGGER.error("Stop Peer Node", e);
+ throw new IllegalStateException(e);
+ }
+ return false;
+ }
+
+ private String writeConsensusContent(String consensusContent, File consensusFile) throws IOException {
+ // 将字符串转换为字节数组
+ byte[] consensusBytes = Base58Utils.decode(consensusContent);
+ forceWrite(consensusBytes, consensusFile);
+ return consensusFile.getName();
+ }
+
+ private void forceWrite(List lines, File file) throws IOException {
+ if (file.exists()) {
+ FileUtils.moveFile(file, new File(file.getPath() + "_bak_" + currentDate()));
+ }
+
+ FileUtils.writeLines(file, StandardCharsets.UTF_8.toString(), lines);
+ }
+
+ private void forceWrite(byte[] content, File file) throws IOException {
+ if (file.exists()) {
+ FileUtils.moveFile(file, new File(file.getPath() + "_bak_" + currentDate()));
+ }
+
+ FileUtils.writeByteArrayToFile(file, content);
+ }
+
+ private void verify(PeerSharedConfigs peerSharedConfigs) {
+ // 校验其中内容
+ List sharedConfigs = peerSharedConfigs.getSharedConfigs();
+
+ // 首先保证其中的数据一致性
+ // 1、name不能重复;
+ // 2、pubKey不能重复;
+ // 3、ipAddr + initPort不能重复;
+
+ Set nameSet = new HashSet<>(),
+ pubKeySet = new HashSet<>(),
+ addrSet = new HashSet<>();
+
+ for (PeerSharedConfig sharedConfig : sharedConfigs) {
+ String name = sharedConfig.getName(),
+ pubKey = sharedConfig.getPubKey(),
+ addr = sharedConfig.addr();
+ if (nameSet.contains(name)) {
+ throw new IllegalStateException(String.format("Name [%s] is Conflict !!!", name));
+ } else {
+ nameSet.add(name);
+ }
+
+ if (pubKeySet.contains(pubKey)) {
+ throw new IllegalStateException(String.format("PubKey [%s] is Conflict !!!", pubKey));
+ } else {
+ pubKeySet.add(pubKey);
+ }
+
+ if (addrSet.contains(addr)) {
+ throw new IllegalStateException(String.format("Address [%s] is Conflict !!!", addr));
+ } else {
+ addrSet.add(addr);
+ }
+ }
+ }
+
+ private void saveInstallSchedule(PeerInstallSchedules installSchedules, MasterAddr masterAddr, String ledgerKey, String ledgerAndNodeKey, String content, ScheduleState state) {
+
+ // 日志打印相关内容
+ LOGGER.info(content);
+
+ // 生成InstallSchedule对象
+ InstallSchedule schedule = installSchedule(ledgerKey, ledgerAndNodeKey, content, state);
+
+ // 加入反馈列表
+ installSchedules.addInstallSchedule(
+ new PeerInstallSchedule(new InstallProcess(content), state));
+
+ // 将InstallSchedule写入数据库
+ umpStateService.save(schedule, masterAddr);
+ }
+
+ private void saveInstallSchedule(PeerInstallSchedules installSchedules, String content, ScheduleState state) {
+
+ // 日志打印相关内容
+ LOGGER.info(content);
+
+ // 加入反馈列表
+ installSchedules.addInstallSchedule(
+ new PeerInstallSchedule(new InstallProcess(content), state));
+ }
+
+ private void saveStartupSchedules(PeerStartupSchedules startupSchedules, String content, ScheduleState state) {
+
+ // 日志打印相关内容
+ LOGGER.info(content);
+
+ // 加入反馈列表
+ startupSchedules.addInstallSchedule(
+ new PeerInstallSchedule(new InstallProcess(content), state));
+ }
+
+ private InstallSchedule installSchedule(String ledgerKey, String ledgerAndNodeKey, String content, ScheduleState state) {
+
+ InstallProcess process = new InstallProcess(content);
+
+ return new InstallSchedule(ledgerKey, ledgerAndNodeKey, process, state);
+
+ }
+
+ private List localConfContents(PeerLocalConfig localConfig, int nodeId) {
+ /**
+ * #当前参与方的 id,与ledger.init文件中cons_parti.id一致,默认从0开始
+ * local.parti.id=0
+ *
+ * #当前参与方的公钥
+ * local.parti.pubkey=
+ *
+ * #当前参与方的私钥(密文编码)
+ * local.parti.privkey=
+ *
+ * #当前参与方的私钥解密密钥(原始口令的一次哈希,Base58格式),如果不设置,则启动过程中需要从控制台输入
+ * local.parti.pwd=
+ *
+ * #账本初始化完成后生成的"账本绑定配置文件"的输出目录
+ * #推荐使用绝对路径,相对路径以当前文件(local.conf)所在目录为基准
+ * ledger.binding.out=../
+ *
+ * #账本数据库的连接字符
+ * #rocksdb数据库连接格式:rocksdb://{path},例如:rocksdb:///export/App08/peer/rocks.db/rocksdb0.db
+ * #redis数据库连接格式:redis://{ip}:{prot}/{db},例如:redis://127.0.0.1:6379/0
+ * ledger.db.uri=
+ *
+ * #账本数据库的连接口令
+ * ledger.db.pwd=
+ */
+
+ List localContents = new ArrayList<>();
+
+ localContents.add(valueToConfig(UmpConstant.LOCAL_PARTI_ID_PREFIX, nodeId));
+
+ localContents.add(valueToConfig(UmpConstant.LOCAL_PARTI_PUBKEY_PREFIX, localConfig.getPubKey()));
+
+ localContents.add(valueToConfig(UmpConstant.LOCAL_PARTI_PRIVKEY_PREFIX, localConfig.getPrivKey()));
+
+ localContents.add(valueToConfig(UmpConstant.LOCAL_PARTI_PWD_PREFIX, localConfig.getEncodePwd()));
+
+ localContents.add(valueToConfig(UmpConstant.LEDGER_BINDING_OUT_PREFIX, localConfig.bindingOutPath()));
+
+ localContents.add(valueToConfig(UmpConstant.LEDGER_DB_URI_PREFIX, dbUri(localConfig.getDbName(), localConfig.getPeerPath())));
+
+ localContents.add(valueToConfig(UmpConstant.LEDGER_DB_PWD_PREFIX, ""));
+
+ return localContents;
+ }
+
+ private String valueToConfig(String prefix, Object value) {
+ return prefix + "=" + value;
+ }
+
+ private String currentDate() {
+ return SDF.format(new Date());
+ }
+
+ private String dbUri(final String dbName, final String peerPath) {
+
+ String dbDirectoryPath = peerPath + File.separator + dbName;
+
+ String dbUri = ROCKSDB_PROTOCOL + dbDirectoryPath;
+
+ File dbDirectory = new File(dbDirectoryPath);
+
+ if (!dbDirectory.exists()) {
+ return dbUri;
+ }
+ throw new IllegalStateException(String.format("DB name = %s, path = %s is Exist !!!", dbName, dbDirectoryPath));
+ }
+
+ private static class CurrentLedger {
+
+ private String ledgerHash;
+
+ private long lastTime;
+
+ public CurrentLedger() {
+ }
+
+ public CurrentLedger(long lastTime) {
+ this.lastTime = lastTime;
+ }
+
+ public String getLedgerHash() {
+ return ledgerHash;
+ }
+
+ public void setLedgerHash(String ledgerHash) {
+ this.ledgerHash = ledgerHash;
+ }
+
+ public long getLastTime() {
+ return lastTime;
+ }
+
+ public void setLastTime(long lastTime) {
+ this.lastTime = lastTime;
+ }
+ }
+}
diff --git a/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UmpSimulateService.java b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UmpSimulateService.java
new file mode 100644
index 00000000..c6c8ea82
--- /dev/null
+++ b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UmpSimulateService.java
@@ -0,0 +1,17 @@
+package com.jd.blockchain.ump.service;
+
+import com.jd.blockchain.ump.model.config.PeerLocalConfig;
+import com.jd.blockchain.ump.model.config.PeerSharedConfigVv;
+import com.jd.blockchain.ump.model.user.UserKeys;
+import com.jd.blockchain.ump.model.user.UserKeysVv;
+
+public interface UmpSimulateService {
+
+ UserKeysVv userKeysVv(int nodeId);
+
+ UserKeys userKeys(int nodeId);
+
+ PeerLocalConfig nodePeerLocalConfig(int nodeId, boolean isMaster);
+
+ PeerSharedConfigVv peerSharedConfigVv(int nodeId, boolean isMaster);
+}
diff --git a/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UmpSimulateServiceHandler.java b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UmpSimulateServiceHandler.java
new file mode 100644
index 00000000..3bfb20bf
--- /dev/null
+++ b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UmpSimulateServiceHandler.java
@@ -0,0 +1,134 @@
+package com.jd.blockchain.ump.service;
+
+import com.jd.blockchain.ump.model.config.PeerLocalConfig;
+import com.jd.blockchain.ump.model.config.PeerSharedConfigVv;
+import com.jd.blockchain.ump.model.user.UserKeys;
+import com.jd.blockchain.ump.model.user.UserKeysVv;
+import com.jd.blockchain.ump.service.consensus.providers.BftsmartConsensusProvider;
+import org.apache.commons.codec.binary.Hex;
+import org.springframework.stereotype.Service;
+
+import java.util.Random;
+
+@Service
+public class UmpSimulateServiceHandler implements UmpSimulateService {
+
+ private static final Random RANDOM_ROCKSDB = new Random();
+
+ private static final String SHARED_KEY = "JDChain";
+
+ private static final int TOTAL_SIZE = 4;
+
+ private static final String LOCALHOST = "127.0.0.1";
+
+ private static final String CONSENSUS_PROVIDER = BftsmartConsensusProvider.BFTSMART_PROVIDER;
+
+ private static final String CONSENSUS_CONF = BftsmartConsensusProvider.BFTSMART_CONFIG_FILE;
+
+ private static final int INIT_PORT_START = 9000;
+
+ private static final String[] PUBKEYS = new String[]{
+ "3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9",
+ "3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX",
+ "3snPdw7i7PZi6TStiyc6mzjprnNhgs2atSGNS8wPYzhbKaUWGFJt7x",
+ "3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk"};
+
+ private static final String[] PRIVKEYS = new String[]{
+ "177gjzHTznYdPgWqZrH43W3yp37onm74wYXT4v9FukpCHBrhRysBBZh7Pzdo5AMRyQGJD7x",
+ "177gju9p5zrNdHJVEQnEEKF4ZjDDYmAXyfG84V5RPGVc5xFfmtwnHA7j51nyNLUFffzz5UT",
+ "177gjtwLgmSx5v1hFb46ijh7L9kdbKUpJYqdKVf9afiEmAuLgo8Rck9yu5UuUcHknWJuWaF",
+ "177gk1pudweTq5zgJTh8y3ENCTwtSFsKyX7YnpuKPo7rKgCkCBXVXh5z2syaTCPEMbuWRns"};
+
+ private static final String ENCODE_PWD = "DYu3G8aGTMBW1WrTw76zxQJQU4DHLw9MLyy7peG4LKkY";
+
+ private static final String BINDING_OUT = "../";
+
+ private static final String[] DB_URIS = new String[]{
+ "rocksdb:///Users/shaozhuguang/Documents/simulate/peer0/rocksdb",
+ "rocksdb:///Users/shaozhuguang/Documents/simulate/peer1/rocksdb",
+ "rocksdb:///Users/shaozhuguang/Documents/simulate/peer2/rocksdb",
+ "rocksdb:///Users/shaozhuguang/Documents/simulate/peer3/rocksdb"};
+
+ private static final String DB_PWD = "";
+
+ private static final String DB_NAME = "rocksdb_";
+
+ private static final String[] PEER_PATHS = new String[]{
+ "/Users/shaozhuguang/Documents/simulate/peer0",
+ "/Users/shaozhuguang/Documents/simulate/peer1",
+ "/Users/shaozhuguang/Documents/simulate/peer2",
+ "/Users/shaozhuguang/Documents/simulate/peer3"};
+
+ private static final String[] CONSENSUS_NODES = new String[]{
+ "127.0.0.1:6000",
+ "127.0.0.1:6010",
+ "127.0.0.1:6020",
+ "127.0.0.1:6030"};
+
+
+ @Override
+ public UserKeysVv userKeysVv(int nodeId) {
+
+ UserKeys userKeys = userKeys(nodeId);
+
+ return userKeys.toUserKeysVv();
+ }
+
+ @Override
+ public UserKeys userKeys(int nodeId) {
+
+ return new UserKeys("Peer-" + nodeId, PRIVKEYS[nodeId], PUBKEYS[nodeId], ENCODE_PWD);
+ }
+
+ @Override
+ public PeerLocalConfig nodePeerLocalConfig(int nodeId, boolean isMaster) {
+
+ UserKeys userKeys = userKeys(nodeId);
+
+ return peerSharedConfigVv(nodeId, isMaster).toPeerLocalConfig(userKeys);
+ }
+
+ @Override
+ public PeerSharedConfigVv peerSharedConfigVv(int nodeId, boolean isMaster) {
+
+ PeerSharedConfigVv sharedConfigVv = new PeerSharedConfigVv();
+
+ sharedConfigVv.setSharedKey(SHARED_KEY);
+ sharedConfigVv.setName(SHARED_KEY + "-" + nodeId);
+ sharedConfigVv.setInitAddr(LOCALHOST);
+ sharedConfigVv.setInitPort(INIT_PORT_START + nodeId * 10);
+ sharedConfigVv.setConsensusNode(CONSENSUS_NODES[nodeId]);
+ sharedConfigVv.setPubKey(PUBKEYS[nodeId]);
+ sharedConfigVv.setUserId(nodeId);
+ sharedConfigVv.setPeerPath(PEER_PATHS[nodeId]);
+ sharedConfigVv.setDbName(dbName());
+
+ if (isMaster) {
+ sharedConfigVv.setLedgerName(ledgerName());
+ sharedConfigVv.setNodeSize(TOTAL_SIZE);
+ } else {
+ sharedConfigVv.setMasterAddr(LOCALHOST);
+ sharedConfigVv.setMasterPort(8080);
+ }
+
+ return sharedConfigVv;
+ }
+
+ private String ledgerName() {
+
+ byte[] nameBytes = new byte[4];
+
+ RANDOM_ROCKSDB.nextBytes(nameBytes);
+
+ return Hex.encodeHexString(nameBytes);
+ }
+
+ private String dbName() {
+
+ byte[] nameBytes = new byte[4];
+
+ RANDOM_ROCKSDB.nextBytes(nameBytes);
+
+ return DB_NAME + Hex.encodeHexString(nameBytes);
+ }
+}
diff --git a/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UmpStateService.java b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UmpStateService.java
new file mode 100644
index 00000000..161ed867
--- /dev/null
+++ b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UmpStateService.java
@@ -0,0 +1,62 @@
+package com.jd.blockchain.ump.service;
+
+import com.jd.blockchain.ump.model.MasterAddr;
+import com.jd.blockchain.ump.model.config.LedgerIdentification;
+import com.jd.blockchain.ump.model.config.PeerLocalConfig;
+import com.jd.blockchain.ump.model.state.*;
+import com.jd.blockchain.ump.model.user.UserKeys;
+import com.jd.blockchain.ump.model.user.UserKeysVv;
+
+import java.util.List;
+import java.util.Map;
+
+public interface UmpStateService {
+
+ void save(String ledgerAndNodeKey, PeerLocalConfig localConfig);
+
+ void save(String ledgerKey, List sharedConfigKeys);
+
+ void save(InstallSchedule installSchedule, MasterAddr masterAddr);
+
+ void save(UserKeys userKeys);
+
+ void save(LedgerPeerInstall peerInstall);
+
+ void save(LedgerMasterInstall masterInstall);
+
+ void save(LedgerIdentification identification);
+
+ void saveLedgerHash(String ledgerAndNodeKey, String ledgerHash);
+
+ List readUserKeysList();
+
+ List readUserKeysVvList();
+
+ UserKeys readUserKeys(int id);
+
+ PeerLocalConfig readConfig(String ledgerAndNodeKey);
+
+ PeerInstallSchedules loadState(String ledgerAndNodeKey);
+
+ PeerInstallSchedules loadInitState(String ledgerAndNodeKey);
+
+ PeerInstallSchedules readState(String ledgerAndNodeKey);
+
+ PeerInstallSchedules readInitState(String ledgerAndNodeKey);
+
+ Map> readStates(String ledgerKey);
+
+ LedgerIdentification readIdentification(String ledgerAndNodeKey);
+
+ List readLedgerPeerInstalls();
+
+ List readLedgerMasterInstalls();
+
+ List readLedgerPeerIniteds();
+
+ List readLedgerPeerIniteds(String search);
+
+ List readLedgerIniteds(String search);
+
+ String readLedgerHash(String ledgerAndNodeKey);
+}
diff --git a/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UmpStateServiceHandler.java b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UmpStateServiceHandler.java
new file mode 100644
index 00000000..5ed51aca
--- /dev/null
+++ b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UmpStateServiceHandler.java
@@ -0,0 +1,880 @@
+package com.jd.blockchain.ump.service;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.jd.blockchain.ump.dao.DBConnection;
+import com.jd.blockchain.ump.model.*;
+import com.jd.blockchain.ump.model.config.LedgerIdentification;
+import com.jd.blockchain.ump.model.config.PeerLocalConfig;
+import com.jd.blockchain.ump.model.state.*;
+import com.jd.blockchain.ump.model.user.UserKeys;
+import com.jd.blockchain.ump.model.user.UserKeysVv;
+import com.jd.blockchain.ump.util.CommandUtils;
+import com.jd.blockchain.ump.util.HttpJsonClientUtils;
+import org.apache.commons.io.FileUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+@Service
+public class UmpStateServiceHandler implements UmpStateService, Closeable {
+
+ private final Logger LOGGER = LoggerFactory.getLogger(getClass());
+
+ private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyyMM-ddHHmmss");
+
+ private static final String PEER_IDENTIFICATION_FORMAT = "PEER_IDENTIFICATION_INDEX_%s";
+
+ private static final String PEER_INSTALL_MAX_KEY = "PEER_INSTALL_MAX_INDEX";
+
+ private static final String PEER_INSTALL_KEY_FORMAT = "PEER_INSTALL_INDEX_%s";
+
+ private static final String MASTER_INSTALL_MAX_KEY = "MASTER_INSTALL_MAX_INDEX";
+
+ private static final String MASTER_INSTALL_KEY_FORMAT = "MASTER_INSTALL_INDEX_%s";
+
+ private static final String USERS_KEY_MAX_KEY = "USERS_KEY_MAX_INDEX";
+
+ private static final String USERS_KEY_FORMAT = "USERS_%s_REGISTER";
+
+ private static final String MAX_SIZE_KEY_SUFFIX = "_MAX_SIZE_KEY";
+
+ private static final String LEDGER_HASH_KEY_SUFFIX = "_LEDGER_HASH_KEY";
+
+ private static final String LEDGER_NODE_KEY_CONFIG_SUFFIX = "_LEDGER_NODE_CONFIG_KEY";
+
+ private static final String LEDGER_NODE_KEY_SUFFIX = "_LEDGER_NODE_KEY";
+
+ private static final String CURRENT_INDEX_KEY_SUFFIX_FORMAT = "_%s_INDEX_KEY";
+
+ private static final String PORT_ARG = "-p";
+
+ private static final String LOCALHOST = "127.0.0.1";
+
+ private ExecutorService singleHttpThread = Executors.newSingleThreadExecutor();
+
+ @Autowired
+ private DBConnection dbConnection;
+
+ @Autowired
+ private LedgerService ledgerService;
+
+ @Override
+ public synchronized void save(String ledgerAndNodeKey, PeerLocalConfig localConfig) {
+
+ String ledgerAndNodeConfigKey = ledgerAndNodeConfigKey(ledgerAndNodeKey);
+
+ dbConnection.put(ledgerAndNodeConfigKey, JSON.toJSONString(localConfig));
+ }
+
+ @Override
+ public synchronized void save(String ledgerKey, List sharedConfigKeys) {
+
+ String ledgerAllNodeKey = ledgerAllNodeKey(ledgerKey);
+
+ StringBuilder sBuilder = new StringBuilder();
+
+ for (String sharedConfigKey : sharedConfigKeys) {
+ if (sBuilder.length() > 0) {
+ sBuilder.append(";");
+ }
+ sBuilder.append(sharedConfigKey);
+ }
+
+ dbConnection.put(ledgerAllNodeKey, sBuilder.toString());
+ }
+
+ @Override
+ public synchronized void save(InstallSchedule installSchedule, MasterAddr masterAddr) {
+ try {
+ String ledgerAndNodeKey = installSchedule.getLedgerAndNodeKey();
+ // 不使用队列,直接将其写入数据库
+ // 需要查询目前该Key对应的最大值是多少
+ String maxKey = ledgerAndNodeMaxKey(ledgerAndNodeKey);
+ String maxIdChars = dbConnection.get(maxKey);
+ int maxId = 0;
+ if (maxIdChars != null && maxIdChars.length() > 0) {
+ maxId = Integer.parseInt(maxIdChars) + 1;
+ }
+
+ String newKey = ledgerAndNodeCurrentNewKey(ledgerAndNodeKey, maxId);
+
+ // 内容写入数据库
+ dbConnection.put(newKey, installSchedule, InstallSchedule.class);
+
+ // 更新最大值
+ dbConnection.put(maxKey, String.valueOf(maxId));
+
+ if (masterAddr != null && masterAddr.legal()) {
+ singleHttpThread.execute(() -> {
+
+ try {
+ // 发送HTTP请求
+ HttpJsonClientUtils.httpPost(masterAddr, UmpConstant.REQUEST_STATE_URL, installSchedule, String.class, false);
+ } catch (Exception e) {
+ // 暂不关注是否发送成功
+ LOGGER.error(e.toString());
+ }
+
+ });
+ }
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @Override
+ public synchronized void save(UserKeys userKeys) {
+
+ int maxIndex = maxIndex(USERS_KEY_MAX_KEY);
+
+ String userKey = usersKey(maxIndex);
+
+ // 重置userId
+ userKeys.setId(maxIndex);
+
+ // 将用户信息写入数据库
+ dbConnection.put(userKey, JSON.toJSONString(userKeys));
+
+ // 更新最大值
+ dbConnection.put(USERS_KEY_MAX_KEY, String.valueOf(maxIndex));
+
+ try {
+ // 将其放入文件中
+ String keysDirPath = UmpConstant.PROJECT_PATH + UmpConstant.PATH_CONFIG_KEYS;
+
+ File keysDir = new File(keysDirPath);
+
+ if (!keysDir.exists()) {
+ // 创建文件夹
+ keysDir.mkdir();
+ }
+ saveKeys2Files(keysDirPath, userKeys);
+ } catch (Exception e) {
+ LOGGER.error("Save Keys To File !", e);
+ }
+ }
+
+ @Override
+ public synchronized void save(LedgerPeerInstall peerInstall) {
+
+ int maxIndex = maxIndex(PEER_INSTALL_MAX_KEY);
+
+ // 将用户信息写入数据库
+ dbConnection.put(peerInstallKey(maxIndex), JSON.toJSONString(peerInstall));
+
+ // 更新最大值
+ dbConnection.put(PEER_INSTALL_MAX_KEY, String.valueOf(maxIndex));
+
+ }
+
+ @Override
+ public synchronized void save(LedgerMasterInstall masterInstall) {
+
+ int maxIndex = maxIndex(MASTER_INSTALL_MAX_KEY);
+
+ // 将用户信息写入数据库
+ dbConnection.put(masterInstallKey(maxIndex), JSON.toJSONString(masterInstall));
+
+ // 更新最大值
+ dbConnection.put(MASTER_INSTALL_MAX_KEY, String.valueOf(maxIndex));
+ }
+
+ @Override
+ public synchronized void save(LedgerIdentification identification) {
+
+ String ledgerAndNodeKey = identification.getLedgerAndNodeKey();
+
+ String idKey = String.format(PEER_IDENTIFICATION_FORMAT, ledgerAndNodeKey);
+
+ dbConnection.put(idKey, JSON.toJSONString(identification));
+ }
+
+ @Override
+ public void saveLedgerHash(String ledgerAndNodeKey, String ledgerHash) {
+
+ String ledgerHashKey = ledgerAndNodeHashKey(ledgerAndNodeKey);
+
+ dbConnection.put(ledgerHashKey, ledgerHash);
+ }
+
+ @Override
+ public List readUserKeysList() {
+
+ List userKeysList = new ArrayList<>();
+
+ String maxIndexChars = dbConnection.get(USERS_KEY_MAX_KEY);
+
+ if (maxIndexChars != null && maxIndexChars.length() > 0) {
+
+ int maxIndex = Integer.parseInt(maxIndexChars);
+
+ for (int i = 0; i <= maxIndex; i++) {
+ try {
+
+ String json = dbConnection.get(usersKey(i));
+
+ if (json != null && json.length() > 0) {
+ userKeysList.add(JSON.parseObject(json, UserKeys.class));
+ }
+ } catch (Exception e) {
+ LOGGER.error(e.toString());
+ }
+ }
+ }
+
+ return userKeysList;
+ }
+
+ @Override
+ public List readUserKeysVvList() {
+
+ List userKeysVvList = new ArrayList<>();
+
+ List userKeysList = readUserKeysList();
+
+ if (!userKeysList.isEmpty()) {
+ for (UserKeys userKeys : userKeysList) {
+
+ userKeysVvList.add(userKeys.toUserKeysVv());
+ }
+ }
+
+ return userKeysVvList;
+ }
+
+ @Override
+ public UserKeys readUserKeys(int id) {
+
+ String userKey = usersKey(id);
+
+ String userKeysJson = dbConnection.get(userKey);
+
+ if (userKeysJson != null && userKeysJson.length() > 0) {
+ return JSON.parseObject(userKeysJson, UserKeys.class);
+ }
+
+ return null;
+ }
+
+ @Override
+ public PeerLocalConfig readConfig(String ledgerAndNodeKey) {
+
+ String json = dbConnection.get(ledgerAndNodeConfigKey(ledgerAndNodeKey));
+
+ if (json != null && json.length() > 0) {
+
+ return JSON.parseObject(json, PeerLocalConfig.class);
+ }
+
+ return null;
+ }
+
+ @Override
+ public PeerInstallSchedules loadState(String ledgerAndNodeKey) {
+
+ PeerInstallSchedules installSchedules = loadInitState(ledgerAndNodeKey);
+
+ String ledgerHash = ledgerService.readLedgerHash(ledgerAndNodeKey);
+
+ if (ledgerHash == null || ledgerHash.length() == 0) {
+ throw new IllegalStateException("Can not find LedgerHash from DataBase !!!");
+ }
+
+ return installSchedules.initLedgerHash(ledgerHash);
+
+ }
+
+ @Override
+ public PeerInstallSchedules loadInitState(String ledgerAndNodeKey) {
+ // 获取LedgerIdentification
+ LedgerIdentification identification = readIdentification(ledgerAndNodeKey);
+
+ if (identification == null) {
+ throw new IllegalStateException("Can not find LedgerIdentification from DataBase !!!");
+ }
+
+ return new PeerInstallSchedules(identification);
+ }
+
+ @Override
+ public PeerInstallSchedules readState(final String ledgerAndNodeKey) {
+
+ PeerInstallSchedules installSchedules = loadState(ledgerAndNodeKey);
+
+ loadInstallSchedules(installSchedules, ledgerAndNodeKey);
+
+ return installSchedules;
+ }
+
+ @Override
+ public PeerInstallSchedules readInitState(String ledgerAndNodeKey) {
+
+ PeerInstallSchedules installSchedules = loadInitState(ledgerAndNodeKey);
+
+ loadInstallSchedules(installSchedules, ledgerAndNodeKey);
+
+ return installSchedules;
+ }
+
+ @Override
+ public Map> readStates(String ledgerKey) {
+
+ String ledgerAllNodeKey = ledgerAllNodeKey(ledgerKey);
+
+ String ledgerAllNodeValues = dbConnection.get(ledgerAllNodeKey);
+
+ String[] ledgerAndNodeKeys = ledgerAllNodeValues.split(";");
+
+ Map> allInstallSchedules = new HashMap<>();
+
+ // 不存在就返回空值
+ if (ledgerAndNodeKeys.length > 0) {
+
+ for (String ledgerAndNodeKey : ledgerAndNodeKeys) {
+ // 获取每个LedgerAndNodeKey数据
+ List installSchedules = readInstallSchedules(ledgerAndNodeKey);
+
+ if (installSchedules != null) {
+
+ allInstallSchedules.put(ledgerAndNodeKey, installSchedules);
+ }
+ }
+ }
+
+ return allInstallSchedules;
+ }
+
+ @Override
+ public LedgerIdentification readIdentification(String ledgerAndNodeKey) {
+
+ String idKey = String.format(PEER_IDENTIFICATION_FORMAT, ledgerAndNodeKey);
+
+ String identificationJson = dbConnection.get(idKey);
+
+ if (identificationJson != null && identificationJson.length() > 0) {
+
+ return JSON.parseObject(identificationJson, LedgerIdentification.class);
+ }
+
+ return null;
+ }
+
+ @Override
+ public List readLedgerPeerInstalls() {
+
+ List peerInstallList = new ArrayList<>();
+
+ String maxIndexChars = dbConnection.get(PEER_INSTALL_MAX_KEY);
+
+ if (maxIndexChars != null && maxIndexChars.length() > 0) {
+
+ int maxIndex = Integer.parseInt(maxIndexChars);
+
+ for (int i = 1; i <= maxIndex; i++) {
+ try {
+ String json = dbConnection.get(peerInstallKey(i));
+
+ if (json != null && json.length() > 0) {
+ peerInstallList.add(JSON.parseObject(json, LedgerPeerInstall.class));
+ }
+ } catch (Exception e) {
+ LOGGER.error(e.toString());
+ }
+ }
+ }
+
+ return peerInstallList;
+ }
+
+ @Override
+ public List readLedgerMasterInstalls() {
+
+ List masterInstalls = new ArrayList<>();
+
+ String maxIndexChars = dbConnection.get(PEER_INSTALL_MAX_KEY);
+
+ if (maxIndexChars != null && maxIndexChars.length() > 0) {
+
+ int maxIndex = Integer.parseInt(maxIndexChars);
+
+ for (int i = 1; i <= maxIndex; i++) {
+ try {
+ String json = dbConnection.get(masterInstallKey(i));
+
+ if (json != null && json.length() > 0) {
+ masterInstalls.add(JSON.parseObject(json, LedgerMasterInstall.class));
+ }
+ } catch (Exception e) {
+ LOGGER.error(e.toString());
+ }
+ }
+ }
+
+ return masterInstalls;
+ }
+
+ @Override
+ public List readLedgerPeerIniteds() {
+
+ List peerIniteds = new ArrayList<>();
+
+ List peerInstalls = readLedgerPeerInstalls();
+
+ if (!peerInstalls.isEmpty()) {
+
+ LOGGER.info("Read LedgerPeerInstalls, Size = {}", peerInstalls.size());
+ for (LedgerPeerInstall peerInstall : peerInstalls) {
+
+ String ledgerAndNodeKey = peerInstall.getLedgerAndNodeKey();
+
+ // 数据库中读取存放的LedgerHash
+ String ledgerHash = readLedgerHash(ledgerAndNodeKey);
+
+ if (ledgerHash == null || ledgerHash.length() == 0) {
+ continue;
+ }
+
+ LedgerPeerInited peerInited = new LedgerPeerInited(ledgerHash, peerInstall);
+
+ // 检测账本中的Hash是否真正存在
+ StartupState startupState = StartupState.UNKNOWN;
+ try {
+ startupState = startupState(ledgerHash, peerInstall);
+ } catch (Exception e) {
+ LOGGER.error("Check Ledger Hash Exist !!!", e);
+ }
+
+ // 设置账本状态
+ peerInited.setStartupState(startupState);
+
+ // 添加到集合
+ peerIniteds.add(peerInited);
+ }
+ } else {
+ LOGGER.error("Read LedgerPeerInstalls is Empty !!!");
+ }
+ return peerIniteds;
+ }
+
+ @Override
+ public List readLedgerPeerIniteds(String search) {
+
+ List initedList = readLedgerPeerIniteds();
+
+ if (search != null && search.length() > 0 && !initedList.isEmpty()) {
+
+ List filterInitedList = new ArrayList<>();
+
+ for (LedgerPeerInited peerInited : initedList) {
+ if (isMatch(peerInited, search)) {
+ filterInitedList.add(peerInited);
+ }
+ }
+
+ return filterInitedList;
+ }
+
+ return initedList;
+ }
+
+ @Override
+ public List readLedgerIniteds(String search) {
+
+ List ledgerInitedsFromConf = loadAllLedgerIniteds(UmpConstant.PROJECT_PATH);
+
+ if (!ledgerInitedsFromConf.isEmpty()) {
+
+ List ledgerIniteds = new ArrayList<>();
+
+ for (LedgerInited ledgerInited : ledgerInitedsFromConf) {
+
+ if (isMatch(ledgerInited, search)) {
+ ledgerIniteds.add(ledgerInited);
+ }
+ }
+
+ return ledgerIniteds;
+ }
+
+ return ledgerInitedsFromConf;
+ }
+
+ @Override
+ public String readLedgerHash(String ledgerAndNodeKey) {
+
+ String ledgerHashKey = ledgerAndNodeHashKey(ledgerAndNodeKey);
+
+ return dbConnection.get(ledgerHashKey);
+ }
+
+ @Override
+ public void close() throws IOException {
+// writeRunner.close();
+ }
+
+ private boolean isMatch(LedgerInited ledgerInited, String search) {
+
+ if (search == null || search.length() == 0) {
+ return true;
+ }
+
+ String ledgerHash = ledgerInited.getLedgerHash();
+ String ledgerName = ledgerInited.getLedgerName();
+ String partiName = ledgerInited.getPartiName();
+ String partiAddress = ledgerInited.getPartiAddress();
+ String dbUri = ledgerInited.getDbUri();
+ StartupState startupState = ledgerInited.getStartupState();
+
+ if (
+ ledgerHash.contains(search) ||
+ startupState.toString().equals(search) ||
+ ledgerName.contains(search) ||
+ partiName.contains(search) ||
+ partiAddress.contains(search) ||
+ dbUri.contains(search)
+ ) {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isMatch(LedgerPeerInited peerInited, String search) {
+
+ if (search == null || search.length() == 0) {
+ return true;
+ }
+
+ String ledgerHash = peerInited.getLedgerHash();
+ StartupState startupState = peerInited.getStartupState();
+ LedgerPeerInstall peerInstall = peerInited.getPeerInstall();
+
+ if (ledgerHash.contains(search) ||
+ startupState.toString().equals(search) ||
+ peerInstall.getNodeName().contains(search) ||
+ peerInstall.getCreateTime().contains(search)
+ ) {
+ return true;
+ }
+ return false;
+ }
+
+ private void loadInstallSchedules(PeerInstallSchedules installSchedules, String ledgerAndNodeKey) {
+ List schedules = readInstallSchedules(ledgerAndNodeKey);
+
+ for (InstallSchedule installSchedule : schedules) {
+ installSchedules.addInstallSchedule(
+ new PeerInstallSchedule(installSchedule.getProcess(), installSchedule.getState()));
+ }
+ }
+
+ private List readInstallSchedules(String ledgerAndNodeKey) {
+ String maxKey = ledgerAndNodeMaxKey(ledgerAndNodeKey);
+ String maxIdChars = dbConnection.get(maxKey);
+ if (maxIdChars == null || maxIdChars.length() == 0) {
+ return null;
+ }
+ int maxId = Integer.parseInt(maxIdChars);
+
+ List schedules = new ArrayList<>();
+
+ for (int i = 0; i <= maxId; i++) {
+
+ try {
+ String currentKey = ledgerAndNodeCurrentNewKey(ledgerAndNodeKey, i);
+
+ String jsonChars = dbConnection.get(currentKey);
+
+ if (jsonChars != null && jsonChars.length() > 0) {
+ schedules.add(JSON.parseObject(jsonChars, InstallSchedule.class));
+ }
+ } catch (Exception e) {
+ // 打印错误,暂不处理其他
+ LOGGER.error(e.toString());
+ }
+ }
+
+ return schedules;
+ }
+
+ private List loadAllLedgerIniteds(String peerPath) {
+
+ List ledgerInitedsFromConf = ledgerService.allLedgerIniteds(peerPath);
+
+ if (!ledgerInitedsFromConf.isEmpty()) {
+
+ // 逐个检查其状态
+ for (LedgerInited ledgerInited : ledgerInitedsFromConf) {
+ // 判断该账本对应的数据库是否存在
+ if (!dbConnection.exist(ledgerInited.getDbUri())) {
+ ledgerInited.setStartupState(StartupState.DB_UNEXIST);
+ continue;
+ }
+
+ String peerVerify = ledgerService.peerVerifyKey(peerPath);
+
+ try {
+ if (!CommandUtils.isActive(peerVerify)) {
+ // 进程不存在
+ LOGGER.info("Can not find Peer Process {} !!!", peerVerify);
+ ledgerInited.setStartupState(StartupState.UNLOAD);
+ continue;
+ }
+ } catch (Exception e) {
+ // 进程处理错误打印日志即可
+ LOGGER.error(String.format("Command Check %s !!!", peerVerify), e);
+ }
+ // 查看该进程对应的监听端口
+ try {
+ int listenPort = listenPort(peerVerify);
+
+ LOGGER.info("Find Listen Port = {} !", listenPort);
+
+ if (listenPort > 0) {
+
+ int maxSize = 5, checkIndex = 1;
+
+ boolean isRead = false;
+
+ while (maxSize > 0) {
+
+ try {
+ // 发送请求到对应地址
+ JSONArray ledgerHashs = HttpJsonClientUtils.httpGet(ledgersUrl(listenPort), JSONArray.class, true);
+
+ if (ledgerHashs != null && !ledgerHashs.isEmpty()) {
+ for(Object hashObj : ledgerHashs) {
+ if (hashObj instanceof JSONObject) {
+ if (ledgerInited.getLedgerHash().equals(((JSONObject) hashObj).getString("value"))) {
+ // 说明该账本已经被加载
+ ledgerInited.setStartupState(StartupState.LOADED);
+ isRead = true;
+ break;
+ }
+ }
+ }
+ if (isRead) {
+ break;
+ }
+ }
+
+ // 6秒休眠
+ Thread.sleep(6000);
+ } catch (Exception e) {
+ LOGGER.error(String.format("Request LedgerHashs from PeerNode [%s]", checkIndex++), e);
+ }
+
+ maxSize --;
+ }
+
+ if (!isRead) {
+ // 表明等待加载,无须再启动
+ ledgerInited.setStartupState(StartupState.LOADING);
+ }
+ }
+ } catch (Exception e) {
+ LOGGER.error(String.format("Command [%s] 'Listen Port Check !!!", peerVerify), e);
+ }
+ }
+ }
+
+ return ledgerInitedsFromConf;
+ }
+
+ private StartupState startupState(String ledgerHash, LedgerPeerInstall peerInstall) {
+
+ String peerPath = peerInstall.getPeerPath();
+
+ // 首先检查文件中是否存在该Hash值
+ LedgerBindingConf ledgerBindingConf = ledgerService.allLedgerHashs(peerPath);
+
+ Set allLedgerHashs = ledgerBindingConf.getLedgerHashs();
+
+ if (!allLedgerHashs.contains(ledgerHash)) {
+
+ // 文件中不存在
+ return StartupState.UNEXIST;
+ }
+
+ // 判断该账本对应的数据库是否存在
+ if (!ledgerService.dbExist(peerPath, ledgerHash)) {
+
+ // 该账本对应数据库不存在
+ return StartupState.DB_UNEXIST;
+ }
+
+ // 文件中存在则检查进程是否存在
+ // 进程存在标识为LOADED,否则标识为LOADING,暂时用不到LOADING
+ String peerVerify = ledgerService.peerVerifyKey(peerPath);
+
+ try {
+ if (!CommandUtils.isActive(peerVerify)) {
+ // 进程不存在
+ return StartupState.UNLOAD;
+ }
+
+ } catch (Exception e) {
+ // 进程处理错误打印日志即可
+ LOGGER.error(String.format("Command Check %s !!!", peerVerify), e);
+ }
+
+ // 查看该进程对应的监听端口
+ try {
+ int listenPort = listenPort(peerVerify);
+
+ LOGGER.info("Find Listen Port = {} !", listenPort);
+
+ if (listenPort > 0) {
+ // 发送请求到对应地址
+ JSONArray ledgerHashs = HttpJsonClientUtils.httpGet(ledgersUrl(listenPort), JSONArray.class, true);
+
+ if (ledgerHashs != null && !ledgerHashs.isEmpty()) {
+ for(Object hashObj : ledgerHashs) {
+ if (hashObj instanceof JSONObject) {
+ if (ledgerHash.equals(((JSONObject) hashObj).getString("value"))) {
+ // 说明该账本已经被加载
+ return StartupState.LOADED;
+ }
+ }
+ }
+ // 表明等待加载,无须再启动
+ return StartupState.LOADING;
+ }
+ }
+ } catch (Exception e) {
+ LOGGER.error(String.format("Command [%s] 'Listen Port Check !!!", peerVerify), e);
+ }
+
+ return StartupState.UNKNOWN;
+ }
+
+ private String ledgersUrl(int listenPort) {
+ return "http://" + LOCALHOST + ":" + listenPort + "/ledgers";
+ }
+
+ private int listenPort(String peerVerify) throws Exception {
+
+ String portArg = mainArg(peerVerify, PORT_ARG);
+
+ if (portArg != null && portArg.length() > 0) {
+ return Integer.parseInt(portArg);
+ }
+
+ return 0;
+ }
+
+ private String mainArg(String processName, String argKey) throws Exception {
+
+ String[] cmdLineArray = mainArgs(processName);
+
+ if (cmdLineArray != null && cmdLineArray.length > 0) {
+ for (int i = 0; i < cmdLineArray.length; i++) {
+ String currArg = cmdLineArray[i].trim();
+ if (currArg.equals(argKey) && (i + 1) < cmdLineArray.length) {
+ return cmdLineArray[i+1].trim();
+ }
+ }
+ }
+ return null;
+ }
+
+ private String[] mainArgs(String processName) throws Exception {
+
+ String mainArgs = CommandUtils.mainArgs(processName);
+
+ if (mainArgs != null && mainArgs.length() > 0) {
+ ///Users/shaozhuguang/Documents/newenv/peer4/system/deployment-peer-1.1.0-SNAPSHOT.jar -home=/Users/shaozhuguang/Documents/newenv/peer4 -c /Users/shaozhuguang/Documents/newenv/peer4/config/ledger-binding.conf -p 7080
+ return mainArgs.split(" ");
+ }
+
+ return null;
+ }
+
+ private synchronized int maxIndex(String key) {
+ int maxIndex = 1;
+ String maxIndexChars = dbConnection.get(key);
+ if (maxIndexChars != null && maxIndexChars.length() > 0) {
+ maxIndex = Integer.parseInt(maxIndexChars) + 1;
+ }
+ return maxIndex;
+ }
+
+ private String usersKey(int userId) {
+ return String.format(USERS_KEY_FORMAT, userId);
+ }
+
+ private String peerInstallKey(int index) {
+ return String.format(PEER_INSTALL_KEY_FORMAT, index);
+ }
+
+ private String masterInstallKey(int index) {
+ return String.format(MASTER_INSTALL_KEY_FORMAT, index);
+ }
+
+ private String ledgerAndNodeConfigKey(String ledgerAndNodeKey) {
+
+ return ledgerAndNodeKey + LEDGER_NODE_KEY_CONFIG_SUFFIX;
+ }
+
+ private String ledgerAllNodeKey(String ledgerKey) {
+
+ return ledgerKey + LEDGER_NODE_KEY_SUFFIX;
+ }
+
+ private String ledgerAndNodeMaxKey(String ledgerAndNodeKey) {
+
+ return ledgerAndNodeKey + MAX_SIZE_KEY_SUFFIX;
+ }
+
+ private String ledgerAndNodeHashKey(String ledgerAndNodeKey) {
+
+ return ledgerAndNodeKey + LEDGER_HASH_KEY_SUFFIX;
+ }
+
+ private String ledgerAndNodeCurrentNewKey(String ledgerAndNodeKey, int currentId) {
+
+ return String.format(
+ ledgerAndNodeKey + CURRENT_INDEX_KEY_SUFFIX_FORMAT,
+ currentId);
+ }
+
+ private void saveKeys2Files(String keysDirPath, UserKeys userKeys) throws IOException {
+
+ // 写入私钥
+ write(keysDirPath, userKeys.getName(), UmpConstant.PRIVATE_KEY_SUFFIX, userKeys.getPrivKey());
+ // 写入公钥
+ write(keysDirPath, userKeys.getName(), UmpConstant.PUBLIC_KEY_SUFFIX, userKeys.getPubKey());
+ // 写入密钥
+ write(keysDirPath, userKeys.getName(), UmpConstant.PWD_SUFFIX, userKeys.getEncodePwd());
+ }
+
+ private void write(String keysDirPath, String name, String suffix, String writeContent) throws IOException {
+
+ String keyeFilePath = keysDirPath + File.separator + name + suffix;
+
+ File keysFile = new File(keyeFilePath);
+
+ if (keysFile.exists()) {
+ // 文件存在,备份文件
+ FileUtils.copyFile(keysFile, new File(keyeFilePath + "_bak_" + currentTime()));
+ }
+
+ // 将Priv文件内容写入
+ FileUtils.writeStringToFile(keysFile, writeContent, StandardCharsets.UTF_8);
+ }
+
+ private String currentTime() {
+ return SDF.format(new Date());
+ }
+}
diff --git a/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UtilService.java b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UtilService.java
new file mode 100644
index 00000000..a2083d88
--- /dev/null
+++ b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UtilService.java
@@ -0,0 +1,15 @@
+package com.jd.blockchain.ump.service;
+
+import com.jd.blockchain.ump.model.user.UserKeyBuilder;
+import com.jd.blockchain.ump.model.user.UserKeys;
+
+public interface UtilService {
+
+ UserKeys create(UserKeyBuilder builder);
+
+ UserKeys create(String name, String seed, String pwd);
+
+ UserKeys read(int id);
+
+ boolean verify(UserKeys userKeys, String pwd);
+}
diff --git a/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UtilServiceHandler.java b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UtilServiceHandler.java
new file mode 100644
index 00000000..3abf5bb4
--- /dev/null
+++ b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UtilServiceHandler.java
@@ -0,0 +1,80 @@
+package com.jd.blockchain.ump.service;
+
+import com.jd.blockchain.crypto.PrivKey;
+import com.jd.blockchain.crypto.PubKey;
+import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
+import com.jd.blockchain.crypto.utils.classic.ED25519Utils;
+import com.jd.blockchain.ump.model.user.UserKeyBuilder;
+import com.jd.blockchain.ump.model.user.UserKeys;
+import com.jd.blockchain.utils.codec.Base58Utils;
+import com.jd.blockchain.utils.security.ShaUtils;
+import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
+import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters;
+import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters;
+import org.bouncycastle.crypto.prng.FixedSecureRandom;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.nio.charset.Charset;
+
+import static com.jd.blockchain.tools.keygen.KeyGenCommand.encodePrivKey;
+import static com.jd.blockchain.tools.keygen.KeyGenCommand.encodePubKey;
+
+@Service
+public class UtilServiceHandler implements UtilService {
+
+ private static final String UTF_8 = "UTF-8";
+
+ @Autowired
+ private UmpStateService umpStateService;
+
+ @Override
+ public UserKeys create(UserKeyBuilder builder) {
+
+ return create(builder.getName(), builder.getSeed(), builder.getPwd());
+ }
+
+ @Override
+ public UserKeys create(String name, String seed, String pwd) {
+
+ AsymmetricCipherKeyPair keyPair = ED25519Utils.generateKeyPair(
+ new FixedSecureRandom(seed.getBytes(Charset.forName(UTF_8))));
+
+ PubKey pubKey = new PubKey(ClassicAlgorithm.ED25519,
+ ((Ed25519PublicKeyParameters) keyPair.getPublic()).getEncoded());
+
+ PrivKey privKey = new PrivKey(ClassicAlgorithm.ED25519,
+ ((Ed25519PrivateKeyParameters) keyPair.getPrivate()).getEncoded());
+
+ return create(name, pubKey, privKey, pwd);
+ }
+
+ @Override
+ public UserKeys read(int userId) {
+
+ return umpStateService.readUserKeys(userId);
+ }
+
+ @Override
+ public boolean verify(UserKeys userKeys, String pwd) {
+
+ String encodePwd = Base58Utils.encode((ShaUtils.hash_256(pwd.getBytes(Charset.forName(UTF_8)))));
+
+ if (encodePwd.equals(userKeys.getEncodePwd())) {
+ return true;
+ }
+ return false;
+ }
+
+ private UserKeys create(String name, PubKey pubKey, PrivKey privKey, String pwd) {
+
+ byte[] pwdBytes = ShaUtils.hash_256(pwd.getBytes(Charset.forName(UTF_8)));
+
+ return new UserKeys(
+ name,
+ encodePrivKey(privKey, pwdBytes),
+ encodePubKey(pubKey),
+// pwd, // 密码不保存到数据库,防止泄露
+ Base58Utils.encode(pwdBytes));
+ }
+}
diff --git a/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/ConsensusProvider.java b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/ConsensusProvider.java
new file mode 100644
index 00000000..124b6d10
--- /dev/null
+++ b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/ConsensusProvider.java
@@ -0,0 +1,21 @@
+package com.jd.blockchain.ump.service.consensus;
+
+import com.jd.blockchain.ump.model.config.PeerLocalConfig;
+
+import java.util.List;
+import java.util.Properties;
+
+public interface ConsensusProvider {
+
+ String NEXT_LINE = "\r\n";
+
+ String provider();
+
+ String configFilePath();
+
+ void setConfig(Properties properties);
+
+ Properties getConfig();
+
+ byte[] handleSharedConfigs(List sharedConfigs);
+}
diff --git a/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/ConsensusService.java b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/ConsensusService.java
new file mode 100644
index 00000000..aeb5fcba
--- /dev/null
+++ b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/ConsensusService.java
@@ -0,0 +1,10 @@
+package com.jd.blockchain.ump.service.consensus;
+
+import com.jd.blockchain.ump.model.config.PeerLocalConfig;
+
+import java.util.List;
+
+public interface ConsensusService {
+
+ String initConsensusConf(String consensusProvider, List sharedConfigs);
+}
diff --git a/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/ConsensusServiceHandler.java b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/ConsensusServiceHandler.java
new file mode 100644
index 00000000..50cdb00f
--- /dev/null
+++ b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/ConsensusServiceHandler.java
@@ -0,0 +1,79 @@
+package com.jd.blockchain.ump.service.consensus;
+
+import com.jd.blockchain.ump.model.config.PeerLocalConfig;
+import com.jd.blockchain.ump.util.Base58Utils;
+import org.reflections.Reflections;
+import org.springframework.stereotype.Service;
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Service
+public class ConsensusServiceHandler implements ConsensusService {
+
+ private static final Map CONSENSUS_PROVIDERS = new ConcurrentHashMap<>();
+
+ static {
+ try {
+ initProviders();
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @Override
+ public String initConsensusConf(String consensusProvider, List sharedConfigs) {
+ // 首先根据provider获取对应的配置信息
+ ConsensusProvider provider = CONSENSUS_PROVIDERS.get(consensusProvider);
+
+ if (provider == null) {
+ throw new IllegalStateException(
+ String.format("ConsensusProvider[%s] can not find Manage-Class !!!", consensusProvider));
+ }
+
+ byte[] result = provider.handleSharedConfigs(sharedConfigs);
+
+ return Base58Utils.encode(result);
+ }
+
+ private static void initProviders() {
+ // 初始化所有实现类
+ Reflections reflections = new Reflections("com.jd.blockchain.ump.service.consensus");
+
+ Set> providerSet =
+ reflections.getSubTypesOf(ConsensusProvider.class);
+
+ for (Class extends ConsensusProvider> clazz : providerSet) {
+
+ if (!clazz.isInterface()) {
+ try {
+ // 根据class生成对象
+ ConsensusProvider provider = clazz.newInstance();
+ String providerKey = provider.provider();
+ if (providerKey != null && providerKey.length() > 0 &&
+ !CONSENSUS_PROVIDERS.containsKey(providerKey)) {
+
+ // 根据value读取配置文件中的内容
+ InputStream currentFileInputStream = ConsensusServiceHandler.class.getResourceAsStream(
+ File.separator + provider.configFilePath());
+
+ Properties currentProps = new Properties();
+
+ currentProps.load(currentFileInputStream);
+
+ provider.setConfig(currentProps);
+
+ CONSENSUS_PROVIDERS.put(providerKey, provider);
+ }
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+ }
+}
diff --git a/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/providers/BftsmartConsensusProvider.java b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/providers/BftsmartConsensusProvider.java
new file mode 100644
index 00000000..acb89a84
--- /dev/null
+++ b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/providers/BftsmartConsensusProvider.java
@@ -0,0 +1,162 @@
+package com.jd.blockchain.ump.service.consensus.providers;
+
+
+import com.jd.blockchain.ump.model.config.PeerLocalConfig;
+import com.jd.blockchain.ump.model.config.PeerSharedConfig;
+import com.jd.blockchain.ump.service.consensus.ConsensusProvider;
+
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+
+public class BftsmartConsensusProvider implements ConsensusProvider {
+
+ public static final String BFTSMART_PROVIDER = "com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider";
+
+ public static final String BFTSMART_CONFIG_FILE = "bftsmart.config";
+
+ private static final int MIN_PARTI_SIZE = 4;
+
+ private Properties bftsmartProps;
+
+ @Override
+ public String provider() {
+ return BFTSMART_PROVIDER;
+ }
+
+ @Override
+ public String configFilePath() {
+ return BFTSMART_CONFIG_FILE;
+ }
+
+ @Override
+ public void setConfig(Properties properties) {
+ bftsmartProps = properties;
+ }
+
+ @Override
+ public Properties getConfig() {
+ return bftsmartProps;
+ }
+
+ @Override
+ public byte[] handleSharedConfigs(List sharedConfigs) {
+
+ // 首先校验其中的ConsensusNode是否完全一致,若完全一致则不可以
+ verify(sharedConfigs);
+
+ StringBuilder sBuilder = new StringBuilder();
+
+ // 先加入当前节点信息
+ List nodeConfigs = nodeConfigs(sharedConfigs);
+
+ for (String nodeConfig : nodeConfigs) {
+ sBuilder.append(nodeConfig).append(NEXT_LINE);
+ }
+
+ int nodeNum = sharedConfigs.size();
+
+ // 写入之前配置文件中的内容
+ for (Map.Entry