diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerInitSetting.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerInitSetting.java
index 90e2d44d..d3ee5d1d 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerInitSetting.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerInitSetting.java
@@ -17,6 +17,7 @@ public interface LedgerInitSetting {
/**
* 账本的种子;
+ *
* @return
*/
@DataField(order = 1, primitiveType = PrimitiveType.BYTES)
@@ -37,9 +38,8 @@ public interface LedgerInitSetting {
*/
@DataField(order = 3, refContract = true)
CryptoSetting getCryptoSetting();
-
-
- @DataField(order = 4, primitiveType=PrimitiveType.TEXT)
+
+ @DataField(order = 4, primitiveType = PrimitiveType.TEXT)
String getConsensusProvider();
/**
@@ -47,7 +47,15 @@ public interface LedgerInitSetting {
*
* @return
*/
- @DataField(order = 5, primitiveType=PrimitiveType.BYTES)
+ @DataField(order = 5, primitiveType = PrimitiveType.BYTES)
Bytes getConsensusSettings();
+ /**
+ * 账本创建时间;
+ *
+ * @return
+ */
+ @DataField(order = 6, primitiveType = PrimitiveType.INT64)
+ long getCreatedTime();
+
}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionBuilder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionBuilder.java
index 26c5cfc5..7f0c6c02 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionBuilder.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionBuilder.java
@@ -11,22 +11,41 @@ import com.jd.blockchain.transaction.LedgerInitOperator;
*
*/
public interface TransactionBuilder extends ClientOperator, LedgerInitOperator {
-
+
HashDigest getLedgerHash();
/**
- * 完成交易定义,并生成就绪的交易数据;
+ * 基于当前的系统时间完成交易定义,并生成就绪的交易数据;
*
- * 注:调用此方法后,不能再向当前对象加入更多的操作;
+ * 注:调用此方法后,不能再向当前对象加入更多的操作;
*
* @return
*/
TransactionRequestBuilder prepareRequest();
-
+
/**
* 生成交易内容;
+ *
* @return
*/
TransactionContent prepareContent();
+ /**
+ * 基于当前的系统时间完成交易定义,并生成就绪的交易数据;
+ *
+ * 注:调用此方法后,不能再向当前对象加入更多的操作;
+ *
+ * @param time 交易时间戳;
+ * @return
+ */
+ TransactionRequestBuilder prepareRequest(long time);
+
+ /**
+ * 生成交易内容;
+ *
+ * @param time 交易时间戳;
+ * @return
+ */
+ TransactionContent prepareContent(long time);
+
}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContentBody.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContentBody.java
index e1819224..5ffa8739 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContentBody.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionContentBody.java
@@ -33,4 +33,13 @@ public interface TransactionContentBody {
@DataField(order = 2, list = true, refContract = true, genericContract = true)
Operation[] getOperations();
+ /**
+ * 生成交易的时间;
+ * 以毫秒为单位,表示距离 1970-1-1 00:00:00 (UTC) 的毫秒数;
+ *
+ * @return
+ */
+ @DataField(order = 3, primitiveType = PrimitiveType.INT64)
+ long getTime();
+
}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LedgerInitSettingData.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LedgerInitSettingData.java
index e4fe8171..a6f6045a 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LedgerInitSettingData.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LedgerInitSettingData.java
@@ -16,6 +16,8 @@ public class LedgerInitSettingData implements LedgerInitSetting {
private String consensusProvider;
private Bytes consensusSettings;
+
+ private long createdTime;
@Override
public byte[] getLedgerSeed() {
@@ -62,4 +64,12 @@ public class LedgerInitSettingData implements LedgerInitSetting {
this.consensusProvider = consensusProvider;
}
+ @Override
+ public long getCreatedTime() {
+ return createdTime;
+ }
+
+ public void setCreatedTime(long createdTime) {
+ this.createdTime = createdTime;
+ }
}
\ No newline at end of file
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxBuilder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxBuilder.java
index cb32c1bd..35e09d78 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxBuilder.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxBuilder.java
@@ -35,14 +35,25 @@ public class TxBuilder implements TransactionBuilder {
@Override
public TransactionRequestBuilder prepareRequest() {
- TransactionContent txContent = prepareContent();
- return new TxRequestBuilder(txContent);
+ return prepareRequest(System.currentTimeMillis());
}
@Override
public TransactionContent prepareContent() {
+ return prepareContent(System.currentTimeMillis());
+ }
+
+ @Override
+ public TransactionRequestBuilder prepareRequest(long time) {
+ TransactionContent txContent = prepareContent(time);
+ return new TxRequestBuilder(txContent);
+ }
+
+ @Override
+ public TransactionContent prepareContent(long time) {
TxContentBlob txContent = new TxContentBlob(ledgerHash);
txContent.addOperations(opFactory.getOperations());
+ txContent.setTime(time);
byte[] contentBodyBytes = BinaryProtocol.encode(txContent, TransactionContentBody.class);
HashDigest contentHash = Crypto.getHashFunction(DEFAULT_HASH_ALGORITHM).hash(contentBodyBytes);
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxContentBlob.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxContentBlob.java
index ccbe3a98..c03f1cc7 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxContentBlob.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxContentBlob.java
@@ -30,6 +30,8 @@ public class TxContentBlob implements TransactionContent {
private HashDigest hash;
private HashDigest ledgerHash;
+
+ private long time;
public TxContentBlob(HashDigest ledgerHash) {
this.ledgerHash = ledgerHash;
@@ -80,6 +82,15 @@ public class TxContentBlob implements TransactionContent {
addOperation(op);
}
}
+
+ @Override
+ public long getTime() {
+ return time;
+ }
+
+ public void setTime(long time) {
+ this.time = time;
+ }
public void addOperation(Operation operation) {
operationList.add(operation);
diff --git a/source/tools/tools-initializer/ledger.init b/source/tools/tools-initializer/ledger.init
deleted file mode 100644
index 6cc31468..00000000
--- a/source/tools/tools-initializer/ledger.init
+++ /dev/null
@@ -1,85 +0,0 @@
-
-#账本的种子;一段16进制字符,最长可以包含64个字符;可以用字符“-”分隔,以便更容易读取;
-ledger.seed=932dfe23-fe23232f-283f32fa-dd32aa76-8322ca2f-56236cda-7136b322-cb323ffe
-
-#账本的描述名称;此属性不参与共识,仅仅在当前参与方的本地节点用于描述用途;
-ledger.name=
-
-#参与方的个数,后续以 cons_parti.id 分别标识每一个参与方的配置;
-cons_parti.count=4
-
-#第0个参与方的名称;
-cons_parti.0.name=jd.com
-#第0个参与方的公钥文件路径;
-cons_parti.0.pubkey-path=keys/jd-com.pub
-#第0个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数;
-cons_parti.0.pubkey=endPsK36koyFr1D245Sa9j83vt6pZUdFBJoJRB3xAsWM6cwhRbna
-#第0个参与方的共识服务的主机地址;
-cons_parti.0.consensus.host=127.0.0.1
-#第0个参与方的共识服务的端口;
-cons_parti.0.consensus.port=8900
-#第0个参与方的共识服务是否开启安全连接;
-cons_parti.0.consensus.secure=true
-#第0个参与方的账本初始服务的主机;
-cons_parti.0.initializer.host=127.0.0.1
-#第0个参与方的账本初始服务的端口;
-cons_parti.0.initializer.port=8800
-#第0个参与方的账本初始服务是否开启安全连接;
-cons_parti.0.initializer.secure=true
-
-#第1个参与方的名称;
-cons_parti.1.name=at.com
-#第1个参与方的公钥文件路径;
-cons_parti.1.pubkey-path=keys/at-com.pub
-#第1个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数;
-cons_parti.1.pubkey=endPsK36sC5JdPCDPDAXUwZtS3sxEmqEhFcC4whayAsTTh8Z6eoZ
-#第1个参与方的共识服务的主机地址;
-cons_parti.1.consensus.host=127.0.0.1
-#第1个参与方的共识服务的端口;
-cons_parti.1.consensus.port=8910
-#第1个参与方的共识服务是否开启安全连接;
-cons_parti.1.consensus.secure=false
-#第1个参与方的账本初始服务的主机;
-cons_parti.1.initializer.host=127.0.0.1
-#第1个参与方的账本初始服务的端口;
-cons_parti.1.initializer.port=8810
-#第1个参与方的账本初始服务是否开启安全连接;
-cons_parti.1.initializer.secure=false
-
-#第2个参与方的名称;
-cons_parti.2.name=bt.com
-#第2个参与方的公钥文件路径;
-cons_parti.2.pubkey-path=keys/bt-com.pub
-#第2个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数;
-cons_parti.2.pubkey=endPsK36jEG281HMHeh6oSqzqLkT95DTnCM6REDURjdb2c67uR3R
-#第2个参与方的共识服务的主机地址;
-cons_parti.2.consensus.host=127.0.0.1
-#第2个参与方的共识服务的端口;
-cons_parti.2.consensus.port=8920
-#第2个参与方的共识服务是否开启安全连接;
-cons_parti.2.consensus.secure=false
-#第2个参与方的账本初始服务的主机;
-cons_parti.2.initializer.host=127.0.0.1
-#第2个参与方的账本初始服务的端口;
-cons_parti.2.initializer.port=8820
-#第2个参与方的账本初始服务是否开启安全连接;
-cons_parti.2.initializer.secure=true
-
-#第3个参与方的名称;
-cons_parti.3.name=xt.com
-#第3个参与方的公钥文件路径;
-cons_parti.3.pubkey-path=keys/xt-com.pub
-#第3个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数;
-cons_parti.3.pubkey=endPsK36nse1dck4uF19zPvAMijCV336Y3zWdgb4rQG8QoRj5ktR
-#第3个参与方的共识服务的主机地址;
-cons_parti.3.consensus.host=127.0.0.1
-#第3个参与方的共识服务的端口;
-cons_parti.3.consensus.port=8930
-#第3个参与方的共识服务是否开启安全连接;
-cons_parti.3.consensus.secure=false
-#第3个参与方的账本初始服务的主机;
-cons_parti.3.initializer.host=127.0.0.1
-#第3个参与方的账本初始服务的端口;
-cons_parti.3.initializer.port=8830
-#第3个参与方的账本初始服务是否开启安全连接;
-cons_parti.3.initializer.secure=false
diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProcess.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProcess.java
index ee1b1692..58b01af5 100644
--- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProcess.java
+++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProcess.java
@@ -1,8 +1,5 @@
package com.jd.blockchain.tools.initializer;
-import com.jd.blockchain.consensus.ConsensusProvider;
-import com.jd.blockchain.consensus.ConsensusSettings;
-import com.jd.blockchain.consensus.service.ConsensusServiceProvider;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PrivKey;
import com.jd.blockchain.ledger.CryptoSetting;
diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProperties.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProperties.java
index c0f5b5a0..ee6be810 100644
--- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProperties.java
+++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProperties.java
@@ -3,6 +3,8 @@ package com.jd.blockchain.tools.initializer;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
@@ -22,6 +24,12 @@ public class LedgerInitProperties {
// 账本种子;
public static final String LEDGER_SEED = "ledger.seed";
+
+ // 声明的账本建立时间;
+ public static final String CREATED_TIME = "created-time";
+ // 创建时间的格式;
+ public static final String CREATED_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss.SSSZ";
+
// 共识参与方的个数,后续以 part.id 分别标识每一个参与方的配置;
public static final String PART_COUNT = "cons_parti.count";
// 共识参与方的名称的模式;
@@ -61,10 +69,16 @@ public class LedgerInitProperties {
private String[] cryptoProviders;
+ private long createdTime;
+
public byte[] getLedgerSeed() {
return ledgerSeed.clone();
}
+ public long getCreatedTime() {
+ return createdTime;
+ }
+
public Properties getConsensusConfig() {
return consensusConfig;
}
@@ -80,11 +94,11 @@ public class LedgerInitProperties {
public List getConsensusParticipants() {
return consensusParticipants;
}
-
+
public String[] getCryptoProviders() {
return cryptoProviders.clone();
}
-
+
public void setCryptoProviders(String[] cryptoProviders) {
this.cryptoProviders = cryptoProviders;
}
@@ -132,6 +146,14 @@ public class LedgerInitProperties {
byte[] ledgerSeed = HexUtils.decode(hexLedgerSeed);
LedgerInitProperties initProps = new LedgerInitProperties(ledgerSeed);
+ // 创建时间;
+ String strCreatedTime = PropertiesUtils.getRequiredProperty(props, CREATED_TIME);
+ try {
+ initProps.createdTime = new SimpleDateFormat(CREATED_TIME_FORMAT).parse(strCreatedTime).getTime();
+ } catch (ParseException ex) {
+ throw new IllegalArgumentException(ex.getMessage(), ex);
+ }
+
// 解析共识相关的属性;
initProps.consensusProvider = PropertiesUtils.getRequiredProperty(props, CONSENSUS_SERVICE_PROVIDER);
String consensusConfigFilePath = PropertiesUtils.getRequiredProperty(props, CONSENSUS_CONFIG);
diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitializeWebController.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitializeWebController.java
index ecf5f640..15546d9e 100644
--- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitializeWebController.java
+++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitializeWebController.java
@@ -338,6 +338,7 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI
ConsensusParticipantConfig[] parties = partiList.toArray(new ConsensusParticipantConfig[partiList.size()]);
ConsensusParticipantConfig[] orderedParties = sortAndVerify(parties);
initSetting.setConsensusParticipants(orderedParties);
+ initSetting.setCreatedTime(ledgerProps.getCreatedTime());
// 创建默认的共识配置;
try {
@@ -377,7 +378,8 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI
BlockchainIdentity superUserId = new BlockchainIdentityData(p.getPubKey());
initTxBuilder.users().register(superUserId);
}
- this.initTxContent = initTxBuilder.prepareContent();
+ // 账本初始化配置声明的创建时间来初始化交易时间戳;注:不能用本地时间,因为共识节点之间的本地时间系统不一致;
+ this.initTxContent = initTxBuilder.prepareContent(initSetting.getCreatedTime());
// 对初始交易签名,生成当前参与者的账本初始化许可;
SignatureDigest permissionSign = TxRequestBuilder.sign(initTxContent, privKey);
@@ -755,7 +757,7 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI
prompter.info("Received request of synchronizing decision! --[RemoteId=%s][CurrentId=%s]", remoteId, currentId);
try {
-
+
DecisionResultHandle resultHandle = this.decisions[remoteId];
if (!validateAndRecordDecision(initDecision, resultHandle)) {
// 签名无效;
diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitPropertiesTest.java b/source/tools/tools-initializer/src/test/java/test/com/jd/blockchain/tools/initializer/LedgerInitPropertiesTest.java
similarity index 74%
rename from source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitPropertiesTest.java
rename to source/tools/tools-initializer/src/test/java/test/com/jd/blockchain/tools/initializer/LedgerInitPropertiesTest.java
index 3f926073..703b86b4 100644
--- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitPropertiesTest.java
+++ b/source/tools/tools-initializer/src/test/java/test/com/jd/blockchain/tools/initializer/LedgerInitPropertiesTest.java
@@ -1,9 +1,12 @@
-package test.com.jd.blockchain.intgr.initializer;
+package test.com.jd.blockchain.tools.initializer;
import static org.junit.Assert.*;
import java.io.IOException;
import java.io.InputStream;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
import com.jd.blockchain.crypto.AddressEncoding;
import org.junit.Test;
@@ -14,12 +17,21 @@ import com.jd.blockchain.tools.initializer.LedgerInitProperties;
import com.jd.blockchain.tools.initializer.LedgerInitProperties.ConsensusParticipantConfig;
import com.jd.blockchain.tools.keygen.KeyGenCommand;
import com.jd.blockchain.utils.codec.HexUtils;
-import test.com.jd.blockchain.intgr.IntegrationBase;
public class LedgerInitPropertiesTest {
+ private static String expectedCreatedTimeStr = "2019-08-01 14:26:58.069+0800";
+
@Test
- public void test() throws IOException {
+ public void testTimeFormat() throws ParseException {
+ SimpleDateFormat timeFormat = new SimpleDateFormat(LedgerInitProperties.CREATED_TIME_FORMAT);
+ Date time = timeFormat.parse(expectedCreatedTimeStr);
+ String actualTimeStr = timeFormat.format(time);
+ assertEquals(expectedCreatedTimeStr, actualTimeStr);
+ }
+
+ @Test
+ public void testProperties() throws IOException, ParseException {
ClassPathResource ledgerInitSettingResource = new ClassPathResource("ledger.init");
InputStream in = ledgerInitSettingResource.getInputStream();
try {
@@ -30,6 +42,13 @@ public class LedgerInitPropertiesTest {
String actualLedgerSeed = HexUtils.encode(initProps.getLedgerSeed());
assertEquals(expectedLedgerSeed, actualLedgerSeed);
+ SimpleDateFormat timeFormat = new SimpleDateFormat(LedgerInitProperties.CREATED_TIME_FORMAT);
+ long expectedTs = timeFormat.parse(expectedCreatedTimeStr).getTime();
+ assertEquals(expectedTs, initProps.getCreatedTime());
+
+ String createdTimeStr = timeFormat.format(new Date(initProps.getCreatedTime()));
+ assertEquals(expectedCreatedTimeStr, createdTimeStr);
+
assertEquals("com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider",
initProps.getConsensusProvider());
@@ -61,7 +80,7 @@ public class LedgerInitPropertiesTest {
@Test
public void testPubKeyAddress() {
- String[] pubKeys = IntegrationBase.PUB_KEYS;
+ String[] pubKeys = TestConsts.PUB_KEYS;
int index = 0;
for (String pubKeyStr : pubKeys) {
System.out.println("[" + index + "][配置] = " + pubKeyStr);
diff --git a/source/tools/tools-initializer/src/test/java/test/com/jd/blockchain/tools/initializer/TestConsts.java b/source/tools/tools-initializer/src/test/java/test/com/jd/blockchain/tools/initializer/TestConsts.java
new file mode 100644
index 00000000..50078db2
--- /dev/null
+++ b/source/tools/tools-initializer/src/test/java/test/com/jd/blockchain/tools/initializer/TestConsts.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright: Copyright 2016-2020 JD.COM All Right Reserved
+ * FileName: test.com.jd.blockchain.intgr.perf.IntegrationBase
+ * Author: shaozhuguang
+ * Department: 区块链研发部
+ * Date: 2018/12/25 下午3:40
+ * Description:
+ */
+package test.com.jd.blockchain.tools.initializer;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+import com.jd.blockchain.binaryproto.DataContractRegistry;
+import com.jd.blockchain.ledger.LedgerInitOperation;
+import com.jd.blockchain.ledger.UserRegisterOperation;
+
+public class TestConsts {
+
+ static {
+ DataContractRegistry.register(LedgerInitOperation.class);
+ DataContractRegistry.register(UserRegisterOperation.class);
+ }
+
+ public static final String PASSWORD = "abc";
+
+ public static final String[] PUB_KEYS = { "3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9",
+ "3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX",
+ "3snPdw7i7PZi6TStiyc6mzjprnNhgs2atSGNS8wPYzhbKaUWGFJt7x",
+ "3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk" };
+
+ public static final String[] PRIV_KEYS = {
+ "177gjzHTznYdPgWqZrH43W3yp37onm74wYXT4v9FukpCHBrhRysBBZh7Pzdo5AMRyQGJD7x",
+ "177gju9p5zrNdHJVEQnEEKF4ZjDDYmAXyfG84V5RPGVc5xFfmtwnHA7j51nyNLUFffzz5UT",
+ "177gjtwLgmSx5v1hFb46ijh7L9kdbKUpJYqdKVf9afiEmAuLgo8Rck9yu5UuUcHknWJuWaF",
+ "177gk1pudweTq5zgJTh8y3ENCTwtSFsKyX7YnpuKPo7rKgCkCBXVXh5z2syaTCPEMbuWRns" };
+
+}
\ No newline at end of file
diff --git a/source/tools/tools-initializer/src/test/resources/bftsmart.config b/source/tools/tools-initializer/src/test/resources/bftsmart.config
new file mode 100644
index 00000000..df69caf5
--- /dev/null
+++ b/source/tools/tools-initializer/src/test/resources/bftsmart.config
@@ -0,0 +1,144 @@
+# Copyright (c) 2007-2013 Alysson Bessani, Eduardo Alchieri, Paulo Sousa, and the authors indicated in the @author tags
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+############################################
+####### Communication Configurations #######
+############################################
+
+#HMAC algorithm used to authenticate messages between processes (HmacMD5 is the default value)
+#This parameter is not currently being used being used
+#system.authentication.hmacAlgorithm = HmacSHA1
+
+#Specify if the communication system should use a thread to send data (true or false)
+system.communication.useSenderThread = true
+
+#Force all processes to use the same public/private keys pair and secret key. This is useful when deploying experiments
+#and benchmarks, but must not be used in production systems.
+system.communication.defaultkeys = true
+
+############################################
+### Replication Algorithm Configurations ###
+############################################
+
+#Timeout to asking for a client request
+system.totalordermulticast.timeout = 2000
+
+
+#Maximum batch size (in number of messages)
+system.totalordermulticast.maxbatchsize = 400
+
+#Number of nonces (for non-determinism actions) generated
+system.totalordermulticast.nonces = 10
+
+#if verification of leader-generated timestamps are increasing
+#it can only be used on systems in which the network clocks
+#are synchronized
+system.totalordermulticast.verifyTimestamps = false
+
+#Quantity of messages that can be stored in the receive queue of the communication system
+system.communication.inQueueSize = 500000
+
+# Quantity of messages that can be stored in the send queue of each replica
+system.communication.outQueueSize = 500000
+
+#Set to 1 if SMaRt should use signatures, set to 0 if otherwise
+system.communication.useSignatures = 0
+
+#Set to 1 if SMaRt should use MAC's, set to 0 if otherwise
+system.communication.useMACs = 1
+
+#Set to 1 if SMaRt should use the standard output to display debug messages, set to 0 if otherwise
+system.debug = 0
+
+#Print information about the replica when it is shutdown
+system.shutdownhook = true
+
+############################################
+###### State Transfer Configurations #######
+############################################
+
+#Activate the state transfer protocol ('true' to activate, 'false' to de-activate)
+system.totalordermulticast.state_transfer = true
+
+#Maximum ahead-of-time message not discarded
+system.totalordermulticast.highMark = 10000
+
+#Maximum ahead-of-time message not discarded when the replica is still on EID 0 (after which the state transfer is triggered)
+system.totalordermulticast.revival_highMark = 10
+
+#Number of ahead-of-time messages necessary to trigger the state transfer after a request timeout occurs
+system.totalordermulticast.timeout_highMark = 200
+
+############################################
+###### Log and Checkpoint Configurations ###
+############################################
+
+system.totalordermulticast.log = true
+system.totalordermulticast.log_parallel = false
+system.totalordermulticast.log_to_disk = false
+system.totalordermulticast.sync_log = false
+
+#Period at which BFT-SMaRt requests the state to the application (for the state transfer state protocol)
+system.totalordermulticast.checkpoint_period = 1000
+system.totalordermulticast.global_checkpoint_period = 120000
+
+system.totalordermulticast.checkpoint_to_disk = false
+system.totalordermulticast.sync_ckp = false
+
+
+############################################
+###### Reconfiguration Configurations ######
+############################################
+
+#The ID of the trust third party (TTP)
+system.ttp.id = 7002
+
+#This sets if the system will function in Byzantine or crash-only mode. Set to "true" to support Byzantine faults
+system.bft = true
+
+#Custom View Storage;
+#view.storage.handler=bftsmart.reconfiguration.views.DefaultViewStorage
+
+
+#Number of servers in the group
+system.servers.num = 4
+
+#Maximum number of faulty replicas
+system.servers.f = 1
+
+#Replicas ID for the initial view, separated by a comma.
+# The number of replicas in this parameter should be equal to that specified in 'system.servers.num'
+system.initial.view = 0,1,2,3
+
+#Configuration of all node servers;
+#PubKey of node server with specified ID, with base58 encoding.
+system.server.0.pubkey=
+system.server.0.network.host=127.0.0.1
+system.server.0.network.port=8900
+system.server.0.network.secure=false
+
+system.server.1.pubkey=
+system.server.1.network.host=127.0.0.1
+system.server.1.network.port=8910
+system.server.1.network.secure=false
+
+system.server.2.pubkey=
+system.server.2.network.host=127.0.0.1
+system.server.2.network.port=8920
+system.server.2.network.secure=false
+
+system.server.3.pubkey=
+system.server.3.network.host=127.0.0.1
+system.server.3.network.port=8920
+system.server.3.network.secure=false
diff --git a/source/tools/tools-initializer/src/test/resources/keys/parti2.pub b/source/tools/tools-initializer/src/test/resources/keys/parti2.pub
new file mode 100644
index 00000000..dde44b8e
--- /dev/null
+++ b/source/tools/tools-initializer/src/test/resources/keys/parti2.pub
@@ -0,0 +1 @@
+3snPdw7i7PZi6TStiyc6mzjprnNhgs2atSGNS8wPYzhbKaUWGFJt7x
\ No newline at end of file
diff --git a/source/tools/tools-initializer/src/test/resources/ledger.init b/source/tools/tools-initializer/src/test/resources/ledger.init
index 6cc31468..ad2b5f1f 100644
--- a/source/tools/tools-initializer/src/test/resources/ledger.init
+++ b/source/tools/tools-initializer/src/test/resources/ledger.init
@@ -5,6 +5,20 @@ ledger.seed=932dfe23-fe23232f-283f32fa-dd32aa76-8322ca2f-56236cda-7136b322-cb323
#账本的描述名称;此属性不参与共识,仅仅在当前参与方的本地节点用于描述用途;
ledger.name=
+#声明的账本创建时间;格式为 “yyyy-MM-dd HH:mm:ss.SSSZ”,表示”年-月-日 时:分:秒:毫秒时区“;例如:“2019-08-01 14:26:58.069+0800”,其中,+0800 表示时区是东8区
+created-time=2019-08-01 14:26:58.069+0800
+
+#共识服务提供者;必须;
+consensus.service-provider=com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider
+
+#共识服务的参数配置;必须;
+consensus.conf=classpath:bftsmart.config
+
+#密码服务提供者列表,以英文逗点“,”分隔;必须;
+crypto.service-providers=com.jd.blockchain.crypto.service.classic.ClassicCryptoService, \
+com.jd.blockchain.crypto.service.sm.SMCryptoService
+
+
#参与方的个数,后续以 cons_parti.id 分别标识每一个参与方的配置;
cons_parti.count=4
@@ -13,7 +27,7 @@ cons_parti.0.name=jd.com
#第0个参与方的公钥文件路径;
cons_parti.0.pubkey-path=keys/jd-com.pub
#第0个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数;
-cons_parti.0.pubkey=endPsK36koyFr1D245Sa9j83vt6pZUdFBJoJRB3xAsWM6cwhRbna
+cons_parti.0.pubkey=3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9
#第0个参与方的共识服务的主机地址;
cons_parti.0.consensus.host=127.0.0.1
#第0个参与方的共识服务的端口;
@@ -32,7 +46,7 @@ cons_parti.1.name=at.com
#第1个参与方的公钥文件路径;
cons_parti.1.pubkey-path=keys/at-com.pub
#第1个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数;
-cons_parti.1.pubkey=endPsK36sC5JdPCDPDAXUwZtS3sxEmqEhFcC4whayAsTTh8Z6eoZ
+cons_parti.1.pubkey=3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX
#第1个参与方的共识服务的主机地址;
cons_parti.1.consensus.host=127.0.0.1
#第1个参与方的共识服务的端口;
@@ -49,9 +63,9 @@ cons_parti.1.initializer.secure=false
#第2个参与方的名称;
cons_parti.2.name=bt.com
#第2个参与方的公钥文件路径;
-cons_parti.2.pubkey-path=keys/bt-com.pub
+cons_parti.2.pubkey-path=classpath:keys/parti2.pub
#第2个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数;
-cons_parti.2.pubkey=endPsK36jEG281HMHeh6oSqzqLkT95DTnCM6REDURjdb2c67uR3R
+cons_parti.2.pubkey=
#第2个参与方的共识服务的主机地址;
cons_parti.2.consensus.host=127.0.0.1
#第2个参与方的共识服务的端口;
@@ -70,7 +84,7 @@ cons_parti.3.name=xt.com
#第3个参与方的公钥文件路径;
cons_parti.3.pubkey-path=keys/xt-com.pub
#第3个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数;
-cons_parti.3.pubkey=endPsK36nse1dck4uF19zPvAMijCV336Y3zWdgb4rQG8QoRj5ktR
+cons_parti.3.pubkey=3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk
#第3个参与方的共识服务的主机地址;
cons_parti.3.consensus.host=127.0.0.1
#第3个参与方的共识服务的端口;