diff --git a/source/deployment/deployment-gateway/src/main/resources/docs/JDChain代码示例.MD b/source/deployment/deployment-gateway/src/main/resources/docs/JDChain代码示例.MD
new file mode 100644
index 00000000..58dadf19
--- /dev/null
+++ b/source/deployment/deployment-gateway/src/main/resources/docs/JDChain代码示例.MD
@@ -0,0 +1,268 @@
+# 1. maven坐标
+```java
+
+ com.jd.blockchain
+ sdk-client
+ ${ledger.version}
+
+
+ com.jd.blockchain
+ contract-starter
+ ${ledger.version}
+
+
+ com.jd.blockchain
+ crypto-classic
+ ${ledger.version}
+
+
+
+ com.jd.blockchain
+ crypto-sm
+ ${ledger.version}
+
+```
+# 2. 数据快速上链
+## 2.1. 服务连接
+
+```java
+ //创建服务代理
+ public BlockchainKeypair CLIENT_CERT = BlockchainKeyGenerator.getInstance().generate();
+ final String GATEWAY_IP = "127.0.0.1";
+ final int GATEWAY_PORT = 80;
+ final boolean SECURE = false;
+ GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IP, GATEWAY_PORT, SECURE,
+ CLIENT_CERT);
+ // 创建服务代理;
+ BlockchainService service = serviceFactory.getBlockchainService();
+ HashDigest[] ledgerHashs = service.getLedgerHashs();
+ // 获取当前账本Hash
+ HashDigest ledgerHash = ledgerHashs[0];
+```
+## 2.2. 用户注册
+```java
+ // 创建服务代理;
+ BlockchainService service = serviceFactory.getBlockchainService();
+ // 在本地定义注册账号的 TX;
+ TransactionTemplate txTemp = service.newTransaction(ledgerHash);
+ BlockchainKeypair user = BlockchainKeyGenerator.getInstance().generate();
+
+ txTemp.users().register(user.getIdentity());
+
+ // TX 准备就绪;
+ PreparedTransaction prepTx = txTemp.prepare();
+ // 使用私钥进行签名;
+ prepTx.sign(CLIENT_CERT);
+ // 提交交易;
+ prepTx.commit();
+```
+## 2.3. 数据账户注册
+```java
+ // 创建服务代理;
+ BlockchainService service = serviceFactory.getBlockchainService();
+ // 在本地定义注册账号的 TX;
+ TransactionTemplate txTemp = service.newTransaction(ledgerHash);
+ BlockchainKeypair dataAccount = BlockchainKeyGenerator.getInstance().generate();
+
+ txTemp.dataAccounts().register(dataAccount.getIdentity());
+
+ // TX 准备就绪;
+ PreparedTransaction prepTx = txTemp.prepare();
+ // 使用私钥进行签名;
+ prepTx.sign(CLIENT_CERT);
+
+ // 提交交易;
+ prepTx.commit();
+```
+## 2.4. 写入数据
+```java
+ // 创建服务代理;
+ BlockchainService service = serviceFactory.getBlockchainService();
+
+ // 在本地定义注册账号的 TX;
+ TransactionTemplate txTemp = service.newTransaction(ledgerHash);
+
+ // --------------------------------------
+ // 将商品信息写入到指定的账户中;
+ // 对象将被序列化为 JSON 形式存储,并基于 JSON 结构建立查询索引;
+ String commodityDataAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf==";
+ txTemp.dataAccount(commodityDataAccount).setText("ASSET_CODE", "value1", -1);
+
+ // TX 准备就绪;
+ PreparedTransaction prepTx = txTemp.prepare();
+
+ String txHash = Base64Utils.encodeToUrlSafeString(prepTx.getHash().toBytes());
+ // 使用私钥进行签名;
+ prepTx.sign(CLIENT_CERT);
+
+ // 提交交易;
+ prepTx.commit();
+```
+## 2.5. 查询数据
+
+> 注:详细的查询可参考模块sdk-samples中SDK_GateWay_Query_Test_相关测试用例
+
+```java
+ // 创建服务代理;
+ BlockchainService service = serviceFactory.getBlockchainService();
+
+ // 查询区块信息;
+ // 区块高度;
+ long ledgerNumber = service.getLedger(ledgerHash).getLatestBlockHeight();
+ // 最新区块;
+ LedgerBlock latestBlock = service.getBlock(ledgerHash, ledgerNumber);
+ // 区块中的交易的数量;
+ long txCount = service.getTransactionCount(ledgerHash, latestBlock.getHash());
+ // 获取交易列表;
+ LedgerTransaction[] txList = service.getTransactions(ledgerHash, ledgerNumber, 0, 100);
+ // 遍历交易列表
+ for (LedgerTransaction ledgerTransaction : txList) {
+ TransactionContent txContent = ledgerTransaction.getTransactionContent();
+ Operation[] operations = txContent.getOperations();
+ if (operations != null && operations.length > 0) {
+ for (Operation operation : operations) {
+ operation = ClientResolveUtil.read(operation);
+ // 操作类型:数据账户注册操作
+ if (operation instanceof DataAccountRegisterOperation) {
+ DataAccountRegisterOperation daro = (DataAccountRegisterOperation) operation;
+ BlockchainIdentity blockchainIdentity = daro.getAccountID();
+ }
+ // 操作类型:用户注册操作
+ else if (operation instanceof UserRegisterOperation) {
+ UserRegisterOperation uro = (UserRegisterOperation) operation;
+ BlockchainIdentity blockchainIdentity = uro.getUserID();
+ }
+ // 操作类型:账本注册操作
+ else if (operation instanceof LedgerInitOperation) {
+
+ LedgerInitOperation ledgerInitOperation = (LedgerInitOperation)operation;
+ LedgerInitSetting ledgerInitSetting = ledgerInitOperation.getInitSetting();
+
+ ParticipantNode[] participantNodes = ledgerInitSetting.getConsensusParticipants();
+ }
+ // 操作类型:合约发布操作
+ else if (operation instanceof ContractCodeDeployOperation) {
+ ContractCodeDeployOperation ccdo = (ContractCodeDeployOperation) operation;
+ BlockchainIdentity blockchainIdentity = ccdo.getContractID();
+ }
+ // 操作类型:合约执行操作
+ else if (operation instanceof ContractEventSendOperation) {
+ ContractEventSendOperation ceso = (ContractEventSendOperation) operation;
+ }
+ // 操作类型:KV存储操作
+ else if (operation instanceof DataAccountKVSetOperation) {
+ DataAccountKVSetOperation.KVWriteEntry[] kvWriteEntries =
+ ((DataAccountKVSetOperation) operation).getWriteSet();
+ if (kvWriteEntries != null && kvWriteEntries.length > 0) {
+ for (DataAccountKVSetOperation.KVWriteEntry kvWriteEntry : kvWriteEntries) {
+ BytesValue bytesValue = kvWriteEntry.getValue();
+ DataType dataType = bytesValue.getType();
+ Object showVal = ClientResolveUtil.readValueByBytesValue(bytesValue);
+ System.out.println("writeSet.key=" + kvWriteEntry.getKey());
+ System.out.println("writeSet.value=" + showVal);
+ System.out.println("writeSet.type=" + dataType);
+ System.out.println("writeSet.version=" + kvWriteEntry.getExpectedVersion());
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // 根据交易的 hash 获得交易;注:客户端生成 PrepareTransaction 时得到交易hash;
+ HashDigest txHash = txList[0].getTransactionContent().getHash();
+ Transaction tx = service.getTransactionByContentHash(ledgerHash, txHash);
+ // 获取数据;
+ String commerceAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf==";
+ String[] objKeys = new String[] { "x001", "x002" };
+ TypedKVEntry[] kvData = service.getDataEntries(ledgerHash, commerceAccount, objKeys);
+
+ long payloadVersion = kvData[0].getVersion();
+
+ // 获取数据账户下所有的KV列表
+ TypedKVEntry[] kvDatas = service.getDataEntries(ledgerHash, commerceAccount, 0, 100);
+ if (kvData != null && kvData.length > 0) {
+ for (TypedKVEntry kvDatum : kvDatas) {
+ System.out.println("kvData.key=" + kvDatum.getKey());
+ System.out.println("kvData.version=" + kvDatum.getVersion());
+ System.out.println("kvData.type=" + kvDatum.getType());
+ System.out.println("kvData.value=" + kvDatum.getValue());
+ }
+ }
+```
+
+## 2.6. 合约发布
+
+```java
+
+ // 创建服务代理;
+ BlockchainService service = serviceFactory.getBlockchainService();
+
+ // 在本地定义TX模板
+ TransactionTemplate txTemp = service.newTransaction(ledgerHash);
+
+ // 合约内容读取
+ byte[] contractBytes = FileUtils.readBytes(new File("CONTRACT_FILE"));
+
+ // 生成用户
+ BlockchainKeypair contractKeyPair = BlockchainKeyGenerator.getInstance().generate();
+
+ // 发布合约
+ txTemp.contracts().deploy(contractKeyPair.getIdentity(), contractBytes);
+
+ // TX 准备就绪;
+ PreparedTransaction prepTx = txTemp.prepare();
+
+ // 使用私钥进行签名;
+ prepTx.sign(CLIENT_CERT);
+
+ // 提交交易;
+ TransactionResponse transactionResponse = prepTx.commit();
+
+ assertTrue(transactionResponse.isSuccess());
+
+ // 打印合约地址
+ System.out.println(contractKeyPair.getIdentity().getAddress().toBase58());
+```
+
+## 2.7. 合约执行
+
+```java
+
+ // 创建服务代理;
+ BlockchainService service = serviceFactory.getBlockchainService();
+
+ // 在本地定义TX模板
+ TransactionTemplate txTemp = service.newTransaction(ledgerHash);
+
+ // 合约地址
+ String contractAddress = "";
+
+ // 使用接口方式调用合约
+ TransferContract transferContract = txTemp.contract(contractAddress, TransferContract.class);
+
+ // 使用decode方式调用合约内部方法(create方法)
+ // 返回GenericValueHolder可通过get方法获取结果,但get方法需要在commit调用后执行
+ String address = "address";
+ String account = "fill account";
+ long money = 100000000L;
+ GenericValueHolder result = ContractReturnValue.decode(transferContract.create(address, account, money));
+
+ PreparedTransaction ptx = txTemp.prepare();
+
+ ptx.sign(CLIENT_CERT);
+
+ TransactionResponse transactionResponse = ptx.commit();
+
+ String cotractExecResult = result.get();
+
+ // TransactionResponse也提供了可供查询结果的接口
+ OperationResult[] operationResults = transactionResponse.getOperationResults();
+
+ // 通过OperationResult获取结果
+ for (int i = 0; i < operationResults.length; i++) {
+ OperationResult opResult = operationResults[i];
+ System.out.printf("Operation[%s].result = %s \r\n",
+ opResult.getIndex(), BytesValueEncoding.decode(opResult.getResult()));
+ }
+```
\ No newline at end of file
diff --git a/source/deployment/deployment-peer/src/main/resources/docs/安装部署.MD b/source/deployment/deployment-peer/src/main/resources/docs/安装部署.MD
index 573d4e48..4c4dbca1 100644
--- a/source/deployment/deployment-peer/src/main/resources/docs/安装部署.MD
+++ b/source/deployment/deployment-peer/src/main/resources/docs/安装部署.MD
@@ -1,6 +1,6 @@
# JDChain安装部署指南
-本部署指南基于JDChain1.0.0.RELEASE版本来构建。
+本部署指南基于JDChain1.1.6.RELEASE版本来构建。
## 1. 部署环境
### 1.1 系统部署结构

@@ -21,7 +21,7 @@ JDChain默认共识机制采用的是BFTSmart,该共识算法要求最低四
### 1.2 服务器配置
#### 1.2.1 硬件配置
-为了更好的运行,JDChain推荐使用 **Linux** 操作系统,Peer节点自身运行对内存要求较低,但对于Rocksdb存储而言,其对运行环境有较高要求,以下为单Peer节点可正常运行 **亿级交易** 的参考指标:
+为了更好的运行,JDChain推荐使用 **Linux** 操作系统,Peer节点自身运行对内存要求较低(单节点建议Xms>=4g),但对于Rocksdb存储而言,其对运行环境有较高要求,以下为单Peer节点可正常运行 **亿级交易** 的参考指标:
+ 内核2.7.x及以上;
+ CPU主频 ≥ 2.0GHz;
+ 内存 ≥ 64G;
@@ -59,8 +59,10 @@ Peer打包程序解压完后的安装包结构如下:
+ bin
- keygen.sh
- ledger-init.sh
- - startup.sh
- - shutdown.sh
+ - peer-startup.sh
+ - peer-shutdown.sh
+ - manager-startup.sh
+ - manager-shutdown.sh
+ config
- init
+ ledger.init
@@ -71,14 +73,13 @@ Peer打包程序解压完后的安装包结构如下:
+ %.pub
+ %.pwd
- ledger-binding.conf
- - application.properties
+ docs
+ libs
+ system
其中目录说明如下:
+ **bin** :相关命令操作目录;
- + **config** :对应命令的配置目录,keys路径解压时不存在,会在执行keygen.sh脚本时自动创建;ledger-binding.conf文件解压时不存在,会在成功执行ledger-init.sh脚本后生成;
+ + **config** :对应命令的配置目录,keys路径解压时不存在,会在执行keygen.sh脚本时自动创建;ledger-binding.conf文件解压时不存在,会在成功执行ledger-init.sh脚本后生成;
+ **docs** :相关文档保存目录;
+ **libs** :项目运行依赖第三方及非system依赖包保存路径;
+ **system** :项目运行系统包保存路径;
@@ -152,8 +153,9 @@ local.parti.pwd=DYu3G8aGTMBW1WrTw76zxQJQU4DHLw9MLyy7peG4LKkY
ledger.binding.out=../config
#账本数据库的连接字符,下为rocksdb样例
-#rocksdb数据库连接格式:rocksdb://{path}
-#redis数据库连接格式:redis://{ip}:{prot}/{db}
+#rocksdb数据库连接格式:rocksdb://{path},例如:rocksdb:///export/App08/peer/rocks.db/rocksdb0.db
+#redis数据库连接格式:redis://{ip}:{prot}/{db},例如:redis://127.0.0.1:6379/0
+#kvdb数据库连接格式:kvdb://{ip}:{prot}/{db},例如:kvdb://127.0.0.1:7078/test
ledger.db.uri=rocksdb:///export/app/peer/rocks.db/rocksdb0.db
#账本数据库的连接口令
@@ -168,32 +170,86 @@ ledger.db.pwd=
ledger.seed=932dfe23-fe23232f-283f32fa-dd32aa76-8322ca2f-56236cda-7136b322-cb323ffe
#账本的描述名称;此属性不参与共识,仅仅在当前参与方的本地节点用于描述用途;
-#ledger.name=
-
-#声明的账本创建时间;格式为 “yyyy-MM-dd HH:mm:ss.SSSZ”,表示”年-月-日 时:分:秒:毫秒时区“;例如:“2019-10-17 05:21:58.069+0800”,其中,+0800 表示时区是东8区
-created-time=2019-10-17 05:21:58.069+0800
-
+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
+
+
+#-----------------------------------------------
+# 初始的角色名称列表;可选项;
+# 角色名称不区分大小写,最长不超过20个字符;多个角色名称之间用半角的逗点“,”分隔;
+# 系统会预置一个默认角色“DEFAULT”,所有未指定角色的用户都以赋予该角色的权限;若初始化时未配置默认角色的权限,则为默认角色分配所有权限;
+#
+# 注:如果声明了角色,但未声明角色对应的权限清单,这会忽略该角色的初始化;
+#
+#security.roles=DEFAULT, ADMIN, MANAGER, GUEST
+
+# 赋予角色的账本权限清单;可选项;
+# 可选的权限如下;
+# AUTHORIZE_ROLES, SET_CONSENSUS, SET_CRYPTO, REGISTER_PARTICIPANT,
+# REGISTER_USER, REGISTER_DATA_ACCOUNT, REGISTER_CONTRACT, UPGRADE_CONTRACT,
+# SET_USER_ATTRIBUTES, WRITE_DATA_ACCOUNT,
+# APPROVE_TX, CONSENSUS_TX
+# 多项权限之间用逗点“,”分隔;
+#
+#security.role.DEFAULT.ledger-privileges=REGISTER_USER, REGISTER_DATA_ACCOUNT
+
+# 赋予角色的交易权限清单;可选项;
+# 可选的权限如下;
+# DIRECT_OPERATION, CONTRACT_OPERATION
+# 多项权限之间用逗点“,”分隔;
+#
+#security.role.DEFAULT.tx-privileges=DIRECT_OPERATION, CONTRACT_OPERATION
+
+# 其它角色的配置示例;
+# 系统管理员角色:只能操作全局性的参数配置和用户注册,只能执行直接操作指令;
+#security.role.ADMIN.ledger-privileges=CONFIGURE_ROLES, AUTHORIZE_USER_ROLES, SET_CONSENSUS, SET_CRYPTO, REGISTER_PARTICIPANT, REGISTER_USER
+#security.role.ADMIN.tx-privileges=DIRECT_OPERATION
+
+# 业务主管角色:只能够执行账本数据相关的操作,包括注册用户、注册数据账户、注册合约、升级合约、写入数据等;能够执行直接操作指令和调用合约;
+#security.role.MANAGER.ledger-privileges=CONFIGURE_ROLES, AUTHORIZE_USER_ROLES, REGISTER_USER, REGISTER_DATA_ACCOUNT, REGISTER_CONTRACT, UPGRADE_CONTRACT, SET_USER_ATTRIBUTES, WRITE_DATA_ACCOUNT,
+#security.role.MANAGER.tx-privileges=DIRECT_OPERATION, CONTRACT_OPERATION
+
+# 访客角色:不具备任何的账本权限,只有数据读取的操作;也只能够通过调用合约来读取数据;
+#security.role.GUEST.ledger-privileges=
+#security.role.GUEST.tx-privileges=CONTRACT_OPERATION
+
+
+#-----------------------------------------------
#共识服务提供者;必须;
consensus.service-provider=com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider
-#共识服务的参数配置;必须;
-#consensus.conf=/export/app/peer/config/init/bftsmart.config
+#共识服务的参数配置;推荐使用绝对路径;必须;
consensus.conf=bftsmart.config
#密码服务提供者列表,以英文逗点“,”分隔;必须;
crypto.service-providers=com.jd.blockchain.crypto.service.classic.ClassicCryptoService, \
com.jd.blockchain.crypto.service.sm.SMCryptoService
+#从存储中加载账本数据时,是否校验哈希;可选;
+crypto.verify-hash=true
+
+#哈希算法;
+crypto.hash-algorithm=SHA256
+
+
#参与方的个数,后续以 cons_parti.id 分别标识每一个参与方的配置;
cons_parti.count=4
-
+#---------------------
#第0个参与方的名称;
cons_parti.0.name=
#第0个参与方的公钥文件路径;
cons_parti.0.pubkey-path=
#第0个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数;
cons_parti.0.pubkey=
+
+#第0个参与方的角色清单;可选项;
+#cons_parti.0.roles=ADMIN, MANAGER
+#第0个参与方的角色权限策略,可选值有:UNION(并集),INTERSECT(交集);可选项;
+#cons_parti.0.roles-policy=UNION
+
#第0个参与方的账本初始服务的主机;
cons_parti.0.initializer.host=127.0.0.1
#第0个参与方的账本初始服务的端口;
@@ -201,24 +257,71 @@ cons_parti.0.initializer.port=8800
#第0个参与方的账本初始服务是否开启安全连接;
cons_parti.0.initializer.secure=false
+#---------------------
#第1个参与方的名称;
cons_parti.1.name=
#第1个参与方的公钥文件路径;
cons_parti.1.pubkey-path=
#第1个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数;
cons_parti.1.pubkey=
+
+#第1个参与方的角色清单;可选项;
+#cons_parti.1.roles=MANAGER
+#第1个参与方的角色权限策略,可选值有:UNION(并集),INTERSECT(交集);可选项;
+#cons_parti.1.roles-policy=UNION
+
#第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=
+#第2个参与方的公钥文件路径;
+cons_parti.2.pubkey-path=
+#第2个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数;
+cons_parti.2.pubkey=
+
+#第2个参与方的角色清单;可选项;
+#cons_parti.2.roles=MANAGER
+#第2个参与方的角色权限策略,可选值有:UNION(并集),INTERSECT(交集);可选项;
+#cons_parti.2.roles-policy=UNION
+
+#第2个参与方的账本初始服务的主机;
+cons_parti.2.initializer.host=127.0.0.1
+#第2个参与方的账本初始服务的端口;
+cons_parti.2.initializer.port=8820
+#第2个参与方的账本初始服务是否开启安全连接;
+cons_parti.2.initializer.secure=false
+
+#---------------------
+#第3个参与方的名称;
+cons_parti.3.name=
+#第3个参与方的公钥文件路径;
+cons_parti.3.pubkey-path=
+#第3个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数;
+cons_parti.3.pubkey=
+
+#第3个参与方的角色清单;可选项;
+#cons_parti.3.roles=GUEST
+#第3个参与方的角色权限策略,可选值有:UNION(并集),INTERSECT(交集);可选项;
+#cons_parti.3.roles-policy=INTERSECT
+
+#第3个参与方的账本初始服务的主机;
+cons_parti.3.initializer.host=127.0.0.1
+#第3个参与方的账本初始服务的端口;
+cons_parti.3.initializer.port=8830
+#第3个参与方的账本初始服务是否开启安全连接;
+cons_parti.3.initializer.secure=false
```
账本初始化过程中,需要其他Peer节点的公钥信息进行验证及保存,因此每个节点都需要获取其他Peer节点的公钥信息至本地。配置中cons_parti.N.*****中的N需按照实际每个参与方定义的序号配置(该配置为local.conf中的local.parti.id)。其他参数根据实际环境进行配置。
> 注意:上述config中只显示了两个参与方(Peer节点)的配置信息,其他参与方(默认是4个节点)的配置方式一致!
-##### 2.3.1.1 bftsmart.config配置
+##### 2.3.1.3 bftsmart.config配置
```config
system.server.0.network.host=127.0.0.1
system.server.0.network.port=16000
@@ -247,27 +350,37 @@ system.initial.view = 0,1,2,3
cd bin
./ledger-init.sh
```
-执行命令之后,会在 *config* 目录下生成ledger-binding.conf文件,该文件即账本初始化生成的文件,Peer节点启动时需要依赖该文件。
+执行命令之后,控制台会显示如下类似信息:
+```
+------ Web controller of Ledger Initializer[127.0.0.1:30010] was started. ------
+
+Init settings and sign permision...
+[PERMISSION_READY] Ledger init permission has already prepared! Any key to continue...
+```
+然后需要依次启动剩余节点的初始化脚本(*ledger-init.sh*),根据提示按任意键继续。
+如果其它节点没有准备好,控制台会展示“Connection refused”异常信息,不断进行重试操作。目前默认设置为重试180次操作,每次间隔时间10秒。
+执行成功后会在 *config* 目录下生成ledger-binding.conf文件,该文件即账本初始化生成的文件,Peer节点启动时需要依赖该文件。
> 1)注意:因为JDChain支持多账本形式,若config/ledger-binding.conf文件在初始化之前就存在的话,初始化操作后不会覆盖其中的内容,会以追加的方式写入。若第一次创建账本,建议先将该文件删除再进行初始化!
-> 2)注意:Peer节点会定时检测ledger-binding.conf,有新账本加入时会自动进行更新,不需要重启Peer节点!目前默认时间为封5自动更新,即:每个小时的5/15/25/35/45/55分钟会执行;
+> 2)注意:Peer节点会定时检测ledger-binding.conf,有新账本加入时会自动进行更新,不需要重启Peer节点!目前默认时间每隔5秒钟自动更新;
账本初始化成功后,每个Peer节点对应的Rocksdb都会写入该账本相关的数据。
-### 2.4 Peer节点安装
-Peer节点启动依赖于 *config* 目录下ledger-binding.conf的配置,该文件由 *2.3章节* 操作生成,无须做任何修改;application.properties文件中主要用于配置Peer节点对外HTTP端口。
-> 注意:application.properties文件可能不存在,可手动创建。该文件中配置适用于SpringBoot2.x版本的相关参数,不限于目前内置的启动端口。
+### 2.4 Peer节点启动
+Peer节点启动依赖于 *config* 目录下ledger-binding.conf的配置,该文件由 *2.3章节* 操作生成,无须做任何修改。
-由于Peer节点启动后会自动与其他参与节点进行通信,因此需要同时启动4个Peer节点,只需要执行startup.sh即可,参考命令:
+由于Peer节点启动后会自动与其他参与节点进行通信,因此需要同时启动4个Peer节点,只需要执行peer-startup.sh即可,参考命令:
```shell
cd bin
-./startup.sh
+./peer-startup.sh
```
-> 1)注意:startup.sh命令中可修改启动端口,默认为:-p 7080;
+> 1)注意:peer-startup.sh命令中可修改启动端口,默认为:-p 7080;
-> 2)注意:Peer节点会与账本中涉及到的参与方进行通信,当通信不成功(例如有节点尚未启动)时,会自动进行重试,因此多个Peer节点启动可不必完全同时进行。目前默认设置为重试16次操作,每次间隔时间2秒。
+> 2)注意:peer-startup.sh命令执行后,会在其所在文件夹中生成对应的peer.out日志文件;
-### 2.5 Gateway节点安装
+> 3)注意:Peer节点会与账本中涉及到的参与方进行通信,当通信不成功(例如有节点尚未启动)时,会自动进行重试,因此多个Peer节点启动可不必完全同时进行。
+
+### 2.5 Gateway节点启动
GateWay(网关)节点可以认为是一个过滤节点,交易的提交及账本的查询都需要通过网关节点与Peer节点进行通信。
Gateway程序可独立部署,不需要依赖Peer节点,它的操作环境是 *2.1.2章节* 中解压后的环境,网关节点启动依赖于配置文件 *config/gateway.conf*。
@@ -301,15 +414,13 @@ keys.default.privkey=
#默认私钥的解码密码;
keys.default.privkey-password=
```
-其中keys.default.% 配置是网关的角色配置,目前暂不支持网关自定义角色,因此,网关可选择4个参与方的任何一个作为其配置(主要是密钥对)。
->注意:keys.default.privkey-password填写内容为*2.2章节*中生成的%.pwd文件中的内容!
启动网关节点只需要执行:startup.sh即可,参考命令:
```shell
cd bin
./startup.sh
```
-
+命令执行后,会在其所在文件夹中生成对应的gw.out日志文件;
网关节点启动成功后,可通过访问区块链浏览器获取其账本相关信息:http://[ip]:[port]
下图为区块链浏览器首页,可供参考: