+
org.springframework.boot
diff --git a/source/gateway/src/main/java/com/jd/blockchain/gateway/GatewayServerBooter.java b/source/gateway/src/main/java/com/jd/blockchain/gateway/GatewayServerBooter.java
index 3b9604f3..76c39b61 100644
--- a/source/gateway/src/main/java/com/jd/blockchain/gateway/GatewayServerBooter.java
+++ b/source/gateway/src/main/java/com/jd/blockchain/gateway/GatewayServerBooter.java
@@ -5,20 +5,20 @@ import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
-import com.jd.blockchain.gateway.web.BlockBrowserController;
import org.apache.commons.io.FileUtils;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.io.ClassPathResource;
import com.jd.blockchain.crypto.AsymmetricKeypair;
+import com.jd.blockchain.crypto.KeyGenUtils;
import com.jd.blockchain.crypto.PrivKey;
import com.jd.blockchain.crypto.PubKey;
-import com.jd.blockchain.tools.keygen.KeyGenCommand;
+import com.jd.blockchain.gateway.web.BlockBrowserController;
import com.jd.blockchain.utils.ArgumentSet;
+import com.jd.blockchain.utils.ArgumentSet.ArgEntry;
import com.jd.blockchain.utils.BaseConstant;
import com.jd.blockchain.utils.ConsoleUtils;
-import com.jd.blockchain.utils.ArgumentSet.ArgEntry;
public class GatewayServerBooter {
@@ -88,19 +88,19 @@ public class GatewayServerBooter {
String base58Pwd = config.keys().getDefault().getPrivKeyPassword();
if (base58Pwd == null || base58Pwd.length() == 0) {
- base58Pwd = KeyGenCommand.readPasswordString();
+ base58Pwd = KeyGenUtils.readPasswordString();
}
// 加载密钥;
- PubKey pubKey = KeyGenCommand.decodePubKey(config.keys().getDefault().getPubKeyValue());
+ PubKey pubKey = KeyGenUtils.decodePubKey(config.keys().getDefault().getPubKeyValue());
PrivKey privKey = null;
String base58PrivKey = config.keys().getDefault().getPrivKeyValue();
if (base58PrivKey == null) {
//注:GatewayConfigProperties 确保了 PrivKeyValue 和 PrivKeyPath 必有其一;
- privKey = KeyGenCommand.readPrivKey(config.keys().getDefault().getPrivKeyPath(), base58Pwd);
+ privKey = KeyGenUtils.readPrivKey(config.keys().getDefault().getPrivKeyPath(), base58Pwd);
} else {
- privKey = KeyGenCommand.decodePrivKey(base58PrivKey, base58Pwd);
+ privKey = KeyGenUtils.decodePrivKey(base58PrivKey, base58Pwd);
}
defaultKeyPair = new AsymmetricKeypair(pubKey, privKey);
}
diff --git a/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryService.java b/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryService.java
index 340527c7..d88f49aa 100644
--- a/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryService.java
+++ b/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryService.java
@@ -4,7 +4,6 @@ import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.sdk.ContractSettings;
import com.jd.blockchain.sdk.LedgerInitSettings;
-import com.jd.blockchain.utils.Bytes;
/**
* queryService only for gateway;
diff --git a/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryServiceHandler.java b/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryServiceHandler.java
index 4ff94632..451beec4 100644
--- a/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryServiceHandler.java
+++ b/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryServiceHandler.java
@@ -6,6 +6,7 @@ import com.jd.blockchain.consensus.ConsensusSettings;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.gateway.PeerService;
import com.jd.blockchain.ledger.ContractInfo;
+import com.jd.blockchain.ledger.LedgerAdminInfo;
import com.jd.blockchain.ledger.LedgerMetadata;
import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.sdk.ContractSettings;
@@ -51,7 +52,9 @@ public class GatewayQueryServiceHandler implements GatewayQueryService {
LedgerMetadata ledgerMetadata = peerService.getQueryService().getLedgerMetadata(ledgerHash);
- return initLedgerInitSettings(participantNodes, ledgerMetadata);
+ LedgerAdminInfo ledgerAdminInfo = peerService.getQueryService().getLedgerAdminInfo(ledgerHash);
+
+ return initLedgerInitSettings(participantNodes, ledgerMetadata, ledgerAdminInfo);
}
@Override
@@ -78,26 +81,26 @@ public class GatewayQueryServiceHandler implements GatewayQueryService {
* 账本元数据
* @return
*/
- private LedgerInitSettings initLedgerInitSettings(ParticipantNode[] participantNodes, LedgerMetadata ledgerMetadata) {
+ private LedgerInitSettings initLedgerInitSettings(ParticipantNode[] participantNodes, LedgerMetadata ledgerMetadata, LedgerAdminInfo ledgerAdminInfo) {
LedgerInitSettings ledgerInitSettings = new LedgerInitSettings();
// 设置参与方
ledgerInitSettings.setParticipantNodes(participantNodes);
// 设置共识设置
- ledgerInitSettings.setConsensusSettings(initConsensusSettings(ledgerMetadata));
+ ledgerInitSettings.setConsensusSettings(initConsensusSettings(ledgerAdminInfo));
// 设置参与方根Hash
ledgerInitSettings.setParticipantsHash(ledgerMetadata.getParticipantsHash());
// 设置算法配置
- ledgerInitSettings.setCryptoSetting(ledgerMetadata.getSetting().getCryptoSetting());
+ ledgerInitSettings.setCryptoSetting(ledgerAdminInfo.getSettings().getCryptoSetting());
// 设置种子
ledgerInitSettings.setSeed(initSeed(ledgerMetadata.getSeed()));
// 设置共识协议
- ledgerInitSettings.setConsensusProtocol(ledgerMetadata.getSetting().getConsensusProvider());
+ ledgerInitSettings.setConsensusProtocol(ledgerAdminInfo.getSettings().getConsensusProvider());
return ledgerInitSettings;
}
@@ -129,14 +132,14 @@ public class GatewayQueryServiceHandler implements GatewayQueryService {
/**
* 初始化共识配置
*
- * @param ledgerMetadata
+ * @param ledgerAdminInfo
* 账本元数据
* @return
*/
- private ConsensusSettings initConsensusSettings(LedgerMetadata ledgerMetadata) {
- String consensusProvider = ledgerMetadata.getSetting().getConsensusProvider();
+ private ConsensusSettings initConsensusSettings(LedgerAdminInfo ledgerAdminInfo) {
+ String consensusProvider = ledgerAdminInfo.getSettings().getConsensusProvider();
ConsensusProvider provider = ConsensusProviders.getProvider(consensusProvider);
- byte[] consensusSettingsBytes = ledgerMetadata.getSetting().getConsensusSetting().toBytes();
+ byte[] consensusSettingsBytes = ledgerAdminInfo.getSettings().getConsensusSetting().toBytes();
return provider.getSettingsFactory().getConsensusSettingsEncoder().decode(consensusSettingsBytes);
}
}
diff --git a/source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java b/source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java
index 91c498aa..162702ab 100644
--- a/source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java
+++ b/source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java
@@ -1,546 +1,581 @@
package com.jd.blockchain.gateway.web;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import com.jd.blockchain.utils.decompiler.utils.DecompilerUtils;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
import com.jd.blockchain.crypto.AddressEncoding;
import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.crypto.KeyGenUtils;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.gateway.PeerService;
import com.jd.blockchain.gateway.service.DataRetrievalService;
-import com.jd.blockchain.gateway.service.GatewayQueryService;
-import com.jd.blockchain.ledger.*;
+import com.jd.blockchain.ledger.AccountHeader;
+import com.jd.blockchain.ledger.ContractInfo;
+import com.jd.blockchain.ledger.KVDataEntry;
+import com.jd.blockchain.ledger.KVInfoVO;
+import com.jd.blockchain.ledger.LedgerAdminInfo;
+import com.jd.blockchain.ledger.LedgerBlock;
+import com.jd.blockchain.ledger.LedgerInfo;
+import com.jd.blockchain.ledger.LedgerMetadata;
+import com.jd.blockchain.ledger.LedgerTransaction;
+import com.jd.blockchain.ledger.ParticipantNode;
+import com.jd.blockchain.ledger.TransactionState;
+import com.jd.blockchain.ledger.UserInfo;
import com.jd.blockchain.sdk.BlockchainExtendQueryService;
import com.jd.blockchain.sdk.ContractSettings;
-import com.jd.blockchain.sdk.LedgerInitSettings;
-import com.jd.blockchain.tools.keygen.KeyGenCommand;
import com.jd.blockchain.utils.BaseConstant;
import com.jd.blockchain.utils.ConsoleUtils;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
-
-import javax.servlet.http.HttpServletRequest;
-import java.util.ArrayList;
-import java.util.List;
@RestController
@RequestMapping(path = "/")
public class BlockBrowserController implements BlockchainExtendQueryService {
- private static org.slf4j.Logger LOGGER = LoggerFactory.getLogger(BlockBrowserController.class);
+ private static org.slf4j.Logger LOGGER = LoggerFactory.getLogger(BlockBrowserController.class);
@Autowired
private PeerService peerService;
@Autowired
- private DataRetrievalService dataRetrievalService;
-
- @Autowired
- private GatewayQueryService gatewayQueryService;
+ private DataRetrievalService dataRetrievalService;
- private String dataRetrievalUrl;
+ private String dataRetrievalUrl;
private static final long BLOCK_MAX_DISPLAY = 3L;
private static final long GENESIS_BLOCK_HEIGHT = 0L;
- @Deprecated
-// @RequestMapping(method = RequestMethod.GET, path = "ledgers")
- @Override
- public HashDigest[] getLedgerHashs() {
- return peerService.getQueryService().getLedgerHashs();
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}")
- @Override
- public LedgerInfo getLedger(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
- return peerService.getQueryService().getLedger(ledgerHash);
- }
-
-// @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/participants")
- @Override
- public ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash) {
- return peerService.getQueryService().getConsensusParticipants(ledgerHash);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/metadata")
- @Override
- public LedgerMetadata getLedgerMetadata(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
- return peerService.getQueryService().getLedgerMetadata(ledgerHash);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/settings")
- public LedgerInitSettings getLedgerInitSettings(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
- return gatewayQueryService.getLedgerInitSettings(ledgerHash);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks")
- public LedgerBlock[] getBlocks(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
- LedgerInfo ledgerInfo = peerService.getQueryService().getLedger(ledgerHash);
- long maxBlockHeight = ledgerInfo.getLatestBlockHeight();
- List ledgerBlocks = new ArrayList<>();
- for (long blockHeight = maxBlockHeight; blockHeight > GENESIS_BLOCK_HEIGHT; blockHeight--) {
- LedgerBlock ledgerBlock = peerService.getQueryService().getBlock(ledgerHash, blockHeight);
- ledgerBlocks.add(0, ledgerBlock);
- if (ledgerBlocks.size() == BLOCK_MAX_DISPLAY) {
- break;
- }
- }
- // 最后增加创世区块
- LedgerBlock genesisBlock = peerService.getQueryService().getBlock(ledgerHash, GENESIS_BLOCK_HEIGHT);
- ledgerBlocks.add(0, genesisBlock);
- LedgerBlock[] blocks = new LedgerBlock[ledgerBlocks.size()];
- ledgerBlocks.toArray(blocks);
- return blocks;
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}")
- @Override
- public LedgerBlock getBlock(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @PathVariable(name = "blockHeight") long blockHeight) {
- return peerService.getQueryService().getBlock(ledgerHash, blockHeight);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}")
- @Override
- public LedgerBlock getBlock(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @PathVariable(name = "blockHash") HashDigest blockHash) {
- return peerService.getQueryService().getBlock(ledgerHash, blockHash);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/txs/count")
- @Override
- public long getTransactionCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @PathVariable(name = "blockHeight") long blockHeight) {
- return peerService.getQueryService().getTransactionCount(ledgerHash, blockHeight);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/txs/count")
- @Override
- public long getTransactionCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @PathVariable(name = "blockHash") HashDigest blockHash) {
- return peerService.getQueryService().getTransactionCount(ledgerHash, blockHash);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/txs/count")
- @Override
- public long getTransactionTotalCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
- return peerService.getQueryService().getTransactionTotalCount(ledgerHash);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/accounts/count")
- @Override
- public long getDataAccountCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @PathVariable(name = "blockHeight") long blockHeight) {
- return peerService.getQueryService().getDataAccountCount(ledgerHash, blockHeight);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/accounts/count")
- @Override
- public long getDataAccountCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @PathVariable(name = "blockHash") HashDigest blockHash) {
- return peerService.getQueryService().getDataAccountCount(ledgerHash, blockHash);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts/count")
- @Override
- public long getDataAccountTotalCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
- return peerService.getQueryService().getDataAccountTotalCount(ledgerHash);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/users/count")
- @Override
- public long getUserCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @PathVariable(name = "blockHeight") long blockHeight) {
- return peerService.getQueryService().getUserCount(ledgerHash, blockHeight);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/users/count")
- @Override
- public long getUserCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @PathVariable(name = "blockHash") HashDigest blockHash) {
- return peerService.getQueryService().getUserCount(ledgerHash, blockHash);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/users/count")
- @Override
- public long getUserTotalCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
- return peerService.getQueryService().getUserTotalCount(ledgerHash);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/contracts/count")
- @Override
- public long getContractCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @PathVariable(name = "blockHeight") long blockHeight) {
- return peerService.getQueryService().getContractCount(ledgerHash, blockHeight);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/contracts/count")
- @Override
- public long getContractCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @PathVariable(name = "blockHash") HashDigest blockHash) {
- return peerService.getQueryService().getContractCount(ledgerHash, blockHash);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts/count")
- @Override
- public long getContractTotalCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
- return peerService.getQueryService().getContractTotalCount(ledgerHash);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/txs")
- @Override
- public LedgerTransaction[] getTransactions(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @PathVariable(name = "blockHeight") long blockHeight,
- @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
- @RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
- return peerService.getQueryService().getTransactions(ledgerHash, blockHeight, fromIndex, count);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/txs")
- @Override
- public LedgerTransaction[] getTransactions(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @PathVariable(name = "blockHash") HashDigest blockHash,
- @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
- @RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
- return peerService.getQueryService().getTransactions(ledgerHash, blockHash, fromIndex, count);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/txs/hash/{contentHash}")
- @Override
- public LedgerTransaction getTransactionByContentHash(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @PathVariable(name = "contentHash") HashDigest contentHash) {
- return peerService.getQueryService().getTransactionByContentHash(ledgerHash, contentHash);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/txs/state/{contentHash}")
- @Override
- public TransactionState getTransactionStateByContentHash(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @PathVariable(name = "contentHash") HashDigest contentHash) {
- return peerService.getQueryService().getTransactionStateByContentHash(ledgerHash, contentHash);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/users/address/{address}")
- @Override
- public UserInfo getUser(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @PathVariable(name = "address") String address) {
- return peerService.getQueryService().getUser(ledgerHash, address);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts/address/{address}")
- @Override
- public AccountHeader getDataAccount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @PathVariable(name = "address") String address) {
-
- return peerService.getQueryService().getDataAccount(ledgerHash, address);
- }
-
- @RequestMapping(method = {RequestMethod.GET, RequestMethod.POST}, path = "ledgers/{ledgerHash}/accounts/{address}/entries")
- @Override
- public KVDataEntry[] getDataEntries(@PathVariable("ledgerHash") HashDigest ledgerHash,
- @PathVariable("address") String address,
- @RequestParam("keys") String... keys) {
- return peerService.getQueryService().getDataEntries(ledgerHash, address, keys);
- }
-
- @RequestMapping(method = {RequestMethod.GET, RequestMethod.POST}, path = "ledgers/{ledgerHash}/accounts/{address}/entries-version")
- public KVDataEntry[] getDataEntries(@PathVariable("ledgerHash") HashDigest ledgerHash,
- @PathVariable("address") String address,
- @RequestBody KVInfoVO kvInfoVO) {
- return peerService.getQueryService().getDataEntries(ledgerHash, address, kvInfoVO);
- }
-
- @RequestMapping(method = {RequestMethod.GET, RequestMethod.POST}, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries")
- @Override
- public KVDataEntry[] getDataEntries(@PathVariable("ledgerHash") HashDigest ledgerHash,
- @PathVariable("address") String address,
- @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
- @RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
- return peerService.getQueryService().getDataEntries(ledgerHash, address, fromIndex, count);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries/count")
- @Override
- public long getDataEntriesTotalCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @PathVariable(name = "address") String address) {
- return peerService.getQueryService().getDataEntriesTotalCount(ledgerHash, address);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts/address/{address}")
- public ContractSettings getContractSettings(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @PathVariable(name = "address") String address) {
- return gatewayQueryService.getContractSettings(ledgerHash, address);
- }
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers")
+ @Override
+ public HashDigest[] getLedgerHashs() {
+ return peerService.getQueryService().getLedgerHashs();
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}")
+ @Override
+ public LedgerInfo getLedger(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
+ return peerService.getQueryService().getLedger(ledgerHash);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/admininfo")
+ @Override
+ public LedgerAdminInfo getLedgerAdminInfo(HashDigest ledgerHash) {
+ return peerService.getQueryService().getLedgerAdminInfo(ledgerHash);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/participants")
+ @Override
+ public ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash) {
+ return peerService.getQueryService().getConsensusParticipants(ledgerHash);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/metadata")
+ @Override
+ public LedgerMetadata getLedgerMetadata(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
+ return peerService.getQueryService().getLedgerMetadata(ledgerHash);
+ }
+
+// @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/settings")
+// public LedgerInitSettings getLedgerInitSettings(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
+// return gatewayQueryService.getLedgerInitSettings(ledgerHash);
+// }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks")
+ public LedgerBlock[] getBlocks(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
+ LedgerInfo ledgerInfo = peerService.getQueryService().getLedger(ledgerHash);
+ long maxBlockHeight = ledgerInfo.getLatestBlockHeight();
+ List ledgerBlocks = new ArrayList<>();
+ for (long blockHeight = maxBlockHeight; blockHeight > GENESIS_BLOCK_HEIGHT; blockHeight--) {
+ LedgerBlock ledgerBlock = peerService.getQueryService().getBlock(ledgerHash, blockHeight);
+ ledgerBlocks.add(0, ledgerBlock);
+ if (ledgerBlocks.size() == BLOCK_MAX_DISPLAY) {
+ break;
+ }
+ }
+ // 最后增加创世区块
+ LedgerBlock genesisBlock = peerService.getQueryService().getBlock(ledgerHash, GENESIS_BLOCK_HEIGHT);
+ ledgerBlocks.add(0, genesisBlock);
+ LedgerBlock[] blocks = new LedgerBlock[ledgerBlocks.size()];
+ ledgerBlocks.toArray(blocks);
+ return blocks;
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}")
+ @Override
+ public LedgerBlock getBlock(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @PathVariable(name = "blockHeight") long blockHeight) {
+ return peerService.getQueryService().getBlock(ledgerHash, blockHeight);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}")
+ @Override
+ public LedgerBlock getBlock(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @PathVariable(name = "blockHash") HashDigest blockHash) {
+ return peerService.getQueryService().getBlock(ledgerHash, blockHash);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/txs/count")
+ @Override
+ public long getTransactionCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @PathVariable(name = "blockHeight") long blockHeight) {
+ return peerService.getQueryService().getTransactionCount(ledgerHash, blockHeight);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/txs/count")
+ @Override
+ public long getTransactionCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @PathVariable(name = "blockHash") HashDigest blockHash) {
+ return peerService.getQueryService().getTransactionCount(ledgerHash, blockHash);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/txs/count")
+ @Override
+ public long getTransactionTotalCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
+ return peerService.getQueryService().getTransactionTotalCount(ledgerHash);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/accounts/count")
+ @Override
+ public long getDataAccountCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @PathVariable(name = "blockHeight") long blockHeight) {
+ return peerService.getQueryService().getDataAccountCount(ledgerHash, blockHeight);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/accounts/count")
+ @Override
+ public long getDataAccountCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @PathVariable(name = "blockHash") HashDigest blockHash) {
+ return peerService.getQueryService().getDataAccountCount(ledgerHash, blockHash);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts/count")
+ @Override
+ public long getDataAccountTotalCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
+ return peerService.getQueryService().getDataAccountTotalCount(ledgerHash);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/users/count")
+ @Override
+ public long getUserCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @PathVariable(name = "blockHeight") long blockHeight) {
+ return peerService.getQueryService().getUserCount(ledgerHash, blockHeight);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/users/count")
+ @Override
+ public long getUserCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @PathVariable(name = "blockHash") HashDigest blockHash) {
+ return peerService.getQueryService().getUserCount(ledgerHash, blockHash);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/users/count")
+ @Override
+ public long getUserTotalCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
+ return peerService.getQueryService().getUserTotalCount(ledgerHash);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/contracts/count")
+ @Override
+ public long getContractCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @PathVariable(name = "blockHeight") long blockHeight) {
+ return peerService.getQueryService().getContractCount(ledgerHash, blockHeight);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/contracts/count")
+ @Override
+ public long getContractCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @PathVariable(name = "blockHash") HashDigest blockHash) {
+ return peerService.getQueryService().getContractCount(ledgerHash, blockHash);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts/count")
+ @Override
+ public long getContractTotalCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
+ return peerService.getQueryService().getContractTotalCount(ledgerHash);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/txs")
+ @Override
+ public LedgerTransaction[] getTransactions(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @PathVariable(name = "blockHeight") long blockHeight,
+ @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
+ @RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
+ return peerService.getQueryService().getTransactions(ledgerHash, blockHeight, fromIndex, count);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/txs")
+ @Override
+ public LedgerTransaction[] getTransactions(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @PathVariable(name = "blockHash") HashDigest blockHash,
+ @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
+ @RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
+ return peerService.getQueryService().getTransactions(ledgerHash, blockHash, fromIndex, count);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/txs/hash/{contentHash}")
+ @Override
+ public LedgerTransaction getTransactionByContentHash(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @PathVariable(name = "contentHash") HashDigest contentHash) {
+ return peerService.getQueryService().getTransactionByContentHash(ledgerHash, contentHash);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/txs/state/{contentHash}")
+ @Override
+ public TransactionState getTransactionStateByContentHash(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @PathVariable(name = "contentHash") HashDigest contentHash) {
+ return peerService.getQueryService().getTransactionStateByContentHash(ledgerHash, contentHash);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/users/address/{address}")
+ @Override
+ public UserInfo getUser(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @PathVariable(name = "address") String address) {
+ return peerService.getQueryService().getUser(ledgerHash, address);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts/address/{address}")
+ @Override
+ public AccountHeader getDataAccount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @PathVariable(name = "address") String address) {
+
+ return peerService.getQueryService().getDataAccount(ledgerHash, address);
+ }
+
+ @RequestMapping(method = { RequestMethod.GET,
+ RequestMethod.POST }, path = "ledgers/{ledgerHash}/accounts/{address}/entries")
+ @Override
+ public KVDataEntry[] getDataEntries(@PathVariable("ledgerHash") HashDigest ledgerHash,
+ @PathVariable("address") String address, @RequestParam("keys") String... keys) {
+ return peerService.getQueryService().getDataEntries(ledgerHash, address, keys);
+ }
+
+ @RequestMapping(method = { RequestMethod.GET,
+ RequestMethod.POST }, path = "ledgers/{ledgerHash}/accounts/{address}/entries-version")
+ @Override
+ public KVDataEntry[] getDataEntries(@PathVariable("ledgerHash") HashDigest ledgerHash,
+ @PathVariable("address") String address, @RequestBody KVInfoVO kvInfoVO) {
+ return peerService.getQueryService().getDataEntries(ledgerHash, address, kvInfoVO);
+ }
+
+ @RequestMapping(method = { RequestMethod.GET,
+ RequestMethod.POST }, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries")
+ @Override
+ public KVDataEntry[] getDataEntries(@PathVariable("ledgerHash") HashDigest ledgerHash,
+ @PathVariable("address") String address,
+ @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
+ @RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
+ return peerService.getQueryService().getDataEntries(ledgerHash, address, fromIndex, count);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries/count")
+ @Override
+ public long getDataEntriesTotalCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @PathVariable(name = "address") String address) {
+ return peerService.getQueryService().getDataEntriesTotalCount(ledgerHash, address);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts/address/{address}")
+ public ContractSettings getContractSettings(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @PathVariable(name = "address") String address) {
+ ContractInfo contractInfo = peerService.getQueryService().getContract(ledgerHash, address);
+ return contractSettings(contractInfo);
+ }
+
+ private ContractSettings contractSettings(ContractInfo contractInfo) {
+ ContractSettings contractSettings = new ContractSettings(contractInfo.getAddress(), contractInfo.getPubKey(),
+ contractInfo.getRootHash());
+ byte[] chainCodeBytes = contractInfo.getChainCode();
+ // 将反编译chainCode
+ String mainClassJava = DecompilerUtils.decompileMainClassFromBytes(chainCodeBytes);
+ contractSettings.setChainCode(mainClassJava);
+ return contractSettings;
+ }
// @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts/address/{address}")
- @Override
- public ContractInfo getContract(HashDigest ledgerHash, String address) {
- return peerService.getQueryService().getContract(ledgerHash, address);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/latest")
- @Override
- public LedgerBlock getLatestBlock(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
- long latestBlockHeight = peerService.getQueryService().getLedger(ledgerHash).getLatestBlockHeight();
- return peerService.getQueryService().getBlock(ledgerHash, latestBlockHeight);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/txs/additional-count")
- @Override
- public long getAdditionalTransactionCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @PathVariable(name = "blockHeight") long blockHeight) {
- // 获取某个区块的交易总数
- long currentBlockTxCount = peerService.getQueryService().getTransactionCount(ledgerHash, blockHeight);
- if (blockHeight == GENESIS_BLOCK_HEIGHT) {
- return currentBlockTxCount;
- }
- long lastBlockHeight = blockHeight - 1;
- long lastBlockTxCount = peerService.getQueryService().getTransactionCount(ledgerHash, lastBlockHeight);
- // 当前区块交易数减上个区块交易数
- return currentBlockTxCount - lastBlockTxCount;
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/txs/additional-count")
- @Override
- public long getAdditionalTransactionCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @PathVariable(name = "blockHash") HashDigest blockHash) {
- LedgerBlock currentBlock = peerService.getQueryService().getBlock(ledgerHash, blockHash);
- long currentBlockTxCount = peerService.getQueryService().getTransactionCount(ledgerHash, blockHash);
- if (currentBlock.getHeight() == GENESIS_BLOCK_HEIGHT) {
- return currentBlockTxCount;
- }
- HashDigest previousHash = currentBlock.getPreviousHash();
- long lastBlockTxCount = peerService.getQueryService().getTransactionCount(ledgerHash, previousHash);
- // 当前区块交易数减上个区块交易数
- return currentBlockTxCount - lastBlockTxCount;
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/txs/additional-count")
- @Override
- public long getAdditionalTransactionCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
- LedgerInfo ledgerInfo = peerService.getQueryService().getLedger(ledgerHash);
- long maxBlockHeight = ledgerInfo.getLatestBlockHeight();
- long totalCount = peerService.getQueryService().getTransactionTotalCount(ledgerHash);
- if (maxBlockHeight == GENESIS_BLOCK_HEIGHT) { // 只有一个创世区块
- return totalCount;
- }
- long lastTotalCount = peerService.getQueryService().getTransactionCount(ledgerHash, maxBlockHeight - 1);
- return totalCount - lastTotalCount;
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/accounts/additional-count")
- @Override
- public long getAdditionalDataAccountCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @PathVariable(name = "blockHeight") long blockHeight) {
- long currentDaCount = peerService.getQueryService().getDataAccountCount(ledgerHash, blockHeight);
- if (blockHeight == GENESIS_BLOCK_HEIGHT) {
- return currentDaCount;
- }
- long lastBlockHeight = blockHeight - 1;
- long lastDaCount = peerService.getQueryService().getDataAccountCount(ledgerHash, lastBlockHeight);
- return currentDaCount - lastDaCount;
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/accounts/additional-count")
- @Override
- public long getAdditionalDataAccountCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @PathVariable(name = "blockHash") HashDigest blockHash) {
- LedgerBlock currentBlock = peerService.getQueryService().getBlock(ledgerHash, blockHash);
- long currentBlockDaCount = peerService.getQueryService().getDataAccountCount(ledgerHash, blockHash);
- if (currentBlock.getHeight() == GENESIS_BLOCK_HEIGHT) {
- return currentBlockDaCount;
- }
- HashDigest previousHash = currentBlock.getPreviousHash();
- long lastBlockDaCount = peerService.getQueryService().getDataAccountCount(ledgerHash, previousHash);
- // 当前区块数据账户数量减上个区块数据账户数量
- return currentBlockDaCount - lastBlockDaCount;
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts/additional-count")
- @Override
- public long getAdditionalDataAccountCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
- LedgerInfo ledgerInfo = peerService.getQueryService().getLedger(ledgerHash);
- long maxBlockHeight = ledgerInfo.getLatestBlockHeight();
- long totalCount = peerService.getQueryService().getDataAccountTotalCount(ledgerHash);
- if (maxBlockHeight == GENESIS_BLOCK_HEIGHT) { // 只有一个创世区块
- return totalCount;
- }
- long lastTotalCount = peerService.getQueryService().getDataAccountCount(ledgerHash, maxBlockHeight - 1);
- return totalCount - lastTotalCount;
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/users/additional-count")
- @Override
- public long getAdditionalUserCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @PathVariable(name = "blockHeight") long blockHeight) {
- long currentUserCount = peerService.getQueryService().getUserCount(ledgerHash, blockHeight);
- if (blockHeight == GENESIS_BLOCK_HEIGHT) {
- return currentUserCount;
- }
- long lastBlockHeight = blockHeight - 1;
- long lastUserCount = peerService.getQueryService().getUserCount(ledgerHash, lastBlockHeight);
- return currentUserCount - lastUserCount;
- }
-
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/users/additional-count")
- @Override
- public long getAdditionalUserCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @PathVariable(name = "blockHash") HashDigest blockHash) {
- LedgerBlock currentBlock = peerService.getQueryService().getBlock(ledgerHash, blockHash);
- long currentBlockUserCount = peerService.getQueryService().getUserCount(ledgerHash, blockHash);
- if (currentBlock.getHeight() == GENESIS_BLOCK_HEIGHT) {
- return currentBlockUserCount;
- }
- HashDigest previousHash = currentBlock.getPreviousHash();
- long lastBlockUserCount = peerService.getQueryService().getUserCount(ledgerHash, previousHash);
- // 当前区块用户数量减上个区块用户数量
- return currentBlockUserCount - lastBlockUserCount;
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/users/additional-count")
- @Override
- public long getAdditionalUserCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
- LedgerInfo ledgerInfo = peerService.getQueryService().getLedger(ledgerHash);
- long maxBlockHeight = ledgerInfo.getLatestBlockHeight();
- long totalCount = peerService.getQueryService().getUserTotalCount(ledgerHash);
- if (maxBlockHeight == GENESIS_BLOCK_HEIGHT) { // 只有一个创世区块
- return totalCount;
- }
- long lastTotalCount = peerService.getQueryService().getUserCount(ledgerHash, maxBlockHeight - 1);
- return totalCount - lastTotalCount;
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/contracts/additional-count")
- @Override
- public long getAdditionalContractCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @PathVariable(name = "blockHeight") long blockHeight) {
- long currentContractCount = peerService.getQueryService().getContractCount(ledgerHash, blockHeight);
- if (blockHeight == GENESIS_BLOCK_HEIGHT) {
- return currentContractCount;
- }
- long lastBlockHeight = blockHeight - 1;
- long lastContractCount = peerService.getQueryService().getUserCount(ledgerHash, lastBlockHeight);
- return currentContractCount - lastContractCount;
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/contracts/additional-count")
- @Override
- public long getAdditionalContractCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @PathVariable(name = "blockHash") HashDigest blockHash) {
- LedgerBlock currentBlock = peerService.getQueryService().getBlock(ledgerHash, blockHash);
- long currentBlockContractCount = peerService.getQueryService().getContractCount(ledgerHash, blockHash);
- if (currentBlock.getHeight() == GENESIS_BLOCK_HEIGHT) {
- return currentBlockContractCount;
- }
- HashDigest previousHash = currentBlock.getPreviousHash();
- long lastBlockContractCount = peerService.getQueryService().getUserCount(ledgerHash, previousHash);
- // 当前区块合约数量减上个区块合约数量
- return currentBlockContractCount - lastBlockContractCount;
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts/additional-count")
- @Override
- public long getAdditionalContractCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
- LedgerInfo ledgerInfo = peerService.getQueryService().getLedger(ledgerHash);
- long maxBlockHeight = ledgerInfo.getLatestBlockHeight();
- long totalCount = peerService.getQueryService().getContractTotalCount(ledgerHash);
- if (maxBlockHeight == GENESIS_BLOCK_HEIGHT) { // 只有一个创世区块
- return totalCount;
- }
- long lastTotalCount = peerService.getQueryService().getContractCount(ledgerHash, maxBlockHeight - 1);
- return totalCount - lastTotalCount;
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "utils/pubkey/{pubkey}/addr")
- public String getAddrByPubKey(@PathVariable(name = "pubkey") String strPubKey) {
- PubKey pubKey = KeyGenCommand.decodePubKey(strPubKey);
- return AddressEncoding.generateAddress(pubKey).toBase58();
- }
-
- @RequestMapping(method = RequestMethod.GET, value = "ledgers/{ledgerHash}/**/search")
- public Object dataRetrieval(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- HttpServletRequest request) {
- String result;
- if (dataRetrievalUrl == null || dataRetrievalUrl.length() <= 0) {
- result = "{'message':'OK','data':'" + "data.retrieval.url is empty" + "'}";
- } else {
- String queryParams = request.getQueryString() == null ? "": request.getQueryString();
- String fullQueryUrl = new StringBuffer(dataRetrievalUrl)
- .append(request.getRequestURI())
- .append(BaseConstant.DELIMETER_QUESTION)
- .append(queryParams)
- .toString();
- try {
- result = dataRetrievalService.retrieval(fullQueryUrl);
- ConsoleUtils.info("request = {%s} \r\n result = {%s} \r\n", fullQueryUrl, result);
- } catch (Exception e) {
- result = "{'message':'OK','data':'" + e.getMessage() + "'}";
- }
- }
- return result;
- }
-
- public void setDataRetrievalUrl(String dataRetrievalUrl) {
- this.dataRetrievalUrl = dataRetrievalUrl;
- }
-
- /**
- * get all ledgers count;
- */
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/count")
- @Override
- public int getLedgersCount() {
- return peerService.getQueryService().getLedgerHashs().length;
- }
-
- /**
- * get all ledgers hashs;
- */
- @RequestMapping(method = RequestMethod.GET, path = "ledgers")
- public HashDigest[] getLedgersHash(@RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
- @RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
- return gatewayQueryService.getLedgersHash(fromIndex, count);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/participants/count")
- public int getConsensusParticipantCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
- return peerService.getQueryService().getConsensusParticipants(ledgerHash).length;
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/participants")
- public ParticipantNode[] getConsensusParticipants(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
- @RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
- return gatewayQueryService.getConsensusParticipants(ledgerHash,fromIndex,count);
- }
-
- /**
- * get more users by fromIndex and count;
- * @param ledgerHash
- * @param fromIndex
- * @param count
- * @return
- */
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/users")
- @Override
- public AccountHeader[] getUsers(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
- @RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
- return peerService.getQueryService().getUsers(ledgerHash, fromIndex, count);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts")
- @Override
- public AccountHeader[] getDataAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
- @RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
- return peerService.getQueryService().getDataAccounts(ledgerHash, fromIndex, count);
- }
-
- @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts")
- @Override
- public AccountHeader[] getContractAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
- @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
- @RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
- return peerService.getQueryService().getContractAccounts(ledgerHash, fromIndex, count);
- }
+ @Override
+ public ContractInfo getContract(HashDigest ledgerHash, String address) {
+ return peerService.getQueryService().getContract(ledgerHash, address);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/latest")
+ @Override
+ public LedgerBlock getLatestBlock(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
+ long latestBlockHeight = peerService.getQueryService().getLedger(ledgerHash).getLatestBlockHeight();
+ return peerService.getQueryService().getBlock(ledgerHash, latestBlockHeight);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/txs/additional-count")
+ @Override
+ public long getAdditionalTransactionCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @PathVariable(name = "blockHeight") long blockHeight) {
+ // 获取某个区块的交易总数
+ long currentBlockTxCount = peerService.getQueryService().getTransactionCount(ledgerHash, blockHeight);
+ if (blockHeight == GENESIS_BLOCK_HEIGHT) {
+ return currentBlockTxCount;
+ }
+ long lastBlockHeight = blockHeight - 1;
+ long lastBlockTxCount = peerService.getQueryService().getTransactionCount(ledgerHash, lastBlockHeight);
+ // 当前区块交易数减上个区块交易数
+ return currentBlockTxCount - lastBlockTxCount;
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/txs/additional-count")
+ @Override
+ public long getAdditionalTransactionCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @PathVariable(name = "blockHash") HashDigest blockHash) {
+ LedgerBlock currentBlock = peerService.getQueryService().getBlock(ledgerHash, blockHash);
+ long currentBlockTxCount = peerService.getQueryService().getTransactionCount(ledgerHash, blockHash);
+ if (currentBlock.getHeight() == GENESIS_BLOCK_HEIGHT) {
+ return currentBlockTxCount;
+ }
+ HashDigest previousHash = currentBlock.getPreviousHash();
+ long lastBlockTxCount = peerService.getQueryService().getTransactionCount(ledgerHash, previousHash);
+ // 当前区块交易数减上个区块交易数
+ return currentBlockTxCount - lastBlockTxCount;
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/txs/additional-count")
+ @Override
+ public long getAdditionalTransactionCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
+ LedgerInfo ledgerInfo = peerService.getQueryService().getLedger(ledgerHash);
+ long maxBlockHeight = ledgerInfo.getLatestBlockHeight();
+ long totalCount = peerService.getQueryService().getTransactionTotalCount(ledgerHash);
+ if (maxBlockHeight == GENESIS_BLOCK_HEIGHT) { // 只有一个创世区块
+ return totalCount;
+ }
+ long lastTotalCount = peerService.getQueryService().getTransactionCount(ledgerHash, maxBlockHeight - 1);
+ return totalCount - lastTotalCount;
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/accounts/additional-count")
+ @Override
+ public long getAdditionalDataAccountCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @PathVariable(name = "blockHeight") long blockHeight) {
+ long currentDaCount = peerService.getQueryService().getDataAccountCount(ledgerHash, blockHeight);
+ if (blockHeight == GENESIS_BLOCK_HEIGHT) {
+ return currentDaCount;
+ }
+ long lastBlockHeight = blockHeight - 1;
+ long lastDaCount = peerService.getQueryService().getDataAccountCount(ledgerHash, lastBlockHeight);
+ return currentDaCount - lastDaCount;
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/accounts/additional-count")
+ @Override
+ public long getAdditionalDataAccountCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @PathVariable(name = "blockHash") HashDigest blockHash) {
+ LedgerBlock currentBlock = peerService.getQueryService().getBlock(ledgerHash, blockHash);
+ long currentBlockDaCount = peerService.getQueryService().getDataAccountCount(ledgerHash, blockHash);
+ if (currentBlock.getHeight() == GENESIS_BLOCK_HEIGHT) {
+ return currentBlockDaCount;
+ }
+ HashDigest previousHash = currentBlock.getPreviousHash();
+ long lastBlockDaCount = peerService.getQueryService().getDataAccountCount(ledgerHash, previousHash);
+ // 当前区块数据账户数量减上个区块数据账户数量
+ return currentBlockDaCount - lastBlockDaCount;
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts/additional-count")
+ @Override
+ public long getAdditionalDataAccountCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
+ LedgerInfo ledgerInfo = peerService.getQueryService().getLedger(ledgerHash);
+ long maxBlockHeight = ledgerInfo.getLatestBlockHeight();
+ long totalCount = peerService.getQueryService().getDataAccountTotalCount(ledgerHash);
+ if (maxBlockHeight == GENESIS_BLOCK_HEIGHT) { // 只有一个创世区块
+ return totalCount;
+ }
+ long lastTotalCount = peerService.getQueryService().getDataAccountCount(ledgerHash, maxBlockHeight - 1);
+ return totalCount - lastTotalCount;
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/users/additional-count")
+ @Override
+ public long getAdditionalUserCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @PathVariable(name = "blockHeight") long blockHeight) {
+ long currentUserCount = peerService.getQueryService().getUserCount(ledgerHash, blockHeight);
+ if (blockHeight == GENESIS_BLOCK_HEIGHT) {
+ return currentUserCount;
+ }
+ long lastBlockHeight = blockHeight - 1;
+ long lastUserCount = peerService.getQueryService().getUserCount(ledgerHash, lastBlockHeight);
+ return currentUserCount - lastUserCount;
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/users/additional-count")
+ @Override
+ public long getAdditionalUserCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @PathVariable(name = "blockHash") HashDigest blockHash) {
+ LedgerBlock currentBlock = peerService.getQueryService().getBlock(ledgerHash, blockHash);
+ long currentBlockUserCount = peerService.getQueryService().getUserCount(ledgerHash, blockHash);
+ if (currentBlock.getHeight() == GENESIS_BLOCK_HEIGHT) {
+ return currentBlockUserCount;
+ }
+ HashDigest previousHash = currentBlock.getPreviousHash();
+ long lastBlockUserCount = peerService.getQueryService().getUserCount(ledgerHash, previousHash);
+ // 当前区块用户数量减上个区块用户数量
+ return currentBlockUserCount - lastBlockUserCount;
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/users/additional-count")
+ @Override
+ public long getAdditionalUserCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
+ LedgerInfo ledgerInfo = peerService.getQueryService().getLedger(ledgerHash);
+ long maxBlockHeight = ledgerInfo.getLatestBlockHeight();
+ long totalCount = peerService.getQueryService().getUserTotalCount(ledgerHash);
+ if (maxBlockHeight == GENESIS_BLOCK_HEIGHT) { // 只有一个创世区块
+ return totalCount;
+ }
+ long lastTotalCount = peerService.getQueryService().getUserCount(ledgerHash, maxBlockHeight - 1);
+ return totalCount - lastTotalCount;
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/contracts/additional-count")
+ @Override
+ public long getAdditionalContractCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @PathVariable(name = "blockHeight") long blockHeight) {
+ long currentContractCount = peerService.getQueryService().getContractCount(ledgerHash, blockHeight);
+ if (blockHeight == GENESIS_BLOCK_HEIGHT) {
+ return currentContractCount;
+ }
+ long lastBlockHeight = blockHeight - 1;
+ long lastContractCount = peerService.getQueryService().getUserCount(ledgerHash, lastBlockHeight);
+ return currentContractCount - lastContractCount;
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/contracts/additional-count")
+ @Override
+ public long getAdditionalContractCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @PathVariable(name = "blockHash") HashDigest blockHash) {
+ LedgerBlock currentBlock = peerService.getQueryService().getBlock(ledgerHash, blockHash);
+ long currentBlockContractCount = peerService.getQueryService().getContractCount(ledgerHash, blockHash);
+ if (currentBlock.getHeight() == GENESIS_BLOCK_HEIGHT) {
+ return currentBlockContractCount;
+ }
+ HashDigest previousHash = currentBlock.getPreviousHash();
+ long lastBlockContractCount = peerService.getQueryService().getUserCount(ledgerHash, previousHash);
+ // 当前区块合约数量减上个区块合约数量
+ return currentBlockContractCount - lastBlockContractCount;
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts/additional-count")
+ @Override
+ public long getAdditionalContractCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
+ LedgerInfo ledgerInfo = peerService.getQueryService().getLedger(ledgerHash);
+ long maxBlockHeight = ledgerInfo.getLatestBlockHeight();
+ long totalCount = peerService.getQueryService().getContractTotalCount(ledgerHash);
+ if (maxBlockHeight == GENESIS_BLOCK_HEIGHT) { // 只有一个创世区块
+ return totalCount;
+ }
+ long lastTotalCount = peerService.getQueryService().getContractCount(ledgerHash, maxBlockHeight - 1);
+ return totalCount - lastTotalCount;
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "utils/pubkey/{pubkey}/addr")
+ public String getAddrByPubKey(@PathVariable(name = "pubkey") String strPubKey) {
+ PubKey pubKey = KeyGenUtils.decodePubKey(strPubKey);
+ return AddressEncoding.generateAddress(pubKey).toBase58();
+ }
+
+ @RequestMapping(method = RequestMethod.GET, value = "ledgers/{ledgerHash}/**/search")
+ public Object dataRetrieval(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, HttpServletRequest request) {
+ String result;
+ if (dataRetrievalUrl == null || dataRetrievalUrl.length() <= 0) {
+ result = "{'message':'OK','data':'" + "data.retrieval.url is empty" + "'}";
+ } else {
+ String queryParams = request.getQueryString() == null ? "" : request.getQueryString();
+ String fullQueryUrl = new StringBuffer(dataRetrievalUrl).append(request.getRequestURI())
+ .append(BaseConstant.DELIMETER_QUESTION).append(queryParams).toString();
+ try {
+ result = dataRetrievalService.retrieval(fullQueryUrl);
+ ConsoleUtils.info("request = {%s} \r\n result = {%s} \r\n", fullQueryUrl, result);
+ } catch (Exception e) {
+ result = "{'message':'OK','data':'" + e.getMessage() + "'}";
+ }
+ }
+ return result;
+ }
+
+ public void setDataRetrievalUrl(String dataRetrievalUrl) {
+ this.dataRetrievalUrl = dataRetrievalUrl;
+ }
+
+ /**
+ * get all ledgers count;
+ */
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/count")
+ @Override
+ public int getLedgersCount() {
+ return peerService.getQueryService().getLedgerHashs().length;
+ }
+
+ // 注: 账本的数量不会很多,不需要分页;
+// /**
+// * get all ledgers hashs;
+// */
+// @RequestMapping(method = RequestMethod.GET, path = "ledgers")
+// public HashDigest[] getLedgersHash(
+// @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
+// @RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
+// return gatewayQueryService.getLedgersHash(fromIndex, count);
+// }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/participants/count")
+ public int getConsensusParticipantCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
+ return peerService.getQueryService().getConsensusParticipants(ledgerHash).length;
+ }
+
+// @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/participants")
+// public ParticipantNode[] getConsensusParticipants(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+// @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
+// @RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
+//
+// ParticipantNode participantNode[] = peerService.getQueryService().getConsensusParticipants(ledgerHash);
+// int indexAndCount[] = QueryUtil.calFromIndexAndCount(fromIndex, count, participantNode.length);
+// ParticipantNode participantNodesNew[] = Arrays.copyOfRange(participantNode, indexAndCount[0],
+// indexAndCount[0] + indexAndCount[1]);
+// return participantNodesNew;
+// }
+
+ /**
+ * get more users by fromIndex and count;
+ *
+ * @param ledgerHash
+ * @param fromIndex
+ * @param count
+ * @return
+ */
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/users")
+ @Override
+ public AccountHeader[] getUsers(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
+ @RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
+ return peerService.getQueryService().getUsers(ledgerHash, fromIndex, count);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts")
+ @Override
+ public AccountHeader[] getDataAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
+ @RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
+ return peerService.getQueryService().getDataAccounts(ledgerHash, fromIndex, count);
+ }
+
+ @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts")
+ @Override
+ public AccountHeader[] getContractAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
+ @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
+ @RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
+ return peerService.getQueryService().getContractAccounts(ledgerHash, fromIndex, count);
+ }
}
diff --git a/source/gateway/src/main/java/com/jd/blockchain/gateway/web/GatewayWebServerConfigurer.java b/source/gateway/src/main/java/com/jd/blockchain/gateway/web/GatewayWebServerConfigurer.java
index 4481088f..fba7295a 100644
--- a/source/gateway/src/main/java/com/jd/blockchain/gateway/web/GatewayWebServerConfigurer.java
+++ b/source/gateway/src/main/java/com/jd/blockchain/gateway/web/GatewayWebServerConfigurer.java
@@ -35,6 +35,7 @@ public class GatewayWebServerConfigurer implements WebMvcConfigurer {
JSONSerializeUtils.disableCircularReferenceDetect();
JSONSerializeUtils.configStringSerializer(ByteArray.class);
DataContractRegistry.register(BftsmartNodeSettings.class);
+ DataContractRegistry.register(LedgerAdminInfo.class);
}
diff --git a/source/gateway/src/main/java/com/jd/blockchain/gateway/web/TxProcessingController.java b/source/gateway/src/main/java/com/jd/blockchain/gateway/web/TxProcessingController.java
index 5405cc98..8f949c69 100644
--- a/source/gateway/src/main/java/com/jd/blockchain/gateway/web/TxProcessingController.java
+++ b/source/gateway/src/main/java/com/jd/blockchain/gateway/web/TxProcessingController.java
@@ -1,6 +1,8 @@
package com.jd.blockchain.gateway.web;
+import com.jd.blockchain.crypto.*;
import com.jd.blockchain.gateway.service.GatewayInterceptService;
+import com.jd.blockchain.transaction.SignatureUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -9,9 +11,6 @@ import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.jd.blockchain.binaryproto.BinaryProtocol;
-import com.jd.blockchain.crypto.Crypto;
-import com.jd.blockchain.crypto.HashDigest;
-import com.jd.blockchain.crypto.SignatureFunction;
import com.jd.blockchain.gateway.PeerService;
import com.jd.blockchain.ledger.DigitalSignature;
import com.jd.blockchain.ledger.TransactionContent;
@@ -60,11 +59,8 @@ public class TxProcessingController implements TransactionService {
throw new IllegalStateException("Not implemented!");
} else {
// 验证签名;
- byte[] content = BinaryProtocol.encode(txRequest.getTransactionContent(), TransactionContent.class);
for (DigitalSignature sign : partiSigns) {
- SignatureFunction signFunc = Crypto
- .getSignatureFunction(sign.getPubKey().getAlgorithm());
- if (!signFunc.verify(sign.getDigest(), sign.getPubKey(), content)) {
+ if (!SignatureUtils.verifySignature(txRequest.getTransactionContent(), sign.getDigest(), sign.getPubKey())) {
throw new BusinessException("The validation of participant signatures fail!");
}
}
diff --git a/source/gateway/src/main/resources/log4j2.xml b/source/gateway/src/main/resources/log4j2.xml
index 3fe4b122..6b49c3e9 100644
--- a/source/gateway/src/main/resources/log4j2.xml
+++ b/source/gateway/src/main/resources/log4j2.xml
@@ -8,17 +8,17 @@
-
+
-
+
-
+
@@ -27,8 +27,8 @@
-
+
@@ -38,8 +38,8 @@
-
+
@@ -51,7 +51,7 @@
-
+
diff --git a/source/ledger/ledger-core/pom.xml b/source/ledger/ledger-core/pom.xml
index ac1e9948..3938916c 100644
--- a/source/ledger/ledger-core/pom.xml
+++ b/source/ledger/ledger-core/pom.xml
@@ -5,7 +5,7 @@
com.jd.blockchain
ledger
- 1.0.0.RELEASE
+ 1.1.0-SNAPSHOT
ledger-core
@@ -68,7 +68,7 @@
test
-
+
@@ -83,42 +83,32 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountPrivilege.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountPrivilege.java
deleted file mode 100644
index c57debff..00000000
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountPrivilege.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.jd.blockchain.ledger.core;
-
-public interface AccountPrivilege {
-
- /**
- * 数据“读”的操作码;
- *
- * @return
- */
- byte getReadingOpCode();
-
- /**
- * “写”的操作码;
- *
- * @return
- */
- byte getWrittingOpCode();
-
- /**
- * 其它的扩展操作码;
- *
- * @return
- */
- byte[] getExtOpCodes();
-
-}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountSet.java
index a28a5fb5..dc4a59cd 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountSet.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountSet.java
@@ -12,6 +12,7 @@ import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
+import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes;
@@ -48,6 +49,10 @@ public class AccountSet implements Transactional, MerkleProvable {
public boolean isReadonly() {
return merkleDataset.isReadonly();
}
+
+ void setReadonly() {
+ merkleDataset.setReadonly();
+ }
public AccountSet(CryptoSetting cryptoSetting, String keyPrefix, ExPolicyKVStorage exStorage,
VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy) {
@@ -65,10 +70,6 @@ public class AccountSet implements Transactional, MerkleProvable {
this.accessPolicy = accessPolicy;
}
- // public HashDigest getAccountRootHash() {
- // return merkleDataset.getRootHash();
- // }
-
@Override
public HashDigest getRootHash() {
return merkleDataset.getRootHash();
@@ -333,9 +334,9 @@ public class AccountSet implements Transactional, MerkleProvable {
if (!updated) {
return;
}
- String[] addresses = new String[latestAccountsCache.size()];
+ Bytes[] addresses = new Bytes[latestAccountsCache.size()];
latestAccountsCache.keySet().toArray(addresses);
- for (String address : addresses) {
+ for (Bytes address : addresses) {
VersioningAccount acc = latestAccountsCache.remove(address);
// cancel;
if (acc.isUpdated()) {
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AuthorizableDataSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AuthorizableDataSet.java
deleted file mode 100644
index ca0a406a..00000000
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AuthorizableDataSet.java
+++ /dev/null
@@ -1,168 +0,0 @@
-//package com.jd.blockchain.ledger.core;
-//
-//import com.jd.blockchain.crypto.hash.HashDigest;
-//
-//import my.utils.Scratchable;
-//import my.utils.io.ByteArray;
-//import my.utils.io.BytesUtils;
-//import my.utils.io.ExistancePolicyKVStorage;
-//import my.utils.io.VersioningKVStorage;
-//
-///**
-// * 可进行授权控制的数据集合;
-// *
-// * @author huanghaiquan
-// *
-// */
-//public class AuthorizableDataSet implements Scratchable {
-//
-// public static final String DATA_PREFIX = "DATA" + LedgerConsts.KEY_SEPERATOR;
-//// public static final String PRIVILEGE_PREFIX = "PRVL" + LedgerConsts.KEY_SEPERATOR;
-//
-// private static final String DEFAULT_PRIVILEGE_KEY = "%";
-//
-// private DataAccessable accessable;
-//
-// protected MerkleDataSet data;
-//
-//// private PrivilegeDataSet privileges;
-//
-// /**
-// * Create a new Account instance;
-// *
-// * @param address
-// * @param pubKey
-// */
-// protected AuthorizableDataSet(CryptoSetting merkleTreeSetting, ExistancePolicyKVStorage simpleStorage,
-// VersioningKVStorage versioningStorage) {
-// this(null, merkleTreeSetting, null, simpleStorage, versioningStorage);
-// }
-//
-// protected AuthorizableDataSet(byte[] dataRootHash, CryptoSetting merkleTreeSetting, byte[] privilegeRootHash,
-// ExistancePolicyKVStorage simpleStorage, VersioningKVStorage versioningStorage) {
-// this(dataRootHash, merkleTreeSetting, privilegeRootHash, simpleStorage, versioningStorage, false);
-// }
-//
-// protected AuthorizableDataSet(byte[] dataRootHash, CryptoSetting merkleTreeSetting, byte[] privilegeRootHash,
-// ExistancePolicyKVStorage simpleStorage, VersioningKVStorage versioningStorage, boolean readonly) {
-// this.data = new MerkleDataSet(dataRootHash, merkleTreeSetting,
-// PrefixAppender.prefix(DATA_PREFIX, simpleStorage),
-// PrefixAppender.prefix(DATA_PREFIX, versioningStorage), readonly);
-//
-//// this.privileges = new PrivilegeDataSet(privilegeRootHash, merkleTreeSetting,
-//// PrefixAppender.prefix(PRIVILEGE_PREFIX, simpleStorage),
-//// PrefixAppender.prefix(PRIVILEGE_PREFIX, versioningStorage), readonly);
-// }
-//
-// public ByteArray getDataRootHash() {
-// return data.getRootHash();
-// }
-//
-//// public ByteArray getPrivilegeRootHash() {
-//// return privileges.getRootHash();
-//// }
-//
-// /**
-// *
-// * @param userAddress
-// * @param op
-// * @param enable
-// */
-// public void setPrivilege(String userAddress, byte op, boolean enable) {
-//
-// }
-//
-// /**
-// *
-// * @param op
-// * @param enable
-// */
-// public void setDefaultPrivilege(byte op, boolean enable) {
-// }
-//
-// public boolean checkCurrentUserPrivilege() {
-// return false;
-// }
-//
-// /**
-// * Return the latest version entry associated the specified key; If the key
-// * doesn't exist, then return -1;
-// *
-// * @param key
-// * @return
-// */
-// public long getVersion(String key) {
-// return data.getVersion(key);
-// }
-//
-// protected long setString(String key, String value, long version) {
-// checkWritting();
-// byte[] bytes = BytesUtils.toBytes(value, LedgerConsts.CHARSET);
-// return data.setValue(key, bytes, version);
-// }
-//
-// protected String getString(String key) {
-// checkReading();
-// byte[] value = data.getValue(key);
-// return BytesUtils.toString(value, LedgerConsts.CHARSET);
-// }
-//
-// protected String getString(String key, long version) {
-// checkReading();
-// byte[] value = data.getValue(key, version);
-// return BytesUtils.toString(value, LedgerConsts.CHARSET);
-// }
-//
-// protected long setValue(String key, byte[] value, long version) {
-// checkWritting();
-// return data.setValue(key, value, version);
-// }
-//
-// protected byte[] getValue(String key) {
-// checkReading();
-// return data.getValue(key);
-// }
-//
-// protected byte[] getValue(String key, long version) {
-// checkReading();
-// return data.getValue(key, version);
-// }
-//
-// private void checkWritting() {
-// // Check writting enable;
-// }
-//
-// private void checkReading() {
-// // TODO Check privilege of reading;
-// }
-//
-// // /**
-// // * 数据“读”的操作码;
-// // *
-// // * @return
-// // */
-// // protected abstract AccountPrivilege getPrivilege();
-//
-// @Override
-// public boolean isUpdated() {
-// return data.isUpdated();
-//// return data.isUpdated()|| privileges.isUpdated();
-// }
-//
-// @Override
-// public void commit() {
-// if (data.isUpdated()) {
-// data.commit();
-// }
-//// if (privileges.isUpdated()) {
-//// privileges.commit();
-//// }
-// }
-//
-// @Override
-// public void cancel() {
-// data.cancel();
-//// privileges.cancel();
-// }
-//
-//}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Authorization.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Authorization.java
deleted file mode 100644
index cba2ffe4..00000000
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Authorization.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.jd.blockchain.ledger.core;
-
-import com.jd.blockchain.ledger.DigitalSignature;
-
-/**
- * {@link Authorization} 抽象了对特定用户/角色的授权信息;
- *
- * @author huanghaiquan
- *
- */
-public interface Authorization {
-
- /**
- * 被授权用户/角色的地址;
- *
- * @return
- */
- String getAddress();
-
- /**
- * 授权码;
- *
- * @return
- */
- byte[] getCode();
-
- /**
- * 授权者的签名;
- *
- * @return
- */
- DigitalSignature getSignature();
-
- // /**
- // * 授权生成的时间戳;
- // * @return
- // */
- // long getTs();
-
-}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AuthorizationVO.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AuthorizationVO.java
deleted file mode 100644
index 24d7f125..00000000
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AuthorizationVO.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.jd.blockchain.ledger.core;
-
-import com.jd.blockchain.ledger.DigitalSignature;
-
-public class AuthorizationVO implements Authorization {
-
- private String address;
-
- private byte[] code;
-
- private DigitalSignature signature;
-
-
- @Override
- public String getAddress() {
- return address;
- }
-
- public void setAddress(String address) {
- this.address = address;
- }
-
- @Override
- public byte[] getCode() {
- return code;
- }
-
- public void setCode(byte[] code) {
- this.code = code;
- }
-
- @Override
- public DigitalSignature getSignature() {
- return signature;
- }
-
-
- public void setSignature(DigitalSignature signature) {
- this.signature = signature;
- }
-
-}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/BaseAccount.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/BaseAccount.java
index 9a57c6d0..1c9b778f 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/BaseAccount.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/BaseAccount.java
@@ -8,6 +8,7 @@ import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.BlockchainIdentityData;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.CryptoSetting;
+import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes;
@@ -64,13 +65,13 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional
/**
* Create a account instance with the specified address and pubkey and load it's
- * merkle dataset with the specified root hash. which is used for storing data
+ * merkle dataset from the specified root hash. This merkle dateset is used for storing data
* of this account.
*
* @param address
* @param pubKey
- * @param dataRootHash merkle root hash of account's data; if null be set,
- * create a new empty merkle dataset;
+ * @param dataRootHash merkle root hash of account's data; if set to a null value,
+ * an empty merkle dataset is created;
* @param cryptoSetting
* @param exStorage
* @param verStorage
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Consensus.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Consensus.java
deleted file mode 100644
index da7b6104..00000000
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Consensus.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.jd.blockchain.ledger.core;
-
-
-/**
- * @author hhq
- * @version 1.0
- * @created 14-6��-2018 12:13:32
- */
-public class Consensus {
-
- public P2PRealm m_P2PRealm;
-
- public Consensus(){
-
- }
-
- public void finalize() throws Throwable {
-
- }
-
-}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java
index c4a94ee6..9f4a8622 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java
@@ -2,10 +2,10 @@ package com.jd.blockchain.ledger.core;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PubKey;
-import com.jd.blockchain.ledger.AccountHeader;
-import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.BytesData;
+import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.ContractInfo;
+import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.utils.Bytes;
public class ContractAccount implements ContractInfo {
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccountQuery.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccountQuery.java
new file mode 100644
index 00000000..4013a239
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccountQuery.java
@@ -0,0 +1,29 @@
+package com.jd.blockchain.ledger.core;
+
+import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.ledger.AccountHeader;
+import com.jd.blockchain.ledger.MerkleProof;
+import com.jd.blockchain.utils.Bytes;
+
+public interface ContractAccountQuery {
+
+ AccountHeader[] getAccounts(int fromIndex, int count);
+
+ HashDigest getRootHash();
+
+ /**
+ * 返回合约总数;
+ *
+ * @return
+ */
+ long getTotalCount();
+
+ MerkleProof getProof(Bytes address);
+
+ boolean contains(Bytes address);
+
+ ContractAccount getContract(Bytes address);
+
+ ContractAccount getContract(Bytes address, long version);
+
+}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccountSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccountSet.java
index 039be73d..89d3ab3d 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccountSet.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccountSet.java
@@ -5,12 +5,13 @@ import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.DigitalSignature;
+import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.Transactional;
-public class ContractAccountSet implements MerkleProvable, Transactional {
+public class ContractAccountSet implements MerkleProvable, Transactional, ContractAccountQuery {
private AccountSet accountSet;
@@ -25,6 +26,7 @@ public class ContractAccountSet implements MerkleProvable, Transactional {
accountSet = new AccountSet(dataRootHash, cryptoSetting, prefix, exStorage, verStorage, readonly, accessPolicy);
}
+ @Override
public AccountHeader[] getAccounts(int fromIndex, int count) {
return accountSet.getAccounts(fromIndex,count);
}
@@ -33,6 +35,10 @@ public class ContractAccountSet implements MerkleProvable, Transactional {
return accountSet.isReadonly();
}
+ void setReadonly() {
+ accountSet.setReadonly();
+ }
+
@Override
public HashDigest getRootHash() {
return accountSet.getRootHash();
@@ -43,6 +49,7 @@ public class ContractAccountSet implements MerkleProvable, Transactional {
*
* @return
*/
+ @Override
public long getTotalCount() {
return accountSet.getTotalCount();
}
@@ -52,15 +59,18 @@ public class ContractAccountSet implements MerkleProvable, Transactional {
return accountSet.getProof(address);
}
+ @Override
public boolean contains(Bytes address) {
return accountSet.contains(address);
}
+ @Override
public ContractAccount getContract(Bytes address) {
BaseAccount accBase = accountSet.getAccount(address);
return new ContractAccount(accBase);
}
+ @Override
public ContractAccount getContract(Bytes address, long version) {
BaseAccount accBase = accountSet.getAccount(address, version);
return new ContractAccount(accBase);
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/CryptoConfig.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/CryptoConfig.java
index 8f5d2ea1..2a23f8bf 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/CryptoConfig.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/CryptoConfig.java
@@ -82,7 +82,7 @@ public class CryptoConfig implements CryptoSetting {
public void setHashAlgorithm(short hashAlgorithm) {
if (codeAlgorithms == null || !codeAlgorithms.containsKey(hashAlgorithm)) {
- throw new LedgerException("The specified algorithm[" + hashAlgorithm + "] has no provider!");
+ throw new LedgerException("Current CryptoConfig has no crypto provider!");
}
this.hashAlgorithm = hashAlgorithm;
}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java
index 792ca704..cee3c29e 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java
@@ -1,14 +1,14 @@
package com.jd.blockchain.ledger.core;
import com.jd.blockchain.binaryproto.BinaryProtocol;
-import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.AccountHeader;
-import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.BytesData;
+import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.KVDataEntry;
import com.jd.blockchain.ledger.KVDataObject;
+import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.utils.Bytes;
public class DataAccount implements AccountHeader, MerkleProvable {
@@ -43,16 +43,85 @@ public class DataAccount implements AccountHeader, MerkleProvable {
}
+ /**
+ * Create or update the value associated the specified key if the version
+ * checking is passed.
+ *
+ * The value of the key will be updated only if it's latest version equals the
+ * specified version argument.
+ * If the key doesn't exist, the version checking will be ignored, and key will
+ * be created with a new sequence number as id.
+ * It also could specify the version argument to -1 to ignore the version
+ * checking.
+ *
+ * If updating is performed, the version of the key increase by 1.
+ * If creating is performed, the version of the key initialize by 0.
+ *
+ * @param key The key of data;
+ * @param value The value of data;
+ * @param version The expected version of the key.
+ * @return The new version of the key.
+ * If the key is new created success, then return 0;
+ * If the key is updated success, then return the new version;
+ * If this operation fail by version checking or other reason, then
+ * return -1;
+ */
public long setBytes(Bytes key, BytesValue value, long version) {
return baseAccount.setBytes(key, value, version);
}
+ /**
+ * Create or update the value associated the specified key if the version
+ * checking is passed.
+ *
+ * The value of the key will be updated only if it's latest version equals the
+ * specified version argument.
+ * If the key doesn't exist, the version checking will be ignored, and key will
+ * be created with a new sequence number as id.
+ * It also could specify the version argument to -1 to ignore the version
+ * checking.
+ *
+ * If updating is performed, the version of the key increase by 1.
+ * If creating is performed, the version of the key initialize by 0.
+ *
+ * @param key The key of data;
+ * @param value The value of data;
+ * @param version The expected version of the key.
+ * @return The new version of the key.
+ * If the key is new created success, then return 0;
+ * If the key is updated success, then return the new version;
+ * If this operation fail by version checking or other reason, then
+ * return -1;
+ */
public long setBytes(Bytes key, String value, long version) {
BytesValue bytesValue = BytesData.fromText(value);
return baseAccount.setBytes(key, bytesValue, version);
}
+ /**
+ * Create or update the value associated the specified key if the version
+ * checking is passed.
+ *
+ * The value of the key will be updated only if it's latest version equals the
+ * specified version argument.
+ * If the key doesn't exist, the version checking will be ignored, and key will
+ * be created with a new sequence number as id.
+ * It also could specify the version argument to -1 to ignore the version
+ * checking.
+ *
+ * If updating is performed, the version of the key increase by 1.
+ * If creating is performed, the version of the key initialize by 0.
+ *
+ * @param key The key of data;
+ * @param value The value of data;
+ * @param version The expected version of the key.
+ * @return The new version of the key.
+ * If the key is new created success, then return 0;
+ * If the key is updated success, then return the new version;
+ * If this operation fail by version checking or other reason, then
+ * return -1;
+ */
public long setBytes(Bytes key, byte[] value, long version) {
BytesValue bytesValue = BytesData.fromBytes(value);
return baseAccount.setBytes(key, bytesValue, version);
@@ -121,6 +190,29 @@ public class DataAccount implements AccountHeader, MerkleProvable {
public BytesValue getBytes(Bytes key, long version) {
return baseAccount.getBytes(key, version);
}
+
+ /**
+ * @param key
+ * @param version
+ * @return
+ */
+ public KVDataEntry getDataEntry(String key, long version) {
+ return getDataEntry(Bytes.fromString(key), version);
+ }
+
+ /**
+ * @param key
+ * @param version
+ * @return
+ */
+ public KVDataEntry getDataEntry(Bytes key, long version) {
+ BytesValue value = baseAccount.getBytes(key, version);
+ if (value == null) {
+ return new KVDataObject(key.toUTF8String(), -1, null);
+ }else {
+ return new KVDataObject(key.toUTF8String(), version, value);
+ }
+ }
/**
* return the specified index's KVDataEntry;
@@ -131,7 +223,7 @@ public class DataAccount implements AccountHeader, MerkleProvable {
*/
public KVDataEntry[] getDataEntries(int fromIndex, int count) {
- if (getDataEntriesTotalCount() == 0 || count == 0) {
+ if (count == 0 || getDataEntriesTotalCount() == 0) {
return null;
}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountQuery.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountQuery.java
new file mode 100644
index 00000000..b7cc8d43
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountQuery.java
@@ -0,0 +1,32 @@
+package com.jd.blockchain.ledger.core;
+
+import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.ledger.AccountHeader;
+import com.jd.blockchain.ledger.MerkleProof;
+import com.jd.blockchain.utils.Bytes;
+
+public interface DataAccountQuery {
+
+ AccountHeader[] getAccounts(int fromIndex, int count);
+
+ HashDigest getRootHash();
+
+ long getTotalCount();
+
+ /**
+ * 返回账户的存在性证明;
+ */
+ MerkleProof getProof(Bytes address);
+
+ /**
+ * 返回数据账户;
+ * 如果不存在,则返回 null;
+ *
+ * @param address
+ * @return
+ */
+ DataAccount getDataAccount(Bytes address);
+
+ DataAccount getDataAccount(Bytes address, long version);
+
+}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountSet.java
index 799a8570..dbc77437 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountSet.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountSet.java
@@ -5,18 +5,19 @@ import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.DigitalSignature;
+import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.Transactional;
-public class DataAccountSet implements MerkleProvable, Transactional {
+public class DataAccountSet implements MerkleProvable, Transactional, DataAccountQuery {
private AccountSet accountSet;
- public DataAccountSet(CryptoSetting cryptoSetting, String prefix,ExPolicyKVStorage exStorage,
+ public DataAccountSet(CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exStorage,
VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy) {
- accountSet = new AccountSet(cryptoSetting,prefix, exStorage, verStorage, accessPolicy);
+ accountSet = new AccountSet(cryptoSetting, prefix, exStorage, verStorage, accessPolicy);
}
public DataAccountSet(HashDigest dataRootHash, CryptoSetting cryptoSetting, String prefix,
@@ -25,19 +26,25 @@ public class DataAccountSet implements MerkleProvable, Transactional {
accountSet = new AccountSet(dataRootHash, cryptoSetting, prefix, exStorage, verStorage, readonly, accessPolicy);
}
+ @Override
public AccountHeader[] getAccounts(int fromIndex, int count) {
- return accountSet.getAccounts(fromIndex,count);
+ return accountSet.getAccounts(fromIndex, count);
}
public boolean isReadonly() {
return accountSet.isReadonly();
}
+ void setReadonly() {
+ accountSet.setReadonly();
+ }
+
@Override
public HashDigest getRootHash() {
return accountSet.getRootHash();
}
+ @Override
public long getTotalCount() {
return accountSet.getTotalCount();
}
@@ -56,11 +63,23 @@ public class DataAccountSet implements MerkleProvable, Transactional {
return new DataAccount(accBase);
}
+ /**
+ * 返回数据账户;
+ * 如果不存在,则返回 null;
+ *
+ * @param address
+ * @return
+ */
+ @Override
public DataAccount getDataAccount(Bytes address) {
BaseAccount accBase = accountSet.getAccount(address);
+ if (accBase == null) {
+ return null;
+ }
return new DataAccount(accBase);
}
+ @Override
public DataAccount getDataAccount(Bytes address, long version) {
BaseAccount accBase = accountSet.getAccount(address, version);
return new DataAccount(accBase);
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DefaultOperationHandleRegisteration.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DefaultOperationHandleRegisteration.java
new file mode 100644
index 00000000..6dd34e0a
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DefaultOperationHandleRegisteration.java
@@ -0,0 +1,132 @@
+package com.jd.blockchain.ledger.core;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.springframework.stereotype.Component;
+
+import com.jd.blockchain.ledger.LedgerException;
+import com.jd.blockchain.ledger.Operation;
+import com.jd.blockchain.ledger.core.handles.ContractCodeDeployOperationHandle;
+import com.jd.blockchain.ledger.core.handles.DataAccountKVSetOperationHandle;
+import com.jd.blockchain.ledger.core.handles.DataAccountRegisterOperationHandle;
+import com.jd.blockchain.ledger.core.handles.JVMContractEventSendOperationHandle;
+import com.jd.blockchain.ledger.core.handles.LedgerInitOperationHandle;
+import com.jd.blockchain.ledger.core.handles.RolesConfigureOperationHandle;
+import com.jd.blockchain.ledger.core.handles.UserAuthorizeOperationHandle;
+import com.jd.blockchain.ledger.core.handles.UserRegisterOperationHandle;
+import com.jd.blockchain.transaction.ContractCodeDeployOpTemplate;
+import com.jd.blockchain.transaction.ContractEventSendOpTemplate;
+import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate;
+import com.jd.blockchain.transaction.DataAccountRegisterOpTemplate;
+import com.jd.blockchain.transaction.LedgerInitOpTemplate;
+import com.jd.blockchain.transaction.RolesConfigureOpTemplate;
+import com.jd.blockchain.transaction.UserAuthorizeOpTemplate;
+import com.jd.blockchain.transaction.UserRegisterOpTemplate;
+
+@Component
+public class DefaultOperationHandleRegisteration implements OperationHandleRegisteration {
+
+ private static Map, OperationHandle> DEFAULT_HANDLES = new HashMap<>();
+
+ private Map, OperationHandle> handles = new ConcurrentHashMap<>();
+
+ static {
+ registerDefaultHandle(new LedgerInitOperationHandle());
+
+ registerDefaultHandle(new RolesConfigureOperationHandle());
+
+ registerDefaultHandle(new UserAuthorizeOperationHandle());
+
+ registerDefaultHandle(new UserRegisterOperationHandle());
+
+ registerDefaultHandle(new DataAccountKVSetOperationHandle());
+
+ registerDefaultHandle(new DataAccountRegisterOperationHandle());
+
+ registerDefaultHandle(new ContractCodeDeployOperationHandle());
+
+ registerDefaultHandle(new JVMContractEventSendOperationHandle());
+ }
+
+ private static void registerDefaultHandle(OperationHandle handle) {
+ DEFAULT_HANDLES.put(handle.getOperationType(), handle);
+ }
+
+ /**
+ * 注册操作处理器;此方法将覆盖默认的操作处理器配置;
+ *
+ * @param handle
+ */
+ public void registerHandle(OperationHandle handle) {
+ List> opTypes = new ArrayList>();
+ for (Class> opType : handles.keySet()) {
+ if (opType.isAssignableFrom(handle.getOperationType())) {
+ opTypes.add(opType);
+ }
+ }
+
+ for (Class> opType : opTypes) {
+ handles.put(opType, handle);
+ }
+ handles.put(handle.getOperationType(), handle);
+ }
+
+ private OperationHandle getRegisteredHandle(Class> operationType) {
+ OperationHandle hdl = handles.get(operationType);
+ if (hdl == null) {
+ hdl = DEFAULT_HANDLES.get(operationType);
+
+ //按“操作类型”的继承关系匹配;
+ if (hdl == null) {
+ for (Class> opType : handles.keySet()) {
+ if (opType.isAssignableFrom(operationType)) {
+ hdl = handles.get(opType);
+ break;
+ }
+ }
+ }
+
+ if (hdl == null) {
+ for (Class> opType : DEFAULT_HANDLES.keySet()) {
+ if (opType.isAssignableFrom(operationType)) {
+ hdl = DEFAULT_HANDLES.get(opType);
+ break;
+ }
+ }
+ }
+
+ if (hdl != null) {
+ handles.put(operationType, hdl);
+ }
+ }
+ return hdl;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.jd.blockchain.ledger.core.impl.OperationHandleRegisteration#getHandle(
+ * java.lang.Class)
+ */
+ @Override
+ public OperationHandle getHandle(Class extends Operation> operationType) {
+ OperationHandle hdl = getRegisteredHandle(operationType);
+ if (hdl == null) {
+ throw new LedgerException("Unsupported operation type[" + operationType.getName() + "]!");
+ }
+ return hdl;
+ }
+
+ private static class OpHandleStub {
+
+ private Class extends Operation> operationType;
+
+ private OperationHandle operationHandle;
+
+ }
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/EmptyLedgerDataset.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/EmptyLedgerDataset.java
new file mode 100644
index 00000000..64e08117
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/EmptyLedgerDataset.java
@@ -0,0 +1,209 @@
+package com.jd.blockchain.ledger.core;
+
+import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.ledger.AccountHeader;
+import com.jd.blockchain.ledger.LedgerAdminInfo;
+import com.jd.blockchain.ledger.MerkleProof;
+import com.jd.blockchain.ledger.ParticipantDataQuery;
+import com.jd.blockchain.ledger.ParticipantNode;
+import com.jd.blockchain.utils.Bytes;
+
+public class EmptyLedgerDataset implements LedgerDataQuery {
+
+ private static final LedgerAdminDataQuery EMPTY_ADMIN_DATA = new EmptyAdminData();
+
+ private static final UserAccountQuery EMPTY_USER_ACCOUNTS = new EmptyUserAccountSet();
+
+ private static final DataAccountQuery EMPTY_DATA_ACCOUNTS = new EmptyDataAccountSet();
+
+ private static final ContractAccountQuery EMPTY_CONTRACT_ACCOUNTS = new EmptyContractAccountSet();
+
+ private static final ParticipantDataQuery EMPTY_PARTICIPANTS = new EmptyParticipantData();
+
+ @Override
+ public LedgerAdminDataQuery getAdminDataset() {
+ return EMPTY_ADMIN_DATA;
+ }
+
+ @Override
+ public UserAccountQuery getUserAccountSet() {
+ return EMPTY_USER_ACCOUNTS;
+ }
+
+ @Override
+ public DataAccountQuery getDataAccountSet() {
+ return EMPTY_DATA_ACCOUNTS;
+ }
+
+ @Override
+ public ContractAccountQuery getContractAccountset() {
+ return EMPTY_CONTRACT_ACCOUNTS;
+ }
+
+
+ private static class EmptyAdminData implements LedgerAdminDataQuery{
+
+
+ @Override
+ public LedgerAdminInfo getAdminInfo() {
+ return null;
+ }
+
+ @Override
+ public ParticipantDataQuery getParticipantDataset() {
+ return EMPTY_PARTICIPANTS;
+ }
+
+ }
+
+ private static class EmptyParticipantData implements ParticipantDataQuery{
+
+ @Override
+ public HashDigest getRootHash() {
+ return null;
+ }
+
+ @Override
+ public MerkleProof getProof(Bytes key) {
+ return null;
+ }
+
+ @Override
+ public long getParticipantCount() {
+ return 0;
+ }
+
+ @Override
+ public boolean contains(Bytes address) {
+ return false;
+ }
+
+ @Override
+ public ParticipantNode getParticipant(Bytes address) {
+ return null;
+ }
+
+ @Override
+ public ParticipantNode[] getParticipants() {
+ return null;
+ }
+
+ }
+
+ private static class EmptyUserAccountSet implements UserAccountQuery{
+
+ @Override
+ public AccountHeader[] getAccounts(int fromIndex, int count) {
+ return null;
+ }
+
+ @Override
+ public long getTotalCount() {
+ return 0;
+ }
+
+ @Override
+ public HashDigest getRootHash() {
+ return null;
+ }
+
+ @Override
+ public MerkleProof getProof(Bytes key) {
+ return null;
+ }
+
+ @Override
+ public UserAccount getUser(String address) {
+ return null;
+ }
+
+ @Override
+ public UserAccount getUser(Bytes address) {
+ return null;
+ }
+
+ @Override
+ public boolean contains(Bytes address) {
+ return false;
+ }
+
+ @Override
+ public UserAccount getUser(Bytes address, long version) {
+ return null;
+ }
+
+
+ }
+
+ private static class EmptyDataAccountSet implements DataAccountQuery{
+
+ @Override
+ public AccountHeader[] getAccounts(int fromIndex, int count) {
+ return null;
+ }
+
+ @Override
+ public HashDigest getRootHash() {
+ return null;
+ }
+
+ @Override
+ public long getTotalCount() {
+ return 0;
+ }
+
+ @Override
+ public MerkleProof getProof(Bytes address) {
+ return null;
+ }
+
+ @Override
+ public DataAccount getDataAccount(Bytes address) {
+ return null;
+ }
+
+ @Override
+ public DataAccount getDataAccount(Bytes address, long version) {
+ return null;
+ }
+
+ }
+
+ private static class EmptyContractAccountSet implements ContractAccountQuery{
+
+ @Override
+ public AccountHeader[] getAccounts(int fromIndex, int count) {
+ return null;
+ }
+
+ @Override
+ public HashDigest getRootHash() {
+ return null;
+ }
+
+ @Override
+ public long getTotalCount() {
+ return 0;
+ }
+
+ @Override
+ public MerkleProof getProof(Bytes address) {
+ return null;
+ }
+
+ @Override
+ public boolean contains(Bytes address) {
+ return false;
+ }
+
+ @Override
+ public ContractAccount getContract(Bytes address) {
+ return null;
+ }
+
+ @Override
+ public ContractAccount getContract(Bytes address, long version) {
+ return null;
+ }
+ }
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/FullPermissionedSecurityManager.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/FullPermissionedSecurityManager.java
new file mode 100644
index 00000000..c217ee34
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/FullPermissionedSecurityManager.java
@@ -0,0 +1,98 @@
+package com.jd.blockchain.ledger.core;
+
+import java.util.Set;
+
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.LedgerSecurityException;
+import com.jd.blockchain.ledger.TransactionPermission;
+import com.jd.blockchain.utils.Bytes;
+
+class FullPermissionedSecurityManager implements LedgerSecurityManager {
+
+ public static final FullPermissionedSecurityManager INSTANCE = new FullPermissionedSecurityManager();
+
+ @Override
+ public SecurityPolicy createSecurityPolicy(Set endpoints, Set nodes) {
+ return new FullPermissionedPolicy(endpoints, nodes);
+ }
+
+ private static class FullPermissionedPolicy implements SecurityPolicy {
+
+ private Set endpoints;
+ private Set nodes;
+
+ public FullPermissionedPolicy(Set endpoints, Set nodes) {
+ this.endpoints = endpoints;
+ this.nodes = nodes;
+ }
+
+ @Override
+ public Set getEndpoints() {
+ return endpoints;
+ }
+
+ @Override
+ public Set getNodes() {
+ return nodes;
+ }
+
+ @Override
+ public boolean isEndpointEnable(LedgerPermission permission, MultiIDsPolicy midPolicy) {
+ return true;
+ }
+
+ @Override
+ public boolean isEndpointEnable(TransactionPermission permission, MultiIDsPolicy midPolicy) {
+ return true;
+ }
+
+ @Override
+ public boolean isNodeEnable(LedgerPermission permission, MultiIDsPolicy midPolicy) {
+ return true;
+ }
+
+ @Override
+ public boolean isNodeEnable(TransactionPermission permission, MultiIDsPolicy midPolicy) {
+ return true;
+ }
+
+ @Override
+ public void checkEndpointPermission(LedgerPermission permission, MultiIDsPolicy midPolicy)
+ throws LedgerSecurityException {
+ }
+
+ @Override
+ public void checkEndpointPermission(TransactionPermission permission, MultiIDsPolicy midPolicy)
+ throws LedgerSecurityException {
+ }
+
+ @Override
+ public void checkNodePermission(LedgerPermission permission, MultiIDsPolicy midPolicy) throws LedgerSecurityException {
+ }
+
+ @Override
+ public void checkNodePermission(TransactionPermission permission, MultiIDsPolicy midPolicy)
+ throws LedgerSecurityException {
+ }
+
+ @Override
+ public boolean isEndpointValid(MultiIDsPolicy midPolicy) {
+ return true;
+ }
+
+ @Override
+ public boolean isNodeValid(MultiIDsPolicy midPolicy) {
+ return true;
+ }
+
+ @Override
+ public void checkEndpointValidity(MultiIDsPolicy midPolicy) throws LedgerSecurityException {
+ }
+
+ @Override
+ public void checkNodeValidity(MultiIDsPolicy midPolicy) throws LedgerSecurityException {
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Gateway.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Gateway.java
deleted file mode 100644
index 6874d8aa..00000000
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Gateway.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.jd.blockchain.ledger.core;
-
-import com.jd.blockchain.ledger.ParticipantNode;
-
-/**
- * @author hhq
- * @version 1.0
- * @created 14-6��-2018 12:13:32
- */
-public class Gateway extends Node {
-
- public ParticipantNode m_Participant;
-
- public Gateway(){
-
- }
-
- public void finalize() throws Throwable {
- super.finalize();
- }
-
-}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/GenesisLedgerStorageProxy.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/GenesisLedgerStorageProxy.java
similarity index 97%
rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/GenesisLedgerStorageProxy.java
rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/GenesisLedgerStorageProxy.java
index 5682c50a..c93e1fed 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/GenesisLedgerStorageProxy.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/GenesisLedgerStorageProxy.java
@@ -1,3 +1,4 @@
+package com.jd.blockchain.ledger.core;
//package com.jd.blockchain.ledger.core.impl;
//
//import com.jd.blockchain.storage.service.ExPolicyKVStorage;
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminAccount.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminAccount.java
deleted file mode 100644
index c22a4ad2..00000000
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminAccount.java
+++ /dev/null
@@ -1,356 +0,0 @@
-package com.jd.blockchain.ledger.core;
-
-import com.jd.blockchain.ledger.LedgerMetadata;
-import com.jd.blockchain.ledger.LedgerSetting;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.jd.blockchain.binaryproto.BinaryProtocol;
-import com.jd.blockchain.binaryproto.DataContractRegistry;
-import com.jd.blockchain.crypto.Crypto;
-import com.jd.blockchain.crypto.HashDigest;
-import com.jd.blockchain.crypto.HashFunction;
-import com.jd.blockchain.ledger.LedgerException;
-import com.jd.blockchain.ledger.LedgerInitSetting;
-import com.jd.blockchain.ledger.ParticipantNode;
-import com.jd.blockchain.storage.service.ExPolicyKVStorage;
-import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy;
-import com.jd.blockchain.storage.service.VersioningKVStorage;
-import com.jd.blockchain.utils.Bytes;
-import com.jd.blockchain.utils.Transactional;
-
-public class LedgerAdminAccount implements Transactional, LedgerAdministration {
-
- static {
- DataContractRegistry.register(LedgerMetadata.class);
- }
-
- private static Logger LOGGER = LoggerFactory.getLogger(LedgerAdminAccount.class);
-
- public static final String LEDGER_META_PREFIX = "MTA" + LedgerConsts.KEY_SEPERATOR;
- public static final String LEDGER_PARTICIPANT_PREFIX = "PAR" + LedgerConsts.KEY_SEPERATOR;
- public static final String LEDGER_PRIVILEGE_PREFIX = "PVL" + LedgerConsts.KEY_SEPERATOR;
-
- private final Bytes metaPrefix;
- private final Bytes privilegePrefix;
-
- private LedgerMetadata origMetadata;
-
- private LedgerMetadataImpl metadata;
-
- /**
- * 原来的账本设置;
- *
- *
- * 对 LedgerMetadata 修改的新配置不能立即生效,需要达成共识后,在下一次区块计算中才生效;
- */
- private LedgerSetting previousSetting;
-
- /**
- * 账本的参与节点;
- */
- private ParticipantDataSet participants;
-
- // /**
- // * 账本的全局权限设置;
- // */
- // private PrivilegeDataSet privileges;
-
- private ExPolicyKVStorage settingsStorage;
-
- private HashDigest adminAccountHash;
-
- private boolean readonly;
-
- private boolean updated;
-
- public HashDigest getHash() {
- return adminAccountHash;
- }
-
- public boolean isReadonly() {
- return readonly;
- }
-
- /**
- * 初始化账本的管理账户;
- *
- *
- *
- * 只在新建账本时调用此方法;
- *
- * @param ledgerSeed
- * @param setting
- * @param partiList
- * @param exPolicyStorage
- * @param versioningStorage
- */
- public LedgerAdminAccount(LedgerInitSetting initSetting, String keyPrefix, ExPolicyKVStorage exPolicyStorage,
- VersioningKVStorage versioningStorage) {
- this.metaPrefix = Bytes.fromString(keyPrefix + LEDGER_META_PREFIX);
- this.privilegePrefix = Bytes.fromString(keyPrefix + LEDGER_PRIVILEGE_PREFIX);
-
- ParticipantNode[] parties = initSetting.getConsensusParticipants();
- if (parties.length == 0) {
- throw new LedgerException("No participant!");
- }
-
- // 检查参与者列表是否已经按照 id 升序排列,并且 id 不冲突;
- // 注:参与者的 id 要求从 0 开始编号,顺序依次递增,不允许跳空;
- for (int i = 0; i < parties.length; i++) {
- // if (parties[i].getAddress() != i) {
- // throw new LedgerException("The id of participant isn't match the order of the
- // participant list!");
- // }
- }
-
- // 初始化元数据;
- this.metadata = new LedgerMetadataImpl();
- this.metadata.setSeed(initSetting.getLedgerSeed());
- // 新配置;
- this.metadata.setting = new LedgerConfiguration(initSetting.getConsensusProvider(),
- initSetting.getConsensusSettings(), initSetting.getCryptoSetting());
- this.previousSetting = new LedgerConfiguration(initSetting.getConsensusProvider(),
- initSetting.getConsensusSettings(), initSetting.getCryptoSetting());
- this.adminAccountHash = null;
-
- // 基于原配置初始化参与者列表;
- String partiPrefix = keyPrefix + LEDGER_PARTICIPANT_PREFIX;
- this.participants = new ParticipantDataSet(previousSetting.getCryptoSetting(), partiPrefix, exPolicyStorage,
- versioningStorage);
-
- for (ParticipantNode p : parties) {
- this.participants.addConsensusParticipant(p);
- }
-
- // 初始化其它属性;
- this.settingsStorage = exPolicyStorage;
- this.readonly = false;
- }
-
- public LedgerAdminAccount(HashDigest adminAccountHash, String keyPrefix, ExPolicyKVStorage kvStorage,
- VersioningKVStorage versioningKVStorage, boolean readonly) {
- this.metaPrefix = Bytes.fromString(keyPrefix + LEDGER_META_PREFIX);
- this.privilegePrefix = Bytes.fromString(keyPrefix + LEDGER_PRIVILEGE_PREFIX);
- this.settingsStorage = kvStorage;
- this.readonly = readonly;
- this.origMetadata = loadAndVerifySettings(adminAccountHash);
- this.metadata = new LedgerMetadataImpl(origMetadata);
- // 复制记录一份配置作为上一个区块的原始配置,该实例仅供读取,不做修改,也不会回写到存储;
- this.previousSetting = new LedgerConfiguration(metadata.getSetting());
- this.adminAccountHash = adminAccountHash;
- // this.privileges = new PrivilegeDataSet(metadata.getPrivilegesHash(),
- // metadata.getSetting().getCryptoSetting(),
- // PrefixAppender.prefix(LEDGER_PRIVILEGE_PREFIX, kvStorage),
- // PrefixAppender.prefix(LEDGER_PRIVILEGE_PREFIX, versioningKVStorage),
- // readonly);
-
- // this.participants = new ParticipantDataSet(metadata.getParticipantsHash(),
- // previousSetting.getCryptoSetting(),
- // PrefixAppender.prefix(LEDGER_PARTICIPANT_PREFIX, kvStorage),
- // PrefixAppender.prefix(LEDGER_PARTICIPANT_PREFIX, versioningKVStorage),
- // readonly);
- String partiPrefix = keyPrefix + LEDGER_PARTICIPANT_PREFIX;
- this.participants = new ParticipantDataSet(metadata.getParticipantsHash(), previousSetting.getCryptoSetting(),
- partiPrefix, kvStorage, versioningKVStorage, readonly);
- }
-
- private LedgerMetadata loadAndVerifySettings(HashDigest adminAccountHash) {
- // String base58Hash = adminAccountHash.toBase58();
- // String key = encodeMetadataKey(base58Hash);
- Bytes key = encodeMetadataKey(adminAccountHash);
- byte[] bytes = settingsStorage.get(key);
- HashFunction hashFunc = Crypto.getHashFunction(adminAccountHash.getAlgorithm());
- if (!hashFunc.verify(adminAccountHash, bytes)) {
- LOGGER.error("The hash verification of ledger settings fail! --[HASH=" + key + "]");
- throw new LedgerException("The hash verification of ledger settings fail!");
- }
- return deserializeMetadata(bytes);
- }
-
- private Bytes encodeMetadataKey(HashDigest metadataHash) {
- // return LEDGER_META_PREFIX + metadataHash;
- // return metaPrefix + metadataHash;
- return metaPrefix.concat(metadataHash);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.jd.blockchain.ledger.core.LedgerAdministration#getMetadata()
- */
- @Override
- public LedgerMetadata getMetadata() {
- return metadata;
- }
-
- /**
- * 返回原来的账本配置;
- *
- *
- * 此方法总是返回从上一个区块加载的账本配置,即时调用 {@link #setLedgerSetting(LedgerSetting)} 做出了新的更改;
- *
- * @return
- */
- public LedgerSetting getPreviousSetting() {
- return previousSetting;
- }
-
- /**
- * 返回当前设置的账本配置;
- *
- * @return
- */
- public LedgerSetting getSetting() {
- return metadata.getSetting();
- }
-
- /**
- * 更新账本配置;
- *
- * @param ledgerSetting
- */
- public void setLedgerSetting(LedgerSetting ledgerSetting) {
- if (readonly) {
- throw new IllegalArgumentException("This merkle dataset is readonly!");
- }
- metadata.setSetting(ledgerSetting);
- }
-
- @Override
- public long getParticipantCount() {
- return participants.getParticipantCount();
- }
-
- // /*
- // * (non-Javadoc)
- // *
- // * @see
- // *
- // com.jd.blockchain.ledger.core.LedgerAdministration#getParticipant(java.lang.
- // * String)
- // */
- // @Override
- // public ParticipantNode getParticipant(int id) {
- // return participants.getParticipant(id);
- // }
-
- @Override
- public ParticipantNode[] getParticipants() {
- return participants.getParticipants();
- }
-
- /**
- * 加入新的参与方; 如果指定的参与方已经存在,则引发 LedgerException 异常;
- *
- * @param participant
- */
- public void addParticipant(ParticipantNode participant) {
- participants.addConsensusParticipant(participant);
- }
-
- @Override
- public boolean isUpdated() {
- return updated || participants.isUpdated();
- }
-
- @Override
- public void commit() {
- if (!isUpdated()) {
- return;
- }
- participants.commit();
-
- metadata.setParticipantsHash(participants.getRootHash());
-
- // 基于之前的密码配置来计算元数据的哈希;
- byte[] metadataBytes = serializeMetadata(metadata);
- HashFunction hashFunc = Crypto
- .getHashFunction(previousSetting.getCryptoSetting().getHashAlgorithm());
- HashDigest metadataHash = hashFunc.hash(metadataBytes);
- if (adminAccountHash == null || !adminAccountHash.equals(metadataHash)) {
- // update modify;
- // String base58MetadataHash = metadataHash.toBase58();
- // String metadataKey = encodeMetadataKey(base58MetadataHash);
- Bytes metadataKey = encodeMetadataKey(metadataHash);
-
- boolean nx = settingsStorage.set(metadataKey, metadataBytes, ExPolicy.NOT_EXISTING);
- if (!nx) {
- // 有可能发生了并发写入冲突,不同的节点都向同一个存储服务器上写入数据;
- // throw new LedgerException(
- // "Ledger metadata already exist! --[LedgerMetadataHash=" + base58MetadataHash
- // + "]");
- // LOGGER.warn("Ledger metadata already exist! --[MetadataHash=" +
- // base58MetadataHash + "]");
- }
-
- adminAccountHash = metadataHash;
- }
-
- updated = false;
- }
-
- private LedgerMetadata deserializeMetadata(byte[] bytes) {
- return BinaryProtocol.decode(bytes);
- }
-
- private byte[] serializeMetadata(LedgerMetadataImpl config) {
- return BinaryProtocol.encode(config, LedgerMetadata.class);
- }
-
- @Override
- public void cancel() {
- if (!isUpdated()) {
- return;
- }
- participants.cancel();
- metadata = new LedgerMetadataImpl(origMetadata);
- }
-
- public static class LedgerMetadataImpl implements LedgerMetadata {
-
- private byte[] seed;
-
- private LedgerSetting setting;
-
- private HashDigest participantsHash;
-
- public LedgerMetadataImpl() {
- }
-
- public LedgerMetadataImpl(LedgerMetadata metadata) {
- this.seed = metadata.getSeed();
- this.setting = metadata.getSetting();
- this.participantsHash = metadata.getParticipantsHash();
- }
-
- @Override
- public byte[] getSeed() {
- return seed;
- }
-
- @Override
- public LedgerSetting getSetting() {
- return setting;
- }
-
- @Override
- public HashDigest getParticipantsHash() {
- return participantsHash;
- }
-
- public void setSeed(byte[] seed) {
- this.seed = seed;
- }
-
- public void setSetting(LedgerSetting setting) {
- // copy a new instance;
- this.setting = new LedgerConfiguration(setting);
- }
-
- public void setParticipantsHash(HashDigest participantsHash) {
- this.participantsHash = participantsHash;
- }
- }
-
-}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminDataQuery.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminDataQuery.java
new file mode 100644
index 00000000..05c62138
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminDataQuery.java
@@ -0,0 +1,12 @@
+package com.jd.blockchain.ledger.core;
+
+import com.jd.blockchain.ledger.LedgerAdminInfo;
+import com.jd.blockchain.ledger.ParticipantDataQuery;
+
+public interface LedgerAdminDataQuery {
+
+ LedgerAdminInfo getAdminInfo();
+
+ ParticipantDataQuery getParticipantDataset();
+
+}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminDataset.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminDataset.java
new file mode 100644
index 00000000..c4961b12
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminDataset.java
@@ -0,0 +1,469 @@
+package com.jd.blockchain.ledger.core;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.jd.blockchain.binaryproto.BinaryProtocol;
+import com.jd.blockchain.binaryproto.DataContractRegistry;
+import com.jd.blockchain.crypto.Crypto;
+import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.crypto.HashFunction;
+import com.jd.blockchain.ledger.LedgerAdminInfo;
+import com.jd.blockchain.ledger.LedgerException;
+import com.jd.blockchain.ledger.LedgerInitSetting;
+import com.jd.blockchain.ledger.LedgerMetadata;
+import com.jd.blockchain.ledger.LedgerMetadata_V2;
+import com.jd.blockchain.ledger.LedgerSettings;
+import com.jd.blockchain.ledger.ParticipantNode;
+import com.jd.blockchain.ledger.RolePrivilegeSettings;
+import com.jd.blockchain.ledger.UserRolesSettings;
+import com.jd.blockchain.storage.service.ExPolicyKVStorage;
+import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy;
+import com.jd.blockchain.storage.service.VersioningKVStorage;
+import com.jd.blockchain.utils.Bytes;
+import com.jd.blockchain.utils.Transactional;
+
+public class LedgerAdminDataset implements Transactional, LedgerAdminDataQuery, LedgerAdminInfo {
+
+ static {
+ DataContractRegistry.register(LedgerMetadata.class);
+ DataContractRegistry.register(LedgerMetadata_V2.class);
+ }
+
+ private static Logger LOGGER = LoggerFactory.getLogger(LedgerAdminDataset.class);
+
+ public static final String LEDGER_META_PREFIX = "MTA" + LedgerConsts.KEY_SEPERATOR;
+ public static final String LEDGER_PARTICIPANT_PREFIX = "PAR" + LedgerConsts.KEY_SEPERATOR;
+ public static final String LEDGER_SETTING_PREFIX = "SET" + LedgerConsts.KEY_SEPERATOR;
+ public static final String ROLE_PRIVILEGE_PREFIX = "RPV" + LedgerConsts.KEY_SEPERATOR;
+ public static final String USER_ROLE_PREFIX = "URO" + LedgerConsts.KEY_SEPERATOR;
+
+ private final Bytes metaPrefix;
+ private final Bytes settingPrefix;
+
+ private LedgerMetadata_V2 origMetadata;
+
+ private LedgerMetadataInfo metadata;
+
+ /**
+ * 原来的账本设置;
+ *
+ *
+ * 对 LedgerMetadata 修改的新配置不能立即生效,需要达成共识后,在下一次区块计算中才生效;
+ */
+ private LedgerSettings previousSettings;
+
+ private HashDigest previousSettingHash;
+
+ /**
+ * 账本的参与节点;
+ */
+ private ParticipantDataset participants;
+
+ /**
+ * “角色-权限”数据集;
+ */
+ private RolePrivilegeDataset rolePrivileges;
+
+ /**
+ * “用户-角色”数据集;
+ */
+ private UserRoleDataset userRoles;
+
+ /**
+ * 账本参数配置;
+ */
+ private LedgerSettings settings;
+
+ private ExPolicyKVStorage storage;
+
+ private HashDigest adminDataHash;
+
+ private boolean readonly;
+
+ private boolean updated;
+
+ public HashDigest getHash() {
+ return adminDataHash;
+ }
+
+ public boolean isReadonly() {
+ return readonly;
+ }
+
+ void setReadonly() {
+ this.readonly = true;
+ }
+
+ public LedgerSettings getPreviousSetting() {
+ return previousSettings;
+ }
+
+ @Override
+ public RolePrivilegeSettings getRolePrivileges() {
+ return rolePrivileges;
+ }
+
+ @Override
+ public UserRolesSettings getUserRoles() {
+ return userRoles;
+ }
+
+ @Override
+ public LedgerAdminInfo getAdminInfo() {
+ return this;
+ }
+
+ /**
+ * 初始化账本的管理账户;
+ *
+ *
+ *
+ * 只在新建账本时调用此方法;
+ *
+ * @param ledgerSeed
+ * @param settings
+ * @param partiList
+ * @param exPolicyStorage
+ * @param versioningStorage
+ */
+ public LedgerAdminDataset(LedgerInitSetting initSetting, String keyPrefix, ExPolicyKVStorage exPolicyStorage,
+ VersioningKVStorage versioningStorage) {
+ this.metaPrefix = Bytes.fromString(keyPrefix + LEDGER_META_PREFIX);
+ this.settingPrefix = Bytes.fromString(keyPrefix + LEDGER_SETTING_PREFIX);
+
+ ParticipantNode[] parties = initSetting.getConsensusParticipants();
+ if (parties.length == 0) {
+ throw new LedgerException("No participant!");
+ }
+
+ // 初始化元数据;
+ this.metadata = new LedgerMetadataInfo();
+ this.metadata.setSeed(initSetting.getLedgerSeed());
+ // 新配置;
+ this.settings = new LedgerConfiguration(initSetting.getConsensusProvider(), initSetting.getConsensusSettings(),
+ initSetting.getCryptoSetting());
+ this.previousSettings = new LedgerConfiguration(settings);
+ this.previousSettingHash = null;
+ this.adminDataHash = null;
+
+ // 基于原配置初始化参与者列表;
+ String partiPrefix = keyPrefix + LEDGER_PARTICIPANT_PREFIX;
+ this.participants = new ParticipantDataset(previousSettings.getCryptoSetting(), partiPrefix, exPolicyStorage,
+ versioningStorage);
+
+ for (ParticipantNode p : parties) {
+ this.participants.addConsensusParticipant(p);
+ }
+
+ String rolePrivilegePrefix = keyPrefix + ROLE_PRIVILEGE_PREFIX;
+ this.rolePrivileges = new RolePrivilegeDataset(this.settings.getCryptoSetting(), rolePrivilegePrefix,
+ exPolicyStorage, versioningStorage);
+
+ String userRolePrefix = keyPrefix + USER_ROLE_PREFIX;
+ this.userRoles = new UserRoleDataset(this.settings.getCryptoSetting(), userRolePrefix, exPolicyStorage,
+ versioningStorage);
+
+ // 初始化其它属性;
+ this.storage = exPolicyStorage;
+ this.readonly = false;
+ }
+
+ public LedgerAdminDataset(HashDigest adminAccountHash, String keyPrefix, ExPolicyKVStorage kvStorage,
+ VersioningKVStorage versioningKVStorage, boolean readonly) {
+ this.metaPrefix = Bytes.fromString(keyPrefix + LEDGER_META_PREFIX);
+ this.settingPrefix = Bytes.fromString(keyPrefix + LEDGER_SETTING_PREFIX);
+ this.storage = kvStorage;
+ this.readonly = readonly;
+ this.origMetadata = loadAndVerifyMetadata(adminAccountHash);
+ this.metadata = new LedgerMetadataInfo(origMetadata);
+ this.settings = loadAndVerifySettings(metadata.getSettingsHash());
+ // 复制记录一份配置作为上一个区块的原始配置,该实例仅供读取,不做修改,也不会回写到存储;
+ this.previousSettings = new LedgerConfiguration(settings);
+ this.previousSettingHash = metadata.getSettingsHash();
+ this.adminDataHash = adminAccountHash;
+
+ String partiPrefix = keyPrefix + LEDGER_PARTICIPANT_PREFIX;
+ this.participants = new ParticipantDataset(metadata.getParticipantsHash(), previousSettings.getCryptoSetting(),
+ partiPrefix, kvStorage, versioningKVStorage, readonly);
+
+ String rolePrivilegePrefix = keyPrefix + ROLE_PRIVILEGE_PREFIX;
+ this.rolePrivileges = new RolePrivilegeDataset(metadata.getRolePrivilegesHash(),
+ previousSettings.getCryptoSetting(), rolePrivilegePrefix, kvStorage, versioningKVStorage, readonly);
+
+ String userRolePrefix = keyPrefix + USER_ROLE_PREFIX;
+ this.userRoles = new UserRoleDataset(metadata.getUserRolesHash(), previousSettings.getCryptoSetting(),
+ userRolePrefix, kvStorage, versioningKVStorage, readonly);
+ }
+
+ private LedgerSettings loadAndVerifySettings(HashDigest settingsHash) {
+ if (settingsHash == null) {
+ return null;
+ }
+ Bytes key = encodeSettingsKey(settingsHash);
+ byte[] bytes = storage.get(key);
+ HashFunction hashFunc = Crypto.getHashFunction(settingsHash.getAlgorithm());
+ if (!hashFunc.verify(settingsHash, bytes)) {
+ String errorMsg = "Verification of the hash for ledger setting failed! --[HASH=" + key + "]";
+ LOGGER.error(errorMsg);
+ throw new LedgerException(errorMsg);
+ }
+ return deserializeSettings(bytes);
+ }
+
+ private LedgerSettings deserializeSettings(byte[] bytes) {
+ return BinaryProtocol.decode(bytes);
+ }
+
+ private byte[] serializeSetting(LedgerSettings setting) {
+ return BinaryProtocol.encode(setting, LedgerSettings.class);
+ }
+
+ private LedgerMetadata_V2 loadAndVerifyMetadata(HashDigest adminAccountHash) {
+ Bytes key = encodeMetadataKey(adminAccountHash);
+ byte[] bytes = storage.get(key);
+ HashFunction hashFunc = Crypto.getHashFunction(adminAccountHash.getAlgorithm());
+ if (!hashFunc.verify(adminAccountHash, bytes)) {
+ String errorMsg = "Verification of the hash for ledger metadata failed! --[HASH=" + key + "]";
+ LOGGER.error(errorMsg);
+ throw new LedgerException(errorMsg);
+ }
+ return deserializeMetadata(bytes);
+ }
+
+ private Bytes encodeSettingsKey(HashDigest settingsHash) {
+ return settingPrefix.concat(settingsHash);
+ }
+
+ private Bytes encodeMetadataKey(HashDigest metadataHash) {
+ // return LEDGER_META_PREFIX + metadataHash;
+ // return metaPrefix + metadataHash;
+ return metaPrefix.concat(metadataHash);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.jd.blockchain.ledger.core.LedgerAdministration#getMetadata()
+ */
+ @Override
+ public LedgerMetadata_V2 getMetadata() {
+ return metadata;
+ }
+
+// /**
+// * 返回原来的账本配置;
+// *
+// *
+// * 此方法总是返回从上一个区块加载的账本配置,即时调用 {@link #setLedgerSetting(LedgerSettings)} 做出了新的更改;
+// *
+// * @return
+// */
+// public LedgerSettings getPreviousSetting() {
+// return previousSettings;
+// }
+
+ /**
+ * 返回当前设置的账本配置;
+ *
+ * @return
+ */
+ public LedgerSettings getSettings() {
+ return settings;
+ }
+
+ /**
+ * 更新账本配置;
+ *
+ * @param ledgerSetting
+ */
+ public void setLedgerSetting(LedgerSettings ledgerSetting) {
+ if (readonly) {
+ throw new IllegalArgumentException("This merkle dataset is readonly!");
+ }
+ settings = ledgerSetting;
+ updated = true;
+ }
+
+ @Override
+ public long getParticipantCount() {
+ return participants.getParticipantCount();
+ }
+
+ @Override
+ public ParticipantNode[] getParticipants() {
+ return participants.getParticipants();
+ }
+
+ @Override
+ public ParticipantDataset getParticipantDataset() {
+ return participants;
+ }
+
+ /**
+ * 加入新的参与方; 如果指定的参与方已经存在,则引发 LedgerException 异常;
+ *
+ * @param participant
+ */
+ public void addParticipant(ParticipantNode participant) {
+ participants.addConsensusParticipant(participant);
+ }
+
+ @Override
+ public boolean isUpdated() {
+ return updated || participants.isUpdated() || rolePrivileges.isUpdated() || userRoles.isUpdated();
+ }
+
+ @Override
+ public void commit() {
+ if (!isUpdated()) {
+ return;
+ }
+ // 计算并更新参与方集合的根哈希;
+ participants.commit();
+ metadata.setParticipantsHash(participants.getRootHash());
+
+ // 计算并更新角色权限集合的根哈希;
+ rolePrivileges.commit();
+ metadata.setRolePrivilegesHash(rolePrivileges.getRootHash());
+
+ // 计算并更新用户角色授权集合的根哈希;
+ userRoles.commit();
+ metadata.setUserRolesHash(userRoles.getRootHash());
+
+ // 当前区块上下文的密码参数设置的哈希函数;
+ HashFunction hashFunc = Crypto.getHashFunction(previousSettings.getCryptoSetting().getHashAlgorithm());
+
+ // 计算并更新参数配置的哈希;
+ if (settings == null) {
+ throw new LedgerException("Missing ledger settings!");
+ }
+ byte[] settingsBytes = serializeSetting(settings);
+ HashDigest settingsHash = hashFunc.hash(settingsBytes);
+ metadata.setSettingsHash(settingsHash);
+ if (previousSettingHash == null || !previousSettingHash.equals(settingsHash)) {
+ Bytes settingsKey = encodeSettingsKey(settingsHash);
+ boolean nx = storage.set(settingsKey, settingsBytes, ExPolicy.NOT_EXISTING);
+ if (!nx) {
+ String base58MetadataHash = settingsHash.toBase58();
+ // 有可能发生了并发写入冲突,不同的节点都向同一个存储服务器上写入数据;
+ String errMsg = "Ledger metadata already exist! --[MetadataHash=" + base58MetadataHash + "]";
+ LOGGER.warn(errMsg);
+ throw new LedgerException(errMsg);
+ }
+ }
+
+ // 基于之前的密码配置来计算元数据的哈希;
+ byte[] metadataBytes = serializeMetadata(metadata);
+
+ HashDigest metadataHash = hashFunc.hash(metadataBytes);
+ if (adminDataHash == null || !adminDataHash.equals(metadataHash)) {
+ // update modify;
+ // String base58MetadataHash = metadataHash.toBase58();
+ // String metadataKey = encodeMetadataKey(base58MetadataHash);
+ Bytes metadataKey = encodeMetadataKey(metadataHash);
+
+ boolean nx = storage.set(metadataKey, metadataBytes, ExPolicy.NOT_EXISTING);
+ if (!nx) {
+ String base58MetadataHash = metadataHash.toBase58();
+ // 有可能发生了并发写入冲突,不同的节点都向同一个存储服务器上写入数据;
+ String errMsg = "Ledger metadata already exist! --[MetadataHash=" + base58MetadataHash + "]";
+ LOGGER.warn(errMsg);
+ throw new LedgerException(errMsg);
+ }
+
+ adminDataHash = metadataHash;
+ }
+
+ updated = false;
+ }
+
+ private LedgerMetadata_V2 deserializeMetadata(byte[] bytes) {
+ return BinaryProtocol.decode(bytes);
+ }
+
+ private byte[] serializeMetadata(LedgerMetadataInfo config) {
+ return BinaryProtocol.encode(config, LedgerMetadata_V2.class);
+ }
+
+ @Override
+ public void cancel() {
+ if (!isUpdated()) {
+ return;
+ }
+ participants.cancel();
+ metadata =origMetadata == null ? new LedgerMetadataInfo() : new LedgerMetadataInfo(origMetadata);
+ }
+
+ public static class LedgerMetadataInfo implements LedgerMetadata_V2 {
+
+ private byte[] seed;
+
+// private LedgerSetting setting;
+
+ private HashDigest participantsHash;
+
+ private HashDigest settingsHash;
+
+ private HashDigest rolePrivilegesHash;
+
+ private HashDigest userRolesHash;
+
+ public LedgerMetadataInfo() {
+ }
+
+ public LedgerMetadataInfo(LedgerMetadata_V2 metadata) {
+ this.seed = metadata.getSeed();
+ this.participantsHash = metadata.getParticipantsHash();
+ this.settingsHash = metadata.getSettingsHash();
+ this.rolePrivilegesHash = metadata.getRolePrivilegesHash();
+ this.userRolesHash = metadata.getUserRolesHash();
+ }
+
+ @Override
+ public byte[] getSeed() {
+ return seed;
+ }
+
+ @Override
+ public HashDigest getSettingsHash() {
+ return settingsHash;
+ }
+
+ @Override
+ public HashDigest getParticipantsHash() {
+ return participantsHash;
+ }
+
+ @Override
+ public HashDigest getRolePrivilegesHash() {
+ return rolePrivilegesHash;
+ }
+
+ @Override
+ public HashDigest getUserRolesHash() {
+ return userRolesHash;
+ }
+
+ public void setSeed(byte[] seed) {
+ this.seed = seed;
+ }
+
+ public void setSettingsHash(HashDigest settingHash) {
+ this.settingsHash = settingHash;
+ }
+
+ public void setParticipantsHash(HashDigest participantsHash) {
+ this.participantsHash = participantsHash;
+ }
+
+ public void setRolePrivilegesHash(HashDigest rolePrivilegesHash) {
+ this.rolePrivilegesHash = rolePrivilegesHash;
+ }
+
+ public void setUserRolesHash(HashDigest userRolesHash) {
+ this.userRolesHash = userRolesHash;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminPrivilege.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminPrivilege.java
deleted file mode 100644
index b436b5da..00000000
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminPrivilege.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.jd.blockchain.ledger.core;
-
-public enum LedgerAdminPrivilege {
-
-}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdministration.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdministration.java
deleted file mode 100644
index cc09138f..00000000
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdministration.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.jd.blockchain.ledger.core;
-
-import com.jd.blockchain.ledger.LedgerMetadata;
-import com.jd.blockchain.ledger.ParticipantNode;
-
-public interface LedgerAdministration {
-
- LedgerMetadata getMetadata();
-
- long getParticipantCount();
-
-// ParticipantNode getParticipant(int id);
-
- ParticipantNode[] getParticipants();
-
-}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerBlockData.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerBlockData.java
similarity index 94%
rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerBlockData.java
rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerBlockData.java
index 24b20401..3c667ebe 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerBlockData.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerBlockData.java
@@ -1,4 +1,4 @@
-package com.jd.blockchain.ledger.core.impl;
+package com.jd.blockchain.ledger.core;
import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.HashDigest;
@@ -33,7 +33,9 @@ public class LedgerBlockData implements LedgerBlock {
// private HashDigest contractPrivilegeHash;
private HashDigest transactionSetHash;
-
+
+ private long timestamp;
+
public LedgerBlockData() {
}
@@ -155,4 +157,14 @@ public class LedgerBlockData implements LedgerBlock {
this.ledgerHash = ledgerHash;
}
+ public long getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(long timestamp) {
+ this.timestamp = timestamp;
+ }
+
+
+
}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerConfiguration.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerConfiguration.java
index 5605003c..e727c5ad 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerConfiguration.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerConfiguration.java
@@ -1,10 +1,10 @@
package com.jd.blockchain.ledger.core;
import com.jd.blockchain.ledger.CryptoSetting;
-import com.jd.blockchain.ledger.LedgerSetting;
+import com.jd.blockchain.ledger.LedgerSettings;
import com.jd.blockchain.utils.Bytes;
-public class LedgerConfiguration implements LedgerSetting {
+public class LedgerConfiguration implements LedgerSettings {
private String consensusProvider;
@@ -16,7 +16,7 @@ public class LedgerConfiguration implements LedgerSetting {
this.cryptoSetting = new CryptoConfig();
}
- public LedgerConfiguration(LedgerSetting origSetting) {
+ public LedgerConfiguration(LedgerSettings origSetting) {
if (origSetting != null) {
this.consensusProvider = origSetting.getConsensusProvider();
this.consensusSetting = origSetting.getConsensusSetting();
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerDataQuery.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerDataQuery.java
new file mode 100644
index 00000000..df70d0c0
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerDataQuery.java
@@ -0,0 +1,19 @@
+package com.jd.blockchain.ledger.core;
+
+/**
+ * {@link LedgerDataset} 表示账本在某一个区块上的数据集合;
+ *
+ * @author huanghaiquan
+ *
+ */
+public interface LedgerDataQuery{
+
+ LedgerAdminDataQuery getAdminDataset();
+
+ UserAccountQuery getUserAccountSet();
+
+ DataAccountQuery getDataAccountSet();
+
+ ContractAccountQuery getContractAccountset();
+
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerDataSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerDataSet.java
deleted file mode 100644
index 40f63da6..00000000
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerDataSet.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.jd.blockchain.ledger.core;
-
-/**
- * {@link LedgerDataSet} 表示账本在某一个区块上的数据集合;
- *
- * @author huanghaiquan
- *
- */
-public interface LedgerDataSet{
-
- boolean isReadonly();
-
- LedgerAdminAccount getAdminAccount();
-
- UserAccountSet getUserAccountSet();
-
- DataAccountSet getDataAccountSet();
-
- ContractAccountSet getContractAccountSet();
-
-}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerDataSetImpl.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerDataset.java
similarity index 62%
rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerDataSetImpl.java
rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerDataset.java
index 4ec9d657..9f840d35 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerDataSetImpl.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerDataset.java
@@ -1,33 +1,31 @@
-package com.jd.blockchain.ledger.core.impl;
+package com.jd.blockchain.ledger.core;
-import com.jd.blockchain.ledger.core.*;
import com.jd.blockchain.utils.Transactional;
-public class LedgerDataSetImpl implements LedgerDataSet, Transactional {
+public class LedgerDataset implements LedgerDataQuery, Transactional {
- private LedgerAdminAccount adminAccount;
+ private LedgerAdminDataset adminDataset;
private UserAccountSet userAccountSet;
private DataAccountSet dataAccountSet;
private ContractAccountSet contractAccountSet;
-
- private boolean readonly;
+ private boolean readonly;
/**
* Create new block;
+ *
* @param adminAccount
* @param userAccountSet
* @param dataAccountSet
* @param contractAccountSet
* @param readonly
*/
- public LedgerDataSetImpl(LedgerAdminAccount adminAccount,
- UserAccountSet userAccountSet, DataAccountSet dataAccountSet, ContractAccountSet contractAccountSet,
- boolean readonly) {
- this.adminAccount = adminAccount;
+ public LedgerDataset(LedgerAdminDataset adminAccount, UserAccountSet userAccountSet,
+ DataAccountSet dataAccountSet, ContractAccountSet contractAccountSet, boolean readonly) {
+ this.adminDataset = adminAccount;
this.userAccountSet = userAccountSet;
this.dataAccountSet = dataAccountSet;
this.contractAccountSet = contractAccountSet;
@@ -36,8 +34,8 @@ public class LedgerDataSetImpl implements LedgerDataSet, Transactional {
}
@Override
- public LedgerAdminAccount getAdminAccount() {
- return adminAccount;
+ public LedgerAdminDataset getAdminDataset() {
+ return adminDataset;
}
@Override
@@ -51,13 +49,13 @@ public class LedgerDataSetImpl implements LedgerDataSet, Transactional {
}
@Override
- public ContractAccountSet getContractAccountSet() {
+ public ContractAccountSet getContractAccountset() {
return contractAccountSet;
}
@Override
public boolean isUpdated() {
- return adminAccount.isUpdated() || userAccountSet.isUpdated() || dataAccountSet.isUpdated()
+ return adminDataset.isUpdated() || userAccountSet.isUpdated() || dataAccountSet.isUpdated()
|| contractAccountSet.isUpdated();
}
@@ -70,7 +68,7 @@ public class LedgerDataSetImpl implements LedgerDataSet, Transactional {
return;
}
- adminAccount.commit();
+ adminDataset.commit();
userAccountSet.commit();
dataAccountSet.commit();
contractAccountSet.commit();
@@ -78,15 +76,22 @@ public class LedgerDataSetImpl implements LedgerDataSet, Transactional {
@Override
public void cancel() {
- adminAccount.cancel();
+ adminDataset.cancel();
userAccountSet.cancel();
dataAccountSet.cancel();
contractAccountSet.cancel();
}
- @Override
public boolean isReadonly() {
return readonly;
}
+ void setReadonly() {
+ this.readonly = true;
+ this.adminDataset.setReadonly();
+ this.userAccountSet.setReadonly();
+ this.dataAccountSet.setReadonly();
+ this.contractAccountSet.setReadonly();
+ }
+
}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerEditor.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerEditor.java
index efa3e750..466dd30a 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerEditor.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerEditor.java
@@ -1,5 +1,6 @@
package com.jd.blockchain.ledger.core;
+import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.LedgerTransaction;
@@ -10,7 +11,7 @@ import com.jd.blockchain.ledger.TransactionRequest;
*
*
* {@link LedgerEditor} 以上一个区块作为数据编辑的起点;
- * 对账本数据({@link #getDataSet()})的批量更改可以作为一个交易({@link LedgerTransaction})整体提交暂存,形成暂存点;
+ * 对账本数据({@link #getDataset()})的批量更改可以作为一个交易({@link LedgerTransaction})整体提交暂存,形成暂存点;
*
*
* @author huanghaiquan
@@ -18,11 +19,39 @@ import com.jd.blockchain.ledger.TransactionRequest;
*/
public interface LedgerEditor {
+ /**
+ * 账本Hash;
+ *
+ * @return
+ */
+ HashDigest getLedgerHash();
+
+ /**
+ * 新区块的高度;
+ *
+ * @return
+ */
+ long getBlockHeight();
+
+ /**
+ * 最新的账本数据集;
+ *
+ * @return
+ */
+ LedgerDataset getLedgerDataset();
+
+ /**
+ * 最新的交易集合;
+ *
+ * @return
+ */
+ TransactionSet getTransactionSet();
+
/**
* 开始新事务;
*
* 方法返回之前,将会校验交易请求的用户签名列表和节点签名列表,并在后续对数据集
- * {@link LedgerTransactionContext#getDataSet()} 的操作时,校验这些用户和节点是否具备权限;
+ * {@link LedgerTransactionContext#getDataset()} 的操作时,校验这些用户和节点是否具备权限;
*
* 校验失败将引发异常 {@link LedgerException};
*
@@ -32,11 +61,15 @@ public interface LedgerEditor {
* 或者全部回滚(通过方法 {@link LedgerTransactionContext#rollback()}),以此实现原子性写入;
*
*
- * 每一次事务性的账本写入操作在提交后,都会记录该事务相关的系统全局快照,以交易对象 {@link LedgerTransaction} 进行保存;
+ * 每一次事务性的账本写入操作在提交后,都会记录该事务相关的系统全局快照,以交易对象 {@link LedgerTransaction} 进行保存;
+ *
+ *
+ *
*
* 注:方法不解析、不执行交易中的操作;
+ *
*
- * @param txRequest
+ * @param txRequest 交易请求;
* @return
*/
LedgerTransactionContext newTransaction(TransactionRequest txRequest);
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitPermission.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitProposal.java
similarity index 92%
rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitPermission.java
rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitProposal.java
index 7ca9e15c..2baaacbd 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitPermission.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitProposal.java
@@ -13,8 +13,8 @@ import com.jd.blockchain.ledger.LedgerInitOperation;
* @author huanghaiquan
*
*/
-@DataContract(code = DataCodes.METADATA_INIT_PERMISSION)
-public interface LedgerInitPermission {
+@DataContract(code = DataCodes.METADATA_INIT_PROPOSAL)
+public interface LedgerInitProposal {
/**
* 做出许可的参与方 ID;
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitPermissionData.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitProposalData.java
similarity index 68%
rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitPermissionData.java
rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitProposalData.java
index ead25a56..4fa95cb7 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitPermissionData.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitProposalData.java
@@ -2,7 +2,7 @@ package com.jd.blockchain.ledger.core;
import com.jd.blockchain.crypto.SignatureDigest;
-public class LedgerInitPermissionData implements LedgerInitPermission {
+public class LedgerInitProposalData implements LedgerInitProposal {
private int participantId;
@@ -11,10 +11,11 @@ public class LedgerInitPermissionData implements LedgerInitPermission {
/**
* a private contructor for deserialize;
*/
- private LedgerInitPermissionData() {
+ @SuppressWarnings("unused")
+ private LedgerInitProposalData() {
}
- public LedgerInitPermissionData(int participantId, SignatureDigest initTxSignature) {
+ public LedgerInitProposalData(int participantId, SignatureDigest initTxSignature) {
this.participantId = participantId;
this.transactionSignature = initTxSignature;
}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitializer.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitializer.java
new file mode 100644
index 00000000..ca159135
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitializer.java
@@ -0,0 +1,215 @@
+package com.jd.blockchain.ledger.core;
+
+import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.crypto.PrivKey;
+import com.jd.blockchain.crypto.SignatureDigest;
+import com.jd.blockchain.ledger.BlockchainIdentity;
+import com.jd.blockchain.ledger.BlockchainIdentityData;
+import com.jd.blockchain.ledger.DigitalSignature;
+import com.jd.blockchain.ledger.LedgerBlock;
+import com.jd.blockchain.ledger.LedgerInitException;
+import com.jd.blockchain.ledger.LedgerInitOperation;
+import com.jd.blockchain.ledger.LedgerInitSetting;
+import com.jd.blockchain.ledger.ParticipantNode;
+import com.jd.blockchain.ledger.RoleInitSettings;
+import com.jd.blockchain.ledger.RolesConfigureOperation;
+import com.jd.blockchain.ledger.SecurityInitSettings;
+import com.jd.blockchain.ledger.TransactionBuilder;
+import com.jd.blockchain.ledger.TransactionContent;
+import com.jd.blockchain.ledger.TransactionRequest;
+import com.jd.blockchain.ledger.UserAuthInitSettings;
+import com.jd.blockchain.ledger.UserAuthorizeOperation;
+import com.jd.blockchain.ledger.UserRegisterOperation;
+import com.jd.blockchain.service.TransactionBatchResultHandle;
+import com.jd.blockchain.storage.service.KVStorageService;
+import com.jd.blockchain.transaction.SignatureUtils;
+import com.jd.blockchain.transaction.TxBuilder;
+import com.jd.blockchain.transaction.TxRequestBuilder;
+
+public class LedgerInitializer {
+
+ private static final FullPermissionedSecurityManager FULL_PERMISSION_SECURITY_MANAGER = new FullPermissionedSecurityManager();
+
+ private static final LedgerDataQuery EMPTY_LEDGER_DATA_QUERY = new EmptyLedgerDataset();
+
+ private static final OperationHandleRegisteration DEFAULT_OP_HANDLE_REG = new DefaultOperationHandleRegisteration();
+
+ private LedgerService EMPTY_LEDGERS = new LedgerManager();
+
+ private LedgerInitSetting initSetting;
+
+ private TransactionContent initTxContent;
+
+ private volatile LedgerBlock genesisBlock;
+
+ private volatile LedgerEditor ledgerEditor;
+
+ private volatile boolean committed = false;
+
+ private volatile boolean canceled = false;
+
+ private TransactionBatchResultHandle txResultsHandle;
+
+ /**
+ * 初始化生成的账本hash;
+ *
+ * 在成功执行 {@link #prepareLedger(KVStorageService, DigitalSignature...)} 之前总是返回
+ * null;
+ *
+ * @return
+ */
+ public HashDigest getLedgerHash() {
+ return genesisBlock == null ? null : genesisBlock.getHash();
+ }
+
+ /**
+ * @param initSetting
+ * @param initTxContent
+ */
+ private LedgerInitializer(LedgerInitSetting initSetting, TransactionContent initTxContent) {
+ this.initSetting = initSetting;
+ this.initTxContent = initTxContent;
+ }
+
+ public TransactionContent getTransactionContent() {
+ return initTxContent;
+ }
+
+ private static SecurityInitSettings createDefaultSecurityInitSettings() {
+ // TODO throw new IllegalStateException("Not implemented!");
+ return null;
+ }
+
+// public static LedgerInitializer create(LedgerInitSetting initSetting) {
+// return create(initSetting, createDefaultSecurityInitSettings());
+// }
+
+ public static LedgerInitializer create(LedgerInitSetting initSetting, SecurityInitSettings securityInitSettings) {
+ // 生成创世交易;
+ TransactionContent initTxContent = buildGenesisTransaction(initSetting, securityInitSettings);
+
+ return new LedgerInitializer(initSetting, initTxContent);
+ }
+
+ /**
+ * 根据初始化配置,生成创始交易;
+ *
+ *
+ * “创世交易”按顺序由以下操作组成:
+ * (1) 账本初始化 {@link LedgerInitOperation}:此操作仅用于锚定了原始的交易配置,对应的
+ * {@link OperationHandle} 执行空操作,由“创世交易”其余的操作来表达对账本的实际修改;
+ * (2) 注册用户 {@link UserRegisterOperation}:有一项或者多项;
+ * (3) 配置角色 {@link RolesConfigureOperation}:有一项或者多项;
+ * (4) 授权用户 {@link UserAuthorizeOperation}:有一项或者多项;
+ *
+ * @param initSetting
+ * @param securityInitSettings
+ * @return
+ */
+ public static TransactionContent buildGenesisTransaction(LedgerInitSetting initSetting,
+ SecurityInitSettings securityInitSettings) {
+ // 账本初始化交易的账本 hash 为 null;
+ TransactionBuilder initTxBuilder = new TxBuilder(null);
+
+ // 定义账本初始化操作;
+ initTxBuilder.ledgers().create(initSetting);
+
+ // TODO: 注册参与方; 目前由 LedgerInitSetting 定义,在 LedgerAdminDataset 中解释执行;
+
+ // 注册用户;
+ for (ParticipantNode p : initSetting.getConsensusParticipants()) {
+ // TODO:暂时只支持注册用户的初始化操作;
+ BlockchainIdentity superUserId = new BlockchainIdentityData(p.getPubKey());
+ initTxBuilder.users().register(superUserId);
+ }
+
+ // 配置角色;
+ for (RoleInitSettings roleSettings : securityInitSettings.getRoles()) {
+ initTxBuilder.security().roles().configure(roleSettings.getRoleName())
+ .enable(roleSettings.getLedgerPermissions()).enable(roleSettings.getTransactionPermissions());
+ }
+
+ // 授权用户;
+ for (UserAuthInitSettings userAuthSettings : securityInitSettings.getUserAuthorizations()) {
+ initTxBuilder.security().authorziations().forUser(userAuthSettings.getUserAddress())
+ .authorize(userAuthSettings.getRoles())
+ .setPolicy(userAuthSettings.getPolicy());
+ }
+
+ // 账本初始化配置声明的创建时间来初始化交易时间戳;注:不能用本地时间,因为共识节点之间的本地时间系统不一致;
+ return initTxBuilder.prepareContent(initSetting.getCreatedTime());
+ }
+
+ public SignatureDigest signTransaction(PrivKey privKey) {
+ return SignatureUtils.sign(initTxContent, privKey);
+ }
+
+ /**
+ * 准备创建账本;
+ *
+ * @param storageService 存储服务;
+ * @param nodeSignatures 节点签名列表;
+ * @return
+ */
+ public LedgerBlock prepareLedger(KVStorageService storageService, DigitalSignature... nodeSignatures) {
+ if (genesisBlock != null) {
+ throw new LedgerInitException("The ledger has been prepared!");
+ }
+ // 生成账本;
+ this.ledgerEditor = createLedgerEditor(this.initSetting, storageService);
+ this.genesisBlock = prepareLedger(ledgerEditor, nodeSignatures);
+
+ return genesisBlock;
+ }
+
+ public void commit() {
+ if (committed) {
+ throw new LedgerInitException("The ledger has been committed!");
+ }
+ if (canceled) {
+ throw new LedgerInitException("The ledger has been canceled!");
+ }
+ committed = true;
+ this.txResultsHandle.commit();
+ }
+
+ public void cancel() {
+ if (canceled) {
+ throw new LedgerInitException("The ledger has been canceled!");
+ }
+ if (committed) {
+ throw new LedgerInitException("The ledger has been committed!");
+ }
+ this.ledgerEditor.cancel();
+ }
+
+ public static LedgerEditor createLedgerEditor(LedgerInitSetting initSetting, KVStorageService storageService) {
+ LedgerEditor genesisBlockEditor = LedgerTransactionalEditor.createEditor(initSetting,
+ LedgerManage.LEDGER_PREFIX, storageService.getExPolicyKVStorage(),
+ storageService.getVersioningKVStorage());
+ return genesisBlockEditor;
+ }
+
+ /**
+ * 初始化账本数据,返回创始区块;
+ *
+ * @param ledgerEditor
+ * @return
+ */
+ private LedgerBlock prepareLedger(LedgerEditor ledgerEditor, DigitalSignature... nodeSignatures) {
+ // 初始化时,自动将参与方注册为账本的用户;
+ TxRequestBuilder txReqBuilder = new TxRequestBuilder(this.initTxContent);
+ txReqBuilder.addNodeSignature(nodeSignatures);
+
+ TransactionRequest txRequest = txReqBuilder.buildRequest();
+
+ TransactionBatchProcessor txProcessor = new TransactionBatchProcessor(FULL_PERMISSION_SECURITY_MANAGER,
+ ledgerEditor, EMPTY_LEDGER_DATA_QUERY, DEFAULT_OP_HANDLE_REG, EMPTY_LEDGERS);
+
+ txProcessor.schedule(txRequest);
+
+ txResultsHandle = txProcessor.prepare();
+ return txResultsHandle.getBlock();
+ }
+
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerManage.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerManage.java
index 0e2ae587..65f8738b 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerManage.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerManage.java
@@ -12,19 +12,21 @@ import com.jd.blockchain.storage.service.KVStorageService;
*/
public interface LedgerManage extends LedgerService {
+ static final String LEDGER_PREFIX = "LDG://";
+
LedgerRepository register(HashDigest ledgerHash, KVStorageService storageService);
void unregister(HashDigest ledgerHash);
- /**
- * 创建新账本;
- *
- * @param initSetting
- * 初始化配置;
- * @param initPermissions
- * 参与者的初始化授权列表;与参与者列表一致;
- * @return
- */
- LedgerEditor newLedger(LedgerInitSetting initSetting, KVStorageService storageService);
+// /**
+// * 创建新账本;
+// *
+// * @param initSetting
+// * 初始化配置;
+// * @param initPermissions
+// * 参与者的初始化授权列表;与参与者列表一致;
+// * @return
+// */
+// LedgerEditor newLedger(LedgerInitSetting initSetting, KVStorageService storageService);
}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerManager.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerManager.java
similarity index 84%
rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerManager.java
rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerManager.java
index 19dfee44..2e66b7ca 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerManager.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerManager.java
@@ -1,4 +1,4 @@
-package com.jd.blockchain.ledger.core.impl;
+package com.jd.blockchain.ledger.core;
import java.util.HashMap;
import java.util.Map;
@@ -9,11 +9,6 @@ import com.jd.blockchain.crypto.CryptoProvider;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
-import com.jd.blockchain.ledger.LedgerInitSetting;
-import com.jd.blockchain.ledger.core.LedgerConsts;
-import com.jd.blockchain.ledger.core.LedgerEditor;
-import com.jd.blockchain.ledger.core.LedgerManage;
-import com.jd.blockchain.ledger.core.LedgerRepository;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.KVStorageService;
import com.jd.blockchain.storage.service.VersioningKVStorage;
@@ -27,8 +22,6 @@ import com.jd.blockchain.utils.codec.Base58Utils;
*/
public class LedgerManager implements LedgerManage {
- private static final String LEDGER_PREFIX = "LDG://";
-
// @Autowired
// private ExistentialKVStorage exPolicyStorage;
//
@@ -69,7 +62,7 @@ public class LedgerManager implements LedgerManage {
ledgerVersioningStorage);
// 校验 crypto service provider ;
- CryptoSetting cryptoSetting = ledgerRepo.getAdminAccount().getSetting().getCryptoSetting();
+ CryptoSetting cryptoSetting = ledgerRepo.getAdminInfo().getSettings().getCryptoSetting();
checkCryptoSetting(cryptoSetting, ledgerHash);
// 创建账本上下文;
@@ -142,18 +135,18 @@ public class LedgerManager implements LedgerManage {
}
}
- /*
- * (non-Javadoc)
- *
- * @see com.jd.blockchain.ledger.core.LedgerManager#newLedger(com.jd.blockchain.
- * ledger.core.ConsensusConfig, com.jd.blockchain.ledger.core.CryptoConfig)
- */
- @Override
- public LedgerEditor newLedger(LedgerInitSetting initSetting, KVStorageService storageService) {
- LedgerEditor genesisBlockEditor = LedgerTransactionalEditor.createEditor(initSetting, LEDGER_PREFIX,
- storageService.getExPolicyKVStorage(), storageService.getVersioningKVStorage());
- return genesisBlockEditor;
- }
+// /*
+// * (non-Javadoc)
+// *
+// * @see com.jd.blockchain.ledger.core.LedgerManager#newLedger(com.jd.blockchain.
+// * ledger.core.ConsensusConfig, com.jd.blockchain.ledger.core.CryptoConfig)
+// */
+// @Override
+// public LedgerEditor newLedger(LedgerInitSetting initSetting, KVStorageService storageService) {
+// LedgerEditor genesisBlockEditor = LedgerTransactionalEditor.createEditor(initSetting, LEDGER_PREFIX,
+// storageService.getExPolicyKVStorage(), storageService.getVersioningKVStorage());
+// return genesisBlockEditor;
+// }
static String getLedgerStoragePrefix(HashDigest ledgerHash) {
String base58LedgerHash = Base58Utils.encode(ledgerHash.toBytes());
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerQueryService.java
similarity index 83%
rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java
rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerQueryService.java
index 5696ded7..0b85c8c6 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerQueryService.java
@@ -1,25 +1,33 @@
-package com.jd.blockchain.ledger.core.impl;
+package com.jd.blockchain.ledger.core;
import java.util.ArrayList;
import java.util.List;
import com.jd.blockchain.contract.ContractException;
import com.jd.blockchain.crypto.HashDigest;
-import com.jd.blockchain.ledger.*;
-import com.jd.blockchain.ledger.core.ContractAccountSet;
-import com.jd.blockchain.ledger.core.DataAccount;
-import com.jd.blockchain.ledger.core.DataAccountSet;
-import com.jd.blockchain.ledger.core.LedgerAdministration;
-import com.jd.blockchain.ledger.core.LedgerRepository;
-import com.jd.blockchain.ledger.core.LedgerService;
-import com.jd.blockchain.ledger.core.TransactionSet;
-import com.jd.blockchain.ledger.core.UserAccountSet;
+import com.jd.blockchain.ledger.AccountHeader;
+import com.jd.blockchain.ledger.BytesValue;
+import com.jd.blockchain.ledger.ContractInfo;
+import com.jd.blockchain.ledger.KVDataEntry;
+import com.jd.blockchain.ledger.KVDataObject;
+import com.jd.blockchain.ledger.KVDataVO;
+import com.jd.blockchain.ledger.KVInfoVO;
+import com.jd.blockchain.ledger.LedgerAdminInfo;
+import com.jd.blockchain.ledger.LedgerBlock;
+import com.jd.blockchain.ledger.LedgerInfo;
+import com.jd.blockchain.ledger.LedgerMetadata;
+import com.jd.blockchain.ledger.LedgerTransaction;
+import com.jd.blockchain.ledger.ParticipantNode;
+import com.jd.blockchain.ledger.TransactionState;
+import com.jd.blockchain.ledger.UserInfo;
import com.jd.blockchain.transaction.BlockchainQueryService;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.QueryUtil;
public class LedgerQueryService implements BlockchainQueryService {
+ private static final KVDataEntry[] EMPTY_ENTRIES = new KVDataEntry[0];
+
private LedgerService ledgerService;
public LedgerQueryService(LedgerService ledgerService) {
@@ -40,15 +48,23 @@ public class LedgerQueryService implements BlockchainQueryService {
ledgerInfo.setLatestBlockHeight(ledger.getLatestBlockHeight());
return ledgerInfo;
}
+
+ @Override
+ public LedgerAdminInfo getLedgerAdminInfo(HashDigest ledgerHash) {
+ LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
+ LedgerBlock block = ledger.getLatestBlock();
+ LedgerAdminInfo administration = ledger.getAdminInfo(block);
+ return administration;
+ }
@Override
public ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash) {
- return ledgerAdministration(ledgerHash).getParticipants();
+ return getLedgerAdminInfo(ledgerHash).getParticipants();
}
@Override
public LedgerMetadata getLedgerMetadata(HashDigest ledgerHash) {
- return ledgerAdministration(ledgerHash).getMetadata();
+ return getLedgerAdminInfo(ledgerHash).getMetadata();
}
@Override
@@ -91,7 +107,7 @@ public class LedgerQueryService implements BlockchainQueryService {
public long getDataAccountCount(HashDigest ledgerHash, long height) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getBlock(height);
- DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
+ DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
return dataAccountSet.getTotalCount();
}
@@ -99,7 +115,7 @@ public class LedgerQueryService implements BlockchainQueryService {
public long getDataAccountCount(HashDigest ledgerHash, HashDigest blockHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getBlock(blockHash);
- DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
+ DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
return dataAccountSet.getTotalCount();
}
@@ -107,7 +123,7 @@ public class LedgerQueryService implements BlockchainQueryService {
public long getDataAccountTotalCount(HashDigest ledgerHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
- DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
+ DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
return dataAccountSet.getTotalCount();
}
@@ -115,7 +131,7 @@ public class LedgerQueryService implements BlockchainQueryService {
public long getUserCount(HashDigest ledgerHash, long height) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getBlock(height);
- UserAccountSet userAccountSet = ledger.getUserAccountSet(block);
+ UserAccountQuery userAccountSet = ledger.getUserAccountSet(block);
return userAccountSet.getTotalCount();
}
@@ -123,7 +139,7 @@ public class LedgerQueryService implements BlockchainQueryService {
public long getUserCount(HashDigest ledgerHash, HashDigest blockHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getBlock(blockHash);
- UserAccountSet userAccountSet = ledger.getUserAccountSet(block);
+ UserAccountQuery userAccountSet = ledger.getUserAccountSet(block);
return userAccountSet.getTotalCount();
}
@@ -131,7 +147,7 @@ public class LedgerQueryService implements BlockchainQueryService {
public long getUserTotalCount(HashDigest ledgerHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
- UserAccountSet userAccountSet = ledger.getUserAccountSet(block);
+ UserAccountQuery userAccountSet = ledger.getUserAccountSet(block);
return userAccountSet.getTotalCount();
}
@@ -139,7 +155,7 @@ public class LedgerQueryService implements BlockchainQueryService {
public long getContractCount(HashDigest ledgerHash, long height) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getBlock(height);
- ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block);
+ ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block);
return contractAccountSet.getTotalCount();
}
@@ -147,7 +163,7 @@ public class LedgerQueryService implements BlockchainQueryService {
public long getContractCount(HashDigest ledgerHash, HashDigest blockHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getBlock(blockHash);
- ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block);
+ ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block);
return contractAccountSet.getTotalCount();
}
@@ -155,7 +171,7 @@ public class LedgerQueryService implements BlockchainQueryService {
public long getContractTotalCount(HashDigest ledgerHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
- ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block);
+ ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block);
return contractAccountSet.getTotalCount();
}
@@ -238,7 +254,7 @@ public class LedgerQueryService implements BlockchainQueryService {
public UserInfo getUser(HashDigest ledgerHash, String address) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
- UserAccountSet userAccountSet = ledger.getUserAccountSet(block);
+ UserAccountQuery userAccountSet = ledger.getUserAccountSet(block);
return userAccountSet.getUser(address);
}
@@ -247,18 +263,18 @@ public class LedgerQueryService implements BlockchainQueryService {
public AccountHeader getDataAccount(HashDigest ledgerHash, String address) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
- DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
+ DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
return dataAccountSet.getDataAccount(Bytes.fromBase58(address));
}
@Override
public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys) {
if (keys == null || keys.length == 0) {
- return null;
+ return EMPTY_ENTRIES;
}
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
- DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
+ DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address));
KVDataEntry[] entries = new KVDataEntry[keys.length];
@@ -266,7 +282,7 @@ public class LedgerQueryService implements BlockchainQueryService {
for (int i = 0; i < entries.length; i++) {
final String currKey = keys[i];
- ver = dataAccount.getDataVersion(Bytes.fromString(currKey));
+ ver = dataAccount == null ? -1 : dataAccount.getDataVersion(Bytes.fromString(currKey));
if (ver < 0) {
entries[i] = new KVDataObject(currKey, -1, null);
@@ -306,7 +322,7 @@ public class LedgerQueryService implements BlockchainQueryService {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
- DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
+ DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address));
KVDataEntry[] entries = new KVDataEntry[keys.length];
@@ -337,7 +353,7 @@ public class LedgerQueryService implements BlockchainQueryService {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
- DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
+ DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address));
int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccount.getDataEntriesTotalCount());
@@ -349,7 +365,7 @@ public class LedgerQueryService implements BlockchainQueryService {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
- DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
+ DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address));
return dataAccount.getDataEntriesTotalCount();
@@ -359,7 +375,7 @@ public class LedgerQueryService implements BlockchainQueryService {
public ContractInfo getContract(HashDigest ledgerHash, String address) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
- ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block);
+ ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block);
return contractAccountSet.getContract(Bytes.fromBase58(address));
}
@@ -367,7 +383,7 @@ public class LedgerQueryService implements BlockchainQueryService {
public AccountHeader[] getUsers(HashDigest ledgerHash, int fromIndex, int count) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
- UserAccountSet userAccountSet = ledger.getUserAccountSet(block);
+ UserAccountQuery userAccountSet = ledger.getUserAccountSet(block);
int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) userAccountSet.getTotalCount());
return userAccountSet.getAccounts(pages[0], pages[1]);
}
@@ -376,7 +392,7 @@ public class LedgerQueryService implements BlockchainQueryService {
public AccountHeader[] getDataAccounts(HashDigest ledgerHash, int fromIndex, int count) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
- DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
+ DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccountSet.getTotalCount());
return dataAccountSet.getAccounts(pages[0], pages[1]);
}
@@ -385,15 +401,9 @@ public class LedgerQueryService implements BlockchainQueryService {
public AccountHeader[] getContractAccounts(HashDigest ledgerHash, int fromIndex, int count) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
- ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block);
+ ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block);
int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) contractAccountSet.getTotalCount());
return contractAccountSet.getAccounts(pages[0], pages[1]);
}
- private LedgerAdministration ledgerAdministration(HashDigest ledgerHash) {
- LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
- LedgerBlock block = ledger.getLatestBlock();
- LedgerAdministration administration = ledger.getAdminAccount(block);
- return administration;
- }
}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerRepository.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerRepository.java
index faa23138..a8790ab0 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerRepository.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerRepository.java
@@ -3,6 +3,7 @@ package com.jd.blockchain.ledger.core;
import java.io.Closeable;
import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.ledger.LedgerAdminInfo;
import com.jd.blockchain.ledger.LedgerBlock;
public interface LedgerRepository extends Closeable {
@@ -51,23 +52,23 @@ public interface LedgerRepository extends Closeable {
*/
LedgerBlock getBlock(long height);
- LedgerAdministration getAdminInfo();
+ LedgerAdminInfo getAdminInfo();
+
+ LedgerAdminInfo getAdminInfo(LedgerBlock block);
LedgerBlock getBlock(HashDigest hash);
- LedgerDataSet getDataSet(LedgerBlock block);
+ LedgerDataQuery getDataSet(LedgerBlock block);
TransactionSet getTransactionSet(LedgerBlock block);
- LedgerAdminAccount getAdminAccount(LedgerBlock block);
+ UserAccountQuery getUserAccountSet(LedgerBlock block);
- UserAccountSet getUserAccountSet(LedgerBlock block);
+ DataAccountQuery getDataAccountSet(LedgerBlock block);
- DataAccountSet getDataAccountSet(LedgerBlock block);
+ ContractAccountQuery getContractAccountSet(LedgerBlock block);
- ContractAccountSet getContractAccountSet(LedgerBlock block);
-
- default LedgerDataSet getDataSet() {
+ default LedgerDataQuery getDataSet() {
return getDataSet(getLatestBlock());
}
@@ -75,19 +76,15 @@ public interface LedgerRepository extends Closeable {
return getTransactionSet(getLatestBlock());
}
- default LedgerAdminAccount getAdminAccount() {
- return getAdminAccount(getLatestBlock());
- }
-
- default UserAccountSet getUserAccountSet() {
+ default UserAccountQuery getUserAccountSet() {
return getUserAccountSet(getLatestBlock());
}
- default DataAccountSet getDataAccountSet() {
+ default DataAccountQuery getDataAccountSet() {
return getDataAccountSet(getLatestBlock());
}
- default ContractAccountSet getContractAccountSet() {
+ default ContractAccountQuery getContractAccountSet() {
return getContractAccountSet(getLatestBlock());
}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerRepositoryImpl.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerRepositoryImpl.java
similarity index 53%
rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerRepositoryImpl.java
rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerRepositoryImpl.java
index 69e3223f..55c9d6d6 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerRepositoryImpl.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerRepositoryImpl.java
@@ -1,22 +1,17 @@
-package com.jd.blockchain.ledger.core.impl;
+package com.jd.blockchain.ledger.core;
import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.HashFunction;
-import com.jd.blockchain.ledger.*;
-import com.jd.blockchain.ledger.core.AccountAccessPolicy;
-import com.jd.blockchain.ledger.core.ContractAccountSet;
-import com.jd.blockchain.ledger.core.DataAccountSet;
-import com.jd.blockchain.ledger.core.LedgerAdminAccount;
-import com.jd.blockchain.ledger.core.LedgerAdministration;
-import com.jd.blockchain.ledger.core.LedgerConsts;
-import com.jd.blockchain.ledger.core.LedgerDataSet;
-import com.jd.blockchain.ledger.core.LedgerEditor;
-import com.jd.blockchain.ledger.core.LedgerRepository;
-import com.jd.blockchain.ledger.core.LedgerTransactionContext;
-import com.jd.blockchain.ledger.core.TransactionSet;
-import com.jd.blockchain.ledger.core.UserAccountSet;
+import com.jd.blockchain.ledger.BlockBody;
+import com.jd.blockchain.ledger.CryptoSetting;
+import com.jd.blockchain.ledger.LedgerAdminInfo;
+import com.jd.blockchain.ledger.LedgerBlock;
+import com.jd.blockchain.ledger.LedgerDataSnapshot;
+import com.jd.blockchain.ledger.LedgerInitSetting;
+import com.jd.blockchain.ledger.LedgerSettings;
+import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes;
@@ -35,7 +30,7 @@ import com.jd.blockchain.utils.codec.Base58Utils;
* @author huanghaiquan
*
*/
-public class LedgerRepositoryImpl implements LedgerRepository {
+class LedgerRepositoryImpl implements LedgerRepository {
private static final Bytes LEDGER_PREFIX = Bytes.fromString("IDX" + LedgerConsts.KEY_SEPERATOR);
@@ -77,8 +72,10 @@ public class LedgerRepositoryImpl implements LedgerRepository {
this.ledgerIndexKey = encodeLedgerIndexKey(ledgerHash);
if (getLatestBlockHeight() < 0) {
- throw new LedgerException("Ledger doesn't exist!");
+ throw new RuntimeException("Ledger doesn't exist!");
}
+
+ retrieveLatestState();
}
/*
@@ -109,25 +106,27 @@ public class LedgerRepositoryImpl implements LedgerRepository {
@Override
public LedgerBlock getLatestBlock() {
- LedgerState state = getLatestState();
- return state.block;
+ return latestState.block;
}
- private LedgerState getLatestState() {
- LedgerState state = latestState;
- if (state == null) {
- LedgerBlock latestBlock = innerGetBlock(innerGetLatestBlockHeight());
- state = new LedgerState(latestBlock);
- latestState = state;
- }
- return state;
+ /**
+ * 重新检索加载最新的状态;
+ *
+ * @return
+ */
+ private LedgerState retrieveLatestState() {
+ LedgerBlock latestBlock = innerGetBlock(innerGetLatestBlockHeight());
+ LedgerDataset ledgerDataset = innerGetLedgerDataset(latestBlock);
+ TransactionSet txSet = loadTransactionSet(latestBlock.getTransactionSetHash(),
+ ledgerDataset.getAdminDataset().getSettings().getCryptoSetting(), keyPrefix, exPolicyStorage,
+ versioningStorage, true);
+ this.latestState = new LedgerState(latestBlock, ledgerDataset, txSet);
+ return latestState;
}
@Override
public LedgerBlock retrieveLatestBlock() {
- LedgerBlock latestBlock = innerGetBlock(innerGetLatestBlockHeight());
- latestState = new LedgerState(latestBlock);
- return latestBlock;
+ return retrieveLatestState().block;
}
@Override
@@ -186,7 +185,7 @@ public class LedgerRepositoryImpl implements LedgerRepository {
if (height < 0) {
return null;
}
- return innerGetBlock(getBlockHash(height));
+ return innerGetBlock(innerGetBlockHash(height));
}
@Override
@@ -205,36 +204,27 @@ public class LedgerRepositoryImpl implements LedgerRepository {
LedgerBlockData block = new LedgerBlockData(deserialize(blockBytes));
if (!blockHash.equals(block.getHash())) {
- throw new LedgerException("Block hash not equals to it's storage key!");
- }
-
- // verify hash;
- // boolean requiredVerifyHash =
- // adminAccount.getMetadata().getSetting().getCryptoSetting().getAutoVerifyHash();
- // TODO: 未实现从配置中加载是否校验 Hash 的设置;
- boolean requiredVerifyHash = false;
- if (requiredVerifyHash) {
- byte[] blockBodyBytes = null;
- if (block.getHeight() == 0) {
- // 计算创世区块的 hash 时,不包括 ledgerHash 字段;
- block.setLedgerHash(null);
- blockBodyBytes = BinaryProtocol.encode(block, BlockBody.class);
- // 恢复;
- block.setLedgerHash(block.getHash());
- } else {
- blockBodyBytes = BinaryProtocol.encode(block, BlockBody.class);
- }
- HashFunction hashFunc = Crypto.getHashFunction(blockHash.getAlgorithm());
- boolean pass = hashFunc.verify(blockHash, blockBodyBytes);
- if (!pass) {
- throw new LedgerException("Block hash verification fail!");
- }
+ throw new RuntimeException("Block hash not equals to it's storage key!");
+ }
+
+ // verify block hash;
+ byte[] blockBodyBytes = null;
+ if (block.getHeight() == 0) {
+ // 计算创世区块的 hash 时,不包括 ledgerHash 字段;
+ blockBodyBytes = BinaryProtocol.encode(block, BlockBody.class);
+ } else {
+ blockBodyBytes = BinaryProtocol.encode(block, BlockBody.class);
+ }
+ HashFunction hashFunc = Crypto.getHashFunction(blockHash.getAlgorithm());
+ boolean pass = hashFunc.verify(blockHash, blockBodyBytes);
+ if (!pass) {
+ throw new RuntimeException("Block hash verification fail!");
}
// verify height;
HashDigest indexedHash = getBlockHash(block.getHeight());
if (indexedHash == null || !indexedHash.equals(blockHash)) {
- throw new LedgerException(
+ throw new RuntimeException(
"Illegal ledger state in storage that ledger height index doesn't match it's block data in height["
+ block.getHeight() + "] and block hash[" + Base58Utils.encode(blockHash.toBytes())
+ "] !");
@@ -243,9 +233,18 @@ public class LedgerRepositoryImpl implements LedgerRepository {
return block;
}
+ /**
+ * 获取最新区块的账本参数;
+ *
+ * @return
+ */
+ private LedgerSettings getLatestSettings() {
+ return getAdminInfo().getSettings();
+ }
+
@Override
- public LedgerAdministration getAdminInfo() {
- return getAdminAccount(getLatestBlock());
+ public LedgerAdminInfo getAdminInfo() {
+ return getAdminInfo(getLatestBlock());
}
private LedgerBlock deserialize(byte[] blockBytes) {
@@ -255,155 +254,110 @@ public class LedgerRepositoryImpl implements LedgerRepository {
@Override
public TransactionSet getTransactionSet(LedgerBlock block) {
long height = getLatestBlockHeight();
- TransactionSet transactionSet = null;
if (height == block.getHeight()) {
- // 缓存读;
- LedgerState state = getLatestState();
- transactionSet = state.transactionSet;
- if (transactionSet == null) {
- LedgerAdminAccount adminAccount = getAdminAccount(block);
- transactionSet = loadTransactionSet(block.getTransactionSetHash(),
- adminAccount.getMetadata().getSetting().getCryptoSetting(), keyPrefix, exPolicyStorage,
- versioningStorage, true);
- state.transactionSet = transactionSet;
- }
- return transactionSet;
+ // 从缓存中返回最新区块的数据集;
+ return latestState.getTransactionSet();
}
- LedgerAdminAccount adminAccount = getAdminAccount(block);
+ LedgerAdminInfo adminAccount = getAdminInfo(block);
// All of existing block is readonly;
- return loadTransactionSet(block.getTransactionSetHash(),
- adminAccount.getMetadata().getSetting().getCryptoSetting(), keyPrefix, exPolicyStorage,
- versioningStorage, true);
+ return loadTransactionSet(block.getTransactionSetHash(), adminAccount.getSettings().getCryptoSetting(),
+ keyPrefix, exPolicyStorage, versioningStorage, true);
}
@Override
- public LedgerAdminAccount getAdminAccount(LedgerBlock block) {
+ public LedgerAdminDataset getAdminInfo(LedgerBlock block) {
long height = getLatestBlockHeight();
- LedgerAdminAccount adminAccount = null;
if (height == block.getHeight()) {
- // 缓存读;
- LedgerState state = getLatestState();
- adminAccount = state.adminAccount;
- if (adminAccount == null) {
- adminAccount = new LedgerAdminAccount(block.getAdminAccountHash(), keyPrefix, exPolicyStorage,
- versioningStorage, true);
- state.adminAccount = adminAccount;
- }
- return adminAccount;
+ return latestState.getAdminDataset();
}
- return new LedgerAdminAccount(block.getAdminAccountHash(), keyPrefix, exPolicyStorage, versioningStorage, true);
+ return createAdminDataset(block);
+ }
+
+ private LedgerAdminDataset createAdminDataset(LedgerBlock block) {
+ return new LedgerAdminDataset(block.getAdminAccountHash(), keyPrefix, exPolicyStorage, versioningStorage, true);
}
@Override
- public UserAccountSet getUserAccountSet(LedgerBlock block) {
+ public UserAccountQuery getUserAccountSet(LedgerBlock block) {
long height = getLatestBlockHeight();
- UserAccountSet userAccountSet = null;
if (height == block.getHeight()) {
- // 缓存读;
- LedgerState state = getLatestState();
- userAccountSet = state.userAccountSet;
- if (userAccountSet == null) {
- LedgerAdminAccount adminAccount = getAdminAccount(block);
- userAccountSet = loadUserAccountSet(block.getUserAccountSetHash(),
- adminAccount.getPreviousSetting().getCryptoSetting(), keyPrefix, exPolicyStorage,
- versioningStorage, true);
- state.userAccountSet = userAccountSet;
- }
- return userAccountSet;
+ return latestState.getUserAccountSet();
}
- LedgerAdminAccount adminAccount = getAdminAccount(block);
- return loadUserAccountSet(block.getUserAccountSetHash(), adminAccount.getPreviousSetting().getCryptoSetting(),
- keyPrefix, exPolicyStorage, versioningStorage, true);
+ LedgerAdminDataset adminAccount = getAdminInfo(block);
+ return createUserAccountSet(block, adminAccount.getSettings().getCryptoSetting());
+ }
+
+ private UserAccountSet createUserAccountSet(LedgerBlock block, CryptoSetting cryptoSetting) {
+ return loadUserAccountSet(block.getUserAccountSetHash(), cryptoSetting, keyPrefix, exPolicyStorage,
+ versioningStorage, true);
}
@Override
- public DataAccountSet getDataAccountSet(LedgerBlock block) {
+ public DataAccountQuery getDataAccountSet(LedgerBlock block) {
long height = getLatestBlockHeight();
- DataAccountSet dataAccountSet = null;
if (height == block.getHeight()) {
- // 缓存读;
- LedgerState state = getLatestState();
- dataAccountSet = state.dataAccountSet;
- if (dataAccountSet == null) {
- LedgerAdminAccount adminAccount = getAdminAccount(block);
- dataAccountSet = loadDataAccountSet(block.getDataAccountSetHash(),
- adminAccount.getPreviousSetting().getCryptoSetting(), keyPrefix, exPolicyStorage,
- versioningStorage, true);
- state.dataAccountSet = dataAccountSet;
- }
- return dataAccountSet;
+ return latestState.getDataAccountSet();
}
- LedgerAdminAccount adminAccount = getAdminAccount(block);
- return loadDataAccountSet(block.getDataAccountSetHash(), adminAccount.getPreviousSetting().getCryptoSetting(),
- keyPrefix, exPolicyStorage, versioningStorage, true);
+ LedgerAdminDataset adminAccount = getAdminInfo(block);
+ return createDataAccountSet(block, adminAccount.getSettings().getCryptoSetting());
+ }
+
+ private DataAccountSet createDataAccountSet(LedgerBlock block, CryptoSetting setting) {
+ return loadDataAccountSet(block.getDataAccountSetHash(), setting, keyPrefix, exPolicyStorage, versioningStorage,
+ true);
}
@Override
- public ContractAccountSet getContractAccountSet(LedgerBlock block) {
+ public ContractAccountQuery getContractAccountSet(LedgerBlock block) {
long height = getLatestBlockHeight();
- ContractAccountSet contractAccountSet = null;
if (height == block.getHeight()) {
- // 缓存读;
- LedgerState state = getLatestState();
- contractAccountSet = state.contractAccountSet;
- if (contractAccountSet == null) {
- LedgerAdminAccount adminAccount = getAdminAccount(block);
- contractAccountSet = loadContractAccountSet(block.getContractAccountSetHash(),
- adminAccount.getPreviousSetting().getCryptoSetting(), keyPrefix, exPolicyStorage,
- versioningStorage, true);
- state.contractAccountSet = contractAccountSet;
- }
- return contractAccountSet;
+ return latestState.getContractAccountSet();
}
- LedgerAdminAccount adminAccount = getAdminAccount(block);
- return loadContractAccountSet(block.getContractAccountSetHash(),
- adminAccount.getPreviousSetting().getCryptoSetting(), keyPrefix, exPolicyStorage, versioningStorage,
- true);
+ LedgerAdminDataset adminAccount = getAdminInfo(block);
+ return createContractAccountSet(block, adminAccount.getSettings().getCryptoSetting());
+ }
+
+ private ContractAccountSet createContractAccountSet(LedgerBlock block, CryptoSetting cryptoSetting) {
+ return loadContractAccountSet(block.getContractAccountSetHash(), cryptoSetting, keyPrefix, exPolicyStorage,
+ versioningStorage, true);
}
@Override
- public LedgerDataSet getDataSet(LedgerBlock block) {
+ public LedgerDataset getDataSet(LedgerBlock block) {
long height = getLatestBlockHeight();
- LedgerDataSet ledgerDataSet = null;
if (height == block.getHeight()) {
- // 缓存读;
- LedgerState state = getLatestState();
- ledgerDataSet = state.ledgerDataSet;
- if (ledgerDataSet == null) {
- ledgerDataSet = innerDataSet(block);
- state.ledgerDataSet = ledgerDataSet;
- }
- return ledgerDataSet;
+ return latestState.getLedgerDataset();
}
// All of existing block is readonly;
- return innerDataSet(block);
+ return innerGetLedgerDataset(block);
}
- private LedgerDataSet innerDataSet(LedgerBlock block) {
- LedgerAdminAccount adminAccount = getAdminAccount(block);
- UserAccountSet userAccountSet = getUserAccountSet(block);
- DataAccountSet dataAccountSet = getDataAccountSet(block);
- ContractAccountSet contractAccountSet = getContractAccountSet(block);
- return new LedgerDataSetImpl(adminAccount, userAccountSet, dataAccountSet, contractAccountSet, true);
+ private LedgerDataset innerGetLedgerDataset(LedgerBlock block) {
+ LedgerAdminDataset adminDataset = createAdminDataset(block);
+ CryptoSetting cryptoSetting = adminDataset.getSettings().getCryptoSetting();
+
+ UserAccountSet userAccountSet = createUserAccountSet(block, cryptoSetting);
+ DataAccountSet dataAccountSet = createDataAccountSet(block, cryptoSetting);
+ ContractAccountSet contractAccountSet = createContractAccountSet(block, cryptoSetting);
+ return new LedgerDataset(adminDataset, userAccountSet, dataAccountSet, contractAccountSet, true);
}
@Override
public synchronized LedgerEditor createNextBlock() {
if (closed) {
- throw new LedgerException("Ledger repository has been closed!");
+ throw new RuntimeException("Ledger repository has been closed!");
}
if (this.nextBlockEditor != null) {
- throw new LedgerException(
+ throw new RuntimeException(
"A new block is in process, cann't create another one until it finish by committing or canceling.");
}
LedgerBlock previousBlock = getLatestBlock();
- LedgerTransactionalEditor editor = LedgerTransactionalEditor.createEditor(
- getAdminInfo().getMetadata().getSetting(), previousBlock, keyPrefix, exPolicyStorage,
- versioningStorage);
+ LedgerTransactionalEditor editor = LedgerTransactionalEditor.createEditor(previousBlock, getLatestSettings(),
+ keyPrefix, exPolicyStorage, versioningStorage);
NewBlockCommittingMonitor committingMonitor = new NewBlockCommittingMonitor(editor, this);
this.nextBlockEditor = committingMonitor;
return committingMonitor;
@@ -420,70 +374,45 @@ public class LedgerRepositoryImpl implements LedgerRepository {
return;
}
if (this.nextBlockEditor != null) {
- throw new LedgerException("A new block is in process, cann't close the ledger repository!");
+ throw new RuntimeException("A new block is in process, cann't close the ledger repository!");
}
closed = true;
}
static Bytes encodeLedgerIndexKey(HashDigest ledgerHash) {
- // return LEDGER_PREFIX + Base58Utils.encode(ledgerHash.toBytes());
- // return new Bytes(ledgerHash.toBytes()).concatTo(LEDGER_PREFIX);
return LEDGER_PREFIX.concat(ledgerHash);
}
static Bytes encodeBlockStorageKey(HashDigest blockHash) {
- // String key = ByteArray.toBase58(blockHash.toBytes());
- // return BLOCK_PREFIX + key;
-
return BLOCK_PREFIX.concat(blockHash);
}
- static LedgerDataSetImpl newDataSet(LedgerInitSetting initSetting, String keyPrefix,
+ static LedgerDataset newDataSet(LedgerInitSetting initSetting, String keyPrefix,
ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage) {
- LedgerAdminAccount adminAccount = new LedgerAdminAccount(initSetting, keyPrefix, ledgerExStorage,
+ LedgerAdminDataset adminAccount = new LedgerAdminDataset(initSetting, keyPrefix, ledgerExStorage,
ledgerVerStorage);
String usersetKeyPrefix = keyPrefix + USER_SET_PREFIX;
String datasetKeyPrefix = keyPrefix + DATA_SET_PREFIX;
String contractsetKeyPrefix = keyPrefix + CONTRACT_SET_PREFIX;
- // String txsetKeyPrefix = keyPrefix + TRANSACTION_SET_PREFIX;
-
- // UserAccountSet userAccountSet = new
- // UserAccountSet(adminAccount.getSetting().getCryptoSetting(),
- // PrefixAppender.prefix(USER_SET_PREFIX, ledgerExStorage),
- // PrefixAppender.prefix(USER_SET_PREFIX, ledgerVerStorage),
- // DEFAULT_ACCESS_POLICY);
- UserAccountSet userAccountSet = new UserAccountSet(adminAccount.getSetting().getCryptoSetting(),
+
+ UserAccountSet userAccountSet = new UserAccountSet(adminAccount.getSettings().getCryptoSetting(),
usersetKeyPrefix, ledgerExStorage, ledgerVerStorage, DEFAULT_ACCESS_POLICY);
- // DataAccountSet dataAccountSet = new
- // DataAccountSet(adminAccount.getSetting().getCryptoSetting(),
- // PrefixAppender.prefix(DATA_SET_PREFIX, ledgerExStorage),
- // PrefixAppender.prefix(DATA_SET_PREFIX, ledgerVerStorage),
- // DEFAULT_ACCESS_POLICY);
- DataAccountSet dataAccountSet = new DataAccountSet(adminAccount.getSetting().getCryptoSetting(),
+ DataAccountSet dataAccountSet = new DataAccountSet(adminAccount.getSettings().getCryptoSetting(),
datasetKeyPrefix, ledgerExStorage, ledgerVerStorage, DEFAULT_ACCESS_POLICY);
- // ContractAccountSet contractAccountSet = new
- // ContractAccountSet(adminAccount.getSetting().getCryptoSetting(),
- // PrefixAppender.prefix(CONTRACT_SET_PREFIX, ledgerExStorage),
- // PrefixAppender.prefix(CONTRACT_SET_PREFIX, ledgerVerStorage),
- // DEFAULT_ACCESS_POLICY);
- ContractAccountSet contractAccountSet = new ContractAccountSet(adminAccount.getSetting().getCryptoSetting(),
+ ContractAccountSet contractAccountSet = new ContractAccountSet(adminAccount.getSettings().getCryptoSetting(),
contractsetKeyPrefix, ledgerExStorage, ledgerVerStorage, DEFAULT_ACCESS_POLICY);
- LedgerDataSetImpl newDataSet = new LedgerDataSetImpl(adminAccount, userAccountSet, dataAccountSet,
+ LedgerDataset newDataSet = new LedgerDataset(adminAccount, userAccountSet, dataAccountSet,
contractAccountSet, false);
return newDataSet;
}
- static TransactionSet newTransactionSet(LedgerSetting ledgerSetting, String keyPrefix,
- ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage) {
- // TransactionSet transactionSet = new
- // TransactionSet(ledgerSetting.getCryptoSetting(),
- // PrefixAppender.prefix(TRANSACTION_SET_PREFIX, ledgerExStorage),
- // PrefixAppender.prefix(TRANSACTION_SET_PREFIX, ledgerVerStorage));
+ static TransactionSet newTransactionSet(LedgerSettings ledgerSetting, String keyPrefix,
+ ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage) {
String txsetKeyPrefix = keyPrefix + TRANSACTION_SET_PREFIX;
@@ -492,13 +421,11 @@ public class LedgerRepositoryImpl implements LedgerRepository {
return transactionSet;
}
- static LedgerDataSetImpl loadDataSet(LedgerDataSnapshot dataSnapshot, String keyPrefix,
+ static LedgerDataset loadDataSet(LedgerDataSnapshot dataSnapshot, CryptoSetting cryptoSetting, String keyPrefix,
ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage, boolean readonly) {
- LedgerAdminAccount adminAccount = new LedgerAdminAccount(dataSnapshot.getAdminAccountHash(), keyPrefix,
+ LedgerAdminDataset adminAccount = new LedgerAdminDataset(dataSnapshot.getAdminAccountHash(), keyPrefix,
ledgerExStorage, ledgerVerStorage, readonly);
- CryptoSetting cryptoSetting = adminAccount.getPreviousSetting().getCryptoSetting();
-
UserAccountSet userAccountSet = loadUserAccountSet(dataSnapshot.getUserAccountSetHash(), cryptoSetting,
keyPrefix, ledgerExStorage, ledgerVerStorage, readonly);
@@ -508,7 +435,7 @@ public class LedgerRepositoryImpl implements LedgerRepository {
ContractAccountSet contractAccountSet = loadContractAccountSet(dataSnapshot.getContractAccountSetHash(),
cryptoSetting, keyPrefix, ledgerExStorage, ledgerVerStorage, readonly);
- LedgerDataSetImpl dataset = new LedgerDataSetImpl(adminAccount, userAccountSet, dataAccountSet,
+ LedgerDataset dataset = new LedgerDataset(adminAccount, userAccountSet, dataAccountSet,
contractAccountSet, readonly);
return dataset;
@@ -517,10 +444,6 @@ public class LedgerRepositoryImpl implements LedgerRepository {
static UserAccountSet loadUserAccountSet(HashDigest userAccountSetHash, CryptoSetting cryptoSetting,
String keyPrefix, ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage,
boolean readonly) {
- // return new UserAccountSet(userAccountSetHash, cryptoSetting,
- // PrefixAppender.prefix(USER_SET_PREFIX, ledgerExStorage),
- // PrefixAppender.prefix(USER_SET_PREFIX, ledgerVerStorage), readonly,
- // DEFAULT_ACCESS_POLICY);
String usersetKeyPrefix = keyPrefix + USER_SET_PREFIX;
return new UserAccountSet(userAccountSetHash, cryptoSetting, usersetKeyPrefix, ledgerExStorage,
@@ -530,10 +453,6 @@ public class LedgerRepositoryImpl implements LedgerRepository {
static DataAccountSet loadDataAccountSet(HashDigest dataAccountSetHash, CryptoSetting cryptoSetting,
String keyPrefix, ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage,
boolean readonly) {
- // return new DataAccountSet(dataAccountSetHash, cryptoSetting,
- // PrefixAppender.prefix(DATA_SET_PREFIX, ledgerExStorage,
- // PrefixAppender.prefix(DATA_SET_PREFIX, ledgerVerStorage), readonly,
- // DEFAULT_ACCESS_POLICY);
String datasetKeyPrefix = keyPrefix + DATA_SET_PREFIX;
return new DataAccountSet(dataAccountSetHash, cryptoSetting, datasetKeyPrefix, ledgerExStorage,
@@ -543,10 +462,6 @@ public class LedgerRepositoryImpl implements LedgerRepository {
static ContractAccountSet loadContractAccountSet(HashDigest contractAccountSetHash, CryptoSetting cryptoSetting,
String keyPrefix, ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage,
boolean readonly) {
- // return new ContractAccountSet(contractAccountSetHash, cryptoSetting,
- // PrefixAppender.prefix(CONTRACT_SET_PREFIX, ledgerExStorage,
- // PrefixAppender.prefix(CONTRACT_SET_PREFIX, ledgerVerStorage), readonly,
- // DEFAULT_ACCESS_POLICY);
String contractsetKeyPrefix = keyPrefix + CONTRACT_SET_PREFIX;
return new ContractAccountSet(contractAccountSetHash, cryptoSetting, contractsetKeyPrefix, ledgerExStorage,
@@ -555,9 +470,6 @@ public class LedgerRepositoryImpl implements LedgerRepository {
static TransactionSet loadTransactionSet(HashDigest txsetHash, CryptoSetting cryptoSetting, String keyPrefix,
ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage, boolean readonly) {
- // return new TransactionSet(txsetHash, cryptoSetting,
- // PrefixAppender.prefix(TRANSACTION_SET_PREFIX, ledgerExStorage),
- // PrefixAppender.prefix(TRANSACTION_SET_PREFIX, ledgerVerStorage), readonly);
String txsetKeyPrefix = keyPrefix + TRANSACTION_SET_PREFIX;
return new TransactionSet(txsetHash, cryptoSetting, txsetKeyPrefix, ledgerExStorage, ledgerVerStorage,
@@ -576,6 +488,26 @@ public class LedgerRepositoryImpl implements LedgerRepository {
this.ledgerRepo = ledgerRepo;
}
+ @Override
+ public HashDigest getLedgerHash() {
+ return editor.getLedgerHash();
+ }
+
+ @Override
+ public long getBlockHeight() {
+ return editor.getBlockHeight();
+ }
+
+ @Override
+ public LedgerDataset getLedgerDataset() {
+ return editor.getLedgerDataset();
+ }
+
+ @Override
+ public TransactionSet getTransactionSet() {
+ return editor.getTransactionSet();
+ }
+
@Override
public LedgerTransactionContext newTransaction(TransactionRequest txRequest) {
return editor.newTransaction(txRequest);
@@ -590,8 +522,9 @@ public class LedgerRepositoryImpl implements LedgerRepository {
public void commit() {
try {
editor.commit();
- LedgerBlock latestBlock = editor.getNewlyBlock();
- ledgerRepo.latestState = new LedgerState(latestBlock);
+ LedgerBlock latestBlock = editor.getCurrentBlock();
+ ledgerRepo.latestState = new LedgerState(latestBlock, editor.getLedgerDataset(),
+ editor.getTransactionSet());
} finally {
ledgerRepo.nextBlockEditor = null;
}
@@ -618,20 +551,39 @@ public class LedgerRepositoryImpl implements LedgerRepository {
private final LedgerBlock block;
- private volatile LedgerAdminAccount adminAccount;
+ private final TransactionSet transactionSet;
- private volatile UserAccountSet userAccountSet;
+ private final LedgerDataset ledgerDataset;
- private volatile DataAccountSet dataAccountSet;
+ public LedgerState(LedgerBlock block, LedgerDataset ledgerDataset, TransactionSet transactionSet) {
+ this.block = block;
+ this.ledgerDataset = ledgerDataset;
+ this.transactionSet = transactionSet;
- private volatile ContractAccountSet contractAccountSet;
+ }
- private volatile TransactionSet transactionSet;
+ public LedgerAdminDataset getAdminDataset() {
+ return ledgerDataset.getAdminDataset();
+ }
- private volatile LedgerDataSet ledgerDataSet;
+ public LedgerDataset getLedgerDataset() {
+ return ledgerDataset;
+ }
- public LedgerState(LedgerBlock block) {
- this.block = block;
+ public ContractAccountQuery getContractAccountSet() {
+ return ledgerDataset.getContractAccountset();
+ }
+
+ public DataAccountQuery getDataAccountSet() {
+ return ledgerDataset.getDataAccountSet();
+ }
+
+ public UserAccountQuery getUserAccountSet() {
+ return ledgerDataset.getUserAccountSet();
+ }
+
+ public TransactionSet getTransactionSet() {
+ return transactionSet;
}
}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerSecurityManager.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerSecurityManager.java
new file mode 100644
index 00000000..ac819e39
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerSecurityManager.java
@@ -0,0 +1,20 @@
+package com.jd.blockchain.ledger.core;
+
+import java.util.Set;
+
+import com.jd.blockchain.utils.Bytes;
+
+public interface LedgerSecurityManager {
+
+ String DEFAULT_ROLE = "DEFAULT";
+
+ /**
+ * 创建一项与指定的终端用户和节点参与方相关的安全策略;
+ *
+ * @param endpoints 终端用户的地址列表;
+ * @param nodes 节点参与方的地址列表;
+ * @return 一项安全策略;
+ */
+ SecurityPolicy createSecurityPolicy(Set endpoints, Set nodes);
+
+}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerSecurityManagerImpl.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerSecurityManagerImpl.java
new file mode 100644
index 00000000..e0987732
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerSecurityManagerImpl.java
@@ -0,0 +1,396 @@
+package com.jd.blockchain.ledger.core;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.LedgerSecurityException;
+import com.jd.blockchain.ledger.ParticipantDataQuery;
+import com.jd.blockchain.ledger.ParticipantDoesNotExistException;
+import com.jd.blockchain.ledger.RolePrivilegeSettings;
+import com.jd.blockchain.ledger.RolePrivileges;
+import com.jd.blockchain.ledger.RolesPolicy;
+import com.jd.blockchain.ledger.TransactionPermission;
+import com.jd.blockchain.ledger.UserDoesNotExistException;
+import com.jd.blockchain.ledger.UserRoles;
+import com.jd.blockchain.ledger.UserRolesSettings;
+import com.jd.blockchain.utils.Bytes;
+
+/**
+ * 账本安全管理器;
+ *
+ * @author huanghaiquan
+ *
+ */
+public class LedgerSecurityManagerImpl implements LedgerSecurityManager {
+
+ private RolePrivilegeSettings rolePrivilegeSettings;
+
+ private UserRolesSettings userRolesSettings;
+
+ // 用户的权限配置
+ private Map userPrivilegesCache = new ConcurrentHashMap<>();
+
+ private Map userRolesCache = new ConcurrentHashMap<>();
+ private Map rolesPrivilegeCache = new ConcurrentHashMap<>();
+
+ private ParticipantDataQuery participantsQuery;
+ private UserAccountQuery userAccountsQuery;
+
+ public LedgerSecurityManagerImpl(RolePrivilegeSettings rolePrivilegeSettings, UserRolesSettings userRolesSettings,
+ ParticipantDataQuery participantsQuery, UserAccountQuery userAccountsQuery) {
+ this.rolePrivilegeSettings = rolePrivilegeSettings;
+ this.userRolesSettings = userRolesSettings;
+ this.participantsQuery = participantsQuery;
+ this.userAccountsQuery = userAccountsQuery;
+ }
+
+ @Override
+ public SecurityPolicy createSecurityPolicy(Set endpoints, Set nodes) {
+ Map endpointPrivilegeMap = new HashMap<>();
+ Map nodePrivilegeMap = new HashMap<>();
+
+ for (Bytes userAddress : endpoints) {
+ UserRolesPrivileges userPrivileges = getUserRolesPrivilegs(userAddress);
+ endpointPrivilegeMap.put(userAddress, userPrivileges);
+ }
+
+ for (Bytes userAddress : nodes) {
+ UserRolesPrivileges userPrivileges = getUserRolesPrivilegs(userAddress);
+ nodePrivilegeMap.put(userAddress, userPrivileges);
+ }
+
+ return new UserRolesSecurityPolicy(endpointPrivilegeMap, nodePrivilegeMap, participantsQuery, userAccountsQuery);
+ }
+
+ private UserRolesPrivileges getUserRolesPrivilegs(Bytes userAddress) {
+ UserRolesPrivileges userPrivileges = userPrivilegesCache.get(userAddress);
+ if (userPrivileges != null) {
+ return userPrivileges;
+ }
+
+ UserRoles userRoles = null;
+
+ List privilegesList = new ArrayList<>();
+
+ // 加载用户的角色列表;
+ userRoles = userRolesCache.get(userAddress);
+ if (userRoles == null) {
+ userRoles = userRolesSettings.getUserRoles(userAddress);
+ if (userRoles != null) {
+ userRolesCache.put(userAddress, userRoles);
+ }
+ }
+
+ // 计算用户的综合权限;
+ if (userRoles != null) {
+ String[] roles = userRoles.getRoles();
+ RolePrivileges privilege = null;
+ for (String role : roles) {
+ // 先从缓存读取,如果没有再从原始数据源进行加载;
+ privilege = rolesPrivilegeCache.get(role);
+ if (privilege == null) {
+ privilege = rolePrivilegeSettings.getRolePrivilege(role);
+ if (privilege == null) {
+ // 略过不存在的无效角色;
+ continue;
+ }
+ rolesPrivilegeCache.put(role, privilege);
+ }
+ privilegesList.add(privilege);
+ }
+ }
+ // 如果用户未被授权任何角色,则采用默认角色的权限;
+ if (privilegesList.size() == 0) {
+ RolePrivileges privilege = getDefaultRolePrivilege();
+ privilegesList.add(privilege);
+ }
+
+ if (userRoles == null) {
+ userPrivileges = new UserRolesPrivileges(userAddress, RolesPolicy.UNION, privilegesList);
+ } else {
+ userPrivileges = new UserRolesPrivileges(userAddress, userRoles.getPolicy(), privilegesList);
+ }
+
+ userPrivilegesCache.put(userAddress, userPrivileges);
+ return userPrivileges;
+ }
+
+ private RolePrivileges getDefaultRolePrivilege() {
+ RolePrivileges privileges = rolesPrivilegeCache.get(DEFAULT_ROLE);
+ if (privileges == null) {
+ privileges = rolePrivilegeSettings.getRolePrivilege(DEFAULT_ROLE);
+ if (privileges == null) {
+ throw new LedgerSecurityException(
+ "This ledger is missing the default role-privilege settings for the users who don't have a role!");
+ }
+ }
+ return privileges;
+ }
+
+ private class UserRolesSecurityPolicy implements SecurityPolicy {
+
+ /**
+ * 终端用户的权限表;
+ */
+ private Map endpointPrivilegeMap = new HashMap<>();
+
+ /**
+ * 节点参与方的权限表;
+ */
+ private Map nodePrivilegeMap = new HashMap<>();
+
+ private ParticipantDataQuery participantsQuery;
+
+ private UserAccountQuery userAccountsQuery;
+
+ public UserRolesSecurityPolicy(Map endpointPrivilegeMap,
+ Map nodePrivilegeMap, ParticipantDataQuery participantsQuery,
+ UserAccountQuery userAccountsQuery) {
+ this.endpointPrivilegeMap = endpointPrivilegeMap;
+ this.nodePrivilegeMap = nodePrivilegeMap;
+ this.participantsQuery = participantsQuery;
+ this.userAccountsQuery = userAccountsQuery;
+ }
+
+ @Override
+ public boolean isEndpointEnable(LedgerPermission permission, MultiIDsPolicy midPolicy) {
+ if (MultiIDsPolicy.AT_LEAST_ONE == midPolicy) {
+ // 至少一个;
+ for (UserRolesPrivileges p : endpointPrivilegeMap.values()) {
+ if (p.getLedgerPrivileges().isEnable(permission)) {
+ return true;
+ }
+ }
+ return false;
+ } else if (MultiIDsPolicy.ALL == midPolicy) {
+ // 全部;
+ for (UserRolesPrivileges p : endpointPrivilegeMap.values()) {
+ if (!p.getLedgerPrivileges().isEnable(permission)) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ throw new IllegalArgumentException("Unsupported MultiIdsPolicy[" + midPolicy + "]!");
+ }
+ }
+
+ @Override
+ public boolean isEndpointEnable(TransactionPermission permission, MultiIDsPolicy midPolicy) {
+ if (MultiIDsPolicy.AT_LEAST_ONE == midPolicy) {
+ // 至少一个;
+ for (UserRolesPrivileges p : endpointPrivilegeMap.values()) {
+ if (p.getTransactionPrivileges().isEnable(permission)) {
+ return true;
+ }
+ }
+ return false;
+ } else if (MultiIDsPolicy.ALL == midPolicy) {
+ // 全部;
+ for (UserRolesPrivileges p : endpointPrivilegeMap.values()) {
+ if (!p.getTransactionPrivileges().isEnable(permission)) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ throw new IllegalArgumentException("Unsupported MultiIdsPolicy[" + midPolicy + "]!");
+ }
+ }
+
+ @Override
+ public boolean isNodeEnable(LedgerPermission permission, MultiIDsPolicy midPolicy) {
+ if (MultiIDsPolicy.AT_LEAST_ONE == midPolicy) {
+ // 至少一个;
+ for (UserRolesPrivileges p : nodePrivilegeMap.values()) {
+ if (p.getLedgerPrivileges().isEnable(permission)) {
+ return true;
+ }
+ }
+ return false;
+ } else if (MultiIDsPolicy.ALL == midPolicy) {
+ // 全部;
+ for (UserRolesPrivileges p : nodePrivilegeMap.values()) {
+ if (!p.getLedgerPrivileges().isEnable(permission)) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ throw new IllegalArgumentException("Unsupported MultiIdsPolicy[" + midPolicy + "]!");
+ }
+ }
+
+ @Override
+ public boolean isNodeEnable(TransactionPermission permission, MultiIDsPolicy midPolicy) {
+ if (MultiIDsPolicy.AT_LEAST_ONE == midPolicy) {
+ // 至少一个;
+ for (UserRolesPrivileges p : nodePrivilegeMap.values()) {
+ if (p.getTransactionPrivileges().isEnable(permission)) {
+ return true;
+ }
+ }
+ return false;
+ } else if (MultiIDsPolicy.ALL == midPolicy) {
+ // 全部;
+ for (UserRolesPrivileges p : nodePrivilegeMap.values()) {
+ if (!p.getTransactionPrivileges().isEnable(permission)) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ throw new IllegalArgumentException("Unsupported MultiIdsPolicy[" + midPolicy + "]!");
+ }
+ }
+
+ @Override
+ public void checkEndpointPermission(LedgerPermission permission, MultiIDsPolicy midPolicy)
+ throws LedgerSecurityException {
+ if (!isEndpointEnable(permission, midPolicy)) {
+ throw new LedgerSecurityException(String.format(
+ "The security policy [Permission=%s, Policy=%s] for endpoints rejected the current operation!",
+ permission, midPolicy));
+ }
+ }
+
+ @Override
+ public void checkEndpointPermission(TransactionPermission permission, MultiIDsPolicy midPolicy)
+ throws LedgerSecurityException {
+ if (!isEndpointEnable(permission, midPolicy)) {
+ throw new LedgerSecurityException(String.format(
+ "The security policy [Permission=%s, Policy=%s] for endpoints rejected the current operation!",
+ permission, midPolicy));
+ }
+ }
+
+ @Override
+ public void checkNodePermission(LedgerPermission permission, MultiIDsPolicy midPolicy)
+ throws LedgerSecurityException {
+ if (!isNodeEnable(permission, midPolicy)) {
+ throw new LedgerSecurityException(String.format(
+ "The security policy [Permission=%s, Policy=%s] for nodes rejected the current operation!",
+ permission, midPolicy));
+ }
+ }
+
+ @Override
+ public void checkNodePermission(TransactionPermission permission, MultiIDsPolicy midPolicy)
+ throws LedgerSecurityException {
+ if (!isNodeEnable(permission, midPolicy)) {
+ throw new LedgerSecurityException(String.format(
+ "The security policy [Permission=%s, Policy=%s] for nodes rejected the current operation!",
+ permission, midPolicy));
+ }
+ }
+
+ @Override
+ public Set getEndpoints() {
+ return endpointPrivilegeMap.keySet();
+ }
+
+ @Override
+ public Set getNodes() {
+ return nodePrivilegeMap.keySet();
+ }
+
+ @Override
+ public boolean isEndpointValid(MultiIDsPolicy midPolicy) {
+ if (MultiIDsPolicy.AT_LEAST_ONE == midPolicy) {
+ // 至少一个;
+ for (Bytes address : getEndpoints()) {
+ if (userAccountsQuery.contains(address)) {
+ return true;
+ }
+ }
+ return false;
+ } else if (MultiIDsPolicy.ALL == midPolicy) {
+ // 全部;
+ for (Bytes address : getEndpoints()) {
+ if (!userAccountsQuery.contains(address)) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ throw new IllegalArgumentException("Unsupported MultiIdsPolicy[" + midPolicy + "]!");
+ }
+ }
+
+ @Override
+ public boolean isNodeValid(MultiIDsPolicy midPolicy) {
+ if (MultiIDsPolicy.AT_LEAST_ONE == midPolicy) {
+ // 至少一个;
+ for (Bytes address : getNodes()) {
+ if (participantsQuery.contains(address)) {
+ return true;
+ }
+ }
+ return false;
+ } else if (MultiIDsPolicy.ALL == midPolicy) {
+ // 全部;
+ for (Bytes address : getNodes()) {
+ if (!participantsQuery.contains(address)) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ throw new IllegalArgumentException("Unsupported MultiIdsPolicy[" + midPolicy + "]!");
+ }
+ }
+
+ @Override
+ public void checkEndpointValidity(MultiIDsPolicy midPolicy) throws LedgerSecurityException {
+ if (MultiIDsPolicy.AT_LEAST_ONE == midPolicy) {
+ // 至少一个;
+ for (Bytes address : getEndpoints()) {
+ if (userAccountsQuery.contains(address)) {
+ return;
+ }
+ }
+ throw new UserDoesNotExistException("All endpoint signers were not registered!");
+ } else if (MultiIDsPolicy.ALL == midPolicy) {
+ // 全部;
+ for (Bytes address : getEndpoints()) {
+ if (!userAccountsQuery.contains(address)) {
+ throw new UserDoesNotExistException("The endpoint signer[" + address + "] was not registered!");
+ }
+ }
+ return;
+ } else {
+ throw new IllegalArgumentException("Unsupported MultiIdsPolicy[" + midPolicy + "]!");
+ }
+ }
+
+ @Override
+ public void checkNodeValidity(MultiIDsPolicy midPolicy) throws LedgerSecurityException {
+ if (MultiIDsPolicy.AT_LEAST_ONE == midPolicy) {
+ // 至少一个;
+ for (Bytes address : getNodes()) {
+ if (participantsQuery.contains(address)) {
+ return;
+ }
+ }
+ throw new ParticipantDoesNotExistException("All node signers were not registered as participant!");
+ } else if (MultiIDsPolicy.ALL == midPolicy) {
+ // 全部;
+ for (Bytes address : getNodes()) {
+ if (!participantsQuery.contains(address)) {
+ throw new ParticipantDoesNotExistException(
+ "The node signer[" + address + "] was not registered as participant!");
+ }
+ }
+ } else {
+ throw new IllegalArgumentException("Unsupported MultiIdsPolicy[" + midPolicy + "]!");
+ }
+ }
+
+ }
+
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionContext.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionContext.java
index 33f589c5..b06721e6 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionContext.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionContext.java
@@ -13,18 +13,25 @@ import java.util.List;
public interface LedgerTransactionContext {
/**
- * 账本数据;
+ * 账本数据集合;
*
* @return
*/
- LedgerDataSet getDataSet();
+ LedgerDataset getDataset();
+
+ /**
+ * 事务集合;
+ *
+ * @return
+ */
+ TransactionSet getTransactionSet();
/**
* 交易请求;
*
* @return
*/
- TransactionRequest getRequestTX();
+ TransactionRequest getTransactionRequest();
/**
* 提交对账本数据的修改,以指定的交易状态提交交易;
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionData.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionData.java
similarity index 69%
rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionData.java
rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionData.java
index 6e231b44..516f338f 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionData.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionData.java
@@ -1,7 +1,4 @@
-package com.jd.blockchain.ledger.core.impl;
-
-import java.util.Arrays;
-import java.util.Comparator;
+package com.jd.blockchain.ledger.core;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.DigitalSignature;
@@ -29,48 +26,27 @@ public class LedgerTransactionData implements LedgerTransaction {
private OperationResult[] operationResults;
- // private HashDigest adminAccountHash;
- //
- // private HashDigest userAccountSetHash;
- //
- // private HashDigest dataAccountSetHash;
- //
- // private HashDigest contractAccountSetHash;
-
/**
* Declare a private no-arguments constructor for deserializing purpose;
*/
+ @SuppressWarnings("unused")
private LedgerTransactionData() {
-// this.txSnapshot = new TransactionStagedSnapshot();
}
/**
- * @param blockHeight
- * 区块链高度;
- * @param txReq
- * 交易请求;
- * @param execState
- * 执行状态;
- * @param txSnapshot
- * 交易级的系统快照;
+ * @param blockHeight 区块链高度;
+ * @param txReq 交易请求;
+ * @param execState 执行状态;
+ * @param txSnapshot 交易级的系统快照;
*/
public LedgerTransactionData(long blockHeight, TransactionRequest txReq, TransactionState execState,
TransactionStagedSnapshot txSnapshot, OperationResult... opResults) {
this.blockHeight = blockHeight;
-// this.txSnapshot = txSnapshot == null ? new TransactionStagedSnapshot() : txSnapshot;
this.txSnapshot = txSnapshot;
this.transactionContent = txReq.getTransactionContent();
this.endpointSignatures = txReq.getEndpointSignatures();
this.nodeSignatures = txReq.getNodeSignatures();
this.executionState = execState;
- if (opResults != null) {
- Arrays.sort(opResults, new Comparator() {
- @Override
- public int compare(OperationResult o1, OperationResult o2) {
- return o1.getIndex() - o2.getIndex();
- }
- });
- }
this.operationResults = opResults;
}
@@ -116,17 +92,17 @@ public class LedgerTransactionData implements LedgerTransaction {
@Override
public HashDigest getUserAccountSetHash() {
- return txSnapshot == null ? null :txSnapshot.getUserAccountSetHash();
+ return txSnapshot == null ? null : txSnapshot.getUserAccountSetHash();
}
@Override
public HashDigest getDataAccountSetHash() {
- return txSnapshot == null ? null :txSnapshot.getDataAccountSetHash();
+ return txSnapshot == null ? null : txSnapshot.getDataAccountSetHash();
}
@Override
public HashDigest getContractAccountSetHash() {
- return txSnapshot == null ? null :txSnapshot.getContractAccountSetHash();
+ return txSnapshot == null ? null : txSnapshot.getContractAccountSetHash();
}
public void setTxSnapshot(TransactionStagedSnapshot txSnapshot) {
@@ -140,20 +116,22 @@ public class LedgerTransactionData implements LedgerTransaction {
this.transactionContent = content;
}
- public void setEndpointSignatures(Object[] participantSignatures) {
- int length = participantSignatures.length;
- this.endpointSignatures = new DigitalSignature[length];
- for (int i = 0; i < length; i++) {
- this.endpointSignatures[i] = (DigitalSignature) participantSignatures[i];
- }
+ public void setEndpointSignatures(DigitalSignature[] participantSignatures) {
+ this.endpointSignatures = participantSignatures;
+// int length = participantSignatures.length;
+// this.endpointSignatures = new DigitalSignature[length];
+// for (int i = 0; i < length; i++) {
+// this.endpointSignatures[i] = (DigitalSignature) participantSignatures[i];
+// }
}
- public void setNodeSignatures(Object[] nodeSignatures) {
- int length = nodeSignatures.length;
- this.nodeSignatures = new DigitalSignature[length];
- for (int i = 0; i < length; i++) {
- this.nodeSignatures[i] = (DigitalSignature) nodeSignatures[i];
- }
+ public void setNodeSignatures(DigitalSignature[] nodeSignatures) {
+ this.nodeSignatures = nodeSignatures;
+// int length = nodeSignatures.length;
+// this.nodeSignatures = new DigitalSignature[length];
+// for (int i = 0; i < length; i++) {
+// this.nodeSignatures[i] = (DigitalSignature) nodeSignatures[i];
+// }
}
public void setExecutionState(TransactionState executionState) {
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionalEditor.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionalEditor.java
new file mode 100644
index 00000000..ea7bb7ed
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionalEditor.java
@@ -0,0 +1,630 @@
+package com.jd.blockchain.ledger.core;
+
+import java.util.List;
+
+import com.jd.blockchain.binaryproto.BinaryProtocol;
+import com.jd.blockchain.crypto.Crypto;
+import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.ledger.BlockBody;
+import com.jd.blockchain.ledger.BlockRollbackException;
+import com.jd.blockchain.ledger.CryptoSetting;
+import com.jd.blockchain.ledger.IllegalTransactionException;
+import com.jd.blockchain.ledger.LedgerBlock;
+import com.jd.blockchain.ledger.LedgerDataSnapshot;
+import com.jd.blockchain.ledger.LedgerInitSetting;
+import com.jd.blockchain.ledger.LedgerSettings;
+import com.jd.blockchain.ledger.LedgerTransaction;
+import com.jd.blockchain.ledger.OperationResult;
+import com.jd.blockchain.ledger.TransactionRequest;
+import com.jd.blockchain.ledger.TransactionRollbackException;
+import com.jd.blockchain.ledger.TransactionState;
+import com.jd.blockchain.storage.service.ExPolicyKVStorage;
+import com.jd.blockchain.storage.service.VersioningKVStorage;
+import com.jd.blockchain.storage.service.utils.BufferedKVStorage;
+import com.jd.blockchain.utils.Bytes;
+import com.jd.blockchain.utils.codec.Base58Utils;
+
+public class LedgerTransactionalEditor implements LedgerEditor {
+
+ private static final boolean PARALLEL_DB_WRITE;
+
+ static {
+ PARALLEL_DB_WRITE = Boolean.getBoolean("parallel-dbwrite");
+ System.out.println("------ [[ parallel-dbwrite=" + PARALLEL_DB_WRITE + " ]] ------");
+ }
+
+ /**
+ * 账本Hash,创世区块的编辑器则返回 null;
+ */
+ private HashDigest ledgerHash;
+
+ private final String ledgerKeyPrefix;
+
+ private CryptoSetting cryptoSetting;
+
+ private LedgerBlockData currentBlock;
+
+// private Stack stagedSnapshots = new Stack<>();
+
+ private boolean prepared = false;
+
+ private boolean canceled = false;
+
+ private boolean committed = false;
+
+ private StagedSnapshot startingPoint;
+
+ /**
+ * 当前区块的存储;
+ */
+ private BufferedKVStorage baseStorage;
+
+ /**
+ * 上一个交易产生的账本快照;
+ */
+ private TxSnapshot previousTxSnapshot;
+
+ /**
+ * 当前交易的上下文;
+ */
+ private volatile LedgerTransactionContextImpl currentTxCtx;
+
+ /**
+ * 最后提交的账本数据集;
+ */
+ private volatile LedgerDataset latestLedgerDataset;
+
+ /**
+ * 最后提交的交易集合;
+ */
+ private volatile TransactionSet latestTransactionSet;
+
+ /**
+ * @param ledgerHash
+ * @param cryptoSetting
+ * @param currentBlock
+ * @param startingPoint
+ * @param ledgerKeyPrefix
+ * @param bufferedStorage
+ * @param verifyTx 是否校验交易请求;当外部调用者在调用前已经实施了验证时,将次参数设置为 false 能够提升性能;
+ */
+ private LedgerTransactionalEditor(HashDigest ledgerHash, CryptoSetting cryptoSetting, LedgerBlockData currentBlock,
+ StagedSnapshot startingPoint, String ledgerKeyPrefix, BufferedKVStorage bufferedStorage) {
+ this.ledgerHash = ledgerHash;
+ this.ledgerKeyPrefix = ledgerKeyPrefix;
+ this.cryptoSetting = cryptoSetting;
+ this.currentBlock = currentBlock;
+ this.baseStorage = bufferedStorage;
+
+ this.startingPoint = startingPoint;
+
+// this.stagedSnapshots.push(startingPoint);
+ }
+
+ /**
+ * 创建账本新区块的编辑器;
+ *
+ * @param ledgerHash 账本哈希;
+ * @param ledgerSetting 账本设置;
+ * @param previousBlock 前置区块;
+ * @param ledgerKeyPrefix 账本数据前缀;
+ * @param ledgerExStorage 账本数据存储;
+ * @param ledgerVerStorage 账本数据版本化存储;
+ * @param verifyTx 是否校验交易请求;当外部调用者在调用前已经实施了验证时,将次参数设置为 false 能够提升性能;
+ * @return
+ */
+ public static LedgerTransactionalEditor createEditor(LedgerBlock previousBlock, LedgerSettings ledgerSetting,
+ String ledgerKeyPrefix, ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage) {
+ // new block;
+ HashDigest ledgerHash = previousBlock.getLedgerHash();
+ if (ledgerHash == null) {
+ ledgerHash = previousBlock.getHash();
+ }
+ if (ledgerHash == null) {
+ throw new IllegalArgumentException("Illegal previous block was specified!");
+ }
+ LedgerBlockData currBlock = new LedgerBlockData(previousBlock.getHeight() + 1, ledgerHash,
+ previousBlock.getHash());
+
+ // init storage;
+ BufferedKVStorage txStagedStorage = new BufferedKVStorage(ledgerExStorage, ledgerVerStorage, PARALLEL_DB_WRITE);
+
+ StagedSnapshot startingPoint = new TxSnapshot(previousBlock, previousBlock.getTransactionSetHash());
+
+ // instantiate editor;
+ return new LedgerTransactionalEditor(ledgerHash, ledgerSetting.getCryptoSetting(), currBlock, startingPoint,
+ ledgerKeyPrefix, txStagedStorage);
+ }
+
+ /**
+ * 创建创世区块的编辑器;
+ *
+ * @param initSetting
+ * @param ledgerKeyPrefix
+ * @param ledgerExStorage
+ * @param ledgerVerStorage
+ * @param verifyTx 是否校验交易请求;当外部调用者在调用前已经实施了验证时,将次参数设置为 false 能够提升性能;
+ * @return
+ */
+ public static LedgerTransactionalEditor createEditor(LedgerInitSetting initSetting, String ledgerKeyPrefix,
+ ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage) {
+ LedgerBlockData genesisBlock = new LedgerBlockData(0, null, null);
+ StagedSnapshot startingPoint = new GenesisSnapshot(initSetting);
+ // init storage;
+ BufferedKVStorage txStagedStorage = new BufferedKVStorage(ledgerExStorage, ledgerVerStorage, false);
+ return new LedgerTransactionalEditor(null, initSetting.getCryptoSetting(), genesisBlock, startingPoint,
+ ledgerKeyPrefix, txStagedStorage);
+ }
+
+ private void commitTxSnapshot(TxSnapshot snapshot) {
+ previousTxSnapshot = snapshot;
+ latestLedgerDataset = currentTxCtx.getDataset();
+ latestLedgerDataset.setReadonly();
+ latestTransactionSet = currentTxCtx.getTransactionSet();
+ latestTransactionSet.setReadonly();
+ currentTxCtx = null;
+ }
+
+ private void rollbackCurrentTx() {
+ currentTxCtx = null;
+ }
+
+ LedgerBlock getCurrentBlock() {
+ return currentBlock;
+ }
+
+ @Override
+ public long getBlockHeight() {
+ return currentBlock.getHeight();
+ }
+
+ @Override
+ public HashDigest getLedgerHash() {
+ return ledgerHash;
+ }
+
+ @Override
+ public LedgerDataset getLedgerDataset() {
+ return latestLedgerDataset;
+ }
+
+ @Override
+ public TransactionSet getTransactionSet() {
+ return latestTransactionSet;
+ }
+
+ /**
+ * 检查当前账本是否是指定交易请求的账本;
+ *
+ * @param txRequest
+ * @return
+ */
+ private boolean isRequestMatched(TransactionRequest txRequest) {
+ HashDigest reqLedgerHash = txRequest.getTransactionContent().getLedgerHash();
+ if (ledgerHash == reqLedgerHash) {
+ return true;
+ }
+ if (ledgerHash == null || reqLedgerHash == null) {
+ return false;
+ }
+ return ledgerHash.equals(reqLedgerHash);
+ }
+
+ /**
+ * 注:此方法不验证交易完整性和签名有效性,仅仅设计为进行交易记录的管理;调用者应在此方法之外进行数据完整性和签名有效性的检查;
+ */
+ @Override
+ public synchronized LedgerTransactionContext newTransaction(TransactionRequest txRequest) {
+// if (SettingContext.txSettings().verifyLedger() && !isRequestMatched(txRequest)) {
+ if (!isRequestMatched(txRequest)) {
+ throw new IllegalTransactionException(
+ "Transaction request is dispatched to a wrong ledger! --[TxHash="
+ + txRequest.getTransactionContent().getHash() + "]!",
+ TransactionState.IGNORED_BY_WRONG_LEDGER);
+ }
+
+ if (currentTxCtx != null) {
+ throw new IllegalStateException(
+ "Unable to open another new transaction before the current transaction is completed! --[TxHash="
+ + txRequest.getTransactionContent().getHash() + "]!");
+ }
+
+ // 检查状态是否允许创建新的交易请求;;
+ checkState();
+
+ // init storage of new transaction;
+ BufferedKVStorage txBufferedStorage = new BufferedKVStorage(baseStorage, baseStorage, false);
+
+ LedgerDataset txDataset = null;
+ TransactionSet txset = null;
+ if (previousTxSnapshot == null) {
+ // load the starting point of the new transaction;
+ if (startingPoint instanceof GenesisSnapshot) {
+ // 准备生成创世区块;
+ GenesisSnapshot snpht = (GenesisSnapshot) startingPoint;
+ txDataset = LedgerRepositoryImpl.newDataSet(snpht.initSetting, ledgerKeyPrefix, txBufferedStorage,
+ txBufferedStorage);
+ txset = LedgerRepositoryImpl.newTransactionSet(txDataset.getAdminDataset().getSettings(),
+ ledgerKeyPrefix, txBufferedStorage, txBufferedStorage);
+ } else if (startingPoint instanceof TxSnapshot) {
+ // 新的区块;
+ // TxSnapshot; reload dataset and txset;
+ TxSnapshot snpht = (TxSnapshot) startingPoint;
+ // load dataset;
+ txDataset = LedgerRepositoryImpl.loadDataSet(snpht.dataSnapshot, cryptoSetting, ledgerKeyPrefix,
+ txBufferedStorage, txBufferedStorage, false);
+
+ // load txset;
+ txset = LedgerRepositoryImpl.loadTransactionSet(snpht.txsetHash, cryptoSetting, ledgerKeyPrefix,
+ txBufferedStorage, txBufferedStorage, false);
+ } else {
+ // Unreachable;
+ throw new IllegalStateException("Unreachable code was accidentally executed!");
+ }
+
+ } else {
+ // Reuse previous object to optimize performance;
+ // load dataset;
+ txDataset = LedgerRepositoryImpl.loadDataSet(previousTxSnapshot.dataSnapshot, cryptoSetting,
+ ledgerKeyPrefix, txBufferedStorage, txBufferedStorage, false);
+
+ // load txset;
+ txset = LedgerRepositoryImpl.loadTransactionSet(previousTxSnapshot.txsetHash, cryptoSetting,
+ ledgerKeyPrefix, txBufferedStorage, txBufferedStorage, false);
+ }
+
+ currentTxCtx = new LedgerTransactionContextImpl(txRequest, txDataset, txset, txBufferedStorage, this);
+
+ return currentTxCtx;
+ }
+
+ @Override
+ public LedgerBlock prepare() {
+ checkState();
+
+ if (currentTxCtx != null) {
+ // 有进行中的交易尚未提交或回滚;
+ throw new IllegalStateException(
+ "There is an ongoing transaction that has been not committed or rolled back!");
+ }
+ if (previousTxSnapshot == null) {
+ // 当前区块没有加入过交易,不允许产生空区块;
+ throw new IllegalStateException(
+ "There is no transaction in the current block, and no empty blocks is allowed!");
+ }
+
+ // do commit when transaction isolation level is BLOCK;
+ currentBlock.setAdminAccountHash(previousTxSnapshot.getAdminAccountHash());
+ currentBlock.setUserAccountSetHash(previousTxSnapshot.getUserAccountSetHash());
+ currentBlock.setDataAccountSetHash(previousTxSnapshot.getDataAccountSetHash());
+ currentBlock.setContractAccountSetHash(previousTxSnapshot.getContractAccountSetHash());
+ currentBlock.setTransactionSetHash(previousTxSnapshot.getTransactionSetHash());
+
+ // TODO: 根据所有交易的时间戳的平均值来生成区块的时间戳;
+// long timestamp =
+// currentBlock.setTimestamp(timestamp);
+
+ // compute block hash;
+ byte[] blockBodyBytes = BinaryProtocol.encode(currentBlock, BlockBody.class);
+ HashDigest blockHash = Crypto.getHashFunction(cryptoSetting.getHashAlgorithm()).hash(blockBodyBytes);
+ currentBlock.setHash(blockHash);
+
+// if (currentBlock.getLedgerHash() == null) {
+// // init GenesisBlock's ledger hash;
+// currentBlock.setLedgerHash(blockHash);
+// }
+
+ // persist block bytes;
+ // only one version per block;
+ byte[] blockBytes = BinaryProtocol.encode(currentBlock, LedgerBlock.class);
+ Bytes blockStorageKey = LedgerRepositoryImpl.encodeBlockStorageKey(currentBlock.getHash());
+ long v = baseStorage.set(blockStorageKey, blockBytes, -1);
+ if (v < 0) {
+ throw new IllegalStateException(
+ "Block already exist! --[BlockHash=" + Base58Utils.encode(currentBlock.getHash().toBytes()) + "]");
+ }
+
+ // persist block hash to ledger index;
+ HashDigest ledgerHash = currentBlock.getLedgerHash();
+ if (ledgerHash == null) {
+ ledgerHash = blockHash;
+ }
+ Bytes ledgerIndexKey = LedgerRepositoryImpl.encodeLedgerIndexKey(ledgerHash);
+ long expectedVersion = currentBlock.getHeight() - 1;
+ v = baseStorage.set(ledgerIndexKey, currentBlock.getHash().toBytes(), expectedVersion);
+ if (v < 0) {
+ throw new IllegalStateException(
+ String.format("Index of BlockHash already exist! --[BlockHeight=%s][BlockHash=%s]",
+ currentBlock.getHeight(), currentBlock.getHash()));
+ }
+
+ prepared = true;
+ return currentBlock;
+ }
+
+ @Override
+ public void commit() {
+ if (committed) {
+ throw new IllegalStateException("The current block has been committed!");
+ }
+ if (canceled) {
+ throw new IllegalStateException("The current block has been canceled!");
+ }
+ if (!prepared) {
+ // 未就绪;
+ throw new IllegalStateException("The current block is not ready yet!");
+ }
+
+ baseStorage.flush();
+
+ committed = true;
+ }
+
+ @Override
+ public void cancel() {
+ if (committed) {
+ throw new IllegalStateException("The current block has been committed!");
+ }
+ if (canceled) {
+ return;
+ }
+
+ canceled = true;
+
+ baseStorage.cancel();
+ }
+
+ private void checkState() {
+ if (prepared) {
+ throw new IllegalStateException("The current block is ready!");
+ }
+ if (committed) {
+ throw new IllegalStateException("The current block has been committed!");
+ }
+ if (canceled) {
+ throw new IllegalStateException("The current block has been canceled!");
+ }
+ }
+
+ // --------------------------- inner type --------------------------
+
+ /**
+ * 用于暂存交易上下文数据的快照对象;
+ *
+ * @author huanghaiquan
+ *
+ */
+ private static interface StagedSnapshot {
+
+ }
+
+ /**
+ * 创世区块的快照对象;
+ *
+ * @author huanghaiquan
+ *
+ */
+ private static class GenesisSnapshot implements StagedSnapshot {
+
+ private LedgerInitSetting initSetting;
+
+ public GenesisSnapshot(LedgerInitSetting initSetting) {
+ this.initSetting = initSetting;
+ }
+ }
+
+ /**
+ * 交易执行完毕后的快照对象;
+ *
+ * @author huanghaiquan
+ *
+ */
+ private static class TxSnapshot implements StagedSnapshot {
+
+ /**
+ * 账本数据的快照;
+ */
+ private LedgerDataSnapshot dataSnapshot;
+
+ /**
+ * 交易集合的快照(根哈希);
+ */
+ private HashDigest txsetHash;
+
+ public HashDigest getAdminAccountHash() {
+ return dataSnapshot.getAdminAccountHash();
+ }
+
+ public HashDigest getUserAccountSetHash() {
+ return dataSnapshot.getUserAccountSetHash();
+ }
+
+ public HashDigest getDataAccountSetHash() {
+ return dataSnapshot.getDataAccountSetHash();
+ }
+
+ public HashDigest getContractAccountSetHash() {
+ return dataSnapshot.getContractAccountSetHash();
+ }
+
+ public HashDigest getTransactionSetHash() {
+ return txsetHash;
+ }
+
+ public TxSnapshot(LedgerDataSnapshot dataSnapshot, HashDigest txsetHash) {
+ this.dataSnapshot = dataSnapshot;
+ this.txsetHash = txsetHash;
+ }
+
+ }
+
+ /**
+ * 交易的上下文;
+ *
+ * @author huanghaiquan
+ *
+ */
+ private static class LedgerTransactionContextImpl implements LedgerTransactionContext {
+
+ private LedgerTransactionalEditor blockEditor;
+
+ private TransactionRequest txRequest;
+
+ private LedgerDataset dataset;
+
+ private TransactionSet txset;
+
+ private BufferedKVStorage storage;
+
+ private boolean committed = false;
+
+ private boolean rollbacked = false;
+
+ private LedgerTransaction transaction;
+
+ private HashDigest txRootHash;
+
+ private LedgerTransactionContextImpl(TransactionRequest txRequest, LedgerDataset dataset,
+ TransactionSet txset, BufferedKVStorage storage, LedgerTransactionalEditor editor) {
+ this.txRequest = txRequest;
+ this.dataset = dataset;
+ this.txset = txset;
+ this.storage = storage;
+ this.blockEditor = editor;
+ }
+
+ @Override
+ public LedgerDataset getDataset() {
+ return dataset;
+ }
+
+ @Override
+ public TransactionSet getTransactionSet() {
+ return txset;
+ }
+
+ @Override
+ public TransactionRequest getTransactionRequest() {
+ return txRequest;
+ }
+
+ @Override
+ public LedgerTransaction commit(TransactionState txResult) {
+ return commit(txResult, null);
+ }
+
+ @Override
+ public LedgerTransaction commit(TransactionState txResult, List operationResults) {
+ checkTxState();
+
+ // capture snapshot
+ this.dataset.commit();
+ TransactionStagedSnapshot txDataSnapshot = takeDataSnapshot();
+
+ LedgerTransactionData tx;
+ try {
+ tx = new LedgerTransactionData(blockEditor.getBlockHeight(), txRequest, txResult, txDataSnapshot,
+ operationResultArray(operationResults));
+ this.txset.add(tx);
+ this.txset.commit();
+ } catch (Exception e) {
+ throw new TransactionRollbackException(e.getMessage(), e);
+ }
+
+ try {
+ this.storage.flush();
+ } catch (Exception e) {
+ throw new BlockRollbackException(e.getMessage(), e);
+ }
+
+ // put snapshot into stack;
+ TxSnapshot snapshot = new TxSnapshot(txDataSnapshot, txset.getRootHash());
+ blockEditor.commitTxSnapshot(snapshot);
+
+ committed = true;
+ return tx;
+ }
+
+ @Override
+ public LedgerTransaction discardAndCommit(TransactionState txResult) {
+ return discardAndCommit(txResult, null);
+ }
+
+ @Override
+ public LedgerTransaction discardAndCommit(TransactionState txResult, List operationResults) {
+ checkTxState();
+
+ // 未处理
+ dataset.cancel();
+
+ TransactionStagedSnapshot txDataSnapshot = takeDataSnapshot();
+
+ LedgerTransactionData tx;
+ try {
+ tx = new LedgerTransactionData(blockEditor.getBlockHeight(), txRequest, txResult, txDataSnapshot,
+ operationResultArray(operationResults));
+ this.txset.add(tx);
+ this.txset.commit();
+ } catch (Exception e) {
+ throw new TransactionRollbackException(e.getMessage(), e);
+ }
+
+ try {
+ this.storage.flush();
+ } catch (Exception e) {
+ throw new BlockRollbackException(e.getMessage(), e);
+ }
+
+ // put snapshot into stack;
+ TxSnapshot snapshot = new TxSnapshot(txDataSnapshot, txset.getRootHash());
+ blockEditor.commitTxSnapshot(snapshot);
+
+ committed = true;
+ return tx;
+ }
+
+ private TransactionStagedSnapshot takeDataSnapshot() {
+ TransactionStagedSnapshot txDataSnapshot = new TransactionStagedSnapshot();
+ txDataSnapshot.setAdminAccountHash(dataset.getAdminDataset().getHash());
+ txDataSnapshot.setContractAccountSetHash(dataset.getContractAccountset().getRootHash());
+ txDataSnapshot.setDataAccountSetHash(dataset.getDataAccountSet().getRootHash());
+ txDataSnapshot.setUserAccountSetHash(dataset.getUserAccountSet().getRootHash());
+ return txDataSnapshot;
+ }
+
+ private OperationResult[] operationResultArray(List operationResults) {
+ OperationResult[] operationResultArray = null;
+ if (operationResults != null && !operationResults.isEmpty()) {
+ operationResultArray = new OperationResult[operationResults.size()];
+ operationResults.toArray(operationResultArray);
+ }
+ return operationResultArray;
+ }
+
+ @Override
+ public void rollback() {
+ if (this.rollbacked) {
+ return;
+ }
+ if (this.committed) {
+ throw new IllegalStateException("This transaction had been committed!");
+ }
+ dataset.cancel();
+ storage.cancel();
+
+ blockEditor.rollbackCurrentTx();
+
+ rollbacked = true;
+ }
+
+ private void checkTxState() {
+ if (this.committed) {
+ throw new IllegalStateException("This transaction had been committed!");
+ }
+ if (this.rollbacked) {
+ throw new IllegalStateException("This transaction had been rollbacked!");
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataEntry.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataEntry.java
index 527e7115..3dd99df0 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataEntry.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataEntry.java
@@ -1,5 +1,6 @@
package com.jd.blockchain.ledger.core;
+import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.storage.service.VersioningKVEntry;
public interface MerkleDataEntry {
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataSet.java
index b8dd170b..16927b97 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataSet.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataSet.java
@@ -3,11 +3,14 @@ package com.jd.blockchain.ledger.core;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
+import com.jd.blockchain.ledger.MerkleDataNode;
+import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy;
import com.jd.blockchain.storage.service.VersioningKVEntry;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.storage.service.utils.BufferedKVStorage;
+import com.jd.blockchain.storage.service.utils.VersioningKVData;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.Transactional;
import com.jd.blockchain.utils.io.BytesUtils;
@@ -62,12 +65,9 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
/**
* 创建一个新的 MerkleDataSet;
*
- * @param setting
- * 密码设置;
- * @param exPolicyStorage
- * 默克尔树的存储;
- * @param versioningStorage
- * 数据的存储;
+ * @param setting 密码设置;
+ * @param exPolicyStorage 默克尔树的存储;
+ * @param versioningStorage 数据的存储;
*/
public MerkleDataSet(CryptoSetting setting, String keyPrefix, ExPolicyKVStorage exPolicyStorage,
VersioningKVStorage versioningStorage) {
@@ -126,6 +126,10 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
return readonly;
}
+ void setReadonly() {
+ this.readonly = true;
+ }
+
public long getDataCount() {
return merkleTree.getDataCount();
}
@@ -150,8 +154,27 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
return values;
}
+ public VersioningKVEntry[] getLatestDataEntries(int fromIndex, int count) {
+ if (count > LedgerConsts.MAX_LIST_COUNT) {
+ throw new IllegalArgumentException("Count exceed the upper limit[" + LedgerConsts.MAX_LIST_COUNT + "]!");
+ }
+ if (fromIndex < 0 || (fromIndex + count) > merkleTree.getDataCount()) {
+ throw new IllegalArgumentException("Index out of bound!");
+ }
+ VersioningKVEntry[] values = new VersioningKVEntry[count];
+ byte[] bytesValue;
+ for (int i = 0; i < count; i++) {
+ MerkleDataNode dataNode = merkleTree.getData(fromIndex + i);
+ Bytes dataKey = encodeDataKey(dataNode.getKey());
+ bytesValue = valueStorage.get(dataKey, dataNode.getVersion());
+ values[i] = new VersioningKVData(dataNode.getKey(), dataNode.getVersion(), bytesValue);
+ }
+ return values;
+ }
+
/**
* get the data at the specific index;
+ *
* @param fromIndex
* @return
*/
@@ -163,15 +186,15 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
/**
* get the key at the specific index;
+ *
* @param fromIndex
* @return
*/
public String getKeyAtIndex(int fromIndex) {
MerkleDataNode dataNode = merkleTree.getData(fromIndex);
- return new String(dataNode.getKey().toBytes());
+ return dataNode.getKey().toUTF8String();
}
-
/**
* Create or update the value associated the specified key if the version
* checking is passed.
@@ -183,12 +206,9 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
* If updating is performed, the version of the key increase by 1.
* If creating is performed, the version of the key initialize by 0.
*
- * @param key
- * The key of data;
- * @param value
- * The value of data;
- * @param version
- * The expected latest version of the key.
+ * @param key The key of data;
+ * @param value The value of data;
+ * @param version The expected latest version of the key.
* @return The new version of the key.
* If the key is new created success, then return 0;
* If the key is updated success, then return the new version;
@@ -210,12 +230,9 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
* If updating is performed, the version of the key increase by 1.
* If creating is performed, the version of the key initialize by 0.
*
- * @param key
- * The key of data;
- * @param value
- * The value of data;
- * @param version
- * The expected latest version of the key.
+ * @param key The key of data;
+ * @param value The value of data;
+ * @param version The expected latest version of the key.
* @return The new version of the key.
* If the key is new created success, then return 0;
* If the key is updated success, then return the new version;
@@ -404,12 +421,22 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
return getDataEntry(Bytes.fromString(key));
}
+ /**
+ *
+ * @param key
+ * @return Null if the key doesn't exist!
+ */
public VersioningKVEntry getDataEntry(Bytes key) {
long latestVersion = getMerkleVersion(key);
if (latestVersion < 0) {
return null;
}
- return valueStorage.getEntry(key, latestVersion);
+ Bytes dataKey = encodeDataKey(key);
+ byte[] value = valueStorage.get(dataKey, latestVersion);
+ if (value == null) {
+ return null;
+ }
+ return new VersioningKVData(key, latestVersion, value);
}
public VersioningKVEntry getDataEntry(Bytes key, long version) {
@@ -420,7 +447,12 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
return null;
}
version = version < 0 ? latestVersion : version;
- return valueStorage.getEntry(key, version);
+ Bytes dataKey = encodeDataKey(key);
+ byte[] value = valueStorage.get(dataKey, version);
+ if (value == null) {
+ return null;
+ }
+ return new VersioningKVData(key, version, value);
}
public MerkleDataEntry getMerkleEntry(Bytes key, long version) {
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleProvable.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleProvable.java
index 2f93bad7..f778279f 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleProvable.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleProvable.java
@@ -1,6 +1,7 @@
package com.jd.blockchain.ledger.core;
import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.utils.Bytes;
public interface MerkleProvable {
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleTree.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleTree.java
index 7c3c077c..d86facba 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleTree.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleTree.java
@@ -20,6 +20,9 @@ import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.HashFunction;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
+import com.jd.blockchain.ledger.MerkleDataNode;
+import com.jd.blockchain.ledger.MerkleNode;
+import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy;
import com.jd.blockchain.utils.Bytes;
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MultiIDsPolicy.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MultiIDsPolicy.java
new file mode 100644
index 00000000..20f1caab
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MultiIDsPolicy.java
@@ -0,0 +1,21 @@
+package com.jd.blockchain.ledger.core;
+
+/**
+ * 多重身份的校验策略;
+ *
+ * @author huanghaiquan
+ *
+ */
+public enum MultiIDsPolicy {
+
+ /**
+ * 至少有一个都能通过;
+ */
+ AT_LEAST_ONE,
+
+ /**
+ * 每一个都能通过;
+ */
+ ALL
+
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/OpeningAccessPolicy.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OpeningAccessPolicy.java
similarity index 82%
rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/OpeningAccessPolicy.java
rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OpeningAccessPolicy.java
index 14c5b9b4..6628aad3 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/OpeningAccessPolicy.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OpeningAccessPolicy.java
@@ -1,8 +1,7 @@
-package com.jd.blockchain.ledger.core.impl;
+package com.jd.blockchain.ledger.core;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.AccountHeader;
-import com.jd.blockchain.ledger.core.AccountAccessPolicy;
import com.jd.blockchain.utils.Bytes;
/**
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OperationHandle.java
index e1a0f567..763ea51a 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OperationHandle.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OperationHandle.java
@@ -2,8 +2,6 @@ package com.jd.blockchain.ledger.core;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.Operation;
-import com.jd.blockchain.ledger.core.impl.OperationHandleContext;
-
public interface OperationHandle {
@@ -13,42 +11,22 @@ public interface OperationHandle {
* @param operationType
* @return
*/
- boolean support(Class> operationType);
+ Class> getOperationType();
/**
* 同步解析和执行操作;
*
*
- * @param op
- * 操作实例;
- * @param newBlockDataset
- * 需要修改的新区块的数据集;
- * @param requestContext
- * 交易请求上下文;
- * @param previousBlockDataset
- * 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集;
+ * @param op 操作实例;
+ * @param newBlockDataset 需要修改的新区块的数据集;
+ * @param requestContext 交易请求上下文;
+ * @param previousBlockDataset 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集;注:此数据集是只读的;
*
- * @return 操作执行结果
+ * @param handleContext 操作上下文;`
+ * @param ledgerService
+ * @return
*/
- BytesValue process(Operation op, LedgerDataSet newBlockDataset, TransactionRequestContext requestContext,
- LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService);
+ BytesValue process(Operation op, LedgerDataset newBlockDataset, TransactionRequestExtension requestContext,
+ LedgerDataQuery previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService);
-// /**
-// * 异步解析和执行操作;
-// * TODO 未来规划实现
-// *
-// *
-// * @param op
-// * 操作实例;
-// * @param newBlockDataset
-// * 需要修改的新区块的数据集;
-// * @param requestContext
-// * 交易请求上下文;
-// * @param previousBlockDataset
-// * 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集;
-// *
-// * @return 操作执行结果
-// */
-// AsyncFuture asyncProcess(Operation op, LedgerDataSet newBlockDataset, TransactionRequestContext requestContext,
-// LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService);
}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OperationHandleContext.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OperationHandleContext.java
new file mode 100644
index 00000000..1d837f15
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OperationHandleContext.java
@@ -0,0 +1,15 @@
+package com.jd.blockchain.ledger.core;
+
+import com.jd.blockchain.ledger.Operation;
+
+/**
+ * 在交易处理过程中,提供对多种交易操作处理器互相调用的机制;
+ *
+ * @author huanghaiquan
+ *
+ */
+public interface OperationHandleContext {
+
+ void handle(Operation operation);
+
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OperationHandleRegisteration.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OperationHandleRegisteration.java
new file mode 100644
index 00000000..1b783eb0
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OperationHandleRegisteration.java
@@ -0,0 +1,9 @@
+package com.jd.blockchain.ledger.core;
+
+import com.jd.blockchain.ledger.Operation;
+
+public interface OperationHandleRegisteration {
+
+ OperationHandle getHandle(Class extends Operation> operationType);
+
+}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/P2PRealm.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/P2PRealm.java
deleted file mode 100644
index c7480e07..00000000
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/P2PRealm.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.jd.blockchain.ledger.core;
-
-
-/**
- * @author hhq
- * @version 1.0
- * @created 14-6��-2018 12:13:33
- */
-public class P2PRealm {
-
- public Peer m_Peer;
-
- public P2PRealm(){
-
- }
-
- public void finalize() throws Throwable {
-
- }
-
-}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantCertData.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantCertData.java
index 05fd0611..82d066e2 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantCertData.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantCertData.java
@@ -2,6 +2,7 @@ package com.jd.blockchain.ledger.core;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.ParticipantNode;
+import com.jd.blockchain.utils.Bytes;
/**
* 参与方证书数据对象;
@@ -12,7 +13,7 @@ import com.jd.blockchain.ledger.ParticipantNode;
public class ParticipantCertData implements ParticipantNode {
private int id;
- private String address;
+ private Bytes address;
private String name;
private PubKey pubKey;
@@ -26,14 +27,14 @@ public class ParticipantCertData implements ParticipantNode {
this.pubKey = participantNode.getPubKey();
}
- public ParticipantCertData(String address, String name, PubKey pubKey) {
+ public ParticipantCertData(Bytes address, String name, PubKey pubKey) {
this.address = address;
this.name = name;
this.pubKey = pubKey;
}
@Override
- public String getAddress() {
+ public Bytes getAddress() {
return address;
}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantDataSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantDataset.java
similarity index 78%
rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantDataSet.java
rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantDataset.java
index bd84185d..71e71199 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantDataSet.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantDataset.java
@@ -4,14 +4,16 @@ import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.ParticipantNode;
+import com.jd.blockchain.ledger.ParticipantDataQuery;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
+import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.Transactional;
-public class ParticipantDataSet implements Transactional, MerkleProvable {
+public class ParticipantDataset implements Transactional, MerkleProvable, ParticipantDataQuery {
static {
DataContractRegistry.register(ParticipantNode.class);
@@ -19,12 +21,12 @@ public class ParticipantDataSet implements Transactional, MerkleProvable {
private MerkleDataSet dataset;
- public ParticipantDataSet(CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exPolicyStorage,
+ public ParticipantDataset(CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exPolicyStorage,
VersioningKVStorage verStorage) {
dataset = new MerkleDataSet(cryptoSetting, prefix, exPolicyStorage, verStorage);
}
- public ParticipantDataSet(HashDigest merkleRootHash, CryptoSetting cryptoSetting, String prefix,
+ public ParticipantDataset(HashDigest merkleRootHash, CryptoSetting cryptoSetting, String prefix,
ExPolicyKVStorage exPolicyStorage, VersioningKVStorage verStorage, boolean readonly) {
dataset = new MerkleDataSet(merkleRootHash, cryptoSetting, prefix, exPolicyStorage, verStorage, readonly);
}
@@ -54,6 +56,7 @@ public class ParticipantDataSet implements Transactional, MerkleProvable {
dataset.cancel();
}
+ @Override
public long getParticipantCount() {
return dataset.getDataCount();
}
@@ -73,9 +76,15 @@ public class ParticipantDataSet implements Transactional, MerkleProvable {
}
}
- private Bytes encodeKey(String address) {
- // return id + "";
- return Bytes.fromString(address);
+ private Bytes encodeKey(Bytes address) {
+ return address;
+ }
+
+ @Override
+ public boolean contains(Bytes address) {
+ Bytes key = encodeKey(address);
+ long latestVersion = dataset.getVersion(key);
+ return latestVersion > -1;
}
/**
@@ -87,7 +96,8 @@ public class ParticipantDataSet implements Transactional, MerkleProvable {
* @param address
* @return
*/
- public ParticipantNode getParticipant(String address) {
+ @Override
+ public ParticipantNode getParticipant(Bytes address) {
Bytes key = encodeKey(address);
byte[] bytes = dataset.getValue(key);
if (bytes == null) {
@@ -95,11 +105,12 @@ public class ParticipantDataSet implements Transactional, MerkleProvable {
}
return BinaryProtocol.decode(bytes);
}
-
+
+ @Override
public ParticipantNode[] getParticipants() {
- byte[][] bytes = dataset.getLatestValues(0, (int)dataset.getDataCount());
+ byte[][] bytes = dataset.getLatestValues(0, (int) dataset.getDataCount());
ParticipantNode[] pns = new ParticipantNode[bytes.length];
-
+
for (int i = 0; i < pns.length; i++) {
pns[i] = BinaryProtocol.decode(bytes[i]);
}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/PermissionService.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/PermissionService.java
index b3b9a7c2..78be086b 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/PermissionService.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/PermissionService.java
@@ -1,7 +1,5 @@
package com.jd.blockchain.ledger.core;
-import java.util.SortedSet;
-
public interface PermissionService {
boolean checkLedgerPermission();
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/PrivilegeDataSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/PrivilegeDataSet.java
deleted file mode 100644
index 9bdc3f3b..00000000
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/PrivilegeDataSet.java
+++ /dev/null
@@ -1,21 +0,0 @@
-//package com.jd.blockchain.ledger.core;
-//
-//import com.jd.blockchain.crypto.hash.HashDigest;
-//import com.jd.blockchain.ledger.data.DigitalSignatureBlob;
-//
-//import my.utils.io.ExistentialKVStorage;
-//import my.utils.io.VersioningKVStorage;
-//
-//public class PrivilegeDataSet extends GenericMerkleDataSet {
-//
-// public PrivilegeDataSet(CryptoSetting setting, ExistentialKVStorage merkleTreeStorage, VersioningKVStorage dataStorage) {
-// this(null, setting, merkleTreeStorage, dataStorage, false);
-// }
-//
-// public PrivilegeDataSet(HashDigest rootHash, CryptoSetting setting, ExistentialKVStorage merkleTreeStorage,
-// VersioningKVStorage dataStorage, boolean readonly) {
-// super(rootHash, setting, merkleTreeStorage, dataStorage, readonly, Authorization.class, AuthorizationVO.class,
-// DigitalSignatureBlob.class);
-// }
-//
-//}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RolePrivilegeDataset.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RolePrivilegeDataset.java
new file mode 100644
index 00000000..14673435
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RolePrivilegeDataset.java
@@ -0,0 +1,293 @@
+package com.jd.blockchain.ledger.core;
+
+import com.jd.blockchain.binaryproto.BinaryProtocol;
+import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.ledger.CryptoSetting;
+import com.jd.blockchain.ledger.LedgerException;
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.LedgerPrivilege;
+import com.jd.blockchain.ledger.MerkleProof;
+import com.jd.blockchain.ledger.PrivilegeSet;
+import com.jd.blockchain.ledger.Privileges;
+import com.jd.blockchain.ledger.RolePrivilegeSettings;
+import com.jd.blockchain.ledger.RolePrivileges;
+import com.jd.blockchain.ledger.TransactionPermission;
+import com.jd.blockchain.ledger.TransactionPrivilege;
+import com.jd.blockchain.storage.service.ExPolicyKVStorage;
+import com.jd.blockchain.storage.service.VersioningKVEntry;
+import com.jd.blockchain.storage.service.VersioningKVStorage;
+import com.jd.blockchain.utils.Bytes;
+import com.jd.blockchain.utils.Transactional;
+
+public class RolePrivilegeDataset implements Transactional, MerkleProvable, RolePrivilegeSettings {
+
+ private MerkleDataSet dataset;
+
+ public RolePrivilegeDataset(CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exPolicyStorage,
+ VersioningKVStorage verStorage) {
+ dataset = new MerkleDataSet(cryptoSetting, prefix, exPolicyStorage, verStorage);
+ }
+
+ public RolePrivilegeDataset(HashDigest merkleRootHash, CryptoSetting cryptoSetting, String prefix,
+ ExPolicyKVStorage exPolicyStorage, VersioningKVStorage verStorage, boolean readonly) {
+ dataset = new MerkleDataSet(merkleRootHash, cryptoSetting, prefix, exPolicyStorage, verStorage, readonly);
+ }
+
+ @Override
+ public HashDigest getRootHash() {
+ return dataset.getRootHash();
+ }
+
+ @Override
+ public MerkleProof getProof(Bytes key) {
+ return dataset.getProof(key);
+ }
+
+ @Override
+ public boolean isUpdated() {
+ return dataset.isUpdated();
+ }
+
+ @Override
+ public void commit() {
+ dataset.commit();
+ }
+
+ @Override
+ public void cancel() {
+ dataset.cancel();
+ }
+
+ @Override
+ public long getRoleCount() {
+ return dataset.getDataCount();
+ }
+
+ @Override
+ public long addRolePrivilege(String roleName, Privileges privileges) {
+ return addRolePrivilege(roleName, privileges.getLedgerPrivilege(), privileges.getTransactionPrivilege());
+ }
+
+ @Override
+ public long addRolePrivilege(String roleName, LedgerPrivilege ledgerPrivilege, TransactionPrivilege txPrivilege) {
+ RolePrivileges roleAuth = new RolePrivileges(roleName, -1, ledgerPrivilege, txPrivilege);
+ long nv = setRolePrivilege(roleAuth);
+ if (nv < 0) {
+ throw new LedgerException("Role[" + roleName + "] already exist!");
+ }
+ return nv;
+ }
+
+ @Override
+ public long addRolePrivilege(String roleName, LedgerPermission[] ledgerPermissions,
+ TransactionPermission[] txPermissions) {
+ LedgerPrivilege ledgerPrivilege = new LedgerPrivilege();
+ for (LedgerPermission lp : ledgerPermissions) {
+ ledgerPrivilege.enable(lp);
+ }
+ TransactionPrivilege txPrivilege = new TransactionPrivilege();
+ for (TransactionPermission tp : txPermissions) {
+ txPrivilege.enable(tp);
+ }
+ return addRolePrivilege(roleName, ledgerPrivilege, txPrivilege);
+ }
+
+ /**
+ * 设置角色权限;
+ * 如果版本校验不匹配,则返回 -1;
+ *
+ * @param roleAuth
+ * @return
+ */
+ private long setRolePrivilege(RolePrivileges roleAuth) {
+ if (roleAuth.getRoleName().length() > MAX_ROLE_NAME_LENGTH) {
+ throw new LedgerException("Too long role name!");
+ }
+ Bytes key = encodeKey(roleAuth.getRoleName());
+ byte[] privilegeBytes = BinaryProtocol.encode(roleAuth, PrivilegeSet.class);
+ return dataset.setValue(key, privilegeBytes, roleAuth.getVersion());
+ }
+
+ /**
+ * 更新角色权限;
+ * 如果指定的角色不存在,或者版本不匹配,则引发 {@link LedgerException} 异常;
+ *
+ * @param participant
+ */
+ @Override
+ public void updateRolePrivilege(RolePrivileges roleAuth) {
+ long nv = setRolePrivilege(roleAuth);
+ if (nv < 0) {
+ throw new LedgerException("Update to RoleAuthorization[" + roleAuth.getRoleName()
+ + "] failed due to wrong version[" + roleAuth.getVersion() + "] !");
+ }
+ }
+
+ /**
+ * 授权角色指定的权限;
+ * 如果角色不存在,则返回 -1;
+ *
+ * @param roleName 角色;
+ * @param permissions 权限列表;
+ * @return
+ */
+ @Override
+ public long enablePermissions(String roleName, LedgerPermission... permissions) {
+ RolePrivileges roleAuth = getRolePrivilege(roleName);
+ if (roleAuth == null) {
+ return -1;
+ }
+ roleAuth.getLedgerPrivilege().enable(permissions);
+ return setRolePrivilege(roleAuth);
+ }
+
+ /**
+ * 授权角色指定的权限;
+ * 如果角色不存在,则返回 -1;
+ *
+ * @param roleName 角色;
+ * @param permissions 权限列表;
+ * @return
+ */
+ @Override
+ public long enablePermissions(String roleName, TransactionPermission... permissions) {
+ RolePrivileges roleAuth = getRolePrivilege(roleName);
+ if (roleAuth == null) {
+ return -1;
+ }
+ roleAuth.getTransactionPrivilege().enable(permissions);
+ return setRolePrivilege(roleAuth);
+ }
+
+ /**
+ * 禁止角色指定的权限;
+ * 如果角色不存在,则返回 -1;
+ *
+ * @param roleName 角色;
+ * @param permissions 权限列表;
+ * @return
+ */
+ @Override
+ public long disablePermissions(String roleName, LedgerPermission... permissions) {
+ RolePrivileges roleAuth = getRolePrivilege(roleName);
+ if (roleAuth == null) {
+ return -1;
+ }
+ roleAuth.getLedgerPrivilege().disable(permissions);
+ return setRolePrivilege(roleAuth);
+ }
+
+ /**
+ * 禁止角色指定的权限;
+ * 如果角色不存在,则返回 -1;
+ *
+ * @param roleName 角色;
+ * @param permissions 权限列表;
+ * @return
+ */
+ @Override
+ public long disablePermissions(String roleName, TransactionPermission... permissions) {
+ RolePrivileges roleAuth = getRolePrivilege(roleName);
+ if (roleAuth == null) {
+ return -1;
+ }
+ roleAuth.getTransactionPrivilege().disable(permissions);
+ return setRolePrivilege(roleAuth);
+ }
+
+ /**
+ * 授权角色指定的权限;
+ * 如果角色不存在,则返回 -1;
+ *
+ * @param roleName
+ * @param ledgerPermissions
+ * @param txPermissions
+ * @return
+ */
+ @Override
+ public long enablePermissions(String roleName, LedgerPermission[] ledgerPermissions,
+ TransactionPermission[] txPermissions) {
+ RolePrivileges roleAuth = getRolePrivilege(roleName);
+ if (roleAuth == null) {
+ return -1;
+ }
+ roleAuth.getLedgerPrivilege().enable(ledgerPermissions);
+ roleAuth.getTransactionPrivilege().enable(txPermissions);
+ return setRolePrivilege(roleAuth);
+ }
+
+ /**
+ * 禁用角色指定的权限;
+ * 如果角色不存在,则返回 -1;
+ *
+ * @param roleName
+ * @param ledgerPermissions
+ * @param txPermissions
+ * @return
+ */
+ @Override
+ public long disablePermissions(String roleName, LedgerPermission[] ledgerPermissions,
+ TransactionPermission[] txPermissions) {
+ RolePrivileges roleAuth = getRolePrivilege(roleName);
+ if (roleAuth == null) {
+ return -1;
+ }
+ roleAuth.getLedgerPrivilege().disable(ledgerPermissions);
+ roleAuth.getTransactionPrivilege().disable(txPermissions);
+ return setRolePrivilege(roleAuth);
+ }
+
+ private Bytes encodeKey(String address) {
+ // return id + "";
+ return Bytes.fromString(address);
+ }
+
+ /**
+ * 查询角色权限;
+ *
+ *
+ * 如果不存在,则返回 null;
+ *
+ * @param address
+ * @return
+ */
+ @Override
+ public RolePrivileges getRolePrivilege(String roleName) {
+ // 只返回最新版本;
+ Bytes key = encodeKey(roleName);
+ VersioningKVEntry kv = dataset.getDataEntry(key);
+ if (kv == null) {
+ return null;
+ }
+ PrivilegeSet privilege = BinaryProtocol.decode(kv.getValue());
+ return new RolePrivileges(roleName, kv.getVersion(), privilege);
+ }
+
+ @Override
+ public RolePrivileges[] getRolePrivileges(int index, int count) {
+ VersioningKVEntry[] kvEntries = dataset.getLatestDataEntries(index, count);
+ RolePrivileges[] pns = new RolePrivileges[kvEntries.length];
+ PrivilegeSet privilege;
+ for (int i = 0; i < pns.length; i++) {
+ privilege = BinaryProtocol.decode(kvEntries[i].getValue());
+ pns[i] = new RolePrivileges(kvEntries[i].getKey().toUTF8String(), kvEntries[i].getVersion(), privilege);
+ }
+ return pns;
+ }
+
+ @Override
+ public RolePrivileges[] getRolePrivileges() {
+ return getRolePrivileges(0, (int) getRoleCount());
+ }
+
+ @Override
+ public boolean isReadonly() {
+ return dataset.isReadonly();
+ }
+
+ @Override
+ public boolean contains(String roleName) {
+ Bytes key = encodeKey(roleName);
+ return dataset.getVersion(key) > -1;
+ }
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SecurityContext.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SecurityContext.java
new file mode 100644
index 00000000..d3ad83ba
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SecurityContext.java
@@ -0,0 +1,38 @@
+package com.jd.blockchain.ledger.core;
+
+import java.util.Set;
+
+import com.jd.blockchain.ledger.BlockchainIdentity;
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.LedgerSecurityException;
+import com.jd.blockchain.ledger.TransactionPermission;
+
+public class SecurityContext {
+
+ private static ThreadLocal policyHolder = new ThreadLocal();
+
+ public static void setContextUsersPolicy(SecurityPolicy policy) {
+ policyHolder.set(policy);
+ }
+
+ public static SecurityPolicy removeContextUsersPolicy() {
+ SecurityPolicy p = policyHolder.get();
+ policyHolder.remove();
+ return p;
+ }
+
+ public static SecurityPolicy getContextUsersPolicy() {
+ return policyHolder.get();
+ }
+
+ /**
+ * 把上下文安全策略切换为指定的策略,并执行参数指定的 {@link Runnable} 操作,当操作完成后恢复原来的上下文策略;
+ *
+ * @param contextUsersPolicy
+ * @param runnable
+ */
+ public static void switchContextUsersPolicy(SecurityPolicy contextUsersPolicy, Runnable runnable) {
+
+ }
+
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SecurityPolicy.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SecurityPolicy.java
new file mode 100644
index 00000000..17d487dd
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SecurityPolicy.java
@@ -0,0 +1,142 @@
+package com.jd.blockchain.ledger.core;
+
+import java.util.Set;
+
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.LedgerSecurityException;
+import com.jd.blockchain.ledger.TransactionPermission;
+import com.jd.blockchain.ledger.TransactionRequest;
+import com.jd.blockchain.utils.Bytes;
+
+/**
+ * 针对特定交易请求的账本安全策略;
+ *
+ * @author huanghaiquan
+ *
+ */
+public interface SecurityPolicy {
+
+ /**
+ * 签署交易的终端用户的地址列表;(来自{@link TransactionRequest#getEndpointSignatures()})
+ *
+ * @return
+ */
+ Set getEndpoints();
+
+ /**
+ * 签署交易的节点参与方的地址列表(来自{@link TransactionRequest#getNodeSignatures()})
+ *
+ * @return
+ */
+ Set getNodes();
+
+ /**
+ * 终端身份是否合法;
+ *
+ * @param midPolicy
+ * @return
+ */
+ boolean isEndpointValid(MultiIDsPolicy midPolicy);
+
+ /**
+ * 节点身份是否合法;
+ *
+ * @param midPolicy
+ * @return
+ */
+ boolean isNodeValid(MultiIDsPolicy midPolicy);
+
+ /**
+ * 检查签署交易的终端用户(来自{@link TransactionRequest#getEndpointSignatures()})是否被授权了参数指定的权限;
+ *
+ * @param permission 要检查的权限;
+ * @param midPolicy 针对多个签名用户的权限策略;
+ * @return 返回 true 表示获得授权; 返回 false 表示未获得授权;
+ */
+ boolean isEndpointEnable(LedgerPermission permission, MultiIDsPolicy midPolicy);
+
+ /**
+ * 检查签署交易的终端用户(来自{@link TransactionRequest#getEndpointSignatures()})是否被授权了参数指定的权限;
+ *
+ * @param permission 要检查的权限;
+ * @param midPolicy 针对多个签名用户的权限策略;
+ * @return 返回 true 表示获得授权; 返回 false 表示未获得授权;
+ */
+ boolean isEndpointEnable(TransactionPermission permission, MultiIDsPolicy midPolicy);
+
+ /**
+ * 检查签署交易的节点参与方(来自{@link TransactionRequest#getNodeSignatures()})是否被授权了参数指定的权限;
+ *
+ * @param permission 要检查的权限;
+ * @param midPolicy 针对多个签名用户的权限策略;
+ * @return 返回 true 表示获得授权; 返回 false 表示未获得授权;
+ */
+ boolean isNodeEnable(LedgerPermission permission, MultiIDsPolicy midPolicy);
+
+ /**
+ * 检查签署交易的节点参与方(来自{@link TransactionRequest#getNodeSignatures()})是否被授权了参数指定的权限;
+ *
+ * @param permission 要检查的权限;
+ * @param midPolicy 针对多个签名用户的权限策略;
+ * @return 返回 true 表示获得授权; 返回 false 表示未获得授权;
+ */
+ boolean isNodeEnable(TransactionPermission permission, MultiIDsPolicy midPolicy);
+
+ /**
+ * 检查终端身份的合法性;
+ *
+ * @param midPolicy
+ * @throws LedgerSecurityException
+ */
+ void checkEndpointValidity(MultiIDsPolicy midPolicy) throws LedgerSecurityException;
+
+ /**
+ * 检查节点身份的合法性;
+ *
+ * @param midPolicy
+ * @throws LedgerSecurityException
+ */
+ void checkNodeValidity(MultiIDsPolicy midPolicy) throws LedgerSecurityException;
+
+ /**
+ * 检查签署交易的终端用户(来自{@link TransactionRequest#getEndpointSignatures()})是否被授权了参数指定的权限;
+ * 如果未获授权,方法将引发 {@link LedgerSecurityException} 异常;
+ *
+ * @param permission 要检查的权限;
+ * @param midPolicy 针对多个签名用户的权限策略;
+ * @throws LedgerSecurityException
+ */
+ void checkEndpointPermission(LedgerPermission permission, MultiIDsPolicy midPolicy) throws LedgerSecurityException;
+
+ /**
+ * 检查签署交易的终端用户(来自{@link TransactionRequest#getEndpointSignatures()})是否被授权了参数指定的权限;
+ * 如果未获授权,方法将引发 {@link LedgerSecurityException} 异常;
+ *
+ * @param permission
+ * @param midPolicy
+ * @throws LedgerSecurityException
+ */
+ void checkEndpointPermission(TransactionPermission permission, MultiIDsPolicy midPolicy)
+ throws LedgerSecurityException;
+
+ /**
+ * 检查签署交易的节点参与方(来自{@link TransactionRequest#getNodeSignatures()})是否被授权了参数指定的权限;
+ * 如果未获授权,方法将引发 {@link LedgerSecurityException} 异常;
+ *
+ * @param permission
+ * @param midPolicy
+ * @throws LedgerSecurityException
+ */
+ void checkNodePermission(LedgerPermission permission, MultiIDsPolicy midPolicy) throws LedgerSecurityException;
+
+ /**
+ * 检查签署交易的节点参与方(来自{@link TransactionRequest#getNodeSignatures()})是否被授权了参数指定的权限;
+ * 如果未获授权,方法将引发 {@link LedgerSecurityException} 异常;
+ *
+ * @param permission
+ * @param midPolicy
+ * @throws LedgerSecurityException
+ */
+ void checkNodePermission(TransactionPermission permission, MultiIDsPolicy midPolicy) throws LedgerSecurityException;
+
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SettingContext.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SettingContext.java
new file mode 100644
index 00000000..f464db7f
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SettingContext.java
@@ -0,0 +1,51 @@
+//package com.jd.blockchain.ledger.core;
+//
+//public class SettingContext {
+//
+// private static final TxSettingContext txSettings = new TxSettingContext();
+//
+// private static final QueryingSettingContext queryingSettings = new QueryingSettingContext();
+//
+// public static TxSettingContext txSettings() {
+// return txSettings;
+// }
+//
+// public static QueryingSettingContext queryingSettings() {
+// return queryingSettings;
+// }
+//
+// /**
+// * 与交易处理相关的设置;
+// * @author huanghaiquan
+// *
+// */
+// public static class TxSettingContext {
+//
+// public boolean verifyLedger() {
+// return true;
+// }
+//
+// public boolean verifySignature() {
+// return true;
+// }
+//
+// }
+//
+// /**
+// * 与账本查询相关的设置;
+// * @author huanghaiquan
+// *
+// */
+// public static class QueryingSettingContext {
+//
+// /**
+// * 查询区块等具有 hash 标识符的对象时是否重新校验哈希;
+// * @return
+// */
+// public boolean verifyHash() {
+// return false;
+// }
+//
+// }
+//
+//}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionBatchProcessor.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionBatchProcessor.java
new file mode 100644
index 00000000..cab2a4e2
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionBatchProcessor.java
@@ -0,0 +1,472 @@
+package com.jd.blockchain.ledger.core;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.ledger.BlockRollbackException;
+import com.jd.blockchain.ledger.BytesValue;
+import com.jd.blockchain.ledger.ContractDoesNotExistException;
+import com.jd.blockchain.ledger.DataAccountDoesNotExistException;
+import com.jd.blockchain.ledger.IllegalTransactionException;
+import com.jd.blockchain.ledger.LedgerBlock;
+import com.jd.blockchain.ledger.LedgerException;
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.LedgerSecurityException;
+import com.jd.blockchain.ledger.Operation;
+import com.jd.blockchain.ledger.OperationResult;
+import com.jd.blockchain.ledger.OperationResultData;
+import com.jd.blockchain.ledger.ParticipantDoesNotExistException;
+import com.jd.blockchain.ledger.TransactionContent;
+import com.jd.blockchain.ledger.TransactionRequest;
+import com.jd.blockchain.ledger.TransactionResponse;
+import com.jd.blockchain.ledger.TransactionRollbackException;
+import com.jd.blockchain.ledger.TransactionState;
+import com.jd.blockchain.ledger.UserDoesNotExistException;
+import com.jd.blockchain.ledger.core.TransactionRequestExtension.Credential;
+import com.jd.blockchain.service.TransactionBatchProcess;
+import com.jd.blockchain.service.TransactionBatchResult;
+import com.jd.blockchain.service.TransactionBatchResultHandle;
+import com.jd.blockchain.transaction.SignatureUtils;
+import com.jd.blockchain.transaction.TxBuilder;
+import com.jd.blockchain.transaction.TxResponseMessage;
+
+public class TransactionBatchProcessor implements TransactionBatchProcess {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(TransactionBatchProcessor.class);
+
+ private LedgerSecurityManager securityManager;
+
+ private LedgerService ledgerService;
+
+ private LedgerEditor newBlockEditor;
+
+ private LedgerDataQuery ledgerQueryer;
+
+ private OperationHandleRegisteration opHandles;
+
+ // 新创建的交易;
+ private LedgerBlock block;
+
+ private TransactionState globalResult;
+
+ private List responseList = new ArrayList<>();
+
+ private TransactionBatchResult batchResult;
+
+ /**
+ * @param newBlockEditor 新区块的数据编辑器;
+ * @param ledgerQueryer 账本查询器,只包含新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集;
+ * @param opHandles 操作处理对象注册表;
+ */
+ public TransactionBatchProcessor(LedgerSecurityManager securityManager, LedgerEditor newBlockEditor,
+ LedgerDataQuery ledgerQueryer, OperationHandleRegisteration opHandles, LedgerService ledgerService) {
+ this.securityManager = securityManager;
+ this.newBlockEditor = newBlockEditor;
+ this.ledgerQueryer = ledgerQueryer;
+ this.opHandles = opHandles;
+ this.ledgerService = ledgerService;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.jd.blockchain.ledger.core.impl.TransactionBatchProcess#schedule(com.jd.
+ * blockchain.ledger.TransactionRequest)
+ */
+ @Override
+ public TransactionResponse schedule(TransactionRequest request) {
+ TransactionResponse resp;
+ try {
+ LOGGER.debug("Start handling transaction... --[BlockHeight={}][RequestHash={}][TxHash={}]",
+ newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash());
+
+ TransactionRequestExtension reqExt = new TransactionRequestExtensionImpl(request);
+
+ // 初始化交易的用户安全策略;
+ SecurityPolicy securityPolicy = securityManager.createSecurityPolicy(reqExt.getEndpointAddresses(),
+ reqExt.getNodeAddresses());
+ SecurityContext.setContextUsersPolicy(securityPolicy);
+
+ // 安全校验;
+ checkSecurity(securityPolicy);
+
+ // 验证交易请求;
+ checkRequest(reqExt);
+
+ // 创建交易上下文;
+ // 此调用将会验证交易签名,验签失败将会抛出异常,同时,不记录签名错误的交易到链上;
+ LedgerTransactionContext txCtx = newBlockEditor.newTransaction(request);
+
+ // 处理交易;
+ resp = handleTx(reqExt, txCtx);
+
+ LOGGER.debug("Complete handling transaction. --[BlockHeight={}][RequestHash={}][TxHash={}]",
+ newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash());
+
+ } catch (IllegalTransactionException e) {
+ // 抛弃发生处理异常的交易请求;
+ resp = discard(request, e.getTxState());
+ LOGGER.error(String.format(
+ "Ignore transaction caused by IllegalTransactionException! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
+ newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(),
+ e.getMessage()), e);
+
+ } catch (BlockRollbackException e) {
+ // 发生区块级别的处理异常,向上重新抛出异常进行处理,整个区块可能被丢弃;
+ LOGGER.error(String.format(
+ "Ignore transaction caused by BlockRollbackException! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
+ newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(),
+ e.getMessage()), e);
+ throw e;
+ } catch (Exception e) {
+ // 抛弃发生处理异常的交易请求;
+ resp = discard(request, TransactionState.SYSTEM_ERROR);
+ LOGGER.error(String.format(
+ "Ignore transaction caused by the system exception! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
+ newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(),
+ e.getMessage()), e);
+
+ } finally {
+ // 清空交易的用户安全策略;
+ SecurityContext.removeContextUsersPolicy();
+ }
+
+ responseList.add(resp);
+ return resp;
+ }
+
+ /**
+ * 执行安全验证;
+ */
+ private void checkSecurity(SecurityPolicy securityPolicy) {
+ // 验证节点和终端身份的合法性;
+ // 多重身份签署的必须全部身份都合法;
+ securityPolicy.checkEndpointValidity(MultiIDsPolicy.ALL);
+ securityPolicy.checkNodeValidity(MultiIDsPolicy.ALL);
+
+ // 验证参与方节点是否具有核准交易的权限;
+ securityPolicy.checkNodePermission(LedgerPermission.APPROVE_TX, MultiIDsPolicy.AT_LEAST_ONE);
+ }
+
+ private void checkRequest(TransactionRequestExtension reqExt) {
+ // TODO: 把验签和创建交易并行化;
+ checkTxContentHash(reqExt);
+ checkEndpointSignatures(reqExt);
+ checkNodeSignatures(reqExt);
+ }
+
+ private void checkTxContentHash(TransactionRequestExtension requestExt) {
+ TransactionContent txContent = requestExt.getTransactionContent();
+ if (!TxBuilder.verifyTxContentHash(txContent, txContent.getHash())) {
+ // 由于哈希校验失败,引发IllegalTransactionException,使外部调用抛弃此交易请求;
+ throw new IllegalTransactionException(
+ "Wrong transaction content hash! --[TxHash=" + requestExt.getTransactionContent().getHash() + "]!",
+ TransactionState.IGNORED_BY_WRONG_CONTENT_SIGNATURE);
+ }
+ }
+
+ private void checkNodeSignatures(TransactionRequestExtension request) {
+ TransactionContent txContent = request.getTransactionContent();
+ Collection nodes = request.getNodes();
+ if (nodes != null) {
+ for (Credential node : nodes) {
+ if (!SignatureUtils.verifyHashSignature(txContent.getHash(), node.getSignature().getDigest(),
+ node.getPubKey())) {
+ // 由于签名校验失败,引发IllegalTransactionException,使外部调用抛弃此交易请求;
+ throw new IllegalTransactionException(
+ String.format("Wrong transaction node signature! --[Tx Hash=%s][Node Signer=%s]!",
+ request.getTransactionContent().getHash(), node.getAddress()),
+ TransactionState.IGNORED_BY_WRONG_CONTENT_SIGNATURE);
+ }
+ }
+ }
+ }
+
+ private void checkEndpointSignatures(TransactionRequestExtension request) {
+ TransactionContent txContent = request.getTransactionContent();
+ Collection endpoints = request.getEndpoints();
+ if (endpoints != null) {
+ for (Credential endpoint : endpoints) {
+ if (!SignatureUtils.verifyHashSignature(txContent.getHash(), endpoint.getSignature().getDigest(),
+ endpoint.getPubKey())) {
+ // 由于签名校验失败,引发IllegalTransactionException,使外部调用抛弃此交易请求;
+ throw new IllegalTransactionException(
+ String.format("Wrong transaction endpoint signature! --[Tx Hash=%s][Endpoint Signer=%s]!",
+ request.getTransactionContent().getHash(), endpoint.getAddress()),
+ TransactionState.IGNORED_BY_WRONG_CONTENT_SIGNATURE);
+ }
+ }
+ }
+ }
+
+ /**
+ * 处理交易;
+ *
+ * 此方法会处理所有的异常,以不同结果的 {@link TransactionResponse} 返回;
+ *
+ * @param request
+ * @param txCtx
+ * @return
+ */
+ private TransactionResponse handleTx(TransactionRequestExtension request, LedgerTransactionContext txCtx) {
+ TransactionState result;
+ List operationResults = new ArrayList<>();
+ try {
+ LedgerDataset dataset = txCtx.getDataset();
+
+ // 执行操作;
+ Operation[] ops = request.getTransactionContent().getOperations();
+ OperationHandleContext handleContext = new OperationHandleContext() {
+ @Override
+ public void handle(Operation operation) {
+ // assert; Instance of operation are one of User related operations or
+ // DataAccount related operations;
+ OperationHandle hdl = opHandles.getHandle(operation.getClass());
+ hdl.process(operation, dataset, request, ledgerQueryer, this, ledgerService);
+ }
+ };
+ OperationHandle opHandle;
+ int opIndex = 0;
+ for (Operation op : ops) {
+ opHandle = opHandles.getHandle(op.getClass());
+ BytesValue opResult = opHandle.process(op, dataset, request, ledgerQueryer, handleContext,
+ ledgerService);
+ if (opResult != null) {
+ operationResults.add(new OperationResultData(opIndex, opResult));
+ }
+ opIndex++;
+ }
+
+ // 提交交易(事务);
+ result = TransactionState.SUCCESS;
+ txCtx.commit(result, operationResults);
+ } catch (TransactionRollbackException e) {
+ result = TransactionState.IGNORED_BY_TX_FULL_ROLLBACK;
+ txCtx.rollback();
+ LOGGER.error(String.format(
+ "Transaction was full rolled back! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
+ newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(),
+ e.getMessage()), e);
+ } catch (BlockRollbackException e) {
+ // 回滚整个区块;
+ result = TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK;
+ txCtx.rollback();
+ LOGGER.error(
+ String.format("Transaction was rolled back! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
+ newBlockEditor.getBlockHeight(), request.getHash(),
+ request.getTransactionContent().getHash(), e.getMessage()),
+ e);
+ // 重新抛出由上层错误处理;
+ throw e;
+ } catch (LedgerException e) {
+ // TODO: 识别更详细的异常类型以及执行对应的处理;
+ result = TransactionState.LEDGER_ERROR;
+ if (e instanceof DataAccountDoesNotExistException) {
+ result = TransactionState.DATA_ACCOUNT_DOES_NOT_EXIST;
+ } else if (e instanceof UserDoesNotExistException) {
+ result = TransactionState.USER_DOES_NOT_EXIST;
+ } else if (e instanceof ContractDoesNotExistException) {
+ result = TransactionState.CONTRACT_DOES_NOT_EXIST;
+ } else if (e instanceof ParticipantDoesNotExistException) {
+ result = TransactionState.PARTICIPANT_DOES_NOT_EXIST;
+ }
+ txCtx.discardAndCommit(result, operationResults);
+ LOGGER.error(String.format(
+ "Due to ledger exception, the data changes resulting from transaction execution will be rolled back and the results of the transaction will be committed! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
+ newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(),
+ e.getMessage()), e);
+ } catch (LedgerSecurityException e) {
+ // TODO: 识别更详细的异常类型以及执行对应的处理;
+ result = TransactionState.REJECTED_BY_SECURITY_POLICY;
+ txCtx.discardAndCommit(result, operationResults);
+ LOGGER.error(String.format(
+ "Due to ledger security exception, the data changes resulting from transaction execution will be rolled back and the results of the transaction will be committed! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
+ newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(),
+ e.getMessage()), e);
+ } catch (Exception e) {
+ result = TransactionState.SYSTEM_ERROR;
+ txCtx.discardAndCommit(TransactionState.SYSTEM_ERROR, operationResults);
+ LOGGER.error(String.format(
+ "Due to system exception, the data changes resulting from transaction execution will be rolled back and the results of the transaction will be committed! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
+ newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(),
+ e.getMessage()), e);
+ }
+ TxResponseHandle resp = new TxResponseHandle(request, result);
+
+ if (!operationResults.isEmpty()) {
+ OperationResult[] operationResultArray = new OperationResult[operationResults.size()];
+ resp.setOperationResults(operationResults.toArray(operationResultArray));
+ }
+ return resp;
+ }
+
+ /**
+ * 直接丢弃交易;
+ *
+ * @param request
+ * @param txState
+ * @return 丢弃交易的回复;只包含原始请求中的交易内容哈希和交易被丢弃的原因,而不包含区块信息;
+ */
+ private TransactionResponse discard(TransactionRequest request, TransactionState txState) {
+ // 丢弃交易的回复;只返回请求的交易内容哈希和交易被丢弃的原因,
+ TxResponseMessage resp = new TxResponseMessage(request.getTransactionContent().getHash());
+ resp.setExecutionState(txState);
+
+ LOGGER.error("Discard transaction request! --[BlockHeight={}][RequestHash={}][TxHash={}][ResponseState={}]",
+ newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(),
+ resp.getExecutionState());
+ return resp;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.jd.blockchain.ledger.core.impl.TransactionBatchProcess#prepare()
+ */
+ @Override
+ public TransactionBatchResultHandle prepare() {
+ if (batchResult != null) {
+ throw new IllegalStateException("Batch result has already been prepared or canceled!");
+ }
+ block = newBlockEditor.prepare();
+ batchResult = new TransactionBatchResultHandleImpl();
+ return (TransactionBatchResultHandle) batchResult;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.jd.blockchain.ledger.core.impl.TransactionBatchProcess#cancel(com.jd.
+ * blockchain.ledger.ExecutionState)
+ */
+ @Override
+ public TransactionBatchResult cancel(TransactionState errorResult) {
+ if (batchResult != null) {
+ throw new IllegalStateException("Batch result has already been prepared or canceled!");
+ }
+
+ cancelInError(errorResult);
+
+ batchResult = new TransactionBatchResultImpl();
+ return batchResult;
+ }
+
+ @Override
+ public long blockHeight() {
+ if (block != null) {
+ return block.getHeight();
+ }
+ return 0;
+ }
+
+ private void commitSuccess() {
+ newBlockEditor.commit();
+ onCommitted();
+ }
+
+ private void cancelInError(TransactionState errorResult) {
+ if (errorResult == TransactionState.SUCCESS) {
+ throw new IllegalArgumentException("Cann't cancel by an success result!");
+ }
+ newBlockEditor.cancel();
+ this.globalResult = errorResult;
+ onCanceled();
+ }
+
+ /**
+ * 模板事件方法:交易已提交;
+ */
+ protected void onCommitted() {
+ }
+
+ /**
+ * 模板事件方法:交易已取消;
+ */
+ protected void onCanceled() {
+ }
+
+ private class TxResponseHandle implements TransactionResponse {
+
+ private TransactionRequest request;
+
+ private TransactionState result;
+
+ private OperationResult[] operationResults;
+
+ public TxResponseHandle(TransactionRequest request, TransactionState result) {
+ this.request = request;
+ this.result = result;
+ }
+
+ @Override
+ public HashDigest getContentHash() {
+ return request.getTransactionContent().getHash();
+ }
+
+ @Override
+ public TransactionState getExecutionState() {
+ return result;
+ }
+
+ @Override
+ public HashDigest getBlockHash() {
+ return block == null ? null : block.getHash();
+ }
+
+ @Override
+ public long getBlockHeight() {
+ return block == null ? -1 : block.getHeight();
+ }
+
+ @Override
+ public boolean isSuccess() {
+ return globalResult == null ? result == TransactionState.SUCCESS : globalResult == TransactionState.SUCCESS;
+ }
+
+ @Override
+ public OperationResult[] getOperationResults() {
+ return operationResults;
+ }
+
+ public void setOperationResults(OperationResult[] operationResults) {
+ this.operationResults = operationResults;
+ }
+ }
+
+ private class TransactionBatchResultImpl implements TransactionBatchResult {
+
+ @Override
+ public LedgerBlock getBlock() {
+ return block;
+ }
+
+ @Override
+ public Iterator getResponses() {
+ return responseList.iterator();
+ }
+
+ }
+
+ private class TransactionBatchResultHandleImpl extends TransactionBatchResultImpl
+ implements TransactionBatchResultHandle {
+
+ @Override
+ public void commit() {
+ commitSuccess();
+ }
+
+ @Override
+ public void cancel(TransactionState errorResult) {
+ cancelInError(errorResult);
+ }
+
+ }
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionEngineImpl.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionEngineImpl.java
similarity index 63%
rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionEngineImpl.java
rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionEngineImpl.java
index bf2470e4..928997fd 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionEngineImpl.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionEngineImpl.java
@@ -1,16 +1,12 @@
-package com.jd.blockchain.ledger.core.impl;
+package com.jd.blockchain.ledger.core;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
-import com.jd.blockchain.crypto.HashDigest;
-import com.jd.blockchain.ledger.LedgerBlock;
import org.springframework.beans.factory.annotation.Autowired;
-import com.jd.blockchain.ledger.core.LedgerDataSet;
-import com.jd.blockchain.ledger.core.LedgerEditor;
-import com.jd.blockchain.ledger.core.LedgerRepository;
-import com.jd.blockchain.ledger.core.LedgerService;
+import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.service.TransactionBatchProcess;
import com.jd.blockchain.service.TransactionEngine;
@@ -44,9 +40,15 @@ public class TransactionEngineImpl implements TransactionEngine {
LedgerBlock ledgerBlock = ledgerRepo.getLatestBlock();
LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();
- LedgerDataSet previousBlockDataset = ledgerRepo.getDataSet(ledgerBlock);
- batch = new InnerTransactionBatchProcessor(ledgerHash, newBlockEditor, previousBlockDataset, opHdlRegs,
- ledgerService, ledgerBlock.getHeight());
+ LedgerDataQuery previousBlockDataset = ledgerRepo.getDataSet(ledgerBlock);
+
+ LedgerAdminDataQuery previousAdminDataset = previousBlockDataset.getAdminDataset();
+ LedgerSecurityManager securityManager = new LedgerSecurityManagerImpl(
+ previousAdminDataset.getAdminInfo().getRolePrivileges(),
+ previousAdminDataset.getAdminInfo().getUserRoles(), previousAdminDataset.getParticipantDataset(),
+ previousBlockDataset.getUserAccountSet());
+ batch = new InnerTransactionBatchProcessor(ledgerHash, securityManager, newBlockEditor, previousBlockDataset,
+ opHdlRegs, ledgerService, ledgerBlock.getHeight());
batchs.put(ledgerHash, batch);
return batch;
}
@@ -69,19 +71,15 @@ public class TransactionEngineImpl implements TransactionEngine {
/**
* 创建交易批处理器;
*
- * @param ledgerHash
- * 账本哈希;
- * @param newBlockEditor
- * 新区块的数据编辑器;
- * @param previousBlockDataset
- * 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集;
- * @param opHandles
- * 操作处理对象注册表;
+ * @param ledgerHash 账本哈希;
+ * @param newBlockEditor 新区块的数据编辑器;
+ * @param previousBlockDataset 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集;
+ * @param opHandles 操作处理对象注册表;
*/
- public InnerTransactionBatchProcessor(HashDigest ledgerHash, LedgerEditor newBlockEditor,
- LedgerDataSet previousBlockDataset, OperationHandleRegisteration opHandles,
- LedgerService ledgerService, long blockHeight) {
- super(newBlockEditor, previousBlockDataset, opHandles, ledgerService);
+ public InnerTransactionBatchProcessor(HashDigest ledgerHash, LedgerSecurityManager securityManager,
+ LedgerEditor newBlockEditor, LedgerDataQuery previousBlockDataset,
+ OperationHandleRegisteration opHandles, LedgerService ledgerService, long blockHeight) {
+ super(securityManager, newBlockEditor, previousBlockDataset, opHandles, ledgerService);
this.ledgerHash = ledgerHash;
this.blockHeight = blockHeight;
}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionRequestContext.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionRequestContext.java
deleted file mode 100644
index 324c4e0e..00000000
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionRequestContext.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.jd.blockchain.ledger.core;
-
-import java.util.Set;
-
-import com.jd.blockchain.ledger.DigitalSignature;
-import com.jd.blockchain.ledger.TransactionRequest;
-import com.jd.blockchain.utils.Bytes;
-
-/**
- * 交易请求上下文;
- *
- * @author huanghaiquan
- *
- */
-public interface TransactionRequestContext {
-
- /**
- * 交易请求;
- *
- * @return
- */
- TransactionRequest getRequest();
-
- /**
- * 签名发起请求的终端用户的地址列表;
- *
- * @return
- */
- Set getEndpoints();
-
- /**
- * 签名发起请求的节点的地址列表;
- *
- * @return
- */
- Set getNodes();
-
- /**
- * 请求的终端发起人列表中是否包含指定地址的终端用户;
- *
- * @param address
- * @return
- */
- boolean containsEndpoint(Bytes address);
-
- /**
- * 请求的经手节点列表中是否包含指定地址的节点;
- *
- * @param address
- * @return
- */
- boolean containsNode(Bytes address);
-
- /**
- * 获取交易请求中指定地址的终端的签名;
- *
- * @param address
- * @return
- */
- DigitalSignature getEndpointSignature(Bytes address);
-
- /**
- * 获取交易请求中指定地址的节点的签名;
- *
- * @param address
- * @return
- */
- DigitalSignature getNodeSignature(Bytes address);
-
-}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionRequestExtension.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionRequestExtension.java
new file mode 100644
index 00000000..ec6b1122
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionRequestExtension.java
@@ -0,0 +1,115 @@
+package com.jd.blockchain.ledger.core;
+
+import java.util.Collection;
+import java.util.Set;
+
+import com.jd.blockchain.crypto.PubKey;
+import com.jd.blockchain.ledger.BlockchainIdentity;
+import com.jd.blockchain.ledger.BlockchainIdentityData;
+import com.jd.blockchain.ledger.DigitalSignature;
+import com.jd.blockchain.ledger.TransactionRequest;
+import com.jd.blockchain.utils.Bytes;
+
+/**
+ * 交易请求上下文;
+ *
+ * @author huanghaiquan
+ *
+ */
+public interface TransactionRequestExtension extends TransactionRequest {
+
+// /**
+// * 交易请求;
+// *
+// * @return
+// */
+// TransactionRequest getRequest();
+
+ /**
+ * 签名发起请求的终端用户的地址列表;
+ *
+ * @return
+ */
+ Set getEndpointAddresses();
+
+ /**
+ * 签名发起请求的终端用户列表;
+ *
+ * @return
+ */
+ Collection getEndpoints();
+
+ /**
+ * 签名发起请求的节点的地址列表;
+ *
+ * @return
+ */
+ Set getNodeAddresses();
+
+ /**
+ * 签名发起请求的节点列表;
+ *
+ * @return
+ */
+ Collection getNodes();
+
+ /**
+ * 请求的终端发起人列表中是否包含指定地址的终端用户;
+ *
+ * @param address
+ * @return
+ */
+ boolean containsEndpoint(Bytes address);
+
+ /**
+ * 请求的经手节点列表中是否包含指定地址的节点;
+ *
+ * @param address
+ * @return
+ */
+ boolean containsNode(Bytes address);
+
+ /**
+ * 获取交易请求中指定地址的终端的签名;
+ *
+ * @param address
+ * @return
+ */
+ DigitalSignature getEndpointSignature(Bytes address);
+
+ /**
+ * 获取交易请求中指定地址的节点的签名;
+ *
+ * @param address
+ * @return
+ */
+ DigitalSignature getNodeSignature(Bytes address);
+
+ public static class Credential {
+
+ private final BlockchainIdentity identity;
+
+ private final DigitalSignature signature;
+
+ Credential(DigitalSignature signature) {
+ this.identity = new BlockchainIdentityData(signature.getPubKey());
+ this.signature = signature;
+ }
+
+ public Bytes getAddress() {
+ return identity.getAddress();
+ }
+
+ public PubKey getPubKey() {
+ return identity.getPubKey();
+ }
+
+ public BlockchainIdentity getIdentity() {
+ return identity;
+ }
+
+ public DigitalSignature getSignature() {
+ return signature;
+ }
+ }
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionRequestExtensionImpl.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionRequestExtensionImpl.java
new file mode 100644
index 00000000..1d93fbbe
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionRequestExtensionImpl.java
@@ -0,0 +1,108 @@
+package com.jd.blockchain.ledger.core;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.ledger.DigitalSignature;
+import com.jd.blockchain.ledger.TransactionContent;
+import com.jd.blockchain.ledger.TransactionRequest;
+import com.jd.blockchain.utils.Bytes;
+
+/**
+ * 交易请求的扩展信息;
+ *
+ * @author huanghaiquan
+ *
+ */
+public class TransactionRequestExtensionImpl implements TransactionRequestExtension {
+
+ private TransactionRequest request;
+
+ private Map endpointSignatures = new HashMap<>();
+
+ private Map nodeSignatures = new HashMap<>();
+
+ public TransactionRequestExtensionImpl(TransactionRequest request) {
+ this.request = request;
+ resolveSigners();
+ }
+
+ private void resolveSigners() {
+ if (request.getEndpointSignatures() != null) {
+ for (DigitalSignature signature : request.getEndpointSignatures()) {
+ Credential cred = new Credential(signature);
+ endpointSignatures.put(cred.getIdentity().getAddress(), cred);
+ }
+ }
+ if (request.getEndpointSignatures() != null) {
+ for (DigitalSignature signature : request.getNodeSignatures()) {
+ Credential cred = new Credential(signature);
+ nodeSignatures.put(cred.getIdentity().getAddress(), cred);
+ }
+ }
+ }
+
+ @Override
+ public Set getEndpointAddresses() {
+ return endpointSignatures.keySet();
+ }
+
+ @Override
+ public Set getNodeAddresses() {
+ return nodeSignatures.keySet();
+ }
+
+ @Override
+ public Collection getEndpoints() {
+ return endpointSignatures.values();
+ }
+
+ @Override
+ public Collection getNodes() {
+ return nodeSignatures.values();
+ }
+
+ @Override
+ public boolean containsEndpoint(Bytes address) {
+ return endpointSignatures.containsKey(address);
+ }
+
+ @Override
+ public boolean containsNode(Bytes address) {
+ return nodeSignatures.containsKey(address);
+ }
+
+ @Override
+ public DigitalSignature getEndpointSignature(Bytes address) {
+ return endpointSignatures.get(address).getSignature();
+ }
+
+ @Override
+ public DigitalSignature getNodeSignature(Bytes address) {
+ return nodeSignatures.get(address).getSignature();
+ }
+
+ @Override
+ public HashDigest getHash() {
+ return request.getHash();
+ }
+
+ @Override
+ public DigitalSignature[] getNodeSignatures() {
+ return request.getNodeSignatures();
+ }
+
+ @Override
+ public DigitalSignature[] getEndpointSignatures() {
+ return request.getEndpointSignatures();
+ }
+
+ @Override
+ public TransactionContent getTransactionContent() {
+ return request.getTransactionContent();
+ }
+
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionSet.java
index 962244e5..24cb6416 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionSet.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionSet.java
@@ -6,6 +6,7 @@ import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.LedgerTransaction;
+import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage;
@@ -153,6 +154,10 @@ public class TransactionSet implements Transactional, MerkleProvable {
public boolean isReadonly() {
return txSet.isReadonly();
}
+
+ void setReadonly() {
+ txSet.setReadonly();
+ }
@Override
public boolean isUpdated() {
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionStagedSnapshot.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionStagedSnapshot.java
similarity index 96%
rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionStagedSnapshot.java
rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionStagedSnapshot.java
index 14d8e8a4..cee5487f 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionStagedSnapshot.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionStagedSnapshot.java
@@ -1,4 +1,4 @@
-package com.jd.blockchain.ledger.core.impl;
+package com.jd.blockchain.ledger.core;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.LedgerDataSnapshot;
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccountQuery.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccountQuery.java
new file mode 100644
index 00000000..3d920b5c
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccountQuery.java
@@ -0,0 +1,31 @@
+package com.jd.blockchain.ledger.core;
+
+import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.ledger.AccountHeader;
+import com.jd.blockchain.ledger.MerkleProof;
+import com.jd.blockchain.utils.Bytes;
+
+public interface UserAccountQuery {
+
+ AccountHeader[] getAccounts(int fromIndex, int count);
+
+ /**
+ * 返回用户总数;
+ *
+ * @return
+ */
+ long getTotalCount();
+
+ HashDigest getRootHash();
+
+ MerkleProof getProof(Bytes key);
+
+ UserAccount getUser(String address);
+
+ UserAccount getUser(Bytes address);
+
+ boolean contains(Bytes address);
+
+ UserAccount getUser(Bytes address, long version);
+
+}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccountSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccountSet.java
index d28c15ed..f1e8bbc3 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccountSet.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccountSet.java
@@ -5,6 +5,7 @@ import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
+import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes;
@@ -14,7 +15,7 @@ import com.jd.blockchain.utils.Transactional;
* @author huanghaiquan
*
*/
-public class UserAccountSet implements Transactional, MerkleProvable {
+public class UserAccountSet implements Transactional, MerkleProvable, UserAccountQuery {
private AccountSet accountSet;
@@ -30,6 +31,7 @@ public class UserAccountSet implements Transactional, MerkleProvable {
accessPolicy);
}
+ @Override
public AccountHeader[] getAccounts(int fromIndex, int count) {
return accountSet.getAccounts(fromIndex,count);
}
@@ -39,6 +41,7 @@ public class UserAccountSet implements Transactional, MerkleProvable {
*
* @return
*/
+ @Override
public long getTotalCount() {
return accountSet.getTotalCount();
}
@@ -46,6 +49,10 @@ public class UserAccountSet implements Transactional, MerkleProvable {
public boolean isReadonly() {
return accountSet.isReadonly();
}
+
+ void setReadonly() {
+ accountSet.setReadonly();
+ }
@Override
public HashDigest getRootHash() {
@@ -57,19 +64,23 @@ public class UserAccountSet implements Transactional, MerkleProvable {
return accountSet.getProof(key);
}
+ @Override
public UserAccount getUser(String address) {
return getUser(Bytes.fromBase58(address));
}
+ @Override
public UserAccount getUser(Bytes address) {
BaseAccount baseAccount = accountSet.getAccount(address);
return new UserAccount(baseAccount);
}
+ @Override
public boolean contains(Bytes address) {
return accountSet.contains(address);
}
+ @Override
public UserAccount getUser(Bytes address, long version) {
BaseAccount baseAccount = accountSet.getAccount(address, version);
return new UserAccount(baseAccount);
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRoleDataset.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRoleDataset.java
new file mode 100644
index 00000000..2f4eb514
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRoleDataset.java
@@ -0,0 +1,196 @@
+package com.jd.blockchain.ledger.core;
+
+import java.util.Collection;
+
+import com.jd.blockchain.binaryproto.BinaryProtocol;
+import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.ledger.AuthorizationException;
+import com.jd.blockchain.ledger.CryptoSetting;
+import com.jd.blockchain.ledger.LedgerException;
+import com.jd.blockchain.ledger.MerkleProof;
+import com.jd.blockchain.ledger.RoleSet;
+import com.jd.blockchain.ledger.RolesPolicy;
+import com.jd.blockchain.ledger.UserRoles;
+import com.jd.blockchain.ledger.UserRolesSettings;
+import com.jd.blockchain.storage.service.ExPolicyKVStorage;
+import com.jd.blockchain.storage.service.VersioningKVEntry;
+import com.jd.blockchain.storage.service.VersioningKVStorage;
+import com.jd.blockchain.utils.Bytes;
+import com.jd.blockchain.utils.Transactional;
+
+/**
+ * User-Role authorization data set;
+ *
+ * @author huanghaiquan
+ *
+ */
+public class UserRoleDataset implements Transactional, MerkleProvable, UserRolesSettings {
+
+ private MerkleDataSet dataset;
+
+ public UserRoleDataset(CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exPolicyStorage,
+ VersioningKVStorage verStorage) {
+ dataset = new MerkleDataSet(cryptoSetting, prefix, exPolicyStorage, verStorage);
+ }
+
+ public UserRoleDataset(HashDigest merkleRootHash, CryptoSetting cryptoSetting, String prefix,
+ ExPolicyKVStorage exPolicyStorage, VersioningKVStorage verStorage, boolean readonly) {
+ dataset = new MerkleDataSet(merkleRootHash, cryptoSetting, prefix, exPolicyStorage, verStorage, readonly);
+ }
+
+ @Override
+ public HashDigest getRootHash() {
+ return dataset.getRootHash();
+ }
+
+ @Override
+ public MerkleProof getProof(Bytes key) {
+ return dataset.getProof(key);
+ }
+
+ @Override
+ public boolean isUpdated() {
+ return dataset.isUpdated();
+ }
+
+ @Override
+ public void commit() {
+ dataset.commit();
+ }
+
+ @Override
+ public void cancel() {
+ dataset.cancel();
+ }
+
+ @Override
+ public long getUserCount() {
+ return dataset.getDataCount();
+ }
+
+ /**
+ * 加入新的用户角色授权;
+ *
+ * 如果该用户的授权已经存在,则引发 {@link LedgerException} 异常;
+ *
+ * @param userAddress
+ * @param rolesPolicy
+ * @param roles
+ */
+ @Override
+ public void addUserRoles(Bytes userAddress, RolesPolicy rolesPolicy, String... roles) {
+ UserRoles roleAuth = new UserRoles(userAddress, -1, rolesPolicy);
+ roleAuth.addRoles(roles);
+ long nv = setUserRolesAuthorization(roleAuth);
+ if (nv < 0) {
+ throw new AuthorizationException("Roles authorization of User[" + userAddress + "] already exists!");
+ }
+ }
+
+ /**
+ * 加入新的用户角色授权;
+ *
+ * 如果该用户的授权已经存在,则引发 {@link LedgerException} 异常;
+ *
+ * @param userAddress
+ * @param rolesPolicy
+ * @param roles
+ */
+ @Override
+ public void addUserRoles(Bytes userAddress, RolesPolicy rolesPolicy, Collection roles) {
+ UserRoles roleAuth = new UserRoles(userAddress, -1, rolesPolicy);
+ roleAuth.addRoles(roles);
+ long nv = setUserRolesAuthorization(roleAuth);
+ if (nv < 0) {
+ throw new AuthorizationException("Roles authorization of User[" + userAddress + "] already exists!");
+ }
+ }
+
+ /**
+ * 设置用户角色授权;
+ * 如果版本校验不匹配,则返回 -1;
+ *
+ * @param userRoles
+ * @return
+ */
+ private long setUserRolesAuthorization(UserRoles userRoles) {
+ if (userRoles.getRoleCount() > MAX_ROLES_PER_USER) {
+ throw new AuthorizationException("The number of roles exceeds the maximum range!");
+ }
+ byte[] rolesetBytes = BinaryProtocol.encode(userRoles, RoleSet.class);
+ return dataset.setValue(userRoles.getUserAddress(), rolesetBytes, userRoles.getVersion());
+ }
+
+ /**
+ * 更新用户角色授权;
+ * 如果指定用户的授权不存在,或者版本不匹配,则引发 {@link LedgerException} 异常;
+ *
+ * @param userRoles
+ */
+ @Override
+ public void updateUserRoles(UserRoles userRoles) {
+ long nv = setUserRolesAuthorization(userRoles);
+ if (nv < 0) {
+ throw new AuthorizationException("Update to roles of user[" + userRoles.getUserAddress()
+ + "] failed due to wrong version[" + userRoles.getVersion() + "] !");
+ }
+ }
+
+ /**
+ * 设置用户的角色;
+ * 如果用户的角色授权不存在,则创建新的授权;
+ *
+ * @param userAddress 用户;
+ * @param policy 角色策略;
+ * @param roles 角色列表;
+ * @return
+ */
+ @Override
+ public long setRoles(Bytes userAddress, RolesPolicy policy, String... roles) {
+ UserRoles userRoles = getUserRoles(userAddress);
+ if (userRoles == null) {
+ userRoles = new UserRoles(userAddress, -1, policy);
+ }
+ userRoles.setPolicy(policy);
+ userRoles.setRoles(roles);
+ return setUserRolesAuthorization(userRoles);
+ }
+
+ /**
+ * 查询角色授权;
+ *
+ *
+ * 如果不存在,则返回 null;
+ *
+ * @param address
+ * @return
+ */
+ @Override
+ public UserRoles getUserRoles(Bytes userAddress) {
+ // 只返回最新版本;
+ VersioningKVEntry kv = dataset.getDataEntry(userAddress);
+ if (kv == null) {
+ return null;
+ }
+ RoleSet roleSet = BinaryProtocol.decode(kv.getValue());
+ return new UserRoles(userAddress, kv.getVersion(), roleSet);
+ }
+
+ @Override
+ public UserRoles[] getUserRoles() {
+ VersioningKVEntry[] kvEntries = dataset.getLatestDataEntries(0, (int) dataset.getDataCount());
+ UserRoles[] pns = new UserRoles[kvEntries.length];
+ RoleSet roleset;
+ for (int i = 0; i < pns.length; i++) {
+ roleset = BinaryProtocol.decode(kvEntries[i].getValue());
+ pns[i] = new UserRoles(kvEntries[i].getKey(), kvEntries[i].getVersion(), roleset);
+ }
+ return pns;
+ }
+
+ @Override
+ public boolean isReadonly() {
+ return dataset.isReadonly();
+ }
+
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRolesPrivileges.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRolesPrivileges.java
new file mode 100644
index 00000000..4a626c70
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRolesPrivileges.java
@@ -0,0 +1,63 @@
+package com.jd.blockchain.ledger.core;
+
+import java.util.Collection;
+
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.LedgerPrivilege;
+import com.jd.blockchain.ledger.PrivilegeBitset;
+import com.jd.blockchain.ledger.RolePrivileges;
+import com.jd.blockchain.ledger.RolesPolicy;
+import com.jd.blockchain.ledger.TransactionPermission;
+import com.jd.blockchain.ledger.TransactionPrivilege;
+import com.jd.blockchain.utils.Bytes;
+
+/**
+ * {@link UserRolesPrivileges} 表示多角色用户的综合权限;
+ *
+ * @author huanghaiquan
+ *
+ */
+class UserRolesPrivileges {
+
+ private Bytes userAddress;
+
+ private PrivilegeBitset ledgerPrivileges;
+
+ private PrivilegeBitset transactionPrivileges;
+
+ public UserRolesPrivileges(Bytes userAddress, RolesPolicy policy, Collection privilegesList) {
+ this.userAddress = userAddress;
+ LedgerPrivilege[] ledgerPrivileges = privilegesList.stream().map(p -> p.getLedgerPrivilege())
+ .toArray(LedgerPrivilege[]::new);
+ TransactionPrivilege[] transactionPrivileges = privilegesList.stream().map(p -> p.getTransactionPrivilege())
+ .toArray(TransactionPrivilege[]::new);
+
+ this.ledgerPrivileges = ledgerPrivileges[0].clone();
+ this.transactionPrivileges = transactionPrivileges[0].clone();
+
+ if (policy == RolesPolicy.UNION) {
+ this.ledgerPrivileges.union(ledgerPrivileges, 1, ledgerPrivileges.length - 1);
+ this.transactionPrivileges.union(transactionPrivileges, 1, transactionPrivileges.length - 1);
+
+ } else if (policy == RolesPolicy.INTERSECT) {
+ this.ledgerPrivileges.intersect(ledgerPrivileges, 1, ledgerPrivileges.length - 1);
+ this.transactionPrivileges.intersect(transactionPrivileges, 1, transactionPrivileges.length - 1);
+ } else {
+ throw new IllegalStateException("Unsupported roles policy[" + policy.toString() + "]!");
+ }
+
+ }
+
+ public Bytes getUserAddress() {
+ return userAddress;
+ }
+
+ public PrivilegeBitset getLedgerPrivileges() {
+ return ledgerPrivileges;
+ }
+
+ public PrivilegeBitset getTransactionPrivileges() {
+ return transactionPrivileges;
+ }
+
+}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/AbstractLedgerOperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/AbstractLedgerOperationHandle.java
new file mode 100644
index 00000000..36a2a0ae
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/AbstractLedgerOperationHandle.java
@@ -0,0 +1,73 @@
+package com.jd.blockchain.ledger.core.handles;
+
+import com.jd.blockchain.binaryproto.DataContractRegistry;
+import com.jd.blockchain.ledger.BytesValue;
+import com.jd.blockchain.ledger.Operation;
+import com.jd.blockchain.ledger.TransactionPermission;
+import com.jd.blockchain.ledger.core.LedgerDataQuery;
+import com.jd.blockchain.ledger.core.LedgerDataset;
+import com.jd.blockchain.ledger.core.LedgerService;
+import com.jd.blockchain.ledger.core.MultiIDsPolicy;
+import com.jd.blockchain.ledger.core.OperationHandle;
+import com.jd.blockchain.ledger.core.OperationHandleContext;
+import com.jd.blockchain.ledger.core.SecurityContext;
+import com.jd.blockchain.ledger.core.SecurityPolicy;
+import com.jd.blockchain.ledger.core.TransactionRequestExtension;
+
+/**
+ * 执行直接账本操作的处理类;
+ *
+ * @author huanghaiquan
+ *
+ * @param
+ */
+public abstract class AbstractLedgerOperationHandle implements OperationHandle {
+
+ static {
+ DataContractRegistry.register(BytesValue.class);
+ }
+
+ private final Class SUPPORTED_OPERATION_TYPE;
+
+ public AbstractLedgerOperationHandle(Class supportedOperationType) {
+ this.SUPPORTED_OPERATION_TYPE = supportedOperationType;
+ }
+
+// @Override
+// public final boolean support(Class> operationType) {
+// return SUPPORTED_OPERATION_TYPE.isAssignableFrom(operationType);
+// }
+
+ @Override
+ public Class> getOperationType() {
+ return SUPPORTED_OPERATION_TYPE;
+ }
+
+ @Override
+ public final BytesValue process(Operation op, LedgerDataset newBlockDataset,
+ TransactionRequestExtension requestContext, LedgerDataQuery previousBlockDataset,
+ OperationHandleContext handleContext, LedgerService ledgerService) {
+ // 权限校验;
+ SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy();
+ securityPolicy.checkEndpointPermission(TransactionPermission.DIRECT_OPERATION, MultiIDsPolicy.AT_LEAST_ONE);
+
+ // 操作账本;
+ @SuppressWarnings("unchecked")
+ T concretedOp = (T) op;
+ doProcess(concretedOp, newBlockDataset, requestContext, previousBlockDataset, handleContext, ledgerService);
+
+ // 账本操作没有返回值;
+ return null;
+ }
+
+ /**
+ * @param op
+ * @param newBlockDataset
+ * @param requestContext
+ * @param previousBlockDataset
+ * @param handleContext
+ * @param ledgerService
+ */
+ protected abstract void doProcess(T op, LedgerDataset newBlockDataset, TransactionRequestExtension requestContext,
+ LedgerDataQuery previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService);
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/AbstractContractEventHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/AbtractContractEventSendOperationHandle.java
similarity index 54%
rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/AbstractContractEventHandle.java
rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/AbtractContractEventSendOperationHandle.java
index 0b2189ae..af1d95b4 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/AbstractContractEventHandle.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/AbtractContractEventSendOperationHandle.java
@@ -1,4 +1,4 @@
-package com.jd.blockchain.ledger.core.impl.handles;
+package com.jd.blockchain.ledger.core.handles;
import org.springframework.stereotype.Service;
@@ -8,30 +8,48 @@ import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.ContractEventSendOperation;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.Operation;
+import com.jd.blockchain.ledger.TransactionPermission;
import com.jd.blockchain.ledger.core.ContractAccount;
-import com.jd.blockchain.ledger.core.ContractAccountSet;
-import com.jd.blockchain.ledger.core.LedgerDataSet;
+import com.jd.blockchain.ledger.core.ContractAccountQuery;
+import com.jd.blockchain.ledger.core.LedgerDataQuery;
+import com.jd.blockchain.ledger.core.LedgerDataset;
+import com.jd.blockchain.ledger.core.LedgerQueryService;
import com.jd.blockchain.ledger.core.LedgerService;
+import com.jd.blockchain.ledger.core.MultiIDsPolicy;
import com.jd.blockchain.ledger.core.OperationHandle;
-import com.jd.blockchain.ledger.core.TransactionRequestContext;
-import com.jd.blockchain.ledger.core.impl.LedgerQueryService;
-import com.jd.blockchain.ledger.core.impl.OperationHandleContext;
+import com.jd.blockchain.ledger.core.OperationHandleContext;
+import com.jd.blockchain.ledger.core.SecurityContext;
+import com.jd.blockchain.ledger.core.SecurityPolicy;
+import com.jd.blockchain.ledger.core.TransactionRequestExtension;
@Service
-public abstract class AbstractContractEventHandle implements OperationHandle {
-
+public abstract class AbtractContractEventSendOperationHandle implements OperationHandle {
+
@Override
- public boolean support(Class> operationType) {
- return ContractEventSendOperation.class.isAssignableFrom(operationType);
+ public Class> getOperationType() {
+ return ContractEventSendOperation.class;
}
@Override
- public BytesValue process(Operation op, LedgerDataSet dataset, TransactionRequestContext requestContext,
- LedgerDataSet previousBlockDataset, OperationHandleContext opHandleContext, LedgerService ledgerService) {
+ public BytesValue process(Operation op, LedgerDataset newBlockDataset, TransactionRequestExtension requestContext,
+ LedgerDataQuery previousBlockDataset, OperationHandleContext opHandleContext, LedgerService ledgerService) {
+ // 权限校验;
+ SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy();
+ securityPolicy.checkEndpointPermission(TransactionPermission.CONTRACT_OPERATION, MultiIDsPolicy.AT_LEAST_ONE);
+
+ // 操作账本;
ContractEventSendOperation contractOP = (ContractEventSendOperation) op;
+
+ return doProcess(requestContext, contractOP, newBlockDataset, previousBlockDataset, opHandleContext,
+ ledgerService);
+ }
+
+ private BytesValue doProcess(TransactionRequestExtension request, ContractEventSendOperation contractOP,
+ LedgerDataset newBlockDataset, LedgerDataQuery previousBlockDataset, OperationHandleContext opHandleContext,
+ LedgerService ledgerService) {
// 先从账本校验合约的有效性;
// 注意:必须在前一个区块的数据集中进行校验,因为那是经过共识的数据;从当前新区块链数据集校验则会带来攻击风险:未经共识的合约得到执行;
- ContractAccountSet contractSet = previousBlockDataset.getContractAccountSet();
+ ContractAccountQuery contractSet = previousBlockDataset.getContractAccountset();
if (!contractSet.contains(contractOP.getContractAddress())) {
throw new LedgerException(String.format("Contract was not registered! --[ContractAddress=%s]",
contractOP.getContractAddress()));
@@ -50,19 +68,17 @@ public abstract class AbstractContractEventHandle implements OperationHandle {
// 创建合约上下文;
LocalContractEventContext localContractEventContext = new LocalContractEventContext(
- requestContext.getRequest().getTransactionContent().getLedgerHash(), contractOP.getEvent());
- localContractEventContext.setArgs(contractOP.getArgs()).setTransactionRequest(requestContext.getRequest())
+ request.getTransactionContent().getLedgerHash(), contractOP.getEvent());
+ localContractEventContext.setArgs(contractOP.getArgs()).setTransactionRequest(request)
.setLedgerContext(ledgerContext);
-
// 装载合约;
ContractCode contractCode = loadContractCode(contract);
// 处理合约事件;
return contractCode.processEvent(localContractEventContext);
}
-
- protected abstract ContractCode loadContractCode(ContractAccount contract);
+ protected abstract ContractCode loadContractCode(ContractAccount contract);
}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ContractCodeDeployOperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ContractCodeDeployOperationHandle.java
new file mode 100644
index 00000000..8835fcb0
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ContractCodeDeployOperationHandle.java
@@ -0,0 +1,45 @@
+package com.jd.blockchain.ledger.core.handles;
+
+import com.jd.blockchain.contract.ContractJarUtils;
+import com.jd.blockchain.ledger.ContractCodeDeployOperation;
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.core.LedgerDataQuery;
+import com.jd.blockchain.ledger.core.LedgerDataset;
+import com.jd.blockchain.ledger.core.LedgerService;
+import com.jd.blockchain.ledger.core.MultiIDsPolicy;
+import com.jd.blockchain.ledger.core.OperationHandleContext;
+import com.jd.blockchain.ledger.core.SecurityContext;
+import com.jd.blockchain.ledger.core.SecurityPolicy;
+import com.jd.blockchain.ledger.core.TransactionRequestExtension;
+
+public class ContractCodeDeployOperationHandle extends AbstractLedgerOperationHandle {
+
+ public ContractCodeDeployOperationHandle() {
+ super(ContractCodeDeployOperation.class);
+ }
+
+ @Override
+ protected void doProcess(ContractCodeDeployOperation op, LedgerDataset newBlockDataset,
+ TransactionRequestExtension requestContext, LedgerDataQuery previousBlockDataset,
+ OperationHandleContext handleContext, LedgerService ledgerService) {
+
+ // TODO: 请求者应该提供合约账户的公钥签名,以确保注册人对注册的地址和公钥具有合法的使用权;
+
+ // 权限校验;
+ SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy();
+ securityPolicy.checkEndpointPermission(LedgerPermission.UPGRADE_CONTRACT, MultiIDsPolicy.AT_LEAST_ONE);
+
+ // 操作账本;
+ ContractCodeDeployOperation contractOP = op;
+
+ // 校验合约内容
+ byte[] chainCode = contractOP.getChainCode();
+
+ // 校验合约代码,不通过会抛出异常
+ ContractJarUtils.verify(chainCode);
+
+ newBlockDataset.getContractAccountset().deploy(contractOP.getContractID().getAddress(),
+ contractOP.getContractID().getPubKey(), contractOP.getAddressSignature(), contractOP.getChainCode());
+ }
+
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractLedgerContext.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ContractLedgerContext.java
similarity index 97%
rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractLedgerContext.java
rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ContractLedgerContext.java
index 5a673722..0d0d3c3d 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractLedgerContext.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ContractLedgerContext.java
@@ -1,4 +1,4 @@
-package com.jd.blockchain.ledger.core.impl.handles;
+package com.jd.blockchain.ledger.core.handles;
import java.util.ArrayList;
import java.util.List;
@@ -6,7 +6,7 @@ import java.util.List;
import com.jd.blockchain.contract.LedgerContext;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.*;
-import com.jd.blockchain.ledger.core.impl.OperationHandleContext;
+import com.jd.blockchain.ledger.core.OperationHandleContext;
import com.jd.blockchain.transaction.BlockchainQueryService;
import com.jd.blockchain.transaction.DataAccountKVSetOperationBuilder;
import com.jd.blockchain.transaction.DataAccountRegisterOperationBuilder;
@@ -38,6 +38,11 @@ public class ContractLedgerContext implements LedgerContext {
public LedgerInfo getLedger(HashDigest ledgerHash) {
return innerQueryService.getLedger(ledgerHash);
}
+
+ @Override
+ public LedgerAdminInfo getLedgerAdminInfo(HashDigest ledgerHash) {
+ return innerQueryService.getLedgerAdminInfo(ledgerHash);
+ }
@Override
public ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash) {
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/DataAccountKVSetOperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/DataAccountKVSetOperationHandle.java
new file mode 100644
index 00000000..19a18cb3
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/DataAccountKVSetOperationHandle.java
@@ -0,0 +1,48 @@
+package com.jd.blockchain.ledger.core.handles;
+
+import com.jd.blockchain.ledger.DataAccountDoesNotExistException;
+import com.jd.blockchain.ledger.DataAccountKVSetOperation;
+import com.jd.blockchain.ledger.DataAccountKVSetOperation.KVWriteEntry;
+import com.jd.blockchain.ledger.DataVersionConflictException;
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.core.DataAccount;
+import com.jd.blockchain.ledger.core.LedgerDataQuery;
+import com.jd.blockchain.ledger.core.LedgerDataset;
+import com.jd.blockchain.ledger.core.LedgerService;
+import com.jd.blockchain.ledger.core.MultiIDsPolicy;
+import com.jd.blockchain.ledger.core.OperationHandleContext;
+import com.jd.blockchain.ledger.core.SecurityContext;
+import com.jd.blockchain.ledger.core.SecurityPolicy;
+import com.jd.blockchain.ledger.core.TransactionRequestExtension;
+import com.jd.blockchain.utils.Bytes;
+
+public class DataAccountKVSetOperationHandle extends AbstractLedgerOperationHandle {
+
+ public DataAccountKVSetOperationHandle() {
+ super(DataAccountKVSetOperation.class);
+ }
+
+ @Override
+ protected void doProcess(DataAccountKVSetOperation kvWriteOp, LedgerDataset newBlockDataset,
+ TransactionRequestExtension requestContext, LedgerDataQuery previousBlockDataset,
+ OperationHandleContext handleContext, LedgerService ledgerService) {
+ // 权限校验;
+ SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy();
+ securityPolicy.checkEndpointPermission(LedgerPermission.WRITE_DATA_ACCOUNT, MultiIDsPolicy.AT_LEAST_ONE);
+
+ // 操作账本;
+ DataAccount account = newBlockDataset.getDataAccountSet().getDataAccount(kvWriteOp.getAccountAddress());
+ if (account == null) {
+ throw new DataAccountDoesNotExistException("DataAccount doesn't exist!");
+ }
+ KVWriteEntry[] writeSet = kvWriteOp.getWriteSet();
+ long v = -1;
+ for (KVWriteEntry kvw : writeSet) {
+ v = account.setBytes(Bytes.fromString(kvw.getKey()), kvw.getValue(), kvw.getExpectedVersion());
+ if (v < 0) {
+ throw new DataVersionConflictException();
+ }
+ }
+ }
+
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/DataAccountRegisterOperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/DataAccountRegisterOperationHandle.java
new file mode 100644
index 00000000..de2264e9
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/DataAccountRegisterOperationHandle.java
@@ -0,0 +1,37 @@
+package com.jd.blockchain.ledger.core.handles;
+
+import com.jd.blockchain.ledger.BlockchainIdentity;
+import com.jd.blockchain.ledger.DataAccountRegisterOperation;
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.core.LedgerDataQuery;
+import com.jd.blockchain.ledger.core.LedgerDataset;
+import com.jd.blockchain.ledger.core.LedgerService;
+import com.jd.blockchain.ledger.core.MultiIDsPolicy;
+import com.jd.blockchain.ledger.core.OperationHandleContext;
+import com.jd.blockchain.ledger.core.SecurityContext;
+import com.jd.blockchain.ledger.core.SecurityPolicy;
+import com.jd.blockchain.ledger.core.TransactionRequestExtension;
+
+public class DataAccountRegisterOperationHandle extends AbstractLedgerOperationHandle {
+
+ public DataAccountRegisterOperationHandle() {
+ super(DataAccountRegisterOperation.class);
+ }
+
+ @Override
+ protected void doProcess(DataAccountRegisterOperation op, LedgerDataset newBlockDataset,
+ TransactionRequestExtension requestContext, LedgerDataQuery previousBlockDataset,
+ OperationHandleContext handleContext, LedgerService ledgerService) {
+ // TODO: 请求者应该提供数据账户的公钥签名,以更好地确保注册人对该地址和公钥具有合法使用权;
+
+ // 权限校验;
+ SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy();
+ securityPolicy.checkEndpointPermission(LedgerPermission.REGISTER_DATA_ACCOUNT, MultiIDsPolicy.AT_LEAST_ONE);
+
+ // 操作账本;
+ DataAccountRegisterOperation dataAccountRegOp = (DataAccountRegisterOperation) op;
+ BlockchainIdentity bid = dataAccountRegOp.getAccountID();
+ newBlockDataset.getDataAccountSet().register(bid.getAddress(), bid.getPubKey(), null);
+ }
+
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/JVMContractEventSendOperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/JVMContractEventSendOperationHandle.java
similarity index 89%
rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/JVMContractEventSendOperationHandle.java
rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/JVMContractEventSendOperationHandle.java
index b05e2189..b153320e 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/JVMContractEventSendOperationHandle.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/JVMContractEventSendOperationHandle.java
@@ -1,4 +1,6 @@
-package com.jd.blockchain.ledger.core.impl.handles;
+package com.jd.blockchain.ledger.core.handles;
+
+import static com.jd.blockchain.utils.BaseConstant.CONTRACT_SERVICE_PROVIDER;
import com.jd.blockchain.contract.engine.ContractCode;
import com.jd.blockchain.contract.engine.ContractEngine;
@@ -8,9 +10,7 @@ import com.jd.blockchain.ledger.core.ContractAccount;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
-import static com.jd.blockchain.utils.BaseConstant.CONTRACT_SERVICE_PROVIDER;
-
-public class JVMContractEventSendOperationHandle extends AbstractContractEventHandle {
+public class JVMContractEventSendOperationHandle extends AbtractContractEventSendOperationHandle {
private static final ContractEngine JVM_ENGINE;
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/LedgerInitOperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/LedgerInitOperationHandle.java
new file mode 100644
index 00000000..39862be0
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/LedgerInitOperationHandle.java
@@ -0,0 +1,27 @@
+package com.jd.blockchain.ledger.core.handles;
+
+import com.jd.blockchain.ledger.BytesValue;
+import com.jd.blockchain.ledger.LedgerInitOperation;
+import com.jd.blockchain.ledger.Operation;
+import com.jd.blockchain.ledger.core.LedgerDataQuery;
+import com.jd.blockchain.ledger.core.LedgerDataset;
+import com.jd.blockchain.ledger.core.LedgerService;
+import com.jd.blockchain.ledger.core.OperationHandle;
+import com.jd.blockchain.ledger.core.OperationHandleContext;
+import com.jd.blockchain.ledger.core.TransactionRequestExtension;
+
+public class LedgerInitOperationHandle implements OperationHandle {
+
+ @Override
+ public Class> getOperationType() {
+ return LedgerInitOperation.class;
+ }
+
+ @Override
+ public BytesValue process(Operation op, LedgerDataset newBlockDataset, TransactionRequestExtension requestContext,
+ LedgerDataQuery previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) {
+ // 对初始化操作不需要做任何处理;
+ return null;
+ }
+
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/RolesConfigureOperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/RolesConfigureOperationHandle.java
new file mode 100644
index 00000000..171a4f7d
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/RolesConfigureOperationHandle.java
@@ -0,0 +1,51 @@
+package com.jd.blockchain.ledger.core.handles;
+
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.RolePrivilegeSettings;
+import com.jd.blockchain.ledger.RolePrivileges;
+import com.jd.blockchain.ledger.RolesConfigureOperation;
+import com.jd.blockchain.ledger.RolesConfigureOperation.RolePrivilegeEntry;
+import com.jd.blockchain.ledger.core.LedgerDataQuery;
+import com.jd.blockchain.ledger.core.LedgerDataset;
+import com.jd.blockchain.ledger.core.LedgerService;
+import com.jd.blockchain.ledger.core.MultiIDsPolicy;
+import com.jd.blockchain.ledger.core.OperationHandleContext;
+import com.jd.blockchain.ledger.core.SecurityContext;
+import com.jd.blockchain.ledger.core.SecurityPolicy;
+import com.jd.blockchain.ledger.core.TransactionRequestExtension;
+
+public class RolesConfigureOperationHandle extends AbstractLedgerOperationHandle {
+
+ public RolesConfigureOperationHandle() {
+ super(RolesConfigureOperation.class);
+ }
+
+ @Override
+ protected void doProcess(RolesConfigureOperation operation, LedgerDataset newBlockDataset,
+ TransactionRequestExtension request, LedgerDataQuery previousBlockDataset,
+ OperationHandleContext handleContext, LedgerService ledgerService) {
+ // 权限校验;
+ SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy();
+ securityPolicy.checkEndpointPermission(LedgerPermission.CONFIGURE_ROLES, MultiIDsPolicy.AT_LEAST_ONE);
+
+ // 操作账本;
+ RolePrivilegeEntry[] rpcfgs = operation.getRoles();
+ RolePrivilegeSettings rpSettings = newBlockDataset.getAdminDataset().getRolePrivileges();
+ if (rpcfgs != null) {
+ for (RolePrivilegeEntry rpcfg : rpcfgs) {
+ RolePrivileges rp = rpSettings.getRolePrivilege(rpcfg.getRoleName());
+ if (rp == null) {
+ rpSettings.addRolePrivilege(rpcfg.getRoleName(), rpcfg.getEnableLedgerPermissions(),
+ rpcfg.getEnableTransactionPermissions());
+ } else {
+ rp.enable(rpcfg.getEnableLedgerPermissions());
+ rp.enable(rpcfg.getEnableTransactionPermissions());
+
+ rp.disable(rpcfg.getDisableLedgerPermissions());
+ rp.disable(rpcfg.getDisableTransactionPermissions());
+ }
+ }
+ }
+ }
+
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/UserAuthorizeOperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/UserAuthorizeOperationHandle.java
new file mode 100644
index 00000000..fb54702d
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/UserAuthorizeOperationHandle.java
@@ -0,0 +1,79 @@
+package com.jd.blockchain.ledger.core.handles;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.RolePrivilegeSettings;
+import com.jd.blockchain.ledger.RolesPolicy;
+import com.jd.blockchain.ledger.UserAuthorizeOperation;
+import com.jd.blockchain.ledger.UserAuthorizeOperation.UserRolesEntry;
+import com.jd.blockchain.ledger.UserRoles;
+import com.jd.blockchain.ledger.UserRolesSettings;
+import com.jd.blockchain.ledger.core.LedgerDataQuery;
+import com.jd.blockchain.ledger.core.LedgerDataset;
+import com.jd.blockchain.ledger.core.LedgerService;
+import com.jd.blockchain.ledger.core.MultiIDsPolicy;
+import com.jd.blockchain.ledger.core.OperationHandleContext;
+import com.jd.blockchain.ledger.core.SecurityContext;
+import com.jd.blockchain.ledger.core.SecurityPolicy;
+import com.jd.blockchain.ledger.core.TransactionRequestExtension;
+import com.jd.blockchain.utils.Bytes;
+
+public class UserAuthorizeOperationHandle extends AbstractLedgerOperationHandle {
+
+ public UserAuthorizeOperationHandle() {
+ super(UserAuthorizeOperation.class);
+ }
+
+ @Override
+ protected void doProcess(UserAuthorizeOperation operation, LedgerDataset newBlockDataset,
+ TransactionRequestExtension request, LedgerDataQuery previousBlockDataset,
+ OperationHandleContext handleContext, LedgerService ledgerService) {
+ // 权限校验;
+ SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy();
+ securityPolicy.checkEndpointPermission(LedgerPermission.CONFIGURE_ROLES, MultiIDsPolicy.AT_LEAST_ONE);
+
+ // 操作账本;
+
+ UserRolesEntry[] urcfgs = operation.getUserRolesAuthorizations();
+ UserRolesSettings urSettings = newBlockDataset.getAdminDataset().getUserRoles();
+ RolePrivilegeSettings rolesSettings = newBlockDataset.getAdminDataset().getRolePrivileges();
+ if (urcfgs != null) {
+ for (UserRolesEntry urcfg : urcfgs) {
+ //
+ String[] authRoles = urcfg.getAuthorizedRoles();
+ List validRoles = new ArrayList();
+ if (authRoles != null) {
+ for (String r : authRoles) {
+ if (rolesSettings.contains(r)) {
+ validRoles.add(r);
+ }
+ }
+ }
+ for (Bytes address : urcfg.getUserAddresses()) {
+ UserRoles ur = urSettings.getUserRoles(address);
+ if (ur == null) {
+ // 这是新的授权;
+ RolesPolicy policy = urcfg.getPolicy();
+ if (policy == null) {
+ policy = RolesPolicy.UNION;
+ }
+ urSettings.addUserRoles(address, policy, validRoles);
+ } else {
+ // 更改之前的授权;
+ ur.addRoles(validRoles);
+ ur.removeRoles(urcfg.getUnauthorizedRoles());
+
+ // 如果请求中设置了策略,才进行更新;
+ RolesPolicy policy = urcfg.getPolicy();
+ if (policy != null) {
+ ur.setPolicy(policy);
+ }
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/UserRegisterOperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/UserRegisterOperationHandle.java
new file mode 100644
index 00000000..be64802a
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/UserRegisterOperationHandle.java
@@ -0,0 +1,39 @@
+package com.jd.blockchain.ledger.core.handles;
+
+import com.jd.blockchain.ledger.BlockchainIdentity;
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.UserRegisterOperation;
+import com.jd.blockchain.ledger.core.LedgerDataQuery;
+import com.jd.blockchain.ledger.core.LedgerDataset;
+import com.jd.blockchain.ledger.core.LedgerService;
+import com.jd.blockchain.ledger.core.MultiIDsPolicy;
+import com.jd.blockchain.ledger.core.OperationHandleContext;
+import com.jd.blockchain.ledger.core.SecurityContext;
+import com.jd.blockchain.ledger.core.SecurityPolicy;
+import com.jd.blockchain.ledger.core.TransactionRequestExtension;
+import com.jd.blockchain.utils.Bytes;
+
+public class UserRegisterOperationHandle extends AbstractLedgerOperationHandle {
+
+ public UserRegisterOperationHandle() {
+ super(UserRegisterOperation.class);
+ }
+
+ @Override
+ protected void doProcess(UserRegisterOperation op, LedgerDataset newBlockDataset,
+ TransactionRequestExtension requestContext, LedgerDataQuery previousBlockDataset,
+ OperationHandleContext handleContext, LedgerService ledgerService) {
+ // 权限校验;
+ SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy();
+ securityPolicy.checkEndpointPermission(LedgerPermission.REGISTER_USER, MultiIDsPolicy.AT_LEAST_ONE);
+
+ // 操作账本;
+ UserRegisterOperation userRegOp = (UserRegisterOperation) op;
+ BlockchainIdentity bid = userRegOp.getUserID();
+
+ Bytes userAddress = bid.getAddress();
+
+ newBlockDataset.getUserAccountSet().register(userAddress, bid.getPubKey());
+ }
+
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/DefaultOperationHandleRegisteration.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/DefaultOperationHandleRegisteration.java
deleted file mode 100644
index 1966c716..00000000
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/DefaultOperationHandleRegisteration.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.jd.blockchain.ledger.core.impl;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.springframework.stereotype.Component;
-
-import com.jd.blockchain.ledger.LedgerException;
-import com.jd.blockchain.ledger.core.OperationHandle;
-import com.jd.blockchain.ledger.core.impl.handles.ContractCodeDeployOperationHandle;
-import com.jd.blockchain.ledger.core.impl.handles.JVMContractEventSendOperationHandle;
-import com.jd.blockchain.ledger.core.impl.handles.DataAccountKVSetOperationHandle;
-import com.jd.blockchain.ledger.core.impl.handles.DataAccountRegisterOperationHandle;
-import com.jd.blockchain.ledger.core.impl.handles.UserRegisterOperationHandle;
-
-@Component
-public class DefaultOperationHandleRegisteration implements OperationHandleRegisteration {
-
- private List opHandles = new ArrayList<>();
-
- public DefaultOperationHandleRegisteration() {
- initDefaultHandles();
- }
-
- /**
- * 针对不采用bean依赖注入的方式来处理;
- */
- private void initDefaultHandles() {
- opHandles.add(new DataAccountKVSetOperationHandle());
- opHandles.add(new DataAccountRegisterOperationHandle());
- opHandles.add(new UserRegisterOperationHandle());
- opHandles.add(new ContractCodeDeployOperationHandle());
- opHandles.add(new JVMContractEventSendOperationHandle());
- }
-
- /**
- * 以最高优先级插入一个操作处理器;
- *
- * @param handle
- */
- public void insertAsTopPriority(OperationHandle handle) {
- opHandles.remove(handle);
- opHandles.add(0, handle);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.jd.blockchain.ledger.core.impl.OperationHandleRegisteration#getHandle(
- * java.lang.Class)
- */
- @Override
- public OperationHandle getHandle(Class> operationType) {
- for (OperationHandle handle : opHandles) {
- if (handle.support(operationType)) {
- return handle;
- }
- }
- throw new LedgerException("Unsupported operation type[" + operationType.getName() + "]!");
- }
-
-}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionContextImpl.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionContextImpl.java
deleted file mode 100644
index c8c09d93..00000000
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionContextImpl.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.jd.blockchain.ledger.core.impl;
-
-import com.jd.blockchain.ledger.TransactionState;
-import com.jd.blockchain.ledger.LedgerTransaction;
-import com.jd.blockchain.ledger.TransactionRequest;
-import com.jd.blockchain.ledger.core.LedgerDataSet;
-import com.jd.blockchain.ledger.core.LedgerTransactionContext;
-import com.jd.blockchain.storage.service.utils.BufferedKVStorage;
-
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionalEditor.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionalEditor.java
deleted file mode 100644
index d939c865..00000000
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionalEditor.java
+++ /dev/null
@@ -1,462 +0,0 @@
-package com.jd.blockchain.ledger.core.impl;
-
-import java.util.List;
-import java.util.Stack;
-
-import com.jd.blockchain.binaryproto.BinaryProtocol;
-import com.jd.blockchain.crypto.Crypto;
-import com.jd.blockchain.crypto.HashDigest;
-import com.jd.blockchain.ledger.*;
-import com.jd.blockchain.ledger.core.LedgerDataSet;
-import com.jd.blockchain.ledger.core.LedgerEditor;
-import com.jd.blockchain.ledger.core.LedgerTransactionContext;
-import com.jd.blockchain.ledger.core.TransactionSet;
-import com.jd.blockchain.storage.service.ExPolicyKVStorage;
-import com.jd.blockchain.storage.service.VersioningKVStorage;
-import com.jd.blockchain.storage.service.utils.BufferedKVStorage;
-import com.jd.blockchain.utils.Bytes;
-import com.jd.blockchain.utils.codec.Base58Utils;
-
-public class LedgerTransactionalEditor implements LedgerEditor {
-
- private static final boolean PARALLEL_DB_WRITE;
-
- static {
- PARALLEL_DB_WRITE = Boolean.getBoolean("parallel-dbwrite");
- System.out.println("------ [[ parallel-dbwrite=" + PARALLEL_DB_WRITE + " ]] ------");
- }
-
- private final String ledgerKeyPrefix;
-
- private CryptoSetting cryptoSetting;
-
- private LedgerBlockData newlyBlock;
-
- private Stack stagedSnapshots = new Stack<>();
-
- private boolean prepared = false;
-
- private boolean canceled = false;
-
- private boolean committed = false;
-
- private BufferedKVStorage bufferedStorage;
-
- /**
- * 最近一个交易上下文;
- */
- private LedgerDataContext lastTxCtx;
-
- private LedgerDataContext newTxCtx;
-
- private LedgerTransactionalEditor(CryptoSetting cryptoSetting, LedgerBlockData newlyBlock,
- StagedSnapshot startingPoint, String ledgerKeyPrefix, BufferedKVStorage bufferedStorage) {
- this.ledgerKeyPrefix = ledgerKeyPrefix;
- this.cryptoSetting = cryptoSetting;
- this.newlyBlock = newlyBlock;
- this.bufferedStorage = bufferedStorage;
-
- this.stagedSnapshots.push(startingPoint);
- }
-
- public static LedgerTransactionalEditor createEditor(LedgerSetting ledgerSetting, LedgerBlock previousBlock,
- String ledgerKeyPrefix, ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage) {
- // new block;
- LedgerBlockData currBlock = new LedgerBlockData(previousBlock.getHeight() + 1, previousBlock.getLedgerHash(),
- previousBlock.getHash());
-
- // init storage;
- BufferedKVStorage txStagedStorage = new BufferedKVStorage(ledgerExStorage, ledgerVerStorage, PARALLEL_DB_WRITE);
-
- StagedSnapshot startingPoint = new TxSnapshot(previousBlock, previousBlock.getTransactionSetHash());
-
- // instantiate editor;
- return new LedgerTransactionalEditor(ledgerSetting.getCryptoSetting(), currBlock, startingPoint,
- ledgerKeyPrefix, txStagedStorage);
- }
-
- public static LedgerTransactionalEditor createEditor(LedgerInitSetting initSetting, String ledgerKeyPrefix,
- ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage) {
- LedgerBlockData genesisBlock = new LedgerBlockData(0, null, null);
- StagedSnapshot startingPoint = new GenesisSnapshot(initSetting);
- // init storage;
- BufferedKVStorage txStagedStorage = new BufferedKVStorage(ledgerExStorage, ledgerVerStorage, false);
- return new LedgerTransactionalEditor(initSetting.getCryptoSetting(), genesisBlock, startingPoint,
- ledgerKeyPrefix, txStagedStorage);
- }
-
- private void commitTxSnapshot(TxSnapshot snapshot) {
- lastTxCtx = newTxCtx;
- newTxCtx = null;
- stagedSnapshots.push(snapshot);
- }
-
- private void rollbackNewTx() {
- newTxCtx = null;
- }
-
- // public LedgerDataSet getLatestDataSet() {
- // if (lastTxCtx == null) {
- // return null;
- // }
- // return lastTxCtx.getDataSet();
- // }
-
- public LedgerBlock getNewlyBlock() {
- return newlyBlock;
- }
-
- @Override
- public LedgerTransactionContext newTransaction(TransactionRequest txRequest) {
- checkState();
- // TODO:验证交易签名;
-
- BufferedKVStorage txBuffStorage = null;
- LedgerDataSetImpl txDataset = null;
- TransactionSet txset = null;
- if (lastTxCtx == null) {
- // init storage of new transaction;
- // txBuffStorage = new BufferedKVStorage(bufferedStorage, bufferedStorage,
- // false);
- txBuffStorage = bufferedStorage;
-
- // load the starting point of the new transaction;
- StagedSnapshot previousSnapshot = stagedSnapshots.peek();
- if (previousSnapshot instanceof GenesisSnapshot) {
- // 准备生成创世区块;
- GenesisSnapshot snpht = (GenesisSnapshot) previousSnapshot;
- txDataset = LedgerRepositoryImpl.newDataSet(snpht.initSetting, ledgerKeyPrefix, txBuffStorage,
- txBuffStorage);
- txset = LedgerRepositoryImpl.newTransactionSet(txDataset.getAdminAccount().getSetting(),
- ledgerKeyPrefix, txBuffStorage, txBuffStorage);
- } else {
- // 新的区块;
- // TxSnapshot; reload dataset and txset;
- TxSnapshot snpht = (TxSnapshot) previousSnapshot;
- // load dataset;
- txDataset = LedgerRepositoryImpl.loadDataSet(snpht.dataSnapshot, ledgerKeyPrefix, txBuffStorage,
- txBuffStorage, false);
-
- // load tx set;
- txset = LedgerRepositoryImpl.loadTransactionSet(snpht.transactionSetHash, this.cryptoSetting,
- ledgerKeyPrefix, txBuffStorage, txBuffStorage, false);
- }
-
- lastTxCtx = new LedgerDataContext(txDataset, txset, txBuffStorage);
- } else {
- // Reuse previous object to optimize performance;
- txBuffStorage = lastTxCtx.storage;
- txDataset = lastTxCtx.dataset;
- txset = lastTxCtx.txset;
- }
-
- // newTxCtx = new LedgerTransactionContextImpl(newlyBlock.getHeight(),
- // txRequest, txDataset, txset, txBuffStorage,
- // this);
- // return newTxCtx;
-
- return new LedgerTransactionContextImpl(newlyBlock.getHeight(), txRequest, txDataset, txset, txBuffStorage,
- this);
- }
-
- @Override
- public LedgerBlock prepare() {
- checkState();
-
- if (newTxCtx != null) {
- throw new IllegalStateException("There is a opening transaction which isn't committed or rollbacked!");
- }
- if (lastTxCtx == null) {
- // Genesis;
- throw new IllegalStateException("No transaction to prepare!");
- }
-
- // do commit when transaction isolation level is BLOCK;
- lastTxCtx.dataset.commit();
- lastTxCtx.txset.commit();
-
- newlyBlock.setAdminAccountHash(lastTxCtx.dataset.getAdminAccount().getHash());
- newlyBlock.setContractAccountSetHash(lastTxCtx.dataset.getContractAccountSet().getRootHash());
- newlyBlock.setDataAccountSetHash(lastTxCtx.dataset.getDataAccountSet().getRootHash());
- newlyBlock.setUserAccountSetHash(lastTxCtx.dataset.getUserAccountSet().getRootHash());
- newlyBlock.setTransactionSetHash(lastTxCtx.txset.getRootHash());
-
- // compute block hash;
- byte[] blockBodyBytes = BinaryProtocol.encode(newlyBlock, BlockBody.class);
- HashDigest blockHash = Crypto.getHashFunction(cryptoSetting.getHashAlgorithm()).hash(blockBodyBytes);
- newlyBlock.setHash(blockHash);
- if (newlyBlock.getLedgerHash() == null) {
- // init GenesisBlock's ledger hash;
- newlyBlock.setLedgerHash(blockHash);
- }
-
- // persist block bytes;
- // only one version per block;
- byte[] blockBytes = BinaryProtocol.encode(newlyBlock, LedgerBlock.class);
- Bytes blockStorageKey = LedgerRepositoryImpl.encodeBlockStorageKey(newlyBlock.getHash());
- long v = bufferedStorage.set(blockStorageKey, blockBytes, -1);
- if (v < 0) {
- throw new IllegalStateException(
- "Block already exist! --[BlockHash=" + Base58Utils.encode(newlyBlock.getHash().toBytes()) + "]");
- }
-
- // persist block hash to ledger index;
- HashDigest ledgerHash = newlyBlock.getLedgerHash();
- Bytes ledgerIndexKey = LedgerRepositoryImpl.encodeLedgerIndexKey(ledgerHash);
- long expectedVersion = newlyBlock.getHeight() - 1;
- v = bufferedStorage.set(ledgerIndexKey, newlyBlock.getHash().toBytes(), expectedVersion);
- if (v < 0) {
- throw new IllegalStateException("Index of BlockHash already exist! --[BlockHash="
- + Base58Utils.encode(newlyBlock.getHash().toBytes()) + "]");
- }
-
- prepared = true;
- return newlyBlock;
- }
-
- @Override
- public void commit() {
- if (committed) {
- throw new IllegalStateException("LedgerEditor had been committed!");
- }
- if (canceled) {
- throw new IllegalStateException("LedgerEditor had been canceled!");
- }
- if (!prepared) {
- // 未就绪;
- throw new IllegalStateException("LedgerEditor has not prepared!");
- }
-
- bufferedStorage.flush();
-
- committed = true;
- }
-
- @Override
- public void cancel() {
- if (committed) {
- throw new IllegalStateException("LedgerEditor had been committed!");
- }
- if (canceled) {
- return;
- }
-
- canceled = true;
- // if (newTxCtx != null) {
- // newTxCtx.rollback();
- // newTxCtx = null;
- // }
- bufferedStorage.cancel();
- }
-
- private void checkState() {
- if (prepared) {
- throw new IllegalStateException("LedgerEditor has been prepared!");
- }
- if (committed) {
- throw new IllegalStateException("LedgerEditor has been committed!");
- }
- if (canceled) {
- throw new IllegalStateException("LedgerEditor has been canceled!");
- }
- }
-
- // --------------------------- inner type --------------------------
-
- private static interface StagedSnapshot {
-
- }
-
- private static class GenesisSnapshot implements StagedSnapshot {
-
- private LedgerInitSetting initSetting;
-
- public GenesisSnapshot(LedgerInitSetting initSetting) {
- this.initSetting = initSetting;
- }
- }
-
- private static class TxSnapshot implements StagedSnapshot {
-
- /**
- * 账本数据的快照;
- */
- private LedgerDataSnapshot dataSnapshot;
-
- /**
- * 交易集合的快照(根哈希);
- */
- private HashDigest transactionSetHash;
-
- public TxSnapshot(LedgerDataSnapshot dataSnapshot, HashDigest txSetHash) {
- this.dataSnapshot = dataSnapshot;
- this.transactionSetHash = txSetHash;
- }
-
- }
-
- private static class LedgerDataContext {
-
- protected LedgerDataSetImpl dataset;
-
- protected TransactionSet txset;
-
- protected BufferedKVStorage storage;
-
- public LedgerDataContext(LedgerDataSetImpl dataset, TransactionSet txset, BufferedKVStorage storage) {
- this.dataset = dataset;
- this.txset = txset;
- this.storage = storage;
- }
-
- }
-
- private static class LedgerTransactionContextImpl extends LedgerDataContext implements LedgerTransactionContext {
-
- private long blockHeight;
-
- private LedgerTransactionalEditor editor;
-
- private TransactionRequest txRequest;
-
- // private LedgerDataSetImpl dataset;
- //
- // private TransactionSet txset;
- //
- // private BufferedKVStorage storage;
-
- private boolean committed = false;
-
- private boolean rollbacked = false;
-
- private LedgerTransactionContextImpl(long blockHeight, TransactionRequest txRequest, LedgerDataSetImpl dataset,
- TransactionSet txset, BufferedKVStorage storage, LedgerTransactionalEditor editor) {
- super(dataset, txset, storage);
- this.txRequest = txRequest;
- // this.dataset = dataset;
- // this.txset = txset;
- // this.storage = storage;
- this.editor = editor;
- this.blockHeight = blockHeight;
- }
-
- @Override
- public LedgerDataSet getDataSet() {
- return dataset;
- }
-
- @Override
- public TransactionRequest getRequestTX() {
- return txRequest;
- }
-
- @Override
- public LedgerTransaction commit(TransactionState txResult) {
- return commit(txResult, null);
- }
-
- @Override
- public LedgerTransaction commit(TransactionState txResult, List operationResults) {
- checkTxState();
-
- // capture snapshot
- // this.dataset.commit();
- // TransactionStagedSnapshot txDataSnapshot = takeSnapshot();
-
- // LedgerTransactionData tx = new LedgerTransactionData(blockHeight, txRequest,
- // txResult, txDataSnapshot);
-
- LedgerTransactionData tx = new LedgerTransactionData(blockHeight, txRequest, txResult, null,
- operationResultArray(operationResults));
- this.txset.add(tx);
- // this.txset.commit();
-
- // this.storage.flush();
-
- // TODO: 未处理出错时 dataset 和 txset 的内部状态恢复,有可能出现不一致的情况;
-
- // put snapshot into stack;
- // TxSnapshot snapshot = new TxSnapshot(txDataSnapshot, txset.getRootHash());
- // editor.commitTxSnapshot(snapshot);
-
- committed = true;
- return tx;
- }
-
- @Override
- public LedgerTransaction discardAndCommit(TransactionState txResult) {
- return discardAndCommit(txResult, null);
- }
-
- @Override
- public LedgerTransaction discardAndCommit(TransactionState txResult, List operationResults) {
- checkTxState();
-
- // 未处理
- // dataset.cancel();
-
- // TransactionStagedSnapshot txDataSnapshot = takeSnapshot();
- // LedgerTransactionData tx = new LedgerTransactionData(blockHeight, txRequest,
- // txResult, txDataSnapshot);
- LedgerTransactionData tx = new LedgerTransactionData(blockHeight, txRequest, txResult, null,
- operationResultArray(operationResults));
- this.txset.add(tx);
- // this.txset.commit();
-
- // this.storage.flush();
-
- // TODO: 未处理出错时 dataset 和 txset 的内部状态恢复,有可能出现不一致的情况;
-
- // put snapshot into stack;
- // TxSnapshot snapshot = new TxSnapshot(txDataSnapshot, txset.getRootHash());
- // editor.commitTxSnapshot(snapshot);
-
- committed = true;
- return tx;
- }
-
- private TransactionStagedSnapshot takeSnapshot() {
- TransactionStagedSnapshot txDataSnapshot = new TransactionStagedSnapshot();
- txDataSnapshot.setAdminAccountHash(dataset.getAdminAccount().getHash());
- txDataSnapshot.setContractAccountSetHash(dataset.getContractAccountSet().getRootHash());
- txDataSnapshot.setDataAccountSetHash(dataset.getDataAccountSet().getRootHash());
- txDataSnapshot.setUserAccountSetHash(dataset.getUserAccountSet().getRootHash());
- return txDataSnapshot;
- }
-
- private OperationResult[] operationResultArray(List operationResults) {
- OperationResult[] operationResultArray = null;
- if (operationResults != null && !operationResults.isEmpty()) {
- operationResultArray = new OperationResult[operationResults.size()];
- operationResults.toArray(operationResultArray);
- }
- return operationResultArray;
- }
-
- @Override
- public void rollback() {
- if (this.rollbacked) {
- return;
- }
- if (this.committed) {
- throw new IllegalStateException("Transaction had been committed!");
- }
- // dataset.cancel();
- // storage.cancel();
-
- // editor.rollbackNewTx();
-
- rollbacked = true;
- }
-
- private void checkTxState() {
- if (this.committed) {
- throw new IllegalStateException("Transaction had been committed!");
- }
- if (this.rollbacked) {
- throw new IllegalStateException("Transaction had been rollbacked!");
- }
- }
- }
-
-}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/OperationHandleContext.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/OperationHandleContext.java
deleted file mode 100644
index 6e702e0b..00000000
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/OperationHandleContext.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.jd.blockchain.ledger.core.impl;
-
-import com.jd.blockchain.ledger.Operation;
-
-public interface OperationHandleContext {
-
- void handle(Operation operation);
-
-}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/OperationHandleRegisteration.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/OperationHandleRegisteration.java
deleted file mode 100644
index 169c5249..00000000
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/OperationHandleRegisteration.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.jd.blockchain.ledger.core.impl;
-
-import com.jd.blockchain.ledger.core.OperationHandle;
-
-public interface OperationHandleRegisteration {
-
- OperationHandle getHandle(Class> operationType);
-
-}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionBatchProcessor.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionBatchProcessor.java
deleted file mode 100644
index b4795c01..00000000
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionBatchProcessor.java
+++ /dev/null
@@ -1,292 +0,0 @@
-package com.jd.blockchain.ledger.core.impl;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.jd.blockchain.crypto.HashDigest;
-import com.jd.blockchain.ledger.BytesValue;
-import com.jd.blockchain.ledger.LedgerBlock;
-import com.jd.blockchain.ledger.LedgerException;
-import com.jd.blockchain.ledger.Operation;
-import com.jd.blockchain.ledger.OperationResult;
-import com.jd.blockchain.ledger.OperationResultData;
-import com.jd.blockchain.ledger.TransactionRequest;
-import com.jd.blockchain.ledger.TransactionResponse;
-import com.jd.blockchain.ledger.TransactionState;
-import com.jd.blockchain.ledger.core.LedgerDataSet;
-import com.jd.blockchain.ledger.core.LedgerEditor;
-import com.jd.blockchain.ledger.core.LedgerService;
-import com.jd.blockchain.ledger.core.LedgerTransactionContext;
-import com.jd.blockchain.ledger.core.OperationHandle;
-import com.jd.blockchain.ledger.core.TransactionRequestContext;
-import com.jd.blockchain.service.TransactionBatchProcess;
-import com.jd.blockchain.service.TransactionBatchResult;
-import com.jd.blockchain.service.TransactionBatchResultHandle;
-import com.jd.blockchain.utils.Bytes;
-
-public class TransactionBatchProcessor implements TransactionBatchProcess {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(TransactionBatchProcessor.class);
-
- private LedgerService ledgerService;
-
- private LedgerEditor newBlockEditor;
-
- private LedgerDataSet previousBlockDataset;
-
- private OperationHandleRegisteration opHandles;
-
- // 新创建的交易;
- private LedgerBlock block;
-
- private TransactionState globalResult;
-
- private List responseList = new ArrayList<>();
-
- private TransactionBatchResult batchResult;
-
- /**
- * @param newBlockEditor
- * 新区块的数据编辑器;
- * @param previousBlockDataset
- * 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集;
- * @param opHandles
- * 操作处理对象注册表;
- */
- public TransactionBatchProcessor(LedgerEditor newBlockEditor, LedgerDataSet previousBlockDataset,
- OperationHandleRegisteration opHandles, LedgerService ledgerService) {
- this.newBlockEditor = newBlockEditor;
- this.previousBlockDataset = previousBlockDataset;
- this.opHandles = opHandles;
- this.ledgerService = ledgerService;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.jd.blockchain.ledger.core.impl.TransactionBatchProcess#schedule(com.jd.
- * blockchain.ledger.TransactionRequest)
- */
- @Override
- public TransactionResponse schedule(TransactionRequest request) {
- // 此调用将会验证交易签名,验签失败将会抛出异常,同时,不记录签名错误的交易到链上;
- LedgerTransactionContext txCtx = newBlockEditor.newTransaction(request);
- TransactionState result;
-
- List operationResults = new ArrayList<>();
-
- try {
-
- LedgerDataSet dataset = txCtx.getDataSet();
- TransactionRequestContext reqCtx = new TransactionRequestContextImpl(request);
- // TODO: 验证签名者的有效性;
- for (Bytes edpAddr : reqCtx.getEndpoints()) {
- if (!previousBlockDataset.getUserAccountSet().contains(edpAddr)) {
- throw new LedgerException("The endpoint signer[" + edpAddr + "] was not registered!");
- }
- }
- for (Bytes edpAddr : reqCtx.getNodes()) {
- if (!previousBlockDataset.getUserAccountSet().contains(edpAddr)) {
- throw new LedgerException("The node signer[" + edpAddr + "] was not registered!");
- }
- }
-
- // 执行操作;
- Operation[] ops = request.getTransactionContent().getOperations();
- OperationHandleContext handleContext = new OperationHandleContext() {
- @Override
- public void handle(Operation operation) {
- //assert; Instance of operation are one of User related operations or DataAccount related operations;
- OperationHandle hdl = opHandles.getHandle(operation.getClass());
- hdl.process(operation, dataset, reqCtx, previousBlockDataset, this, ledgerService);
- }
- };
- OperationHandle opHandle;
- int opIndex = 0;
- for (Operation op : ops) {
- opHandle = opHandles.getHandle(op.getClass());
- BytesValue opResult = opHandle.process(op, dataset, reqCtx, previousBlockDataset, handleContext, ledgerService);
- if (opResult != null) {
- operationResults.add(new OperationResultData(opIndex, opResult));
- }
- opIndex++;
- }
-
- // 提交交易(事务);
- result = TransactionState.SUCCESS;
-
- txCtx.commit(result, operationResults);
- } catch (LedgerException e) {
- // TODO: 识别更详细的异常类型以及执行对应的处理;
- result = TransactionState.LEDGER_ERROR;
- txCtx.discardAndCommit(TransactionState.LEDGER_ERROR, operationResults);
- LOGGER.warn(String.format("Transaction rollback caused by the ledger exception! --[TxHash=%s] --%s",
- request.getHash().toBase58(), e.getMessage()), e);
- } catch (Exception e) {
- result = TransactionState.SYSTEM_ERROR;
- txCtx.discardAndCommit(TransactionState.SYSTEM_ERROR, operationResults);
- LOGGER.warn(String.format("Transaction rollback caused by the system exception! --[TxHash=%s] --%s",
- request.getHash().toBase58(), e.getMessage()), e);
- }
- TxResponseHandle resp = new TxResponseHandle(request, result);
-
- if (!operationResults.isEmpty()) {
- OperationResult[] operationResultArray = new OperationResult[operationResults.size()];
- resp.setOperationResults(operationResults.toArray(operationResultArray));
- }
-
- responseList.add(resp);
-
- return resp;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.jd.blockchain.ledger.core.impl.TransactionBatchProcess#prepare()
- */
- @Override
- public TransactionBatchResultHandle prepare() {
- if (batchResult != null) {
- throw new IllegalStateException("Batch result has already been prepared or canceled!");
- }
- block = newBlockEditor.prepare();
- batchResult = new TransactionBatchResultHandleImpl();
- return (TransactionBatchResultHandle) batchResult;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.jd.blockchain.ledger.core.impl.TransactionBatchProcess#cancel(com.jd.
- * blockchain.ledger.ExecutionState)
- */
- @Override
- public TransactionBatchResult cancel(TransactionState errorResult) {
- if (batchResult != null) {
- throw new IllegalStateException("Batch result has already been prepared or canceled!");
- }
-
- cancelInError(errorResult);
-
- batchResult = new TransactionBatchResultImpl();
- return batchResult;
- }
-
- @Override
- public long blockHeight() {
- if (block != null) {
- return block.getHeight();
- }
- return 0;
- }
-
- private void commitSuccess() {
- newBlockEditor.commit();
- onCommitted();
- }
-
- private void cancelInError(TransactionState errorResult) {
- if (errorResult == TransactionState.SUCCESS) {
- throw new IllegalArgumentException("Cann't cancel by an success result!");
- }
- newBlockEditor.cancel();
- this.globalResult = errorResult;
- onCanceled();
- }
-
- /**
- * 模板事件方法:交易已提交;
- */
- protected void onCommitted() {
- }
-
- /**
- * 模板事件方法:交易已取消;
- */
- protected void onCanceled() {
- }
-
- private class TxResponseHandle implements TransactionResponse {
-
- private TransactionRequest request;
-
- private TransactionState result;
-
- private OperationResult[] operationResults;
-
- public TxResponseHandle(TransactionRequest request, TransactionState result) {
- this.request = request;
- this.result = result;
- }
-
- @Override
- public HashDigest getContentHash() {
- return request.getTransactionContent().getHash();
- }
-
- @Override
- public TransactionState getExecutionState() {
- return result;
- }
-
- @Override
- public HashDigest getBlockHash() {
- return block == null ? null : block.getHash();
- }
-
- @Override
- public long getBlockHeight() {
- return block == null ? -1 : block.getHeight();
- }
-
- @Override
- public boolean isSuccess() {
- return globalResult == null ? result == TransactionState.SUCCESS : globalResult == TransactionState.SUCCESS;
- }
-
- @Override
- public OperationResult[] getOperationResults() {
- return operationResults;
- }
-
- public void setOperationResults(OperationResult[] operationResults) {
- this.operationResults = operationResults;
- }
- }
-
- private class TransactionBatchResultImpl implements TransactionBatchResult {
-
- @Override
- public LedgerBlock getBlock() {
- return block;
- }
-
- @Override
- public Iterator getResponses() {
- return responseList.iterator();
- }
-
- }
-
- private class TransactionBatchResultHandleImpl extends TransactionBatchResultImpl
- implements TransactionBatchResultHandle {
-
- @Override
- public void commit() {
- commitSuccess();
- }
-
- @Override
- public void cancel(TransactionState errorResult) {
- cancelInError(errorResult);
- }
-
- }
-}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionRequestContextImpl.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionRequestContextImpl.java
deleted file mode 100644
index ec53360a..00000000
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionRequestContextImpl.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package com.jd.blockchain.ledger.core.impl;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-import com.jd.blockchain.crypto.AddressEncoding;
-import com.jd.blockchain.ledger.DigitalSignature;
-import com.jd.blockchain.ledger.TransactionRequest;
-import com.jd.blockchain.ledger.core.TransactionRequestContext;
-import com.jd.blockchain.utils.Bytes;
-
-/**
- * @Author zhaogw
- * @Date 2018/9/5 14:52
- */
-public class TransactionRequestContextImpl implements TransactionRequestContext {
-
- private TransactionRequest request;
-
- private Map endpointSignatures = new HashMap<>();
-
- private Map nodeSignatures = new HashMap<>();
-
- public TransactionRequestContextImpl(TransactionRequest request) {
- this.request = request;
- resolveSigners();
- }
-
- private void resolveSigners() {
- if (request.getEndpointSignatures() != null) {
- for (DigitalSignature signature : request.getEndpointSignatures()) {
- Bytes address = AddressEncoding.generateAddress(signature.getPubKey());
- endpointSignatures.put(address, signature);
- }
- }
- if (request.getEndpointSignatures() != null) {
- for (DigitalSignature signature : request.getNodeSignatures()) {
- Bytes address = AddressEncoding.generateAddress(signature.getPubKey());
- nodeSignatures.put(address, signature);
- }
- }
- }
-
- @Override
- public TransactionRequest getRequest() {
- return request;
- }
-
- @Override
- public Set getEndpoints() {
- return endpointSignatures.keySet();
- }
-
- @Override
- public Set getNodes() {
- return nodeSignatures.keySet();
- }
-
- @Override
- public boolean containsEndpoint(Bytes address) {
- return endpointSignatures.containsKey(address);
- }
-
- @Override
- public boolean containsNode(Bytes address) {
- return nodeSignatures.containsKey(address);
- }
-
- @Override
- public DigitalSignature getEndpointSignature(Bytes address) {
- return endpointSignatures.get(address);
- }
-
- @Override
- public DigitalSignature getNodeSignature(Bytes address) {
- return nodeSignatures.get(address);
- }
-
-}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractCodeDeployOperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractCodeDeployOperationHandle.java
deleted file mode 100644
index ed7b1981..00000000
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractCodeDeployOperationHandle.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.jd.blockchain.ledger.core.impl.handles;
-
-import com.jd.blockchain.contract.ContractJarUtils;
-import org.springframework.stereotype.Service;
-
-import com.jd.blockchain.ledger.BytesValue;
-import com.jd.blockchain.ledger.ContractCodeDeployOperation;
-import com.jd.blockchain.ledger.Operation;
-import com.jd.blockchain.ledger.core.LedgerDataSet;
-import com.jd.blockchain.ledger.core.LedgerService;
-import com.jd.blockchain.ledger.core.OperationHandle;
-import com.jd.blockchain.ledger.core.TransactionRequestContext;
-import com.jd.blockchain.ledger.core.impl.OperationHandleContext;
-
-@Service
-public class ContractCodeDeployOperationHandle implements OperationHandle {
-
- @Override
- public BytesValue process(Operation op, LedgerDataSet dataset, TransactionRequestContext requestContext,
- LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) {
- ContractCodeDeployOperation contractOP = (ContractCodeDeployOperation) op;
- // TODO: 校验合约代码的正确性;
-
- // TODO: 请求者应该提供合约账户的公钥签名,已确定注册的地址的唯一性;
-
- byte[] chainCode = contractOP.getChainCode();
- // 校验合约代码,不通过会抛出异常
- ContractJarUtils.verify(chainCode);
-
- dataset.getContractAccountSet().deploy(contractOP.getContractID().getAddress(),
- contractOP.getContractID().getPubKey(), contractOP.getAddressSignature(), chainCode);
-
- return null;
- }
-
-// @Override
-// public AsyncFuture asyncProcess(Operation op, LedgerDataSet newBlockDataset, TransactionRequestContext requestContext, LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) {
-// return null;
-// }
-
- @Override
- public boolean support(Class> operationType) {
- return ContractCodeDeployOperation.class.isAssignableFrom(operationType);
- }
-}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/DataAccountKVSetOperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/DataAccountKVSetOperationHandle.java
deleted file mode 100644
index c07dd628..00000000
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/DataAccountKVSetOperationHandle.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.jd.blockchain.ledger.core.impl.handles;
-
-import org.springframework.stereotype.Service;
-
-import com.jd.blockchain.binaryproto.DataContractRegistry;
-import com.jd.blockchain.ledger.BytesValue;
-import com.jd.blockchain.ledger.DataAccountKVSetOperation;
-import com.jd.blockchain.ledger.DataAccountKVSetOperation.KVWriteEntry;
-import com.jd.blockchain.ledger.Operation;
-import com.jd.blockchain.ledger.core.DataAccount;
-import com.jd.blockchain.ledger.core.LedgerDataSet;
-import com.jd.blockchain.ledger.core.LedgerService;
-import com.jd.blockchain.ledger.core.OperationHandle;
-import com.jd.blockchain.ledger.core.TransactionRequestContext;
-import com.jd.blockchain.ledger.core.impl.OperationHandleContext;
-import com.jd.blockchain.utils.Bytes;
-
-@Service
-public class DataAccountKVSetOperationHandle implements OperationHandle {
- static {
- DataContractRegistry.register(BytesValue.class);
- }
-
- @Override
- public BytesValue process(Operation op, LedgerDataSet dataset, TransactionRequestContext requestContext,
- LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) {
- DataAccountKVSetOperation kvWriteOp = (DataAccountKVSetOperation) op;
- DataAccount account = dataset.getDataAccountSet().getDataAccount(kvWriteOp.getAccountAddress());
- KVWriteEntry[] writeSet = kvWriteOp.getWriteSet();
- for (KVWriteEntry kvw : writeSet) {
-// byte[] value = BinaryProtocol.encode(kvw.getValue(), BytesValue.class);
- account.setBytes(Bytes.fromString(kvw.getKey()), kvw.getValue(), kvw.getExpectedVersion());
- }
- return null;
- }
-
-// @Override
-// public AsyncFuture asyncProcess(Operation op, LedgerDataSet newBlockDataset, TransactionRequestContext requestContext, LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) {
-// return null;
-// }
-
- @Override
- public boolean support(Class> operationType) {
- return DataAccountKVSetOperation.class.isAssignableFrom(operationType);
- }
-
-}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/DataAccountRegisterOperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/DataAccountRegisterOperationHandle.java
deleted file mode 100644
index 69337dfa..00000000
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/DataAccountRegisterOperationHandle.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.jd.blockchain.ledger.core.impl.handles;
-
-import org.springframework.stereotype.Service;
-
-import com.jd.blockchain.ledger.BlockchainIdentity;
-import com.jd.blockchain.ledger.BytesValue;
-import com.jd.blockchain.ledger.DataAccountRegisterOperation;
-import com.jd.blockchain.ledger.Operation;
-import com.jd.blockchain.ledger.core.LedgerDataSet;
-import com.jd.blockchain.ledger.core.LedgerService;
-import com.jd.blockchain.ledger.core.OperationHandle;
-import com.jd.blockchain.ledger.core.TransactionRequestContext;
-import com.jd.blockchain.ledger.core.impl.OperationHandleContext;
-
-@Service
-public class DataAccountRegisterOperationHandle implements OperationHandle {
-
- @Override
- public BytesValue process(Operation op, LedgerDataSet dataset, TransactionRequestContext requestContext,
- LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) {
- DataAccountRegisterOperation dataAccountRegOp = (DataAccountRegisterOperation) op;
- BlockchainIdentity bid = dataAccountRegOp.getAccountID();
-
- //TODO: 校验用户身份;
-
- //TODO: 请求者应该提供数据账户的公钥签名,已确定注册的地址的唯一性;
- dataset.getDataAccountSet().register(bid.getAddress(), bid.getPubKey(), null);
-
- return null;
- }
-
-// @Override
-// public AsyncFuture asyncProcess(Operation op, LedgerDataSet newBlockDataset, TransactionRequestContext requestContext, LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) {
-// return null;
-// }
-
- @Override
- public boolean support(Class> operationType) {
- return DataAccountRegisterOperation.class.isAssignableFrom(operationType);
- }
-
-}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/UserRegisterOperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/UserRegisterOperationHandle.java
deleted file mode 100644
index f583e8cd..00000000
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/UserRegisterOperationHandle.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.jd.blockchain.ledger.core.impl.handles;
-
-import com.jd.blockchain.ledger.BlockchainIdentity;
-import com.jd.blockchain.ledger.BytesValue;
-import com.jd.blockchain.ledger.Operation;
-import com.jd.blockchain.ledger.UserRegisterOperation;
-import com.jd.blockchain.ledger.core.LedgerDataSet;
-import com.jd.blockchain.ledger.core.LedgerService;
-import com.jd.blockchain.ledger.core.OperationHandle;
-import com.jd.blockchain.ledger.core.TransactionRequestContext;
-import com.jd.blockchain.ledger.core.impl.OperationHandleContext;
-import com.jd.blockchain.utils.Bytes;
-
-
-public class UserRegisterOperationHandle implements OperationHandle {
-
- @Override
- public BytesValue process(Operation op, LedgerDataSet dataset, TransactionRequestContext requestContext,
- LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) {
-
-
- UserRegisterOperation userRegOp = (UserRegisterOperation) op;
- BlockchainIdentity bid = userRegOp.getUserID();
-
- Bytes userAddress = bid.getAddress();
-
- dataset.getUserAccountSet().register(userAddress, bid.getPubKey());
-
- return null;
- }
-
- @Override
- public boolean support(Class> operationType) {
- return UserRegisterOperation.class.isAssignableFrom(operationType);
- }
-
-}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/serialize/LedgerBlockSerializer.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/serialize/LedgerBlockSerializer.java
index 65b15129..09cedf9d 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/serialize/LedgerBlockSerializer.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/serialize/LedgerBlockSerializer.java
@@ -1,13 +1,12 @@
package com.jd.blockchain.ledger.core.serialize;
+import java.lang.reflect.Type;
+
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import com.alibaba.fastjson.serializer.SerializeWriter;
-import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.LedgerBlock;
-import java.lang.reflect.Type;
-
public class LedgerBlockSerializer implements ObjectSerializer {
@Override
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/ContractInvokingHandle.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/ContractInvokingHandle.java
index 553cac68..2a2be01d 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/ContractInvokingHandle.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/ContractInvokingHandle.java
@@ -8,10 +8,10 @@ import com.jd.blockchain.contract.engine.ContractCode;
import com.jd.blockchain.contract.jvm.AbstractContractCode;
import com.jd.blockchain.contract.jvm.ContractDefinition;
import com.jd.blockchain.ledger.core.ContractAccount;
-import com.jd.blockchain.ledger.core.impl.handles.AbstractContractEventHandle;
+import com.jd.blockchain.ledger.core.handles.AbtractContractEventSendOperationHandle;
import com.jd.blockchain.utils.Bytes;
-public class ContractInvokingHandle extends AbstractContractEventHandle {
+public class ContractInvokingHandle extends AbtractContractEventSendOperationHandle {
private Map contractInstances = new ConcurrentHashMap();
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/ContractInvokingTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/ContractInvokingTest.java
index 86ec8c2e..49d14071 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/ContractInvokingTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/ContractInvokingTest.java
@@ -1,202 +1,199 @@
-package test.com.jd.blockchain.ledger;
-
-import com.jd.blockchain.binaryproto.BinaryProtocol;
-import com.jd.blockchain.binaryproto.DataContractRegistry;
-import com.jd.blockchain.crypto.HashDigest;
-import com.jd.blockchain.ledger.*;
-import com.jd.blockchain.ledger.core.*;
-import com.jd.blockchain.ledger.core.impl.DefaultOperationHandleRegisteration;
-import com.jd.blockchain.ledger.core.impl.LedgerManager;
-import com.jd.blockchain.ledger.core.impl.LedgerTransactionalEditor;
-import com.jd.blockchain.ledger.core.impl.TransactionBatchProcessor;
-import com.jd.blockchain.service.TransactionBatchResultHandle;
-import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
-import com.jd.blockchain.transaction.TxBuilder;
-import com.jd.blockchain.utils.Bytes;
-import com.jd.blockchain.utils.io.BytesUtils;
-import org.apache.commons.io.IOUtils;
-import org.junit.Test;
-import org.mockito.Mockito;
-
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.util.Random;
-
-import static org.junit.Assert.*;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.*;
-
-public class ContractInvokingTest {
- static {
- DataContractRegistry.register(TransactionContent.class);
- DataContractRegistry.register(TransactionContentBody.class);
- DataContractRegistry.register(TransactionRequest.class);
- DataContractRegistry.register(NodeRequest.class);
- DataContractRegistry.register(EndpointRequest.class);
- DataContractRegistry.register(TransactionResponse.class);
- DataContractRegistry.register(UserRegisterOperation.class);
- }
-
- private static final String LEDGER_KEY_PREFIX = "LDG://";
-
- private BlockchainKeypair parti0 = BlockchainKeyGenerator.getInstance().generate();
- private BlockchainKeypair parti1 = BlockchainKeyGenerator.getInstance().generate();
- private BlockchainKeypair parti2 = BlockchainKeyGenerator.getInstance().generate();
- private BlockchainKeypair parti3 = BlockchainKeyGenerator.getInstance().generate();
-
- // 采用基于内存的 Storage;
- private MemoryKVStorage storage = new MemoryKVStorage();
-
- // 用于测试的发布合约文件
- private static final String CONTRACT_JAR = "contract-JDChain-Contract.jar";
-
- @Test
- public void test() {
- // 初始化账本到指定的存储库;
- HashDigest ledgerHash = initLedger(storage, parti0, parti1, parti2, parti3);
-
- // 重新加载账本;
- LedgerManager ledgerManager = new LedgerManager();
- LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, storage);
-
- // 创建合约处理器;
- ContractInvokingHandle contractInvokingHandle = new ContractInvokingHandle();
-
- // 创建和加载合约实例;
- BlockchainKeypair contractKey = BlockchainKeyGenerator.getInstance().generate();
- Bytes contractAddress = contractKey.getAddress();
- TestContract contractInstance = Mockito.mock(TestContract.class);
- contractInvokingHandle.setup(contractAddress, TestContract.class, contractInstance);
-
- // 注册合约处理器;
- DefaultOperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration();
- opReg.insertAsTopPriority(contractInvokingHandle);
-
- // 发布指定地址合约
- deploy(ledgerRepo, ledgerManager, opReg, ledgerHash, contractKey);
-
-
- // 创建新区块的交易处理器;
- LedgerBlock preBlock = ledgerRepo.getLatestBlock();
- LedgerDataSet previousBlockDataset = ledgerRepo.getDataSet(preBlock);
-
- // 加载合约
- LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();
- TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(newBlockEditor, previousBlockDataset,
- opReg, ledgerManager);
-
- // 构建基于接口调用合约的交易请求,用于测试合约调用;
- TxBuilder txBuilder = new TxBuilder(ledgerHash);
- TestContract contractProxy = txBuilder.contract(contractAddress, TestContract.class);
-
- String asset = "AK";
- long issueAmount = new Random().nextLong();
- when(contractInstance.issue(anyString(), anyLong())).thenReturn(issueAmount);
- contractProxy.issue(asset, issueAmount);
-
- TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest();
- txReqBuilder.signAsEndpoint(parti0);
- txReqBuilder.signAsNode(parti0);
- TransactionRequest txReq = txReqBuilder.buildRequest();
-
- TransactionResponse resp = txbatchProcessor.schedule(txReq);
- verify(contractInstance, times(1)).issue(asset, issueAmount);
- OperationResult[] opResults = resp.getOperationResults();
- assertEquals(1, opResults.length);
- assertEquals(0, opResults[0].getIndex());
-
- byte[] expectedRetnBytes = BinaryProtocol.encode(BytesData.fromInt64(issueAmount), BytesValue.class);
- byte[] reallyRetnBytes = BinaryProtocol.encode(opResults[0].getResult(), BytesValue.class);
- assertArrayEquals(expectedRetnBytes, reallyRetnBytes);
-
- // 提交区块;
- TransactionBatchResultHandle txResultHandle = txbatchProcessor.prepare();
- txResultHandle.commit();
-
- LedgerBlock latestBlock = ledgerRepo.getLatestBlock();
- assertEquals(preBlock.getHeight() + 1, latestBlock.getHeight());
- assertEquals(resp.getBlockHeight(), latestBlock.getHeight());
- assertEquals(resp.getBlockHash(), latestBlock.getHash());
-
- // 再验证一次结果;
- assertEquals(1, opResults.length);
- assertEquals(0, opResults[0].getIndex());
-
- reallyRetnBytes = BinaryProtocol.encode(opResults[0].getResult(), BytesValue.class);
- assertArrayEquals(expectedRetnBytes, reallyRetnBytes);
-
- }
-
- private void deploy(LedgerRepository ledgerRepo, LedgerManager ledgerManager,
- DefaultOperationHandleRegisteration opReg, HashDigest ledgerHash,
- BlockchainKeypair contractKey) {
- // 创建新区块的交易处理器;
- LedgerBlock preBlock = ledgerRepo.getLatestBlock();
- LedgerDataSet previousBlockDataset = ledgerRepo.getDataSet(preBlock);
-
- // 加载合约
- LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();
- TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(newBlockEditor, previousBlockDataset,
- opReg, ledgerManager);
-
- // 构建基于接口调用合约的交易请求,用于测试合约调用;
- TxBuilder txBuilder = new TxBuilder(ledgerHash);
- txBuilder.contracts().deploy(contractKey.getIdentity(), chainCode());
- TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest();
- txReqBuilder.signAsEndpoint(parti0);
- txReqBuilder.signAsNode(parti0);
- TransactionRequest txReq = txReqBuilder.buildRequest();
-
- TransactionResponse resp = txbatchProcessor.schedule(txReq);
- OperationResult[] opResults = resp.getOperationResults();
- assertNull(opResults);
-
- // 提交区块;
- TransactionBatchResultHandle txResultHandle = txbatchProcessor.prepare();
- txResultHandle.commit();
- }
-
- private HashDigest initLedger(MemoryKVStorage storage, BlockchainKeypair... partiKeys) {
- // 创建初始化配置;
- LedgerInitSetting initSetting = LedgerTestUtils.createLedgerInitSetting(partiKeys);
-
- // 创建账本;
- LedgerEditor ldgEdt = LedgerTransactionalEditor.createEditor(initSetting, LEDGER_KEY_PREFIX, storage, storage);
-
- TransactionRequest genesisTxReq = LedgerTestUtils.createTxRequest_UserReg(null);
- LedgerTransactionContext genisisTxCtx = ldgEdt.newTransaction(genesisTxReq);
- LedgerDataSet ldgDS = genisisTxCtx.getDataSet();
-
- for (int i = 0; i < partiKeys.length; i++) {
- UserAccount userAccount = ldgDS.getUserAccountSet().register(partiKeys[i].getAddress(),
- partiKeys[i].getPubKey());
- userAccount.setProperty("Name", "参与方-" + i, -1);
- userAccount.setProperty("Share", "" + (10 + i), -1);
- }
-
- LedgerTransaction tx = genisisTxCtx.commit(TransactionState.SUCCESS);
-
- assertEquals(genesisTxReq.getTransactionContent().getHash(), tx.getTransactionContent().getHash());
- assertEquals(0, tx.getBlockHeight());
-
- LedgerBlock block = ldgEdt.prepare();
-
- assertEquals(0, block.getHeight());
- assertNotNull(block.getHash());
- assertNull(block.getPreviousHash());
-
- assertEquals(block.getHash(), block.getLedgerHash());
-
- // 提交数据,写入存储;
- ldgEdt.commit();
-
- HashDigest ledgerHash = block.getHash();
- return ledgerHash;
- }
-
- private byte[] chainCode() {
-
- return BytesUtils.copyToBytes(this.getClass().getResourceAsStream("/" + CONTRACT_JAR));
- }
-}
+//package test.com.jd.blockchain.ledger;
+//
+//import com.jd.blockchain.binaryproto.BinaryProtocol;
+//import com.jd.blockchain.binaryproto.DataContractRegistry;
+//import com.jd.blockchain.crypto.HashDigest;
+//import com.jd.blockchain.ledger.*;
+//import com.jd.blockchain.ledger.core.*;
+//import com.jd.blockchain.service.TransactionBatchResultHandle;
+//import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
+//import com.jd.blockchain.transaction.TxBuilder;
+//import com.jd.blockchain.utils.Bytes;
+//import com.jd.blockchain.utils.io.BytesUtils;
+//import org.apache.commons.io.IOUtils;
+//import org.junit.Test;
+//import org.mockito.Mockito;
+//import test.com.jd.blockchain.ledger.core.TestContract;
+//
+//import java.io.ByteArrayOutputStream;
+//import java.io.InputStream;
+//import java.util.Random;
+//
+//import static org.junit.Assert.*;
+//import static org.mockito.Matchers.anyLong;
+//import static org.mockito.Matchers.anyString;
+//import static org.mockito.Mockito.*;
+//
+//public class ContractInvokingTest {
+// static {
+// DataContractRegistry.register(TransactionContent.class);
+// DataContractRegistry.register(TransactionContentBody.class);
+// DataContractRegistry.register(TransactionRequest.class);
+// DataContractRegistry.register(NodeRequest.class);
+// DataContractRegistry.register(EndpointRequest.class);
+// DataContractRegistry.register(TransactionResponse.class);
+// DataContractRegistry.register(UserRegisterOperation.class);
+// }
+//
+// private static final String LEDGER_KEY_PREFIX = "LDG://";
+//
+// private BlockchainKeypair parti0 = BlockchainKeyGenerator.getInstance().generate();
+// private BlockchainKeypair parti1 = BlockchainKeyGenerator.getInstance().generate();
+// private BlockchainKeypair parti2 = BlockchainKeyGenerator.getInstance().generate();
+// private BlockchainKeypair parti3 = BlockchainKeyGenerator.getInstance().generate();
+//
+// // 采用基于内存的 Storage;
+// private MemoryKVStorage storage = new MemoryKVStorage();
+//
+// // 用于测试的发布合约文件
+// private static final String CONTRACT_JAR = "contract-JDChain-Contract.jar";
+//
+// @Test
+// public void test() {
+// // 初始化账本到指定的存储库;
+// HashDigest ledgerHash = initLedger(storage, parti0, parti1, parti2, parti3);
+//
+// // 重新加载账本;
+// LedgerManager ledgerManager = new LedgerManager();
+// LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, storage);
+//
+// // 创建合约处理器;
+// ContractInvokingHandle contractInvokingHandle = new ContractInvokingHandle();
+//
+// // 创建和加载合约实例;
+// BlockchainKeypair contractKey = BlockchainKeyGenerator.getInstance().generate();
+// Bytes contractAddress = contractKey.getAddress();
+// TestContract contractInstance = Mockito.mock(TestContract.class);
+// contractInvokingHandle.setup(contractAddress, TestContract.class, contractInstance);
+//
+// // 注册合约处理器;
+// DefaultOperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration();
+// opReg.insertAsTopPriority(contractInvokingHandle);
+//
+// // 发布指定地址合约
+// deploy(ledgerRepo, ledgerManager, opReg, ledgerHash, contractKey);
+//
+//
+// // 创建新区块的交易处理器;
+// LedgerBlock preBlock = ledgerRepo.getLatestBlock();
+// LedgerDataSet previousBlockDataset = ledgerRepo.getDataSet(preBlock);
+//
+// // 加载合约
+// LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();
+// TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(newBlockEditor, previousBlockDataset,
+// opReg, ledgerManager);
+//
+// // 构建基于接口调用合约的交易请求,用于测试合约调用;
+// TxBuilder txBuilder = new TxBuilder(ledgerHash);
+// TestContract contractProxy = txBuilder.contract(contractAddress, TestContract.class);
+//
+// String asset = "AK";
+// long issueAmount = new Random().nextLong();
+// when(contractInstance.issue(anyString(), anyLong())).thenReturn(issueAmount);
+// contractProxy.issue(asset, issueAmount);
+//
+// TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest();
+// txReqBuilder.signAsEndpoint(parti0);
+// txReqBuilder.signAsNode(parti0);
+// TransactionRequest txReq = txReqBuilder.buildRequest();
+//
+// TransactionResponse resp = txbatchProcessor.schedule(txReq);
+// verify(contractInstance, times(1)).issue(asset, issueAmount);
+// OperationResult[] opResults = resp.getOperationResults();
+// assertEquals(1, opResults.length);
+// assertEquals(0, opResults[0].getIndex());
+//
+// byte[] expectedRetnBytes = BinaryProtocol.encode(BytesData.fromInt64(issueAmount), BytesValue.class);
+// byte[] reallyRetnBytes = BinaryProtocol.encode(opResults[0].getResult(), BytesValue.class);
+// assertArrayEquals(expectedRetnBytes, reallyRetnBytes);
+//
+// // 提交区块;
+// TransactionBatchResultHandle txResultHandle = txbatchProcessor.prepare();
+// txResultHandle.commit();
+//
+// LedgerBlock latestBlock = ledgerRepo.getLatestBlock();
+// assertEquals(preBlock.getHeight() + 1, latestBlock.getHeight());
+// assertEquals(resp.getBlockHeight(), latestBlock.getHeight());
+// assertEquals(resp.getBlockHash(), latestBlock.getHash());
+//
+// // 再验证一次结果;
+// assertEquals(1, opResults.length);
+// assertEquals(0, opResults[0].getIndex());
+//
+// reallyRetnBytes = BinaryProtocol.encode(opResults[0].getResult(), BytesValue.class);
+// assertArrayEquals(expectedRetnBytes, reallyRetnBytes);
+//
+// }
+//
+// private void deploy(LedgerRepository ledgerRepo, LedgerManager ledgerManager,
+// DefaultOperationHandleRegisteration opReg, HashDigest ledgerHash,
+// BlockchainKeypair contractKey) {
+// // 创建新区块的交易处理器;
+// LedgerBlock preBlock = ledgerRepo.getLatestBlock();
+// LedgerDataSet previousBlockDataset = ledgerRepo.getDataSet(preBlock);
+//
+// // 加载合约
+// LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();
+// TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(newBlockEditor, previousBlockDataset,
+// opReg, ledgerManager);
+//
+// // 构建基于接口调用合约的交易请求,用于测试合约调用;
+// TxBuilder txBuilder = new TxBuilder(ledgerHash);
+// txBuilder.contracts().deploy(contractKey.getIdentity(), chainCode());
+// TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest();
+// txReqBuilder.signAsEndpoint(parti0);
+// txReqBuilder.signAsNode(parti0);
+// TransactionRequest txReq = txReqBuilder.buildRequest();
+//
+// TransactionResponse resp = txbatchProcessor.schedule(txReq);
+// OperationResult[] opResults = resp.getOperationResults();
+// assertNull(opResults);
+//
+// // 提交区块;
+// TransactionBatchResultHandle txResultHandle = txbatchProcessor.prepare();
+// txResultHandle.commit();
+// }
+//
+// private HashDigest initLedger(MemoryKVStorage storage, BlockchainKeypair... partiKeys) {
+// // 创建初始化配置;
+// LedgerInitSetting initSetting = LedgerTestUtils.createLedgerInitSetting(partiKeys);
+//
+// // 创建账本;
+// LedgerEditor ldgEdt = LedgerTransactionalEditor.createEditor(initSetting, LEDGER_KEY_PREFIX, storage, storage);
+//
+// TransactionRequest genesisTxReq = LedgerTestUtils.createTxRequest_UserReg(null);
+// LedgerTransactionContext genisisTxCtx = ldgEdt.newTransaction(genesisTxReq);
+// LedgerDataSet ldgDS = genisisTxCtx.getDataSet();
+//
+// for (int i = 0; i < partiKeys.length; i++) {
+// UserAccount userAccount = ldgDS.getUserAccountSet().register(partiKeys[i].getAddress(),
+// partiKeys[i].getPubKey());
+// userAccount.setProperty("Name", "参与方-" + i, -1);
+// userAccount.setProperty("Share", "" + (10 + i), -1);
+// }
+//
+// LedgerTransaction tx = genisisTxCtx.commit(TransactionState.SUCCESS);
+//
+// assertEquals(genesisTxReq.getTransactionContent().getHash(), tx.getTransactionContent().getHash());
+// assertEquals(0, tx.getBlockHeight());
+//
+// LedgerBlock block = ldgEdt.prepare();
+//
+// assertEquals(0, block.getHeight());
+// assertNotNull(block.getHash());
+// assertNull(block.getPreviousHash());
+//
+// assertEquals(block.getHash(), block.getLedgerHash());
+//
+// // 提交数据,写入存储;
+// ldgEdt.commit();
+//
+// HashDigest ledgerHash = block.getHash();
+// return ledgerHash;
+// }
+//
+// private byte[] chainCode() {
+//
+// return BytesUtils.copyToBytes(this.getClass().getResourceAsStream("/" + CONTRACT_JAR));
+// }
+//}
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/KeyValueEntry.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/KeyValueEntry.java
new file mode 100644
index 00000000..c4b40d59
--- /dev/null
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/KeyValueEntry.java
@@ -0,0 +1,19 @@
+package test.com.jd.blockchain.ledger;
+
+import com.jd.blockchain.binaryproto.DataContract;
+import com.jd.blockchain.binaryproto.DataField;
+import com.jd.blockchain.binaryproto.PrimitiveType;
+
+@DataContract(code = 0x4010)
+public interface KeyValueEntry {
+
+ @DataField(order = 1, primitiveType = PrimitiveType.TEXT)
+ String getKey();
+
+ @DataField(order = 2, primitiveType = PrimitiveType.TEXT)
+ String getValue();
+
+ @DataField(order = 3, primitiveType = PrimitiveType.INT64)
+ long getVersion();
+
+}
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/KeyValueObject.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/KeyValueObject.java
new file mode 100644
index 00000000..24215ea7
--- /dev/null
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/KeyValueObject.java
@@ -0,0 +1,47 @@
+package test.com.jd.blockchain.ledger;
+
+public class KeyValueObject implements KeyValueEntry {
+
+ private String key;
+
+ private String value;
+
+ private long version;
+
+ public KeyValueObject() {
+ }
+
+ public KeyValueObject(String key, String value, long version) {
+ this.key = key;
+ this.value = value;
+ this.version = version;
+ }
+
+ @Override
+ public String getKey() {
+ return key;
+ }
+
+ @Override
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public long getVersion() {
+ return version;
+ }
+
+ public void setKey(String key) {
+ this.key = key;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ public void setVersion(long version) {
+ this.version = version;
+ }
+
+}
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerAdminAccountTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerAdminAccountTest.java
deleted file mode 100644
index 1293a9d8..00000000
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerAdminAccountTest.java
+++ /dev/null
@@ -1,221 +0,0 @@
-package test.com.jd.blockchain.ledger;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Arrays;
-import java.util.Random;
-
-import com.jd.blockchain.ledger.LedgerMetadata;
-import org.junit.Test;
-
-import com.jd.blockchain.crypto.AddressEncoding;
-import com.jd.blockchain.crypto.Crypto;
-import com.jd.blockchain.crypto.CryptoProvider;
-import com.jd.blockchain.crypto.HashDigest;
-import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
-import com.jd.blockchain.crypto.service.classic.ClassicCryptoService;
-import com.jd.blockchain.crypto.service.sm.SMCryptoService;
-import com.jd.blockchain.ledger.BlockchainKeyGenerator;
-import com.jd.blockchain.ledger.BlockchainKeypair;
-import com.jd.blockchain.ledger.ParticipantNode;
-import com.jd.blockchain.ledger.core.CryptoConfig;
-import com.jd.blockchain.ledger.core.LedgerAdminAccount;
-import com.jd.blockchain.ledger.core.LedgerConfiguration;
-import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
-import com.jd.blockchain.transaction.ConsensusParticipantData;
-import com.jd.blockchain.transaction.LedgerInitSettingData;
-import com.jd.blockchain.utils.Bytes;
-import com.jd.blockchain.utils.io.BytesUtils;
-import com.jd.blockchain.utils.net.NetworkAddress;
-
-public class LedgerAdminAccountTest {
-
- private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(),
- SMCryptoService.class.getName() };
-
- private Random rand = new Random();
-
- @Test
- public void test() {
- String keyPrefix = "";
- LedgerInitSettingData initSetting = new LedgerInitSettingData();
- ConsensusParticipantData[] parties = new ConsensusParticipantData[5];
- BlockchainKeypair[] bckeys = new BlockchainKeypair[parties.length];
- for (int i = 0; i < parties.length; i++) {
- bckeys[i] = BlockchainKeyGenerator.getInstance().generate();
- parties[i] = new ConsensusParticipantData();
- parties[i].setId(i);
- parties[i].setAddress(AddressEncoding.generateAddress(bckeys[i].getPubKey()).toBase58());
- parties[i].setHostAddress(new NetworkAddress("192.168.10." + (10 + i), 10010 + 10 * i));
- parties[i].setName("Participant[" + i + "]");
- parties[i].setPubKey(bckeys[i].getPubKey());
- }
- ConsensusParticipantData[] parties1 = Arrays.copyOf(parties, 4);
- initSetting.setConsensusParticipants(parties1);
-
- byte[] csSysSettingBytes = new byte[64];
- rand.nextBytes(csSysSettingBytes);
- initSetting.setConsensusSettings(new Bytes(csSysSettingBytes));
- initSetting.setConsensusProvider("consensus-provider");
-
- CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length];
- for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) {
- supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]);
- }
-
- CryptoConfig cryptoSetting = new CryptoConfig();
- cryptoSetting.setSupportedProviders(supportedProviders);
- cryptoSetting.setAutoVerifyHash(true);
- cryptoSetting.setHashAlgorithm(ClassicAlgorithm.SHA256);
- initSetting.setCryptoSetting(cryptoSetting);
-
- byte[] ledgerSeed = new byte[16];
- rand.nextBytes(ledgerSeed);
- initSetting.setLedgerSeed(ledgerSeed);
-
- MemoryKVStorage testStorage = new MemoryKVStorage();
-
- // Create intance with init setting;
- LedgerAdminAccount ledgerAdminAccount = new LedgerAdminAccount(initSetting, keyPrefix, testStorage,
- testStorage);
-
- // New created instance is updated until being committed;
- assertTrue(ledgerAdminAccount.isUpdated());
- // Hash of account is null until being committed;
- assertNull(ledgerAdminAccount.getHash());
-
- LedgerMetadata meta = ledgerAdminAccount.getMetadata();
- assertNull(meta.getParticipantsHash());
-
- // Commit, and check the storage keys;
- ledgerAdminAccount.commit();
-
- // New created instance isn't updated after being committed;
- assertFalse(ledgerAdminAccount.isUpdated());
- // Hash of account isn't null after being committed;
- assertNotNull(ledgerAdminAccount.getHash());
-
- meta = ledgerAdminAccount.getMetadata();
- assertNotNull(meta.getParticipantsHash());
-
- // ----------------------
- // Reload account from storage with readonly mode, and check the integrity of
- // data;
- HashDigest adminAccHash = ledgerAdminAccount.getHash();
- LedgerAdminAccount reloadAdminAccount = new LedgerAdminAccount(adminAccHash, keyPrefix, testStorage,
- testStorage, true);
-
- // verify realod settings of admin account;
- verifyRealoadingSettings(reloadAdminAccount, adminAccHash, ledgerAdminAccount.getMetadata());
-
- // verify the consensus participant list;
- verifyReadlingParities(reloadAdminAccount, parties1);
-
- // It will throw exeception because of this account is readonly;
- verifyReadonlyState(reloadAdminAccount);
-
- // --------------
- // reload again with writing mode;
- reloadAdminAccount = new LedgerAdminAccount(adminAccHash, keyPrefix, testStorage, testStorage, false);
- LedgerConfiguration newSetting = new LedgerConfiguration(reloadAdminAccount.getPreviousSetting());
- byte[] newCsSettingBytes = new byte[64];
- rand.nextBytes(newCsSettingBytes);
- newSetting.setConsensusSetting(new Bytes(newCsSettingBytes));
- newSetting.getCryptoSetting().setAutoVerifyHash(false);
- reloadAdminAccount.setLedgerSetting(newSetting);
-
- reloadAdminAccount.addParticipant(parties[4]);
- reloadAdminAccount.commit();
-
- // record the new account hash;
- HashDigest newAccHash = reloadAdminAccount.getHash();
- LedgerMetadata newMeta = reloadAdminAccount.getMetadata();
-
- // load the last version of account and verify again;
- reloadAdminAccount = new LedgerAdminAccount(adminAccHash, keyPrefix, testStorage, testStorage, true);
- verifyRealoadingSettings(reloadAdminAccount, adminAccHash, ledgerAdminAccount.getMetadata());
- verifyReadlingParities(reloadAdminAccount, parties1);
- verifyReadonlyState(reloadAdminAccount);
-
- // load the hash of new committing;
- reloadAdminAccount = new LedgerAdminAccount(newAccHash, keyPrefix, testStorage, testStorage, true);
- verifyRealoadingSettings(reloadAdminAccount, newAccHash, newMeta);
- verifyReadlingParities(reloadAdminAccount, parties);
- verifyReadonlyState(reloadAdminAccount);
-
- // System.out.println("========= [LedgerAdminAccount Test] Show generated
- // storage keys... =======");
- // testStorage.printStoragedKeys();
- }
-
- private void verifyRealoadingSettings(LedgerAdminAccount actualAccount, HashDigest expHash,
- LedgerMetadata expMeta) {
- // 验证基本信息;
- assertFalse(actualAccount.isUpdated());
- assertTrue(actualAccount.isReadonly());
-
- assertEquals(expHash, actualAccount.getHash());
-
- // verify metadata;
- LedgerMetadata rlmeta = actualAccount.getMetadata();
- assertEquals(expMeta.getParticipantsHash(), rlmeta.getParticipantsHash());
-
- assertTrue(BytesUtils.equals(expMeta.getSeed(), rlmeta.getSeed()));
-
- assertNotNull(rlmeta.getSetting());
- assertTrue(expMeta.getSetting().getConsensusSetting().equals(rlmeta.getSetting().getConsensusSetting()));
- assertEquals(expMeta.getSetting().getConsensusProvider(), rlmeta.getSetting().getConsensusProvider());
-
- assertEquals(expMeta.getSetting().getCryptoSetting().getAutoVerifyHash(),
- rlmeta.getSetting().getCryptoSetting().getAutoVerifyHash());
- assertEquals(expMeta.getSetting().getCryptoSetting().getHashAlgorithm(),
- rlmeta.getSetting().getCryptoSetting().getHashAlgorithm());
- }
-
- private void verifyReadlingParities(LedgerAdminAccount actualAccount, ParticipantNode[] expParties) {
- assertEquals(expParties.length, actualAccount.getParticipantCount());
- ParticipantNode[] actualPaticipants = actualAccount.getParticipants();
- assertEquals(expParties.length, actualPaticipants.length);
- for (int i = 0; i < actualPaticipants.length; i++) {
- ParticipantNode rlParti = actualPaticipants[i];
- assertEquals(expParties[i].getAddress(), rlParti.getAddress());
- assertEquals(expParties[i].getName(), rlParti.getName());
- // assertEquals(expParties[i].getConsensusAddress(),
- // rlParti.getConsensusAddress());
- assertEquals(expParties[i].getPubKey(), rlParti.getPubKey());
- }
- }
-
- private void verifyReadonlyState(LedgerAdminAccount actualAccount) {
- ConsensusParticipantData newParti = new ConsensusParticipantData();
- newParti.setId((int) actualAccount.getParticipantCount());
- newParti.setHostAddress(
- new NetworkAddress("192.168.10." + (10 + newParti.getAddress()), 10010 + 10 * newParti.getId()));
- newParti.setName("Participant[" + newParti.getAddress() + "]");
-
- BlockchainKeypair newKey = BlockchainKeyGenerator.getInstance().generate();
- newParti.setPubKey(newKey.getPubKey());
-
- Throwable ex = null;
- try {
- actualAccount.addParticipant(newParti);
- } catch (Exception e) {
- ex = e;
- }
- assertNotNull(ex);
-
- ex = null;
- try {
- LedgerConfiguration newLedgerSetting = new LedgerConfiguration(actualAccount.getSetting());
- actualAccount.setLedgerSetting(newLedgerSetting);
- } catch (Exception e) {
- ex = e;
- }
- assertNotNull(ex);
- }
-
-}
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TransactionBatchProcessorTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TransactionBatchProcessorTest.java
deleted file mode 100644
index 72c8a848..00000000
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TransactionBatchProcessorTest.java
+++ /dev/null
@@ -1,140 +0,0 @@
-package test.com.jd.blockchain.ledger;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import org.junit.Test;
-
-import com.jd.blockchain.binaryproto.DataContractRegistry;
-import com.jd.blockchain.crypto.HashDigest;
-import com.jd.blockchain.ledger.BlockchainKeyGenerator;
-import com.jd.blockchain.ledger.BlockchainKeypair;
-import com.jd.blockchain.ledger.EndpointRequest;
-import com.jd.blockchain.ledger.LedgerBlock;
-import com.jd.blockchain.ledger.LedgerInitSetting;
-import com.jd.blockchain.ledger.LedgerTransaction;
-import com.jd.blockchain.ledger.NodeRequest;
-import com.jd.blockchain.ledger.TransactionContent;
-import com.jd.blockchain.ledger.TransactionContentBody;
-import com.jd.blockchain.ledger.TransactionRequest;
-import com.jd.blockchain.ledger.TransactionResponse;
-import com.jd.blockchain.ledger.TransactionState;
-import com.jd.blockchain.ledger.UserRegisterOperation;
-import com.jd.blockchain.ledger.core.LedgerDataSet;
-import com.jd.blockchain.ledger.core.LedgerEditor;
-import com.jd.blockchain.ledger.core.LedgerRepository;
-import com.jd.blockchain.ledger.core.LedgerTransactionContext;
-import com.jd.blockchain.ledger.core.UserAccount;
-import com.jd.blockchain.ledger.core.impl.DefaultOperationHandleRegisteration;
-import com.jd.blockchain.ledger.core.impl.LedgerManager;
-import com.jd.blockchain.ledger.core.impl.LedgerTransactionalEditor;
-import com.jd.blockchain.ledger.core.impl.OperationHandleRegisteration;
-import com.jd.blockchain.ledger.core.impl.TransactionBatchProcessor;
-import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
-
-public class TransactionBatchProcessorTest {
- static {
- DataContractRegistry.register(TransactionContent.class);
- DataContractRegistry.register(TransactionContentBody.class);
- DataContractRegistry.register(TransactionRequest.class);
- DataContractRegistry.register(NodeRequest.class);
- DataContractRegistry.register(EndpointRequest.class);
- DataContractRegistry.register(TransactionResponse.class);
- DataContractRegistry.register(UserRegisterOperation.class);
- }
-
- private static final String LEDGER_KEY_PREFIX = "LDG://";
-
- private HashDigest ledgerHash = null;
-
- private BlockchainKeypair parti0 = BlockchainKeyGenerator.getInstance().generate();
- private BlockchainKeypair parti1 = BlockchainKeyGenerator.getInstance().generate();
- private BlockchainKeypair parti2 = BlockchainKeyGenerator.getInstance().generate();
- private BlockchainKeypair parti3 = BlockchainKeyGenerator.getInstance().generate();
-
- private TransactionRequest transactionRequest;
-
- // 采用基于内存的 Storage;
- private MemoryKVStorage storage = new MemoryKVStorage();
-
- @Test
- public void testTxReqProcess() {
- // 初始化账本到指定的存储库;
- ledgerHash = initLedger(storage, parti0, parti1, parti2, parti3);
-
- // 加载账本;
- LedgerManager ledgerManager = new LedgerManager();
- LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, storage);
-
- // 验证参与方账户的存在;
- LedgerDataSet previousBlockDataset = ledgerRepo.getDataSet(ledgerRepo.getLatestBlock());
- UserAccount user0 = previousBlockDataset.getUserAccountSet().getUser(parti0.getAddress());
- assertNotNull(user0);
- boolean partiRegistered = previousBlockDataset.getUserAccountSet().contains(parti0.getAddress());
- assertTrue(partiRegistered);
-
- // 生成新区块;
- LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();
-
- OperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration();
- TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(newBlockEditor, previousBlockDataset,
- opReg, ledgerManager);
-
- // 注册新用户;
- BlockchainKeypair userKeypair = BlockchainKeyGenerator.getInstance().generate();
- transactionRequest = LedgerTestUtils.createTxRequest_UserReg(ledgerHash, userKeypair, parti0);
- txbatchProcessor.schedule(transactionRequest);
-
- LedgerBlock newBlock = newBlockEditor.prepare();
- newBlockEditor.commit();
-
- // 验证正确性;
- ledgerManager = new LedgerManager();
- ledgerRepo = ledgerManager.register(ledgerHash, storage);
-
- LedgerBlock latestBlock = ledgerRepo.getLatestBlock();
- assertEquals(newBlock.getHash(), latestBlock.getHash());
- assertEquals(1, newBlock.getHeight());
- }
-
- private HashDigest initLedger(MemoryKVStorage storage, BlockchainKeypair... partiKeys) {
- // 创建初始化配置;
- LedgerInitSetting initSetting = LedgerTestUtils.createLedgerInitSetting(partiKeys);
-
- // 创建账本;
- LedgerEditor ldgEdt = LedgerTransactionalEditor.createEditor(initSetting, LEDGER_KEY_PREFIX, storage, storage);
-
- TransactionRequest genesisTxReq = LedgerTestUtils.createTxRequest_UserReg(null);
- LedgerTransactionContext genisisTxCtx = ldgEdt.newTransaction(genesisTxReq);
- LedgerDataSet ldgDS = genisisTxCtx.getDataSet();
-
- for (int i = 0; i < partiKeys.length; i++) {
- UserAccount userAccount = ldgDS.getUserAccountSet().register(partiKeys[i].getAddress(),
- partiKeys[i].getPubKey());
- userAccount.setProperty("Name", "参与方-" + i, -1);
- userAccount.setProperty("Share", "" + (10 + i), -1);
- }
-
- LedgerTransaction tx = genisisTxCtx.commit(TransactionState.SUCCESS);
-
- assertEquals(genesisTxReq.getTransactionContent().getHash(), tx.getTransactionContent().getHash());
- assertEquals(0, tx.getBlockHeight());
-
- LedgerBlock block = ldgEdt.prepare();
-
- assertEquals(0, block.getHeight());
- assertNotNull(block.getHash());
- assertNull(block.getPreviousHash());
-
- assertEquals(block.getHash(), block.getLedgerHash());
-
- // 提交数据,写入存储;
- ldgEdt.commit();
-
- HashDigest ledgerHash = block.getHash();
- return ledgerHash;
- }
-
-}
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TxTestContract.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TxTestContract.java
new file mode 100644
index 00000000..80ee477f
--- /dev/null
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TxTestContract.java
@@ -0,0 +1,15 @@
+package test.com.jd.blockchain.ledger;
+
+import com.jd.blockchain.contract.Contract;
+import com.jd.blockchain.contract.ContractEvent;
+
+@Contract
+public interface TxTestContract {
+
+ @ContractEvent(name = "testReadable")
+ boolean testReadable();
+
+ @ContractEvent(name = "testRollbackWhileVersionConfliction")
+ void testRollbackWhileVersionConfliction(String address, String key, String value, long version);
+
+}
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TxTestContractImpl.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TxTestContractImpl.java
new file mode 100644
index 00000000..60ee6864
--- /dev/null
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TxTestContractImpl.java
@@ -0,0 +1,74 @@
+package test.com.jd.blockchain.ledger;
+
+import com.jd.blockchain.contract.ContractEventContext;
+import com.jd.blockchain.contract.ContractLifecycleAware;
+import com.jd.blockchain.contract.EventProcessingAware;
+import com.jd.blockchain.ledger.KVDataEntry;
+import com.jd.blockchain.utils.Bytes;
+
+public class TxTestContractImpl implements TxTestContract, ContractLifecycleAware, EventProcessingAware {
+
+ private ContractEventContext eventContext;
+
+ private Bytes dataAddress;
+
+ public static String KEY = "k1";
+
+ @Override
+ public boolean testReadable() {
+ KVDataEntry v1 = eventContext.getLedger().getDataEntries(eventContext.getCurrentLedgerHash(),
+ dataAddress.toBase58(), KEY)[0];
+ String text1 = (String) v1.getValue();
+ System.out.printf("k1=%s, version=%s \r\n", text1, v1.getVersion());
+
+ text1 = null == text1 ? "v" : text1;
+ String newValue = text1 + "-" + (v1.getVersion() + 1);
+ System.out.printf("new value = %s\r\n", newValue);
+ eventContext.getLedger().dataAccount(dataAddress).setText(KEY, newValue, v1.getVersion());
+
+ KVDataEntry v2 = eventContext.getLedger().getDataEntries(eventContext.getCurrentLedgerHash(),
+ dataAddress.toBase58(), KEY)[0];
+ System.out.printf("---- read new value ----\r\nk1=%s, version=%s \r\n", v2.getValue(), v2.getVersion());
+
+ String text2 = (String) v2.getValue();
+ return text1.equals(text2);
+ }
+
+ @Override
+ public void testRollbackWhileVersionConfliction(String address, String key, String value, long version) {
+ eventContext.getLedger().dataAccount(address).setText(key, value, version);
+ }
+
+
+ @Override
+ public void postConstruct() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void beforeDestroy() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void beforeEvent(ContractEventContext eventContext) {
+ this.eventContext = eventContext;
+ }
+
+ @Override
+ public void postEvent(ContractEventContext eventContext, Exception error) {
+ this.eventContext = null;
+ }
+
+ public Bytes getDataAddress() {
+ return dataAddress;
+ }
+
+ public void setDataAddress(Bytes dataAddress) {
+ this.dataAddress = dataAddress;
+ }
+
+
+}
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/AccountSetTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/AccountSetTest.java
similarity index 96%
rename from source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/AccountSetTest.java
rename to source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/AccountSetTest.java
index 5b69b118..d3e565a5 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/AccountSetTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/AccountSetTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger;
+package test.com.jd.blockchain.ledger.core;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -17,7 +17,7 @@ import com.jd.blockchain.ledger.BlockchainKeypair;
import com.jd.blockchain.ledger.core.AccountSet;
import com.jd.blockchain.ledger.core.BaseAccount;
import com.jd.blockchain.ledger.core.CryptoConfig;
-import com.jd.blockchain.ledger.core.impl.OpeningAccessPolicy;
+import com.jd.blockchain.ledger.core.OpeningAccessPolicy;
import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
public class AccountSetTest {
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/BaseAccountTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/BaseAccountTest.java
similarity index 98%
rename from source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/BaseAccountTest.java
rename to source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/BaseAccountTest.java
index 4a641b7d..d02f9b11 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/BaseAccountTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/BaseAccountTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger;
+package test.com.jd.blockchain.ledger.core;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/ContractInvokingHandle.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/ContractInvokingHandle.java
new file mode 100644
index 00000000..2bd98895
--- /dev/null
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/ContractInvokingHandle.java
@@ -0,0 +1,28 @@
+package test.com.jd.blockchain.ledger.core;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import com.jd.blockchain.contract.engine.ContractCode;
+import com.jd.blockchain.contract.jvm.InstantiatedContractCode;
+import com.jd.blockchain.ledger.core.ContractAccount;
+import com.jd.blockchain.ledger.core.handles.AbtractContractEventSendOperationHandle;
+import com.jd.blockchain.utils.Bytes;
+
+public class ContractInvokingHandle extends AbtractContractEventSendOperationHandle {
+
+ private Map contractInstances = new ConcurrentHashMap();
+
+ @Override
+ protected ContractCode loadContractCode(ContractAccount contract) {
+ return contractInstances.get(contract.getAddress());
+ }
+
+ public ContractCode setup(Bytes address, Class contractIntf, T instance) {
+ InstantiatedContractCode contract = new InstantiatedContractCode(address, 0, contractIntf, instance);
+ contractInstances.put(address, contract);
+ return contract;
+ }
+
+
+}
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/ContractInvokingTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/ContractInvokingTest.java
new file mode 100644
index 00000000..32fd8263
--- /dev/null
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/ContractInvokingTest.java
@@ -0,0 +1,501 @@
+package test.com.jd.blockchain.ledger.core;
+
+import static com.jd.blockchain.transaction.ContractReturnValue.decode;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.InputStream;
+import java.util.Random;
+
+import com.jd.blockchain.utils.io.BytesUtils;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import com.jd.blockchain.binaryproto.BinaryProtocol;
+import com.jd.blockchain.binaryproto.DataContractRegistry;
+import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.ledger.BlockchainKeyGenerator;
+import com.jd.blockchain.ledger.BlockchainKeypair;
+import com.jd.blockchain.ledger.BytesData;
+import com.jd.blockchain.ledger.BytesValue;
+import com.jd.blockchain.ledger.DataAccountRegisterOperation;
+import com.jd.blockchain.ledger.EndpointRequest;
+import com.jd.blockchain.ledger.KVDataEntry;
+import com.jd.blockchain.ledger.LedgerBlock;
+import com.jd.blockchain.ledger.LedgerInitSetting;
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.LedgerTransaction;
+import com.jd.blockchain.ledger.NodeRequest;
+import com.jd.blockchain.ledger.OperationResult;
+import com.jd.blockchain.ledger.TransactionContent;
+import com.jd.blockchain.ledger.TransactionContentBody;
+import com.jd.blockchain.ledger.TransactionPermission;
+import com.jd.blockchain.ledger.TransactionRequest;
+import com.jd.blockchain.ledger.TransactionRequestBuilder;
+import com.jd.blockchain.ledger.TransactionResponse;
+import com.jd.blockchain.ledger.TransactionState;
+import com.jd.blockchain.ledger.UserRegisterOperation;
+import com.jd.blockchain.ledger.core.DefaultOperationHandleRegisteration;
+import com.jd.blockchain.ledger.core.LedgerDataQuery;
+import com.jd.blockchain.ledger.core.LedgerDataset;
+import com.jd.blockchain.ledger.core.LedgerEditor;
+import com.jd.blockchain.ledger.core.LedgerManager;
+import com.jd.blockchain.ledger.core.LedgerRepository;
+import com.jd.blockchain.ledger.core.LedgerSecurityManager;
+import com.jd.blockchain.ledger.core.LedgerService;
+import com.jd.blockchain.ledger.core.LedgerTransactionContext;
+import com.jd.blockchain.ledger.core.LedgerTransactionalEditor;
+import com.jd.blockchain.ledger.core.OperationHandleRegisteration;
+import com.jd.blockchain.ledger.core.SecurityPolicy;
+import com.jd.blockchain.ledger.core.TransactionBatchProcessor;
+import com.jd.blockchain.ledger.core.UserAccount;
+import com.jd.blockchain.service.TransactionBatchResultHandle;
+import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
+import com.jd.blockchain.transaction.BooleanValueHolder;
+import com.jd.blockchain.transaction.TxBuilder;
+import com.jd.blockchain.utils.Bytes;
+
+import test.com.jd.blockchain.ledger.TxTestContract;
+import test.com.jd.blockchain.ledger.TxTestContractImpl;
+
+public class ContractInvokingTest {
+ static {
+ DataContractRegistry.register(TransactionContent.class);
+ DataContractRegistry.register(TransactionContentBody.class);
+ DataContractRegistry.register(TransactionRequest.class);
+ DataContractRegistry.register(NodeRequest.class);
+ DataContractRegistry.register(EndpointRequest.class);
+ DataContractRegistry.register(TransactionResponse.class);
+ DataContractRegistry.register(UserRegisterOperation.class);
+ DataContractRegistry.register(DataAccountRegisterOperation.class);
+ }
+
+ private static final String LEDGER_KEY_PREFIX = "LDG://";
+
+ private BlockchainKeypair parti0 = BlockchainKeyGenerator.getInstance().generate();
+ private BlockchainKeypair parti1 = BlockchainKeyGenerator.getInstance().generate();
+ private BlockchainKeypair parti2 = BlockchainKeyGenerator.getInstance().generate();
+ private BlockchainKeypair parti3 = BlockchainKeyGenerator.getInstance().generate();
+
+ // 采用基于内存的 Storage;
+ private MemoryKVStorage storage = new MemoryKVStorage();
+
+ private static final String CONTRACT_JAR = "contract-JDChain-Contract.jar";
+
+ @Test
+ public void testNormal() {
+ // 初始化账本到指定的存储库;
+ HashDigest ledgerHash = initLedger(storage, parti0, parti1, parti2, parti3);
+
+ // 重新加载账本;
+ LedgerManager ledgerManager = new LedgerManager();
+ LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, storage);
+
+ // 创建合约处理器;
+ ContractInvokingHandle contractInvokingHandle = new ContractInvokingHandle();
+
+ // 创建和加载合约实例;
+ BlockchainKeypair contractKey = BlockchainKeyGenerator.getInstance().generate();
+ Bytes contractAddress = contractKey.getAddress();
+
+ TestContract contractInstance = Mockito.mock(TestContract.class);
+ final String asset = "AK";
+ final long issueAmount = new Random().nextLong();
+ when(contractInstance.issue(anyString(), anyLong())).thenReturn(issueAmount);
+
+ // 装载合约;
+ contractInvokingHandle.setup(contractAddress, TestContract.class, contractInstance);
+
+ // 注册合约处理器;
+ DefaultOperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration();
+ opReg.registerHandle(contractInvokingHandle);
+
+ // 发布指定地址合约
+ deploy(ledgerRepo, ledgerManager, opReg, ledgerHash, contractKey);
+ // 创建新区块的交易处理器;
+ LedgerBlock preBlock = ledgerRepo.getLatestBlock();
+ LedgerDataQuery previousBlockDataset = ledgerRepo.getDataSet(preBlock);
+
+ // 加载合约
+ LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();
+ LedgerSecurityManager securityManager = getSecurityManager();
+ TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor,
+ previousBlockDataset, opReg, ledgerManager);
+
+ // 构建基于接口调用合约的交易请求,用于测试合约调用;
+ TxBuilder txBuilder = new TxBuilder(ledgerHash);
+ TestContract contractProxy = txBuilder.contract(contractAddress, TestContract.class);
+
+ // 构造调用合约的交易;
+ contractProxy.issue(asset, issueAmount);
+
+ TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest();
+ txReqBuilder.signAsEndpoint(parti0);
+ txReqBuilder.signAsNode(parti0);
+ TransactionRequest txReq = txReqBuilder.buildRequest();
+
+ TransactionResponse resp = txbatchProcessor.schedule(txReq);
+ verify(contractInstance, times(1)).issue(asset, issueAmount);
+ OperationResult[] opResults = resp.getOperationResults();
+ assertEquals(1, opResults.length);
+ assertEquals(0, opResults[0].getIndex());
+
+ byte[] expectedRetnBytes = BinaryProtocol.encode(BytesData.fromInt64(issueAmount), BytesValue.class);
+ byte[] reallyRetnBytes = BinaryProtocol.encode(opResults[0].getResult(), BytesValue.class);
+ assertArrayEquals(expectedRetnBytes, reallyRetnBytes);
+
+ // 提交区块;
+ TransactionBatchResultHandle txResultHandle = txbatchProcessor.prepare();
+ txResultHandle.commit();
+
+ LedgerBlock latestBlock = ledgerRepo.getLatestBlock();
+ assertEquals(preBlock.getHeight() + 1, latestBlock.getHeight());
+ assertEquals(resp.getBlockHeight(), latestBlock.getHeight());
+ assertEquals(resp.getBlockHash(), latestBlock.getHash());
+
+ // 再验证一次结果;
+ assertEquals(1, opResults.length);
+ assertEquals(0, opResults[0].getIndex());
+
+ reallyRetnBytes = BinaryProtocol.encode(opResults[0].getResult(), BytesValue.class);
+ assertArrayEquals(expectedRetnBytes, reallyRetnBytes);
+
+ }
+
+// @Test
+ public void testReadNewWritting() {
+ // 初始化账本到指定的存储库;
+ HashDigest ledgerHash = initLedger(storage, parti0, parti1, parti2, parti3);
+
+ // 重新加载账本;
+ LedgerManager ledgerManager = new LedgerManager();
+ LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, storage);
+
+ // 创建合约处理器;
+ ContractInvokingHandle contractInvokingHandle = new ContractInvokingHandle();
+
+ // 创建和加载合约实例;
+ BlockchainKeypair contractKey = BlockchainKeyGenerator.getInstance().generate();
+ Bytes contractAddress = contractKey.getAddress();
+ TxTestContractImpl contractInstance = new TxTestContractImpl();
+ contractInvokingHandle.setup(contractAddress, TxTestContract.class, contractInstance);
+
+ // 注册合约处理器;
+ DefaultOperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration();
+ opReg.registerHandle(contractInvokingHandle);
+
+ // 发布指定地址合约
+ deploy(ledgerRepo, ledgerManager, opReg, ledgerHash, contractKey);
+
+ // 创建新区块的交易处理器;
+ LedgerBlock preBlock = ledgerRepo.getLatestBlock();
+ LedgerDataQuery previousBlockDataset = ledgerRepo.getDataSet(preBlock);
+
+ // 加载合约
+ LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();
+ TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(getSecurityManager(), newBlockEditor,
+ previousBlockDataset, opReg, ledgerManager);
+
+ String key = TxTestContractImpl.KEY;
+ String value = "VAL";
+
+ TxBuilder txBuilder = new TxBuilder(ledgerHash);
+ BlockchainKeypair kpDataAccount = BlockchainKeyGenerator.getInstance().generate();
+ contractInstance.setDataAddress(kpDataAccount.getAddress());
+
+ txBuilder.dataAccounts().register(kpDataAccount.getIdentity());
+ TransactionRequestBuilder txReqBuilder1 = txBuilder.prepareRequest();
+ txReqBuilder1.signAsEndpoint(parti0);
+ txReqBuilder1.signAsNode(parti0);
+ TransactionRequest txReq1 = txReqBuilder1.buildRequest();
+
+ // 构建基于接口调用合约的交易请求,用于测试合约调用;
+ txBuilder = new TxBuilder(ledgerHash);
+ TxTestContract contractProxy = txBuilder.contract(contractAddress, TxTestContract.class);
+ BooleanValueHolder readableHolder = decode(contractProxy.testReadable());
+
+ TransactionRequestBuilder txReqBuilder2 = txBuilder.prepareRequest();
+ txReqBuilder2.signAsEndpoint(parti0);
+ txReqBuilder2.signAsNode(parti0);
+ TransactionRequest txReq2 = txReqBuilder2.buildRequest();
+
+ TransactionResponse resp1 = txbatchProcessor.schedule(txReq1);
+ TransactionResponse resp2 = txbatchProcessor.schedule(txReq2);
+
+ // 提交区块;
+ TransactionBatchResultHandle txResultHandle = txbatchProcessor.prepare();
+ txResultHandle.commit();
+
+ BytesValue latestValue = ledgerRepo.getDataAccountSet().getDataAccount(kpDataAccount.getAddress()).getBytes(key,
+ -1);
+ System.out.printf("latest value=[%s] %s \r\n", latestValue.getType(), latestValue.getValue().toUTF8String());
+
+ boolean readable = readableHolder.get();
+ assertTrue(readable);
+
+ LedgerBlock latestBlock = ledgerRepo.getLatestBlock();
+ assertEquals(preBlock.getHeight() + 1, latestBlock.getHeight());
+ assertEquals(resp1.getBlockHeight(), latestBlock.getHeight());
+ assertEquals(resp1.getBlockHash(), latestBlock.getHash());
+ }
+
+ /**
+ * 验证在合约方法中写入数据账户时,如果版本校验失败是否会引发异常而导致回滚;
+ * 期待正确的表现是引发异常而回滚当前交易;
+ */
+ @Test
+ public void testRollbackWhileVersionConfliction() {
+ // 初始化账本到指定的存储库;
+ HashDigest ledgerHash = initLedger(storage, parti0, parti1, parti2, parti3);
+
+ // 重新加载账本;
+ LedgerManager ledgerManager = new LedgerManager();
+ LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, storage);
+
+ // 创建合约处理器;
+ ContractInvokingHandle contractInvokingHandle = new ContractInvokingHandle();
+
+ // 创建和加载合约实例;
+ BlockchainKeypair contractKey = BlockchainKeyGenerator.getInstance().generate();
+ Bytes contractAddress = contractKey.getAddress();
+ TxTestContractImpl contractInstance = new TxTestContractImpl();
+ contractInvokingHandle.setup(contractAddress, TxTestContract.class, contractInstance);
+
+ // 注册合约处理器;
+ DefaultOperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration();
+ opReg.registerHandle(contractInvokingHandle);
+
+ // 发布指定地址合约
+ deploy(ledgerRepo, ledgerManager, opReg, ledgerHash, contractKey);
+
+ // 注册数据账户;
+ BlockchainKeypair kpDataAccount = BlockchainKeyGenerator.getInstance().generate();
+ contractInstance.setDataAddress(kpDataAccount.getAddress());
+ registerDataAccount(ledgerRepo, ledgerManager, opReg, ledgerHash, kpDataAccount);
+
+ // 调用合约
+ // 构建基于接口调用合约的交易请求,用于测试合约调用;
+ buildBlock(ledgerRepo, ledgerManager, opReg, new TxDefinitor() {
+ @Override
+ public void buildTx(TxBuilder txBuilder) {
+ TxTestContract contractProxy = txBuilder.contract(contractAddress, TxTestContract.class);
+ contractProxy.testRollbackWhileVersionConfliction(kpDataAccount.getAddress().toBase58(), "K1", "V1-0",
+ -1);
+ contractProxy.testRollbackWhileVersionConfliction(kpDataAccount.getAddress().toBase58(), "K2", "V2-0",
+ -1);
+ }
+ });
+ // 预期数据都能够正常写入;
+ KVDataEntry kv1 = ledgerRepo.getDataAccountSet().getDataAccount(kpDataAccount.getAddress()).getDataEntry("K1",
+ 0);
+ KVDataEntry kv2 = ledgerRepo.getDataAccountSet().getDataAccount(kpDataAccount.getAddress()).getDataEntry("K2",
+ 0);
+ assertEquals(0, kv1.getVersion());
+ assertEquals(0, kv2.getVersion());
+ assertEquals("V1-0", kv1.getValue());
+ assertEquals("V2-0", kv2.getValue());
+
+ // 构建基于接口调用合约的交易请求,用于测试合约调用;
+ buildBlock(ledgerRepo, ledgerManager, opReg, new TxDefinitor() {
+ @Override
+ public void buildTx(TxBuilder txBuilder) {
+ TxTestContract contractProxy = txBuilder.contract(contractAddress, TxTestContract.class);
+ contractProxy.testRollbackWhileVersionConfliction(kpDataAccount.getAddress().toBase58(), "K1", "V1-1",
+ 0);
+ contractProxy.testRollbackWhileVersionConfliction(kpDataAccount.getAddress().toBase58(), "K2", "V2-1",
+ 0);
+ }
+ });
+ // 预期数据都能够正常写入;
+ kv1 = ledgerRepo.getDataAccountSet().getDataAccount(kpDataAccount.getAddress()).getDataEntry("K1", 1);
+ kv2 = ledgerRepo.getDataAccountSet().getDataAccount(kpDataAccount.getAddress()).getDataEntry("K2", 1);
+ assertEquals(1, kv1.getVersion());
+ assertEquals(1, kv2.getVersion());
+ assertEquals("V1-1", kv1.getValue());
+ assertEquals("V2-1", kv2.getValue());
+
+ // 构建基于接口调用合约的交易请求,用于测试合约调用;
+ buildBlock(ledgerRepo, ledgerManager, opReg, new TxDefinitor() {
+ @Override
+ public void buildTx(TxBuilder txBuilder) {
+ TxTestContract contractProxy = txBuilder.contract(contractAddress, TxTestContract.class);
+ contractProxy.testRollbackWhileVersionConfliction(kpDataAccount.getAddress().toBase58(), "K1", "V1-2",
+ 1);
+ contractProxy.testRollbackWhileVersionConfliction(kpDataAccount.getAddress().toBase58(), "K2", "V2-2",
+ 0);
+ }
+ });
+ // 预期数据都能够正常写入;
+ kv1 = ledgerRepo.getDataAccountSet().getDataAccount(kpDataAccount.getAddress()).getDataEntry("K1", 1);
+ assertEquals(1, kv1.getVersion());
+ assertEquals("V1-1", kv1.getValue());
+ kv1 = ledgerRepo.getDataAccountSet().getDataAccount(kpDataAccount.getAddress()).getDataEntry("K1", 2);
+ assertEquals(-1, kv1.getVersion());
+ assertEquals(null, kv1.getValue());
+
+ }
+
+ private LedgerBlock buildBlock(LedgerRepository ledgerRepo, LedgerService ledgerService,
+ OperationHandleRegisteration opReg, TxDefinitor txDefinitor) {
+ LedgerBlock preBlock = ledgerRepo.getLatestBlock();
+ LedgerDataQuery previousBlockDataset = ledgerRepo.getDataSet(preBlock);
+ LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();
+ TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(getSecurityManager(), newBlockEditor,
+ previousBlockDataset, opReg, ledgerService);
+
+ TxBuilder txBuilder = new TxBuilder(ledgerRepo.getHash());
+ txDefinitor.buildTx(txBuilder);
+
+ TransactionRequest txReq = buildAndSignRequest(txBuilder, parti0, parti0);
+ TransactionResponse resp = txbatchProcessor.schedule(txReq);
+
+ // 提交区块;
+ TransactionBatchResultHandle txResultHandle = txbatchProcessor.prepare();
+ txResultHandle.commit();
+
+ LedgerBlock latestBlock = ledgerRepo.getLatestBlock();
+ assertNotNull(resp.getBlockHash());
+ assertEquals(preBlock.getHeight() + 1, resp.getBlockHeight());
+ return latestBlock;
+ }
+
+ private TransactionRequest buildAndSignRequest(TxBuilder txBuilder, BlockchainKeypair endpointKey,
+ BlockchainKeypair nodeKey) {
+ TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest();
+ txReqBuilder.signAsEndpoint(endpointKey);
+ txReqBuilder.signAsNode(nodeKey);
+ TransactionRequest txReq = txReqBuilder.buildRequest();
+ return txReq;
+ }
+
+ private void registerDataAccount(LedgerRepository ledgerRepo, LedgerManager ledgerManager,
+ DefaultOperationHandleRegisteration opReg, HashDigest ledgerHash, BlockchainKeypair kpDataAccount) {
+ LedgerBlock preBlock = ledgerRepo.getLatestBlock();
+ LedgerDataQuery previousBlockDataset = ledgerRepo.getDataSet(preBlock);
+
+ // 加载合约
+ LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();
+ TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(getSecurityManager(), newBlockEditor,
+ previousBlockDataset, opReg, ledgerManager);
+
+ // 注册数据账户;
+ TxBuilder txBuilder = new TxBuilder(ledgerHash);
+
+ txBuilder.dataAccounts().register(kpDataAccount.getIdentity());
+ TransactionRequestBuilder txReqBuilder1 = txBuilder.prepareRequest();
+ txReqBuilder1.signAsEndpoint(parti0);
+ txReqBuilder1.signAsNode(parti0);
+ TransactionRequest txReq = txReqBuilder1.buildRequest();
+
+ TransactionResponse resp = txbatchProcessor.schedule(txReq);
+
+ TransactionBatchResultHandle txResultHandle = txbatchProcessor.prepare();
+ txResultHandle.commit();
+
+ assertNotNull(resp.getBlockHash());
+ assertEquals(TransactionState.SUCCESS, resp.getExecutionState());
+ assertEquals(preBlock.getHeight() + 1, resp.getBlockHeight());
+ }
+
+ private void deploy(LedgerRepository ledgerRepo, LedgerManager ledgerManager,
+ DefaultOperationHandleRegisteration opReg, HashDigest ledgerHash, BlockchainKeypair contractKey) {
+ // 创建新区块的交易处理器;
+ LedgerBlock preBlock = ledgerRepo.getLatestBlock();
+ LedgerDataQuery previousBlockDataset = ledgerRepo.getDataSet(preBlock);
+
+ // 加载合约
+ LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();
+ LedgerSecurityManager securityManager = getSecurityManager();
+ TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor,
+ previousBlockDataset, opReg, ledgerManager);
+
+ // 构建基于接口调用合约的交易请求,用于测试合约调用;
+ TxBuilder txBuilder = new TxBuilder(ledgerHash);
+ txBuilder.contracts().deploy(contractKey.getIdentity(), chainCode());
+ TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest();
+ txReqBuilder.signAsEndpoint(parti0);
+ txReqBuilder.signAsNode(parti0);
+ TransactionRequest txReq = txReqBuilder.buildRequest();
+
+ TransactionResponse resp = txbatchProcessor.schedule(txReq);
+ OperationResult[] opResults = resp.getOperationResults();
+ assertNull(opResults);
+
+ // 提交区块;
+ TransactionBatchResultHandle txResultHandle = txbatchProcessor.prepare();
+ txResultHandle.commit();
+ }
+
+ private HashDigest initLedger(MemoryKVStorage storage, BlockchainKeypair... partiKeys) {
+ // 创建初始化配置;
+ LedgerInitSetting initSetting = LedgerTestUtils.createLedgerInitSetting(partiKeys);
+
+ // 创建账本;
+ LedgerEditor ldgEdt = LedgerTransactionalEditor.createEditor(initSetting, LEDGER_KEY_PREFIX, storage, storage);
+
+ TransactionRequest genesisTxReq = LedgerTestUtils.createLedgerInitTxRequest(partiKeys);
+ LedgerTransactionContext genisisTxCtx = ldgEdt.newTransaction(genesisTxReq);
+ LedgerDataset ldgDS = genisisTxCtx.getDataset();
+
+ for (int i = 0; i < partiKeys.length; i++) {
+ UserAccount userAccount = ldgDS.getUserAccountSet().register(partiKeys[i].getAddress(),
+ partiKeys[i].getPubKey());
+ userAccount.setProperty("Name", "参与方-" + i, -1);
+ userAccount.setProperty("Share", "" + (10 + i), -1);
+ }
+
+ LedgerTransaction tx = genisisTxCtx.commit(TransactionState.SUCCESS);
+
+ assertEquals(genesisTxReq.getTransactionContent().getHash(), tx.getTransactionContent().getHash());
+ assertEquals(0, tx.getBlockHeight());
+
+ LedgerBlock block = ldgEdt.prepare();
+
+ assertEquals(0, block.getHeight());
+ assertNotNull(block.getHash());
+ assertNull(block.getLedgerHash());
+ assertNull(block.getPreviousHash());
+
+ // 提交数据,写入存储;
+ ldgEdt.commit();
+
+ HashDigest ledgerHash = block.getHash();
+ return ledgerHash;
+ }
+
+ private byte[] chainCode() {
+
+ InputStream in = this.getClass().getResourceAsStream("/" + CONTRACT_JAR);
+
+ return BytesUtils.copyToBytes(in);
+ }
+
+ private static LedgerSecurityManager getSecurityManager() {
+ LedgerSecurityManager securityManager = Mockito.mock(LedgerSecurityManager.class);
+
+ SecurityPolicy securityPolicy = Mockito.mock(SecurityPolicy.class);
+ when(securityPolicy.isEndpointEnable(any(LedgerPermission.class), any())).thenReturn(true);
+ when(securityPolicy.isEndpointEnable(any(TransactionPermission.class), any())).thenReturn(true);
+ when(securityPolicy.isNodeEnable(any(LedgerPermission.class), any())).thenReturn(true);
+ when(securityPolicy.isNodeEnable(any(TransactionPermission.class), any())).thenReturn(true);
+
+ when(securityManager.createSecurityPolicy(any(), any())).thenReturn(securityPolicy);
+
+ return securityManager;
+ }
+
+ public static interface TxDefinitor {
+
+ void buildTx(TxBuilder txBuilder);
+
+ }
+}
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerAccountTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerAccountTest.java
similarity index 97%
rename from source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerAccountTest.java
rename to source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerAccountTest.java
index 18566ca6..27dcc438 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerAccountTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerAccountTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger;
+package test.com.jd.blockchain.ledger.core;
import static org.junit.Assert.assertEquals;
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerAdminDatasetTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerAdminDatasetTest.java
new file mode 100644
index 00000000..e591aa7f
--- /dev/null
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerAdminDatasetTest.java
@@ -0,0 +1,305 @@
+package test.com.jd.blockchain.ledger.core;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.Random;
+
+import org.junit.Test;
+
+import com.jd.blockchain.crypto.AddressEncoding;
+import com.jd.blockchain.crypto.Crypto;
+import com.jd.blockchain.crypto.CryptoProvider;
+import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
+import com.jd.blockchain.crypto.service.classic.ClassicCryptoService;
+import com.jd.blockchain.crypto.service.sm.SMCryptoService;
+import com.jd.blockchain.ledger.BlockchainKeyGenerator;
+import com.jd.blockchain.ledger.BlockchainKeypair;
+import com.jd.blockchain.ledger.LedgerAdminInfo;
+import com.jd.blockchain.ledger.LedgerMetadata_V2;
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.LedgerSettings;
+import com.jd.blockchain.ledger.ParticipantNode;
+import com.jd.blockchain.ledger.RolePrivilegeSettings;
+import com.jd.blockchain.ledger.RolePrivileges;
+import com.jd.blockchain.ledger.RolesPolicy;
+import com.jd.blockchain.ledger.TransactionPermission;
+import com.jd.blockchain.ledger.UserRolesSettings;
+import com.jd.blockchain.ledger.UserRoles;
+import com.jd.blockchain.ledger.core.CryptoConfig;
+import com.jd.blockchain.ledger.core.LedgerAdminDataset;
+import com.jd.blockchain.ledger.core.LedgerConfiguration;
+import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
+import com.jd.blockchain.transaction.ConsensusParticipantData;
+import com.jd.blockchain.transaction.LedgerInitData;
+import com.jd.blockchain.utils.Bytes;
+import com.jd.blockchain.utils.net.NetworkAddress;
+
+public class LedgerAdminDatasetTest {
+
+ private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(),
+ SMCryptoService.class.getName() };
+
+ private Random rand = new Random();
+
+ @Test
+ public void testSerialization() {
+ String keyPrefix = "";
+ LedgerInitData initSetting = new LedgerInitData();
+ ConsensusParticipantData[] parties = new ConsensusParticipantData[5];
+ BlockchainKeypair[] bckeys = new BlockchainKeypair[parties.length];
+ for (int i = 0; i < parties.length; i++) {
+ bckeys[i] = BlockchainKeyGenerator.getInstance().generate();
+ parties[i] = new ConsensusParticipantData();
+ parties[i].setId(i);
+ parties[i].setAddress(AddressEncoding.generateAddress(bckeys[i].getPubKey()));
+ parties[i].setHostAddress(new NetworkAddress("192.168.10." + (10 + i), 10010 + 10 * i));
+ parties[i].setName("Participant[" + i + "]");
+ parties[i].setPubKey(bckeys[i].getPubKey());
+ }
+ ConsensusParticipantData[] parties1 = Arrays.copyOf(parties, 4);
+ initSetting.setConsensusParticipants(parties1);
+
+ byte[] csSysSettingBytes = new byte[64];
+ rand.nextBytes(csSysSettingBytes);
+ initSetting.setConsensusSettings(new Bytes(csSysSettingBytes));
+ initSetting.setConsensusProvider("consensus-provider");
+
+ CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length];
+ for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) {
+ supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]);
+ }
+ CryptoConfig cryptoSetting = new CryptoConfig();
+ cryptoSetting.setSupportedProviders(supportedProviders);
+ cryptoSetting.setAutoVerifyHash(true);
+ cryptoSetting.setHashAlgorithm(ClassicAlgorithm.SHA256);
+ initSetting.setCryptoSetting(cryptoSetting);
+
+ byte[] ledgerSeed = new byte[16];
+ rand.nextBytes(ledgerSeed);
+ initSetting.setLedgerSeed(ledgerSeed);
+
+ MemoryKVStorage testStorage = new MemoryKVStorage();
+
+ // Create intance with init setting;
+ LedgerAdminDataset ledgerAdminDataset = new LedgerAdminDataset(initSetting, keyPrefix, testStorage,
+ testStorage);
+
+ ledgerAdminDataset.getRolePrivileges().addRolePrivilege("DEFAULT",
+ new LedgerPermission[] { LedgerPermission.CONFIGURE_ROLES, LedgerPermission.REGISTER_USER,
+ LedgerPermission.APPROVE_TX },
+ new TransactionPermission[] { TransactionPermission.DIRECT_OPERATION,
+ TransactionPermission.CONTRACT_OPERATION });
+
+ ledgerAdminDataset.getUserRoles().addUserRoles(parties[0].getAddress(), RolesPolicy.UNION, "DEFAULT");
+
+ // New created instance is updated until being committed;
+ assertTrue(ledgerAdminDataset.isUpdated());
+ // Hash of account is null until being committed;
+ assertNull(ledgerAdminDataset.getHash());
+
+ LedgerMetadata_V2 meta = ledgerAdminDataset.getMetadata();
+ assertNull(meta.getParticipantsHash());
+
+ // Commit, and check the storage keys;
+ ledgerAdminDataset.commit();
+
+ // New created instance isn't updated after being committed;
+ assertFalse(ledgerAdminDataset.isUpdated());
+ // Hash of account isn't null after being committed;
+ assertNotNull(ledgerAdminDataset.getHash());
+
+ meta = ledgerAdminDataset.getMetadata();
+ assertNotNull(meta.getParticipantsHash());
+ assertNotNull(meta.getSettingsHash());
+ assertNotNull(meta.getRolePrivilegesHash());
+ assertNotNull(meta.getUserRolesHash());
+
+ assertNotNull(ledgerAdminDataset.getRolePrivileges().getRolePrivilege("DEFAULT"));
+
+ // ----------------------
+ // Reload account from storage with readonly mode, and check the integrity of
+ // data;
+ HashDigest adminAccHash = ledgerAdminDataset.getHash();
+ LedgerAdminDataset reloadAdminAccount1 = new LedgerAdminDataset(adminAccHash, keyPrefix, testStorage,
+ testStorage, true);
+
+ LedgerMetadata_V2 meta2 = reloadAdminAccount1.getMetadata();
+ assertNotNull(meta2.getParticipantsHash());
+ assertNotNull(meta2.getSettingsHash());
+ assertNotNull(meta2.getRolePrivilegesHash());
+ assertNotNull(meta2.getUserRolesHash());
+
+ // verify realod settings of admin account;
+ verifyRealoadingSettings(reloadAdminAccount1, adminAccHash, ledgerAdminDataset.getMetadata(),
+ ledgerAdminDataset.getSettings());
+ // verify the consensus participant list;
+ verifyRealoadingParities(reloadAdminAccount1, parties1);
+ // It will throw exeception because of this account is readonly;
+ verifyReadonlyState(reloadAdminAccount1);
+
+ verifyRealoadingRoleAuthorizations(reloadAdminAccount1, ledgerAdminDataset.getRolePrivileges(),
+ ledgerAdminDataset.getUserRoles());
+
+ // --------------
+ // 重新加载,并进行修改;
+ LedgerAdminDataset reloadAdminAccount2 = new LedgerAdminDataset(adminAccHash, keyPrefix, testStorage, testStorage, false);
+ LedgerConfiguration newSetting = new LedgerConfiguration(reloadAdminAccount2.getPreviousSetting());
+ byte[] newCsSettingBytes = new byte[64];
+ rand.nextBytes(newCsSettingBytes);
+ newSetting.setConsensusSetting(new Bytes(newCsSettingBytes));
+ newSetting.getCryptoSetting().setAutoVerifyHash(false);
+ reloadAdminAccount2.setLedgerSetting(newSetting);
+
+ reloadAdminAccount2.addParticipant(parties[4]);
+
+ reloadAdminAccount2.getRolePrivileges().addRolePrivilege("ADMIN",
+ new LedgerPermission[] { LedgerPermission.APPROVE_TX },
+ new TransactionPermission[] { TransactionPermission.DIRECT_OPERATION });
+
+ reloadAdminAccount2.getRolePrivileges().disablePermissions("DEFAULT", TransactionPermission.CONTRACT_OPERATION);
+
+ reloadAdminAccount2.getUserRoles().addUserRoles(parties[1].getAddress(), RolesPolicy.UNION, "DEFAULT", "ADMIN");
+
+ reloadAdminAccount2.commit();
+
+ LedgerSettings newlyLedgerSettings = reloadAdminAccount2.getSettings();
+
+ // record the new account hash;
+ HashDigest newAccHash = reloadAdminAccount2.getHash();
+ LedgerMetadata_V2 newMeta = reloadAdminAccount2.getMetadata();
+
+ // load the last version of account and verify again;
+ LedgerAdminDataset previousAdminAccount = new LedgerAdminDataset(adminAccHash, keyPrefix, testStorage,
+ testStorage, true);
+ verifyRealoadingSettings(previousAdminAccount, adminAccHash, ledgerAdminDataset.getMetadata(),
+ ledgerAdminDataset.getSettings());
+ verifyRealoadingParities(previousAdminAccount, parties1);
+ verifyReadonlyState(previousAdminAccount);
+
+ // load the hash of new committing;
+ LedgerAdminDataset newlyAdminAccount = new LedgerAdminDataset(newAccHash, keyPrefix, testStorage, testStorage,
+ true);
+ verifyRealoadingSettings(newlyAdminAccount, newAccHash, newMeta, newlyLedgerSettings);
+ verifyRealoadingParities(newlyAdminAccount, parties);
+ verifyReadonlyState(newlyAdminAccount);
+
+// System.out.println("========= [LedgerAdminAccount Test] Show generated storage keys... =======");
+// testStorage.printStoragedKeys();
+ }
+
+ private void verifyRealoadingSettings(LedgerAdminDataset actualAccount, HashDigest expAccRootHash,
+ LedgerMetadata_V2 expMeta, LedgerSettings expLedgerSettings) {
+ // 验证基本信息;
+ assertFalse(actualAccount.isUpdated());
+ assertTrue(actualAccount.isReadonly());
+
+ assertEquals(expAccRootHash, actualAccount.getHash());
+
+ // verify metadata;
+ LedgerMetadata_V2 actualMeta = actualAccount.getMetadata();
+ assertArrayEquals(expMeta.getSeed(), actualMeta.getSeed());
+ assertEquals(expMeta.getParticipantsHash(), actualMeta.getParticipantsHash());
+ assertNotNull(actualMeta.getSettingsHash());
+ assertEquals(expMeta.getSettingsHash(), actualMeta.getSettingsHash());
+ assertNotNull(actualMeta.getRolePrivilegesHash());
+ assertEquals(expMeta.getRolePrivilegesHash(), actualMeta.getRolePrivilegesHash());
+ assertNotNull(actualMeta.getUserRolesHash());
+ assertEquals(expMeta.getUserRolesHash(), actualMeta.getUserRolesHash());
+
+ LedgerSettings actualLedgerSettings = actualAccount.getSettings();
+
+ assertEquals(expLedgerSettings.getConsensusSetting(), actualLedgerSettings.getConsensusSetting());
+ assertEquals(expLedgerSettings.getConsensusProvider(), actualLedgerSettings.getConsensusProvider());
+
+ assertEquals(expLedgerSettings.getCryptoSetting().getAutoVerifyHash(),
+ actualLedgerSettings.getCryptoSetting().getAutoVerifyHash());
+ assertEquals(expLedgerSettings.getCryptoSetting().getHashAlgorithm(),
+ actualLedgerSettings.getCryptoSetting().getHashAlgorithm());
+ }
+
+ private void verifyRealoadingRoleAuthorizations(LedgerAdminInfo actualAccount,
+ RolePrivilegeSettings expRolePrivilegeSettings, UserRolesSettings expUserRoleSettings) {
+ // 验证基本信息;
+ RolePrivilegeSettings actualRolePrivileges = actualAccount.getRolePrivileges();
+ RolePrivileges[] expRPs = expRolePrivilegeSettings.getRolePrivileges();
+
+ assertEquals(expRPs.length, actualRolePrivileges.getRoleCount());
+
+ for (RolePrivileges expRP : expRPs) {
+ RolePrivileges actualRP = actualRolePrivileges.getRolePrivilege(expRP.getRoleName());
+ assertNotNull(actualRP);
+ assertArrayEquals(expRP.getLedgerPrivilege().toBytes(), actualRP.getLedgerPrivilege().toBytes());
+ assertArrayEquals(expRP.getTransactionPrivilege().toBytes(), actualRP.getTransactionPrivilege().toBytes());
+ }
+
+ UserRolesSettings actualUserRoleSettings = actualAccount.getUserRoles();
+ UserRoles[] expUserRoles = expUserRoleSettings.getUserRoles();
+ assertEquals(expUserRoles.length, actualUserRoleSettings.getUserCount());
+
+ for (UserRoles expUR : expUserRoles) {
+ UserRoles actualUR = actualAccount.getUserRoles().getUserRoles(expUR.getUserAddress());
+ assertNotNull(actualUR);
+ assertEquals(expUR.getPolicy(), actualUR.getPolicy());
+ String[] expRoles = expUR.getRoles();
+ Arrays.sort(expRoles);
+ String[] actualRoles = actualUR.getRoles();
+ Arrays.sort(actualRoles);
+ assertArrayEquals(expRoles, actualRoles);
+ }
+ }
+
+ private void verifyRealoadingParities(LedgerAdminInfo actualAccount, ParticipantNode[] expParties) {
+ assertEquals(expParties.length, actualAccount.getParticipantCount());
+ ParticipantNode[] actualPaticipants = actualAccount.getParticipants();
+ assertEquals(expParties.length, actualPaticipants.length);
+ for (int i = 0; i < actualPaticipants.length; i++) {
+ ParticipantNode rlParti = actualPaticipants[i];
+ assertEquals(expParties[i].getAddress(), rlParti.getAddress());
+ assertEquals(expParties[i].getName(), rlParti.getName());
+ // assertEquals(expParties[i].getConsensusAddress(),
+ // rlParti.getConsensusAddress());
+ assertEquals(expParties[i].getPubKey(), rlParti.getPubKey());
+ }
+ }
+
+ /**
+ * 验证指定账户是否只读;
+ *
+ * @param readonlyAccount
+ */
+ private void verifyReadonlyState(LedgerAdminDataset readonlyAccount) {
+ ConsensusParticipantData newParti = new ConsensusParticipantData();
+ newParti.setId((int) readonlyAccount.getParticipantCount());
+ newParti.setHostAddress(
+ new NetworkAddress("192.168.10." + (10 + newParti.getId()), 10010 + 10 * newParti.getId()));
+ newParti.setName("Participant[" + newParti.getAddress() + "]");
+
+ BlockchainKeypair newKey = BlockchainKeyGenerator.getInstance().generate();
+ newParti.setPubKey(newKey.getPubKey());
+
+ Throwable ex = null;
+ try {
+ readonlyAccount.addParticipant(newParti);
+ } catch (Exception e) {
+ ex = e;
+ }
+ assertNotNull(ex);
+
+ ex = null;
+ try {
+ LedgerConfiguration newLedgerSetting = new LedgerConfiguration(readonlyAccount.getSettings());
+ readonlyAccount.setLedgerSetting(newLedgerSetting);
+ } catch (Exception e) {
+ ex = e;
+ }
+ assertNotNull(ex);
+ }
+
+}
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerBlockImplTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerBlockImplTest.java
similarity index 96%
rename from source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerBlockImplTest.java
rename to source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerBlockImplTest.java
index ce29e1a5..9479cc2b 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerBlockImplTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerBlockImplTest.java
@@ -6,7 +6,7 @@
* Date: 2018/8/30 上午10:45
* Description:
*/
-package test.com.jd.blockchain.ledger;
+package test.com.jd.blockchain.ledger.core;
import static org.junit.Assert.assertEquals;
@@ -19,8 +19,8 @@ import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerDataSnapshot;
-import com.jd.blockchain.ledger.core.impl.LedgerBlockData;
-import com.jd.blockchain.ledger.core.impl.TransactionStagedSnapshot;
+import com.jd.blockchain.ledger.core.LedgerBlockData;
+import com.jd.blockchain.ledger.core.TransactionStagedSnapshot;
/**
*
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerEditerTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerEditorTest.java
similarity index 81%
rename from source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerEditerTest.java
rename to source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerEditorTest.java
index c7f3d6e6..97979205 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerEditerTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerEditorTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger;
+package test.com.jd.blockchain.ledger.core;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -16,6 +16,7 @@ import com.jd.blockchain.crypto.SignatureFunction;
import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
import com.jd.blockchain.crypto.service.classic.ClassicCryptoService;
import com.jd.blockchain.crypto.service.sm.SMCryptoService;
+import com.jd.blockchain.ledger.BlockchainKeyGenerator;
import com.jd.blockchain.ledger.BlockchainKeypair;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.DataType;
@@ -26,19 +27,19 @@ import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.ledger.core.CryptoConfig;
import com.jd.blockchain.ledger.core.DataAccount;
-import com.jd.blockchain.ledger.core.LedgerDataSet;
+import com.jd.blockchain.ledger.core.LedgerDataset;
import com.jd.blockchain.ledger.core.LedgerEditor;
import com.jd.blockchain.ledger.core.LedgerTransactionContext;
+import com.jd.blockchain.ledger.core.LedgerTransactionalEditor;
import com.jd.blockchain.ledger.core.UserAccount;
-import com.jd.blockchain.ledger.core.impl.LedgerTransactionalEditor;
import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
import com.jd.blockchain.transaction.ConsensusParticipantData;
-import com.jd.blockchain.transaction.LedgerInitSettingData;
+import com.jd.blockchain.transaction.LedgerInitData;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.io.BytesUtils;
import com.jd.blockchain.utils.net.NetworkAddress;
-public class LedgerEditerTest {
+public class LedgerEditorTest {
private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(),
SMCryptoService.class.getName() };
@@ -52,6 +53,13 @@ public class LedgerEditerTest {
private static final String LEDGER_KEY_PREFIX = "LDG://";
private SignatureFunction signatureFunction;
+ private BlockchainKeypair parti0 = BlockchainKeyGenerator.getInstance().generate();
+ private BlockchainKeypair parti1 = BlockchainKeyGenerator.getInstance().generate();
+ private BlockchainKeypair parti2 = BlockchainKeyGenerator.getInstance().generate();
+ private BlockchainKeypair parti3 = BlockchainKeyGenerator.getInstance().generate();
+
+ private BlockchainKeypair[] participants = { parti0, parti1, parti2, parti3 };
+
/**
* 初始化一个;
*/
@@ -74,8 +82,8 @@ public class LedgerEditerTest {
return LedgerTransactionalEditor.createEditor(initSetting, LEDGER_KEY_PREFIX, storage, storage);
}
- private LedgerTransactionContext createGenisisTx(LedgerEditor ldgEdt) {
- TransactionRequest genesisTxReq = LedgerTestUtils.createTxRequest_UserReg(null);
+ private LedgerTransactionContext createGenisisTx(LedgerEditor ldgEdt, BlockchainKeypair[] partis) {
+ TransactionRequest genesisTxReq = LedgerTestUtils.createLedgerInitTxRequest(partis);
LedgerTransactionContext txCtx = ldgEdt.newTransaction(genesisTxReq);
@@ -86,8 +94,8 @@ public class LedgerEditerTest {
@Test
public void testWriteDataAccoutKvOp() {
LedgerEditor ldgEdt = createLedgerInitEditor();
- LedgerTransactionContext genisisTxCtx = createGenisisTx(ldgEdt);
- LedgerDataSet ldgDS = genisisTxCtx.getDataSet();
+ LedgerTransactionContext genisisTxCtx = createGenisisTx(ldgEdt, participants);
+ LedgerDataset ldgDS = genisisTxCtx.getDataset();
AsymmetricKeypair cryptoKeyPair = signatureFunction.generateKeypair();
BlockchainKeypair dataKP = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey());
@@ -119,8 +127,8 @@ public class LedgerEditerTest {
@Test
public void testGennesisBlockCreation() {
LedgerEditor ldgEdt = createLedgerInitEditor();
- LedgerTransactionContext genisisTxCtx = createGenisisTx(ldgEdt);
- LedgerDataSet ldgDS = genisisTxCtx.getDataSet();
+ LedgerTransactionContext genisisTxCtx = createGenisisTx(ldgEdt, participants);
+ LedgerDataset ldgDS = genisisTxCtx.getDataset();
AsymmetricKeypair cryptoKeyPair = signatureFunction.generateKeypair();
BlockchainKeypair userKP = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey());
@@ -130,7 +138,7 @@ public class LedgerEditerTest {
LedgerTransaction tx = genisisTxCtx.commit(TransactionState.SUCCESS);
- TransactionRequest genesisTxReq = genisisTxCtx.getRequestTX();
+ TransactionRequest genesisTxReq = genisisTxCtx.getTransactionRequest();
assertEquals(genesisTxReq.getTransactionContent().getHash(), tx.getTransactionContent().getHash());
assertEquals(0, tx.getBlockHeight());
@@ -138,13 +146,12 @@ public class LedgerEditerTest {
assertEquals(0, block.getHeight());
assertNotNull(block.getHash());
+ assertNull(block.getLedgerHash());
assertNull(block.getPreviousHash());
- assertEquals(block.getHash(), block.getLedgerHash());
-
// 提交数据,写入存储;
ldgEdt.commit();
}
-
+
}
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitOperationTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerInitOperationTest.java
similarity index 96%
rename from source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitOperationTest.java
rename to source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerInitOperationTest.java
index 9cee71df..8c245fa2 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitOperationTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerInitOperationTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger;
+package test.com.jd.blockchain.ledger.core;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -25,7 +25,7 @@ import com.jd.blockchain.ledger.core.CryptoConfig;
import com.jd.blockchain.ledger.core.ParticipantCertData;
import com.jd.blockchain.transaction.ConsensusParticipantData;
import com.jd.blockchain.transaction.LedgerInitOpTemplate;
-import com.jd.blockchain.transaction.LedgerInitSettingData;
+import com.jd.blockchain.transaction.LedgerInitData;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.net.NetworkAddress;
@@ -36,7 +36,7 @@ public class LedgerInitOperationTest {
byte[] seed = null;
byte[] csSysSettingBytes = null;
- LedgerInitSettingData ledgerInitSettingData = new LedgerInitSettingData();
+ LedgerInitData ledgerInitSettingData = new LedgerInitData();
@Before
public void initCfg() {
@@ -76,7 +76,7 @@ public class LedgerInitOperationTest {
keys[i] = BlockchainKeyGenerator.getInstance().generate();
parties[i] = new ConsensusParticipantData();
// parties[i].setId(i);
- parties[i].setAddress(AddressEncoding.generateAddress(keys[i].getPubKey()).toBase58());
+ parties[i].setAddress(AddressEncoding.generateAddress(keys[i].getPubKey()));
parties[i].setHostAddress(new NetworkAddress("192.168.10." + (10 + i), 10010 + 10 * i));
parties[i].setName("Participant[" + i + "]");
parties[i].setPubKey(keys[i].getPubKey());
@@ -117,7 +117,7 @@ public class LedgerInitOperationTest {
for (int i = 0; i < parties.length; i++) {
keys[i] = BlockchainKeyGenerator.getInstance().generate();
- parties[i] = new ParticipantCertData(AddressEncoding.generateAddress(keys[i].getPubKey()).toBase58(),
+ parties[i] = new ParticipantCertData(AddressEncoding.generateAddress(keys[i].getPubKey()),
"Participant[" + i + "]", keys[i].getPubKey());
}
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitSettingSerializeTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerInitSettingSerializeTest.java
similarity index 96%
rename from source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitSettingSerializeTest.java
rename to source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerInitSettingSerializeTest.java
index f867ae9b..46c96f65 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitSettingSerializeTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerInitSettingSerializeTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger;
+package test.com.jd.blockchain.ledger.core;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -24,14 +24,14 @@ import com.jd.blockchain.ledger.core.CryptoConfig;
import com.jd.blockchain.ledger.core.ParticipantCertData;
import com.jd.blockchain.transaction.ConsensusParticipantData;
import com.jd.blockchain.transaction.LedgerInitOpTemplate;
-import com.jd.blockchain.transaction.LedgerInitSettingData;
+import com.jd.blockchain.transaction.LedgerInitData;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.net.NetworkAddress;
public class LedgerInitSettingSerializeTest {
byte[] seed = null;
byte[] csSysSettingBytes = null;
- LedgerInitSettingData ledgerInitSettingData = new LedgerInitSettingData();
+ LedgerInitData ledgerInitSettingData = new LedgerInitData();
LedgerInitOpTemplate template = new LedgerInitOpTemplate();
private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(),
@@ -76,7 +76,7 @@ public class LedgerInitSettingSerializeTest {
keys[i] = BlockchainKeyGenerator.getInstance().generate();
parties[i] = new ConsensusParticipantData();
// parties[i].setId(i);
- parties[i].setAddress(AddressEncoding.generateAddress(keys[i].getPubKey()).toBase58());
+ parties[i].setAddress(AddressEncoding.generateAddress(keys[i].getPubKey()));
parties[i].setHostAddress(new NetworkAddress("192.168.10." + (10 + i), 10010 + 10 * i));
parties[i].setName("Participant[" + i + "]");
parties[i].setPubKey(keys[i].getPubKey());
@@ -84,7 +84,7 @@ public class LedgerInitSettingSerializeTest {
ConsensusParticipantData[] parties1 = Arrays.copyOf(parties, 4);
ledgerInitSettingData.setConsensusParticipants(parties1);
-
+
byte[] encode = BinaryProtocol.encode(ledgerInitSettingData, LedgerInitSetting.class);
LedgerInitSetting decode = BinaryProtocol.decode(encode);
@@ -121,7 +121,7 @@ public class LedgerInitSettingSerializeTest {
for (int i = 0; i < parties.length; i++) {
keys[i] = BlockchainKeyGenerator.getInstance().generate();
- parties[i] = new ParticipantCertData(AddressEncoding.generateAddress(keys[i].getPubKey()).toBase58(),
+ parties[i] = new ParticipantCertData(AddressEncoding.generateAddress(keys[i].getPubKey()),
"Participant[" + i + "]", keys[i].getPubKey());
}
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerManagerTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerManagerTest.java
similarity index 81%
rename from source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerManagerTest.java
rename to source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerManagerTest.java
index 9639602c..0297efdf 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerManagerTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerManagerTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger;
+package test.com.jd.blockchain.ledger.core;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -32,19 +32,20 @@ import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.ledger.TransactionRequestBuilder;
import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.ledger.UserRegisterOperation;
-import com.jd.blockchain.ledger.core.ContractAccountSet;
+import com.jd.blockchain.ledger.core.ContractAccountQuery;
import com.jd.blockchain.ledger.core.CryptoConfig;
-import com.jd.blockchain.ledger.core.DataAccountSet;
-import com.jd.blockchain.ledger.core.LedgerDataSet;
+import com.jd.blockchain.ledger.core.DataAccountQuery;
+import com.jd.blockchain.ledger.core.LedgerDataset;
import com.jd.blockchain.ledger.core.LedgerEditor;
+import com.jd.blockchain.ledger.core.LedgerInitializer;
+import com.jd.blockchain.ledger.core.LedgerManager;
import com.jd.blockchain.ledger.core.LedgerRepository;
import com.jd.blockchain.ledger.core.LedgerTransactionContext;
import com.jd.blockchain.ledger.core.UserAccount;
-import com.jd.blockchain.ledger.core.UserAccountSet;
-import com.jd.blockchain.ledger.core.impl.LedgerManager;
+import com.jd.blockchain.ledger.core.UserAccountQuery;
import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
import com.jd.blockchain.transaction.ConsensusParticipantData;
-import com.jd.blockchain.transaction.LedgerInitSettingData;
+import com.jd.blockchain.transaction.LedgerInitData;
import com.jd.blockchain.transaction.TxBuilder;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.io.BytesUtils;
@@ -63,6 +64,13 @@ public class LedgerManagerTest {
public static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(),
SMCryptoService.class.getName() };
+ private BlockchainKeypair parti0 = BlockchainKeyGenerator.getInstance().generate();
+ private BlockchainKeypair parti1 = BlockchainKeyGenerator.getInstance().generate();
+ private BlockchainKeypair parti2 = BlockchainKeyGenerator.getInstance().generate();
+ private BlockchainKeypair parti3 = BlockchainKeyGenerator.getInstance().generate();
+
+ private BlockchainKeypair[] participants = { parti0, parti1, parti2, parti3 };
+
private SignatureFunction signatureFunction;
@Before
@@ -74,22 +82,21 @@ public class LedgerManagerTest {
public void testLedgerInit() {
// 创建账本初始化配置;
LedgerInitSetting initSetting = createLedgerInitSetting();
-
+
// 采用基于内存的 Storage;
MemoryKVStorage storage = new MemoryKVStorage();
// 新建账本;
- LedgerManager ledgerManager = new LedgerManager();
- LedgerEditor ldgEdt = ledgerManager.newLedger(initSetting, storage);
+ LedgerEditor ldgEdt = LedgerInitializer.createLedgerEditor(initSetting, storage);
// 创建一个模拟的创世交易;
- TransactionRequest genesisTxReq = LedgerTestUtils.createTxRequest_UserReg(null);
+ TransactionRequest genesisTxReq = LedgerTestUtils.createLedgerInitTxRequest(participants);
// 记录交易,注册用户;
LedgerTransactionContext txCtx = ldgEdt.newTransaction(genesisTxReq);
- LedgerDataSet ldgDS = txCtx.getDataSet();
+ LedgerDataset ldgDS = txCtx.getDataset();
BlockchainKeypair userKP = BlockchainKeyGenerator.getInstance().generate();
-
+
UserAccount userAccount = ldgDS.getUserAccountSet().register(userKP.getAddress(), userKP.getPubKey());
userAccount.setProperty("Name", "孙悟空", -1);
userAccount.setProperty("Age", "10000", -1);
@@ -109,10 +116,14 @@ public class LedgerManagerTest {
assertEquals(0, genesisBlock.getHeight());
assertNotNull(genesisBlock.getHash());
assertNull(genesisBlock.getPreviousHash());
- assertEquals(ledgerHash, genesisBlock.getLedgerHash());
+ // 创世区块的账本hash 为null;创世区块本身的哈希就代表了账本的哈希;
+ assertNull(genesisBlock.getLedgerHash());
// 提交数据,写入存储;
ldgEdt.commit();
+
+ assertNull(genesisBlock.getLedgerHash());
+ assertNotNull(genesisBlock.getHash());
// 重新加载并校验结果;
LedgerManager reloadLedgerManager = new LedgerManager();
@@ -124,7 +135,8 @@ public class LedgerManagerTest {
LedgerBlock latestBlock = reloadLedgerRepo.getLatestBlock();
assertEquals(0, latestBlock.getHeight());
assertEquals(ledgerHash, latestBlock.getHash());
- assertEquals(ledgerHash, latestBlock.getLedgerHash());
+ // 创世区块的账本hash 为null;创世区块本身的哈希就代表了账本的哈希;
+ assertNull(latestBlock.getLedgerHash());
LedgerEditor editor1 = reloadLedgerRepo.createNextBlock();
@@ -136,7 +148,7 @@ public class LedgerManagerTest {
TransactionRequest txRequest = txReqBuilder.buildRequest();
LedgerTransactionContext txCtx1 = editor1.newTransaction(txRequest);
- txCtx1.getDataSet().getDataAccountSet().register(dataKey.getAddress(), dataKey.getPubKey(), null);
+ txCtx1.getDataset().getDataAccountSet().register(dataKey.getAddress(), dataKey.getPubKey(), null);
txCtx1.commit(TransactionState.SUCCESS);
LedgerBlock block1 = editor1.prepare();
@@ -158,9 +170,9 @@ public class LedgerManagerTest {
assertEquals(1, latestBlock.getHeight());
assertEquals(block1.getHash(), latestBlock.getHash());
- DataAccountSet dataAccountSet = reloadLedgerRepo.getDataAccountSet(latestBlock);
- UserAccountSet userAccountSet = reloadLedgerRepo.getUserAccountSet(latestBlock);
- ContractAccountSet contractAccountSet = reloadLedgerRepo.getContractAccountSet(latestBlock);
+ DataAccountQuery dataAccountSet = reloadLedgerRepo.getDataAccountSet(latestBlock);
+ UserAccountQuery userAccountSet = reloadLedgerRepo.getUserAccountSet(latestBlock);
+ ContractAccountQuery contractAccountSet = reloadLedgerRepo.getContractAccountSet(latestBlock);
}
@@ -190,7 +202,7 @@ public class LedgerManagerTest {
defCryptoSetting.setAutoVerifyHash(true);
defCryptoSetting.setHashAlgorithm(ClassicAlgorithm.SHA256);
- LedgerInitSettingData initSetting = new LedgerInitSettingData();
+ LedgerInitData initSetting = new LedgerInitData();
initSetting.setLedgerSeed(BytesUtils.toBytes("A Test Ledger seed!", "UTF-8"));
initSetting.setCryptoSetting(defCryptoSetting);
@@ -200,7 +212,7 @@ public class LedgerManagerTest {
parties[0].setName("John");
AsymmetricKeypair kp0 = signatureFunction.generateKeypair();
parties[0].setPubKey(kp0.getPubKey());
- parties[0].setAddress(AddressEncoding.generateAddress(kp0.getPubKey()).toBase58());
+ parties[0].setAddress(AddressEncoding.generateAddress(kp0.getPubKey()));
parties[0].setHostAddress(new NetworkAddress("127.0.0.1", 9000));
parties[1] = new ConsensusParticipantData();
@@ -208,7 +220,7 @@ public class LedgerManagerTest {
parties[1].setName("Mary");
AsymmetricKeypair kp1 = signatureFunction.generateKeypair();
parties[1].setPubKey(kp1.getPubKey());
- parties[1].setAddress(AddressEncoding.generateAddress(kp1.getPubKey()).toBase58());
+ parties[1].setAddress(AddressEncoding.generateAddress(kp1.getPubKey()));
parties[1].setHostAddress(new NetworkAddress("127.0.0.1", 9010));
parties[2] = new ConsensusParticipantData();
@@ -216,7 +228,7 @@ public class LedgerManagerTest {
parties[2].setName("Jerry");
AsymmetricKeypair kp2 = signatureFunction.generateKeypair();
parties[2].setPubKey(kp2.getPubKey());
- parties[2].setAddress(AddressEncoding.generateAddress(kp2.getPubKey()).toBase58());
+ parties[2].setAddress(AddressEncoding.generateAddress(kp2.getPubKey()));
parties[2].setHostAddress(new NetworkAddress("127.0.0.1", 9020));
parties[3] = new ConsensusParticipantData();
@@ -224,7 +236,7 @@ public class LedgerManagerTest {
parties[3].setName("Tom");
AsymmetricKeypair kp3 = signatureFunction.generateKeypair();
parties[3].setPubKey(kp3.getPubKey());
- parties[3].setAddress(AddressEncoding.generateAddress(kp3.getPubKey()).toBase58());
+ parties[3].setAddress(AddressEncoding.generateAddress(kp3.getPubKey()));
parties[3].setHostAddress(new NetworkAddress("127.0.0.1", 9030));
initSetting.setConsensusParticipants(parties);
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerMetaDataTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerMetaDataTest.java
similarity index 90%
rename from source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerMetaDataTest.java
rename to source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerMetaDataTest.java
index 401c5de2..e7cba7ad 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerMetaDataTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerMetaDataTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger;
+package test.com.jd.blockchain.ledger.core;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -8,7 +8,7 @@ import static org.junit.Assert.assertTrue;
import java.util.Random;
import com.jd.blockchain.ledger.LedgerMetadata;
-import com.jd.blockchain.ledger.LedgerSetting;
+import com.jd.blockchain.ledger.LedgerSettings;
import org.junit.Before;
import org.junit.Test;
@@ -16,6 +16,7 @@ import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.AddressEncoding;
import com.jd.blockchain.crypto.Crypto;
+import com.jd.blockchain.crypto.CryptoAlgorithm;
import com.jd.blockchain.crypto.CryptoProvider;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PubKey;
@@ -25,7 +26,7 @@ import com.jd.blockchain.crypto.service.sm.SMCryptoService;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.ledger.core.CryptoConfig;
-import com.jd.blockchain.ledger.core.LedgerAdminAccount;
+import com.jd.blockchain.ledger.core.LedgerAdminDataset;
import com.jd.blockchain.ledger.core.LedgerConfiguration;
import com.jd.blockchain.ledger.core.ParticipantCertData;
import com.jd.blockchain.utils.Bytes;
@@ -74,12 +75,14 @@ public class LedgerMetaDataTest {
cryptoConfig.setAutoVerifyHash(true);
cryptoConfig.setHashAlgorithm(ClassicAlgorithm.SHA256);
- LedgerConfiguration ledgerConfiguration = new LedgerConfiguration(consensusProvider,
- new Bytes(consensusSettingBytes), cryptoConfig);
- LedgerAdminAccount.LedgerMetadataImpl ledgerMetadata = new LedgerAdminAccount.LedgerMetadataImpl();
+// LedgerConfiguration ledgerConfiguration = new LedgerConfiguration(consensusProvider,
+// new Bytes(consensusSettingBytes), cryptoConfig);
+ HashDigest settingsHash = Crypto.getHashFunction("SHA256").hash(consensusSettingBytes);
+
+ LedgerAdminDataset.LedgerMetadataInfo ledgerMetadata = new LedgerAdminDataset.LedgerMetadataInfo();
ledgerMetadata.setSeed(seed);
- ledgerMetadata.setSetting(ledgerConfiguration);
+ ledgerMetadata.setSettingsHash(settingsHash);
HashDigest hashDigest = new HashDigest(ClassicAlgorithm.SHA256, rawDigestBytes);
ledgerMetadata.setParticipantsHash(hashDigest);
@@ -91,7 +94,7 @@ public class LedgerMetaDataTest {
// verify start
assertArrayEquals(ledgerMetadata.getSeed(), deLedgerMetaData.getSeed());
assertEquals(ledgerMetadata.getParticipantsHash(), deLedgerMetaData.getParticipantsHash());
- assertNotEquals(ledgerMetadata.getSetting(), deLedgerMetaData.getSetting());
+ assertEquals(ledgerMetadata.getSettingsHash(), deLedgerMetaData.getSettingsHash());
return;
}
@@ -119,8 +122,8 @@ public class LedgerMetaDataTest {
LedgerConfiguration ledgerConfiguration = new LedgerConfiguration(consensusProvider, new Bytes(csSettingsBytes),
cryptoConfig);
- byte[] encodeBytes = BinaryProtocol.encode(ledgerConfiguration, LedgerSetting.class);
- LedgerSetting deLedgerConfiguration = BinaryProtocol.decode(encodeBytes);
+ byte[] encodeBytes = BinaryProtocol.encode(ledgerConfiguration, LedgerSettings.class);
+ LedgerSettings deLedgerConfiguration = BinaryProtocol.decode(encodeBytes);
// verify start
assertTrue(ledgerConfiguration.getConsensusSetting().equals(deLedgerConfiguration.getConsensusSetting()));
assertEquals(ledgerConfiguration.getCryptoSetting().getAutoVerifyHash(),
@@ -185,7 +188,7 @@ public class LedgerMetaDataTest {
String name = "John";
// NetworkAddress consensusAddress = new NetworkAddress("192.168.1.1", 9001,
// false);
- String address = AddressEncoding.generateAddress(pubKey).toBase58();
+ Bytes address = AddressEncoding.generateAddress(pubKey);
ParticipantCertData participantCertData = new ParticipantCertData(address, name, pubKey);
// encode and decode
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerSecurityManagerTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerSecurityManagerTest.java
new file mode 100644
index 00000000..7c82d21b
--- /dev/null
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerSecurityManagerTest.java
@@ -0,0 +1,181 @@
+package test.com.jd.blockchain.ledger.core;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import com.jd.blockchain.crypto.Crypto;
+import com.jd.blockchain.crypto.CryptoAlgorithm;
+import com.jd.blockchain.crypto.CryptoProvider;
+import com.jd.blockchain.crypto.service.classic.ClassicCryptoService;
+import com.jd.blockchain.crypto.service.sm.SMCryptoService;
+import com.jd.blockchain.ledger.BlockchainKeyGenerator;
+import com.jd.blockchain.ledger.BlockchainKeypair;
+import com.jd.blockchain.ledger.CryptoSetting;
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.ParticipantDataQuery;
+import com.jd.blockchain.ledger.Privileges;
+import com.jd.blockchain.ledger.RolesPolicy;
+import com.jd.blockchain.ledger.TransactionPermission;
+import com.jd.blockchain.ledger.core.CryptoConfig;
+import com.jd.blockchain.ledger.core.LedgerSecurityManager;
+import com.jd.blockchain.ledger.core.LedgerSecurityManagerImpl;
+import com.jd.blockchain.ledger.core.MultiIDsPolicy;
+import com.jd.blockchain.ledger.core.RolePrivilegeDataset;
+import com.jd.blockchain.ledger.core.SecurityPolicy;
+import com.jd.blockchain.ledger.core.UserAccountQuery;
+import com.jd.blockchain.ledger.core.UserRoleDataset;
+import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
+import com.jd.blockchain.utils.Bytes;
+
+public class LedgerSecurityManagerTest {
+
+ private static final String[] SUPPORTED_PROVIDER_NAMES = { ClassicCryptoService.class.getName(),
+ SMCryptoService.class.getName() };
+
+ private static final CryptoAlgorithm HASH_ALGORITHM = Crypto.getAlgorithm("SHA256");
+
+ private static final CryptoProvider[] SUPPORTED_PROVIDERS = new CryptoProvider[SUPPORTED_PROVIDER_NAMES.length];
+
+ private static final CryptoSetting CRYPTO_SETTINGS;
+
+ static {
+ for (int i = 0; i < SUPPORTED_PROVIDER_NAMES.length; i++) {
+ SUPPORTED_PROVIDERS[i] = Crypto.getProvider(SUPPORTED_PROVIDER_NAMES[i]);
+ }
+
+ CryptoConfig cryptoConfig = new CryptoConfig();
+ cryptoConfig.setAutoVerifyHash(true);
+ cryptoConfig.setSupportedProviders(SUPPORTED_PROVIDERS);
+ cryptoConfig.setHashAlgorithm(HASH_ALGORITHM);
+
+ CRYPTO_SETTINGS = cryptoConfig;
+ }
+
+ private RolePrivilegeDataset createRolePrivilegeDataset(MemoryKVStorage testStorage) {
+ String prefix = "role-privilege/";
+ RolePrivilegeDataset rolePrivilegeDataset = new RolePrivilegeDataset(CRYPTO_SETTINGS, prefix, testStorage,
+ testStorage);
+
+ return rolePrivilegeDataset;
+ }
+
+ private UserRoleDataset createUserRoleDataset(MemoryKVStorage testStorage) {
+ String prefix = "user-roles/";
+ UserRoleDataset userRolesDataset = new UserRoleDataset(CRYPTO_SETTINGS, prefix, testStorage, testStorage);
+
+ return userRolesDataset;
+ }
+
+ @Test
+ public void testGetSecurityPolicy() {
+ MemoryKVStorage testStorage = new MemoryKVStorage();
+
+ // 定义不同角色用户的 keypair;
+ final BlockchainKeypair kpManager = BlockchainKeyGenerator.getInstance().generate();
+ final BlockchainKeypair kpEmployee = BlockchainKeyGenerator.getInstance().generate();
+ final BlockchainKeypair kpDevoice = BlockchainKeyGenerator.getInstance().generate();
+ final BlockchainKeypair kpPlatform = BlockchainKeyGenerator.getInstance().generate();
+
+ // 定义角色和权限;
+ final String ROLE_ADMIN = "ID_ADMIN";
+ final String ROLE_OPERATOR = "OPERATOR";
+ final String ROLE_DATA_COLLECTOR = "DATA_COLLECTOR";
+ final String ROLE_PLATFORM = "PLATFORM";
+
+ // 定义管理员角色的权限:【账本权限只允许:注册用户、注册数据账户】【交易权限只允许:调用账本直接操作】
+ final Privileges PRIVILEGES_ADMIN = Privileges.configure()
+ .enable(LedgerPermission.REGISTER_USER, LedgerPermission.REGISTER_DATA_ACCOUNT)
+ .enable(TransactionPermission.DIRECT_OPERATION);
+
+ // 定义操作员角色的权限:【账本权限只允许:写入数据账户】【交易权限只允许:调用合约】
+ final Privileges PRIVILEGES_OPERATOR = Privileges.configure().enable(LedgerPermission.WRITE_DATA_ACCOUNT)
+ .enable(TransactionPermission.CONTRACT_OPERATION);
+
+ // 定义数据收集器角色的权限:【账本权限只允许:写入数据账户】【交易权限只允许:调用账本直接操作】
+ final Privileges PRIVILEGES_DATA_COLLECTOR = Privileges.configure().enable(LedgerPermission.WRITE_DATA_ACCOUNT)
+ .enable(TransactionPermission.DIRECT_OPERATION);
+
+ // 定义平台角色的权限:【账本权限只允许:签署合约】 (只允许作为节点签署交易,不允许作为终端发起交易指令)
+ final Privileges PRIVILEGES_PLATFORM = Privileges.configure().enable(LedgerPermission.APPROVE_TX);
+
+ RolePrivilegeDataset rolePrivilegeDataset = createRolePrivilegeDataset(testStorage);
+ long v = rolePrivilegeDataset.addRolePrivilege(ROLE_ADMIN, PRIVILEGES_ADMIN);
+ assertTrue(v > -1);
+ v = rolePrivilegeDataset.addRolePrivilege(ROLE_OPERATOR, PRIVILEGES_OPERATOR);
+ assertTrue(v > -1);
+ v = rolePrivilegeDataset.addRolePrivilege(ROLE_DATA_COLLECTOR, PRIVILEGES_DATA_COLLECTOR);
+ assertTrue(v > -1);
+ v = rolePrivilegeDataset.addRolePrivilege(ROLE_PLATFORM, PRIVILEGES_PLATFORM);
+ assertTrue(v > -1);
+ rolePrivilegeDataset.commit();
+
+ // 为用户分配角色;
+ String[] managerRoles = new String[] { ROLE_ADMIN, ROLE_OPERATOR };
+ String[] employeeRoles = new String[] { ROLE_OPERATOR };
+ String[] devoiceRoles = new String[] { ROLE_DATA_COLLECTOR };
+ String[] platformRoles = new String[] { ROLE_PLATFORM };
+ UserRoleDataset userRolesDataset = createUserRoleDataset(testStorage);
+ userRolesDataset.addUserRoles(kpManager.getAddress(), RolesPolicy.UNION, managerRoles);
+ userRolesDataset.addUserRoles(kpEmployee.getAddress(), RolesPolicy.UNION, employeeRoles);
+ userRolesDataset.addUserRoles(kpDevoice.getAddress(), RolesPolicy.UNION, devoiceRoles);
+ userRolesDataset.addUserRoles(kpPlatform.getAddress(), RolesPolicy.UNION, platformRoles);
+ userRolesDataset.commit();
+
+ ParticipantDataQuery partisQuery = Mockito.mock(ParticipantDataQuery.class);
+ UserAccountQuery usersQuery = Mockito.mock(UserAccountQuery.class);
+
+ // 创建安全管理器;
+ LedgerSecurityManager securityManager = new LedgerSecurityManagerImpl(rolePrivilegeDataset, userRolesDataset,
+ partisQuery, usersQuery);
+
+ // 定义终端用户列表;终端用户一起共同具有 ADMIN、OPERATOR 角色;
+ final Map endpoints = new HashMap<>();
+ endpoints.put(kpManager.getAddress(), kpManager);
+ endpoints.put(kpEmployee.getAddress(), kpEmployee);
+
+ // 定义节点参与方列表;
+ final Map nodes = new HashMap<>();
+ nodes.put(kpPlatform.getAddress(), kpPlatform);
+
+ // 创建一项与指定的终端用户和节点参与方相关的安全策略;
+ SecurityPolicy policy = securityManager.createSecurityPolicy(endpoints.keySet(), nodes.keySet());
+
+ // 校验安全策略的正确性;
+ LedgerPermission[] ledgerPermissions = LedgerPermission.values();
+ for (LedgerPermission p : ledgerPermissions) {
+ // 终端节点有 ADMIN 和 OPERATOR 两种角色的合并权限;
+ if (p == LedgerPermission.REGISTER_USER || p == LedgerPermission.REGISTER_DATA_ACCOUNT
+ || p == LedgerPermission.WRITE_DATA_ACCOUNT) {
+ assertTrue(policy.isEndpointEnable(p, MultiIDsPolicy.AT_LEAST_ONE));
+ } else {
+ assertFalse(policy.isEndpointEnable(p, MultiIDsPolicy.AT_LEAST_ONE));
+ }
+
+ if (p == LedgerPermission.APPROVE_TX) {
+ // 共识参与方只有 PLATFORM 角色的权限:核准交易;
+ assertTrue(policy.isNodeEnable(p, MultiIDsPolicy.AT_LEAST_ONE));
+ } else {
+ assertFalse(policy.isNodeEnable(p, MultiIDsPolicy.AT_LEAST_ONE));
+ }
+ }
+
+ TransactionPermission[] transactionPermissions = TransactionPermission.values();
+ for (TransactionPermission p : transactionPermissions) {
+ // 终端节点有 ADMIN 和 OPERATOR 两种角色的合并权限;
+ if (p == TransactionPermission.DIRECT_OPERATION || p == TransactionPermission.CONTRACT_OPERATION) {
+ assertTrue(policy.isEndpointEnable(p, MultiIDsPolicy.AT_LEAST_ONE));
+ } else {
+ assertFalse(policy.isEndpointEnable(p, MultiIDsPolicy.AT_LEAST_ONE));
+ }
+
+ assertFalse(policy.isNodeEnable(p, MultiIDsPolicy.AT_LEAST_ONE));
+ }
+ }
+
+}
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerTestUtils.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerTestUtils.java
similarity index 53%
rename from source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerTestUtils.java
rename to source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerTestUtils.java
index 3a631ad3..eb6835b5 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerTestUtils.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerTestUtils.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger;
+package test.com.jd.blockchain.ledger.core;
import java.util.Random;
@@ -19,11 +19,12 @@ import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.ledger.TransactionRequestBuilder;
import com.jd.blockchain.ledger.TransactionResponse;
import com.jd.blockchain.ledger.core.CryptoConfig;
-import com.jd.blockchain.ledger.core.impl.TransactionStagedSnapshot;
+import com.jd.blockchain.ledger.core.TransactionStagedSnapshot;
import com.jd.blockchain.transaction.ConsensusParticipantData;
-import com.jd.blockchain.transaction.LedgerInitSettingData;
+import com.jd.blockchain.transaction.LedgerInitData;
import com.jd.blockchain.transaction.TransactionService;
import com.jd.blockchain.transaction.TxBuilder;
+import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.io.BytesUtils;
import com.jd.blockchain.utils.net.NetworkAddress;
@@ -38,10 +39,10 @@ public class LedgerTestUtils {
private static Random rand = new Random();
- public static TransactionRequest createTxRequest_UserReg(HashDigest ledgerHash) {
- BlockchainKeypair key = BlockchainKeyGenerator.getInstance().generate(ED25519);
- return createTxRequest_UserReg(ledgerHash, key);
- }
+// public static TransactionRequest createTxRequest_UserReg(HashDigest ledgerHash) {
+// BlockchainKeypair key = BlockchainKeyGenerator.getInstance().generate(ED25519);
+// return createTxRequest_UserReg(ledgerHash, key);
+// }
public static LedgerInitSetting createLedgerInitSetting() {
BlockchainKeypair[] partiKeys = new BlockchainKeypair[2];
@@ -61,7 +62,7 @@ public class LedgerTestUtils {
defCryptoSetting.setAutoVerifyHash(true);
defCryptoSetting.setHashAlgorithm(ClassicAlgorithm.SHA256);
- LedgerInitSettingData initSetting = new LedgerInitSettingData();
+ LedgerInitData initSetting = new LedgerInitData();
initSetting.setLedgerSeed(BytesUtils.toBytes("A Test Ledger seed!", "UTF-8"));
initSetting.setCryptoSetting(defCryptoSetting);
@@ -71,7 +72,7 @@ public class LedgerTestUtils {
parties[i].setId(0);
parties[i].setName("Parti-" + i);
parties[i].setPubKey(partiKeys[i].getPubKey());
- parties[i].setAddress(AddressEncoding.generateAddress(partiKeys[i].getPubKey()).toBase58());
+ parties[i].setAddress(AddressEncoding.generateAddress(partiKeys[i].getPubKey()));
parties[i].setHostAddress(new NetworkAddress("192.168.1." + (10 + i), 9000));
}
@@ -81,22 +82,112 @@ public class LedgerTestUtils {
return initSetting;
}
- public static TransactionRequest createTxRequest_UserReg(HashDigest ledgerHash, BlockchainKeypair userKeypair) {
- return createTxRequest_UserReg(ledgerHash, userKeypair, null);
+// public static TransactionRequest createTxRequest_UserReg(BlockchainKeypair userKeypair, HashDigest ledgerHash, BlockchainKeypair... partiKeys) {
+// return createTxRequest_UserReg(userKeypair, ledgerHash, null, null);
+// }
+
+ public static TransactionRequest createLedgerInitTxRequest(BlockchainKeypair... participants) {
+ TxBuilder txBuilder = new TxBuilder(null);
+
+ for (BlockchainKeypair parti : participants) {
+ txBuilder.users().register(parti.getIdentity());
+ }
+
+ TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest();
+ for (BlockchainKeypair parti : participants) {
+ txReqBuilder.signAsNode(parti);
+ }
+
+ return txReqBuilder.buildRequest();
}
- public static TransactionRequest createTxRequest_UserReg(HashDigest ledgerHash, BlockchainKeypair userKeypair,
- BlockchainKeypair gatewayKeypair) {
+// public static TransactionRequest createTxRequest_UserReg(HashDigest ledgerHash, BlockchainKeypair nodeKeypair,
+// BlockchainKeypair... signers) {
+// return createTxRequest_UserReg(BlockchainKeyGenerator.getInstance().generate(), ledgerHash, nodeKeypair,
+// signers);
+// }
+
+ public static TransactionRequest createTxRequest_UserReg(BlockchainKeypair userKeypair, HashDigest ledgerHash,
+ BlockchainKeypair nodeKeypair, BlockchainKeypair... signers) {
TxBuilder txBuilder = new TxBuilder(ledgerHash);
txBuilder.users().register(userKeypair.getIdentity());
TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest();
- txReqBuilder.signAsEndpoint(userKeypair);
- if (gatewayKeypair != null) {
- txReqBuilder.signAsNode(gatewayKeypair);
+ if (signers != null) {
+ for (BlockchainKeypair signer : signers) {
+ txReqBuilder.signAsEndpoint(signer);
+ }
+ }
+ if (nodeKeypair != null) {
+ txReqBuilder.signAsNode(nodeKeypair);
+ }
+
+ return txReqBuilder.buildRequest();
+ }
+
+ public static TransactionRequest createTxRequest_DataAccountReg(BlockchainKeypair dataAccountID,
+ HashDigest ledgerHash, BlockchainKeypair nodeKeypair, BlockchainKeypair... signers) {
+ TxBuilder txBuilder = new TxBuilder(ledgerHash);
+
+ txBuilder.dataAccounts().register(dataAccountID.getIdentity());
+
+ TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest();
+ if (signers != null) {
+ for (BlockchainKeypair signer : signers) {
+ txReqBuilder.signAsEndpoint(signer);
+ }
}
-
+ if (nodeKeypair != null) {
+ txReqBuilder.signAsNode(nodeKeypair);
+ }
+
+ return txReqBuilder.buildRequest();
+ }
+
+ public static TransactionRequest createTxRequest_DataAccountWrite(Bytes dataAccountAddress, String key,
+ String value, long version, HashDigest ledgerHash, BlockchainKeypair nodeKeypair,
+ BlockchainKeypair... signers) {
+ TxBuilder txBuilder = new TxBuilder(ledgerHash);
+
+ txBuilder.dataAccount(dataAccountAddress).setText(key, value, version);
+
+ TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest();
+ if (signers != null) {
+ for (BlockchainKeypair signer : signers) {
+ txReqBuilder.signAsEndpoint(signer);
+ }
+ }
+ if (nodeKeypair != null) {
+ txReqBuilder.signAsNode(nodeKeypair);
+ }
+
+ return txReqBuilder.buildRequest();
+ }
+
+ /**
+ * @param userKeypair 要注册的用户key;
+ * @param ledgerHash 账本哈希;
+ * @param nodeKeypair 节点key;
+ * @param signers 签名者列表;
+ * @return
+ */
+ public static TransactionRequest createTxRequest_MultiOPs_WithNotExistedDataAccount(BlockchainKeypair userKeypair,
+ HashDigest ledgerHash, BlockchainKeypair nodeKeypair, BlockchainKeypair... signers) {
+ TxBuilder txBuilder = new TxBuilder(ledgerHash);
+
+ txBuilder.users().register(userKeypair.getIdentity());
+
+ // 故意构建一个错误的
+ BlockchainKeypair testKey = BlockchainKeyGenerator.getInstance().generate();
+ txBuilder.dataAccount(testKey.getAddress()).setBytes("AA", "Value".getBytes(), 1);
+
+ TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest();
+ txReqBuilder.signAsEndpoint(nodeKeypair);
+ if (nodeKeypair != null) {
+ txReqBuilder.signAsNode(nodeKeypair);
+ }
+
return txReqBuilder.buildRequest();
}
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerTransactionDataTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerTransactionDataTest.java
similarity index 98%
rename from source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerTransactionDataTest.java
rename to source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerTransactionDataTest.java
index 9e53ae24..f676ea87 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerTransactionDataTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerTransactionDataTest.java
@@ -6,7 +6,7 @@
* Date: 2018/8/30 上午9:48
* Description:
*/
-package test.com.jd.blockchain.ledger;
+package test.com.jd.blockchain.ledger.core;
import static org.junit.Assert.assertEquals;
@@ -35,8 +35,8 @@ import com.jd.blockchain.ledger.Transaction;
import com.jd.blockchain.ledger.TransactionContent;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.ledger.TransactionState;
-import com.jd.blockchain.ledger.core.impl.LedgerTransactionData;
-import com.jd.blockchain.ledger.core.impl.TransactionStagedSnapshot;
+import com.jd.blockchain.ledger.core.LedgerTransactionData;
+import com.jd.blockchain.ledger.core.TransactionStagedSnapshot;
import com.jd.blockchain.transaction.BlockchainOperationFactory;
import com.jd.blockchain.transaction.DigitalSignatureBlob;
import com.jd.blockchain.transaction.TxContentBlob;
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/MerkleDataSetTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/MerkleDataSetTest.java
similarity index 87%
rename from source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/MerkleDataSetTest.java
rename to source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/MerkleDataSetTest.java
index fbb5eb09..a90806d6 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/MerkleDataSetTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/MerkleDataSetTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger;
+package test.com.jd.blockchain.ledger.core;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
@@ -20,9 +20,9 @@ import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
import com.jd.blockchain.crypto.service.classic.ClassicCryptoService;
import com.jd.blockchain.crypto.service.sm.SMCryptoService;
+import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.ledger.core.CryptoConfig;
import com.jd.blockchain.ledger.core.MerkleDataSet;
-import com.jd.blockchain.ledger.core.MerkleProof;
import com.jd.blockchain.storage.service.VersioningKVEntry;
import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
import com.jd.blockchain.utils.Bytes;
@@ -32,6 +32,38 @@ public class MerkleDataSetTest {
private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(),
SMCryptoService.class.getName() };
+
+ /**
+ * 测试存储的增长;
+ */
+ @Test
+ public void testKeyIndex() {
+
+ CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length];
+ for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) {
+ supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]);
+ }
+
+ String keyPrefix = "";
+ CryptoConfig cryptoConfig = new CryptoConfig();
+ cryptoConfig.setSupportedProviders(supportedProviders);
+ cryptoConfig.setHashAlgorithm(ClassicAlgorithm.SHA256);
+ cryptoConfig.setAutoVerifyHash(true);
+
+ MemoryKVStorage storage = new MemoryKVStorage();
+
+ MerkleDataSet mds = new MerkleDataSet(cryptoConfig, keyPrefix, storage, storage);
+ mds.setValue("A", "A".getBytes(), -1);
+ mds.setValue("B", "B".getBytes(), -1);
+ mds.setValue("C", "C".getBytes(), -1);
+
+ mds.commit();
+
+ //校验 Key 的正确性;
+ assertEquals("A", mds.getKeyAtIndex(0));
+ assertEquals("B", mds.getKeyAtIndex(1));
+ assertEquals("C", mds.getKeyAtIndex(2));
+ }
/**
* 测试存储的增长;
@@ -59,6 +91,20 @@ public class MerkleDataSetTest {
mds.commit();
+ byte[] va = mds.getValue("A");
+ assertNotNull(va);
+ assertEquals("A", new String(va));
+
+ byte[] vc = mds.getValue("C");
+ VersioningKVEntry ventry = mds.getDataEntry("C");
+ assertNotNull(vc);
+ assertNotNull(ventry);
+ assertEquals("C", new String(vc));
+ assertEquals("C", ventry.getKey().toUTF8String());
+
+ HashDigest root1 = mds.getRootHash();
+
+
// 1个KV项的存储KEY的数量= 1 + 1(保存SN) + Merkle节点数量;
// 所以:3 项;
// so the expected item count in storage is 10;
@@ -68,6 +114,8 @@ public class MerkleDataSetTest {
mds.setValue("B", "B".getBytes(), 0);
mds.setValue("C", "C".getBytes(), 0);
mds.commit();
+ HashDigest root2 = mds.getRootHash();
+ assertNotEquals(root1, root2);
// Version changed only;仅仅增加 merkle 节点,此时 Merkle 树只有 1 层路径节点,因此只更新2个数据节点和 1
// 个路径节点;(注:版本值是在同一个 key 下按序列保存的);
@@ -76,6 +124,9 @@ public class MerkleDataSetTest {
mds.setValue("D", "DValue".getBytes(), -1);
mds.commit();
+ HashDigest root3 = mds.getRootHash();
+ assertNotEquals(root2, root3);
+ assertNotEquals(root1, root3);
// New key added, include 1 versioning kv, 1 sn key, 2 merkle nodes;
// String[] keys = StringUtils.toStringArray(storage.keySet());
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/MerkleTreeTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/MerkleTreeTest.java
similarity index 99%
rename from source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/MerkleTreeTest.java
rename to source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/MerkleTreeTest.java
index d8cb3d29..afe8e435 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/MerkleTreeTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/MerkleTreeTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger;
+package test.com.jd.blockchain.ledger.core;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
@@ -17,9 +17,9 @@ import org.mockito.Mockito;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
import com.jd.blockchain.ledger.CryptoSetting;
-import com.jd.blockchain.ledger.core.MerkleDataNode;
-import com.jd.blockchain.ledger.core.MerkleNode;
-import com.jd.blockchain.ledger.core.MerkleProof;
+import com.jd.blockchain.ledger.MerkleDataNode;
+import com.jd.blockchain.ledger.MerkleNode;
+import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.ledger.core.MerkleTree;
import com.jd.blockchain.storage.service.utils.ExistancePolicyKVStorageMap;
import com.jd.blockchain.utils.Bytes;
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/RolePrivilegeDatasetTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/RolePrivilegeDatasetTest.java
new file mode 100644
index 00000000..18937fa0
--- /dev/null
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/RolePrivilegeDatasetTest.java
@@ -0,0 +1,69 @@
+package test.com.jd.blockchain.ledger.core;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import com.jd.blockchain.crypto.Crypto;
+import com.jd.blockchain.crypto.CryptoAlgorithm;
+import com.jd.blockchain.crypto.CryptoProvider;
+import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.crypto.service.classic.ClassicCryptoService;
+import com.jd.blockchain.crypto.service.sm.SMCryptoService;
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.RolePrivileges;
+import com.jd.blockchain.ledger.TransactionPermission;
+import com.jd.blockchain.ledger.core.CryptoConfig;
+import com.jd.blockchain.ledger.core.RolePrivilegeDataset;
+import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
+
+public class RolePrivilegeDatasetTest {
+
+ private static final String[] SUPPORTED_PROVIDER_NAMES = { ClassicCryptoService.class.getName(),
+ SMCryptoService.class.getName() };
+
+ private static final CryptoAlgorithm HASH_ALGORITHM = Crypto.getAlgorithm("SHA256");
+
+ private static final CryptoProvider[] SUPPORTED_PROVIDERS = new CryptoProvider[SUPPORTED_PROVIDER_NAMES.length];
+ static {
+ for (int i = 0; i < SUPPORTED_PROVIDER_NAMES.length; i++) {
+ SUPPORTED_PROVIDERS[i] = Crypto.getProvider(SUPPORTED_PROVIDER_NAMES[i]);
+ }
+ }
+
+ @Test
+ public void testAddRolePrivilege() {
+
+ CryptoConfig cryptoConfig = new CryptoConfig();
+ cryptoConfig.setAutoVerifyHash(true);
+ cryptoConfig.setSupportedProviders(SUPPORTED_PROVIDERS);
+ cryptoConfig.setHashAlgorithm(HASH_ALGORITHM);
+
+ MemoryKVStorage testStorage = new MemoryKVStorage();
+
+ String roleName = "DEFAULT";
+ String prefix = "role-privilege/";
+ RolePrivilegeDataset rolePrivilegeDataset = new RolePrivilegeDataset(cryptoConfig, prefix, testStorage,
+ testStorage);
+ rolePrivilegeDataset.addRolePrivilege(roleName, new LedgerPermission[] { LedgerPermission.REGISTER_USER },
+ new TransactionPermission[] { TransactionPermission.CONTRACT_OPERATION });
+
+ rolePrivilegeDataset.commit();
+
+ RolePrivileges rolePrivilege = rolePrivilegeDataset.getRolePrivilege(roleName);
+ assertNotNull(rolePrivilege);
+
+ HashDigest rootHash = rolePrivilegeDataset.getRootHash();
+ RolePrivilegeDataset newRolePrivilegeDataset = new RolePrivilegeDataset(rootHash, cryptoConfig, prefix,
+ testStorage, testStorage, true);
+ rolePrivilege = newRolePrivilegeDataset.getRolePrivilege(roleName);
+ assertNotNull(rolePrivilege);
+
+ assertTrue(rolePrivilege.getLedgerPrivilege().isEnable(LedgerPermission.REGISTER_USER));
+ assertTrue(rolePrivilege.getTransactionPrivilege().isEnable(TransactionPermission.CONTRACT_OPERATION));
+
+
+ }
+
+}
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TestContract.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TestContract.java
similarity index 96%
rename from source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TestContract.java
rename to source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TestContract.java
index 4d9a5ccd..4cbe2784 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TestContract.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TestContract.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger;
+package test.com.jd.blockchain.ledger.core;
import com.jd.blockchain.contract.Contract;
import com.jd.blockchain.contract.ContractEvent;
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TestContractImpl.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TestContractImpl.java
similarity index 94%
rename from source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TestContractImpl.java
rename to source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TestContractImpl.java
index 3375f7f3..339cb4fb 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TestContractImpl.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TestContractImpl.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger;
+package test.com.jd.blockchain.ledger.core;
public interface TestContractImpl {
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionBatchProcessorTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionBatchProcessorTest.java
new file mode 100644
index 00000000..1f7dbbc1
--- /dev/null
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionBatchProcessorTest.java
@@ -0,0 +1,454 @@
+package test.com.jd.blockchain.ledger.core;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.when;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import com.jd.blockchain.binaryproto.DataContractRegistry;
+import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.ledger.BlockchainKeyGenerator;
+import com.jd.blockchain.ledger.BlockchainKeypair;
+import com.jd.blockchain.ledger.BytesValue;
+import com.jd.blockchain.ledger.DataAccountRegisterOperation;
+import com.jd.blockchain.ledger.DataVersionConflictException;
+import com.jd.blockchain.ledger.EndpointRequest;
+import com.jd.blockchain.ledger.LedgerBlock;
+import com.jd.blockchain.ledger.LedgerInitSetting;
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.LedgerTransaction;
+import com.jd.blockchain.ledger.NodeRequest;
+import com.jd.blockchain.ledger.TransactionContent;
+import com.jd.blockchain.ledger.TransactionContentBody;
+import com.jd.blockchain.ledger.TransactionPermission;
+import com.jd.blockchain.ledger.TransactionRequest;
+import com.jd.blockchain.ledger.TransactionResponse;
+import com.jd.blockchain.ledger.TransactionState;
+import com.jd.blockchain.ledger.UserRegisterOperation;
+import com.jd.blockchain.ledger.core.DataAccount;
+import com.jd.blockchain.ledger.core.DefaultOperationHandleRegisteration;
+import com.jd.blockchain.ledger.core.LedgerDataQuery;
+import com.jd.blockchain.ledger.core.LedgerDataset;
+import com.jd.blockchain.ledger.core.LedgerEditor;
+import com.jd.blockchain.ledger.core.LedgerManager;
+import com.jd.blockchain.ledger.core.LedgerRepository;
+import com.jd.blockchain.ledger.core.LedgerSecurityManager;
+import com.jd.blockchain.ledger.core.LedgerTransactionContext;
+import com.jd.blockchain.ledger.core.LedgerTransactionalEditor;
+import com.jd.blockchain.ledger.core.OperationHandleRegisteration;
+import com.jd.blockchain.ledger.core.SecurityPolicy;
+import com.jd.blockchain.ledger.core.TransactionBatchProcessor;
+import com.jd.blockchain.ledger.core.UserAccount;
+import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
+
+public class TransactionBatchProcessorTest {
+ static {
+ DataContractRegistry.register(TransactionContent.class);
+ DataContractRegistry.register(TransactionContentBody.class);
+ DataContractRegistry.register(TransactionRequest.class);
+ DataContractRegistry.register(NodeRequest.class);
+ DataContractRegistry.register(EndpointRequest.class);
+ DataContractRegistry.register(TransactionResponse.class);
+ DataContractRegistry.register(UserRegisterOperation.class);
+ DataContractRegistry.register(DataAccountRegisterOperation.class);
+ }
+
+ private static final String LEDGER_KEY_PREFIX = "LDG://";
+
+ private HashDigest ledgerHash = null;
+
+ private BlockchainKeypair parti0 = BlockchainKeyGenerator.getInstance().generate();
+ private BlockchainKeypair parti1 = BlockchainKeyGenerator.getInstance().generate();
+ private BlockchainKeypair parti2 = BlockchainKeyGenerator.getInstance().generate();
+ private BlockchainKeypair parti3 = BlockchainKeyGenerator.getInstance().generate();
+
+ private BlockchainKeypair[] participants = { parti0, parti1, parti2, parti3 };
+
+ // TODO: 验证无效签名会被拒绝;
+
+ @Test
+ public void testSingleTxProcess() {
+ final MemoryKVStorage STORAGE = new MemoryKVStorage();
+
+ // 初始化账本到指定的存储库;
+ ledgerHash = initLedger(STORAGE, parti0, parti1, parti2, parti3);
+
+ // 加载账本;
+ LedgerManager ledgerManager = new LedgerManager();
+ LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, STORAGE);
+
+ // 验证参与方账户的存在;
+ LedgerDataQuery previousBlockDataset = ledgerRepo.getDataSet(ledgerRepo.getLatestBlock());
+ UserAccount user0 = previousBlockDataset.getUserAccountSet().getUser(parti0.getAddress());
+ assertNotNull(user0);
+ boolean partiRegistered = previousBlockDataset.getUserAccountSet().contains(parti0.getAddress());
+ assertTrue(partiRegistered);
+
+ // 生成新区块;
+ LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();
+
+ OperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration();
+ LedgerSecurityManager securityManager = getSecurityManager();
+ TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor,
+ previousBlockDataset, opReg, ledgerManager);
+
+ // 注册新用户;
+ BlockchainKeypair userKeypair = BlockchainKeyGenerator.getInstance().generate();
+ TransactionRequest transactionRequest = LedgerTestUtils.createTxRequest_UserReg(userKeypair, ledgerHash, parti0,
+ parti0);
+ TransactionResponse txResp = txbatchProcessor.schedule(transactionRequest);
+
+ LedgerBlock newBlock = newBlockEditor.prepare();
+ newBlockEditor.commit();
+
+ // 验证正确性;
+ ledgerManager = new LedgerManager();
+ ledgerRepo = ledgerManager.register(ledgerHash, STORAGE);
+
+ LedgerBlock latestBlock = ledgerRepo.getLatestBlock();
+ assertEquals(newBlock.getHash(), latestBlock.getHash());
+ assertEquals(1, newBlock.getHeight());
+
+ assertEquals(TransactionState.SUCCESS, txResp.getExecutionState());
+ }
+
+ private static LedgerSecurityManager getSecurityManager() {
+ LedgerSecurityManager securityManager = Mockito.mock(LedgerSecurityManager.class);
+
+ SecurityPolicy securityPolicy = Mockito.mock(SecurityPolicy.class);
+ when(securityPolicy.isEndpointEnable(any(LedgerPermission.class), any())).thenReturn(true);
+ when(securityPolicy.isEndpointEnable(any(TransactionPermission.class), any())).thenReturn(true);
+ when(securityPolicy.isNodeEnable(any(LedgerPermission.class), any())).thenReturn(true);
+ when(securityPolicy.isNodeEnable(any(TransactionPermission.class), any())).thenReturn(true);
+
+ when(securityManager.createSecurityPolicy(any(), any())).thenReturn(securityPolicy);
+
+ return securityManager;
+ }
+
+ @Test
+ public void testMultiTxsProcess() {
+ final MemoryKVStorage STORAGE = new MemoryKVStorage();
+
+ // 初始化账本到指定的存储库;
+ ledgerHash = initLedger(STORAGE, parti0, parti1, parti2, parti3);
+
+ // 加载账本;
+ LedgerManager ledgerManager = new LedgerManager();
+ LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, STORAGE);
+
+ // 验证参与方账户的存在;
+ LedgerDataQuery previousBlockDataset = ledgerRepo.getDataSet(ledgerRepo.getLatestBlock());
+ UserAccount user0 = previousBlockDataset.getUserAccountSet().getUser(parti0.getAddress());
+ assertNotNull(user0);
+ boolean partiRegistered = previousBlockDataset.getUserAccountSet().contains(parti0.getAddress());
+ assertTrue(partiRegistered);
+
+ // 生成新区块;
+ LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();
+
+ OperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration();
+ LedgerSecurityManager securityManager = getSecurityManager();
+ TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor,
+ previousBlockDataset, opReg, ledgerManager);
+
+ // 注册新用户;
+ BlockchainKeypair userKeypair1 = BlockchainKeyGenerator.getInstance().generate();
+ TransactionRequest transactionRequest1 = LedgerTestUtils.createTxRequest_UserReg(userKeypair1, ledgerHash,
+ parti0, parti0);
+ TransactionResponse txResp1 = txbatchProcessor.schedule(transactionRequest1);
+
+ BlockchainKeypair userKeypair2 = BlockchainKeyGenerator.getInstance().generate();
+ TransactionRequest transactionRequest2 = LedgerTestUtils.createTxRequest_UserReg(userKeypair2, ledgerHash,
+ parti0, parti0);
+ TransactionResponse txResp2 = txbatchProcessor.schedule(transactionRequest2);
+
+ LedgerBlock newBlock = newBlockEditor.prepare();
+ newBlockEditor.commit();
+
+ assertEquals(TransactionState.SUCCESS, txResp1.getExecutionState());
+ assertEquals(TransactionState.SUCCESS, txResp2.getExecutionState());
+
+ // 验证正确性;
+ ledgerManager = new LedgerManager();
+ ledgerRepo = ledgerManager.register(ledgerHash, STORAGE);
+
+ LedgerBlock latestBlock = ledgerRepo.getLatestBlock();
+ assertEquals(newBlock.getHash(), latestBlock.getHash());
+ assertEquals(1, newBlock.getHeight());
+
+ LedgerDataQuery ledgerDS = ledgerRepo.getDataSet(latestBlock);
+ boolean existUser1 = ledgerDS.getUserAccountSet().contains(userKeypair1.getAddress());
+ boolean existUser2 = ledgerDS.getUserAccountSet().contains(userKeypair2.getAddress());
+ assertTrue(existUser1);
+ assertTrue(existUser2);
+ }
+
+ @Test
+ public void testTxRollback() {
+ final MemoryKVStorage STORAGE = new MemoryKVStorage();
+
+ // 初始化账本到指定的存储库;
+ ledgerHash = initLedger(STORAGE, parti0, parti1, parti2, parti3);
+
+ // 加载账本;
+ LedgerManager ledgerManager = new LedgerManager();
+ LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, STORAGE);
+
+ // 验证参与方账户的存在;
+ LedgerDataQuery previousBlockDataset = ledgerRepo.getDataSet(ledgerRepo.getLatestBlock());
+ UserAccount user0 = previousBlockDataset.getUserAccountSet().getUser(parti0.getAddress());
+ assertNotNull(user0);
+ boolean partiRegistered = previousBlockDataset.getUserAccountSet().contains(parti0.getAddress());
+ assertTrue(partiRegistered);
+
+ // 生成新区块;
+ LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();
+
+ OperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration();
+ LedgerSecurityManager securityManager = getSecurityManager();
+ TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor,
+ previousBlockDataset, opReg, ledgerManager);
+
+ // 注册新用户;
+ BlockchainKeypair userKeypair1 = BlockchainKeyGenerator.getInstance().generate();
+ TransactionRequest transactionRequest1 = LedgerTestUtils.createTxRequest_UserReg(userKeypair1, ledgerHash,
+ parti0, parti0);
+ TransactionResponse txResp1 = txbatchProcessor.schedule(transactionRequest1);
+
+ BlockchainKeypair userKeypair2 = BlockchainKeyGenerator.getInstance().generate();
+ TransactionRequest transactionRequest2 = LedgerTestUtils
+ .createTxRequest_MultiOPs_WithNotExistedDataAccount(userKeypair2, ledgerHash, parti0, parti0);
+ TransactionResponse txResp2 = txbatchProcessor.schedule(transactionRequest2);
+
+ BlockchainKeypair userKeypair3 = BlockchainKeyGenerator.getInstance().generate();
+ TransactionRequest transactionRequest3 = LedgerTestUtils.createTxRequest_UserReg(userKeypair3, ledgerHash,
+ parti0, parti0);
+ TransactionResponse txResp3 = txbatchProcessor.schedule(transactionRequest3);
+
+ LedgerBlock newBlock = newBlockEditor.prepare();
+ newBlockEditor.commit();
+
+ assertEquals(TransactionState.SUCCESS, txResp1.getExecutionState());
+ assertEquals(TransactionState.DATA_ACCOUNT_DOES_NOT_EXIST, txResp2.getExecutionState());
+ assertEquals(TransactionState.SUCCESS, txResp3.getExecutionState());
+
+ // 验证正确性;
+ ledgerManager = new LedgerManager();
+ ledgerRepo = ledgerManager.register(ledgerHash, STORAGE);
+
+ LedgerBlock latestBlock = ledgerRepo.getLatestBlock();
+ assertEquals(newBlock.getHash(), latestBlock.getHash());
+ assertEquals(1, newBlock.getHeight());
+
+ LedgerTransaction tx1 = ledgerRepo.getTransactionSet()
+ .get(transactionRequest1.getTransactionContent().getHash());
+ LedgerTransaction tx2 = ledgerRepo.getTransactionSet()
+ .get(transactionRequest2.getTransactionContent().getHash());
+ LedgerTransaction tx3 = ledgerRepo.getTransactionSet()
+ .get(transactionRequest3.getTransactionContent().getHash());
+
+ assertNotNull(tx1);
+ assertEquals(TransactionState.SUCCESS, tx1.getExecutionState());
+ assertNotNull(tx2);
+ assertEquals(TransactionState.DATA_ACCOUNT_DOES_NOT_EXIST, tx2.getExecutionState());
+ assertNotNull(tx3);
+ assertEquals(TransactionState.SUCCESS, tx3.getExecutionState());
+
+ LedgerDataQuery ledgerDS = ledgerRepo.getDataSet(latestBlock);
+ boolean existUser1 = ledgerDS.getUserAccountSet().contains(userKeypair1.getAddress());
+ boolean existUser2 = ledgerDS.getUserAccountSet().contains(userKeypair2.getAddress());
+ boolean existUser3 = ledgerDS.getUserAccountSet().contains(userKeypair3.getAddress());
+ assertTrue(existUser1);
+ assertFalse(existUser2);
+ assertTrue(existUser3);
+ }
+
+ @Test
+ public void testTxRollbackByVersionsConflict() {
+ final MemoryKVStorage STORAGE = new MemoryKVStorage();
+
+ // 初始化账本到指定的存储库;
+ ledgerHash = initLedger(STORAGE, parti0, parti1, parti2, parti3);
+
+ // 加载账本;
+ LedgerManager ledgerManager = new LedgerManager();
+ LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, STORAGE);
+
+ // 验证参与方账户的存在;
+ LedgerDataQuery previousBlockDataset = ledgerRepo.getDataSet(ledgerRepo.getLatestBlock());
+ UserAccount user0 = previousBlockDataset.getUserAccountSet().getUser(parti0.getAddress());
+ assertNotNull(user0);
+ boolean partiRegistered = previousBlockDataset.getUserAccountSet().contains(parti0.getAddress());
+ assertTrue(partiRegistered);
+
+ // 注册数据账户;
+ // 生成新区块;
+ LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();
+
+ OperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration();
+ LedgerSecurityManager securityManager = getSecurityManager();
+ TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor,
+ previousBlockDataset, opReg, ledgerManager);
+
+ BlockchainKeypair dataAccountKeypair = BlockchainKeyGenerator.getInstance().generate();
+ TransactionRequest transactionRequest1 = LedgerTestUtils.createTxRequest_DataAccountReg(dataAccountKeypair,
+ ledgerHash, parti0, parti0);
+ TransactionResponse txResp1 = txbatchProcessor.schedule(transactionRequest1);
+ LedgerBlock newBlock = newBlockEditor.prepare();
+ newBlockEditor.commit();
+
+ assertEquals(TransactionState.SUCCESS, txResp1.getExecutionState());
+ DataAccount dataAccount = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress());
+ assertNotNull(dataAccount);
+
+ // 正确写入 KV 数据;
+ TransactionRequest txreq1 = LedgerTestUtils.createTxRequest_DataAccountWrite(dataAccountKeypair.getAddress(),
+ "K1", "V-1-1", -1, ledgerHash, parti0, parti0);
+ TransactionRequest txreq2 = LedgerTestUtils.createTxRequest_DataAccountWrite(dataAccountKeypair.getAddress(),
+ "K2", "V-2-1", -1, ledgerHash, parti0, parti0);
+ TransactionRequest txreq3 = LedgerTestUtils.createTxRequest_DataAccountWrite(dataAccountKeypair.getAddress(),
+ "K3", "V-3-1", -1, ledgerHash, parti0, parti0);
+
+ // 连续写 K1,K1的版本将变为1;
+ TransactionRequest txreq4 = LedgerTestUtils.createTxRequest_DataAccountWrite(dataAccountKeypair.getAddress(),
+ "K1", "V-1-2", 0, ledgerHash, parti0, parti0);
+
+ newBlockEditor = ledgerRepo.createNextBlock();
+ previousBlockDataset = ledgerRepo.getDataSet(ledgerRepo.getLatestBlock());
+ txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor, previousBlockDataset, opReg,
+ ledgerManager);
+
+ txbatchProcessor.schedule(txreq1);
+ txbatchProcessor.schedule(txreq2);
+ txbatchProcessor.schedule(txreq3);
+ txbatchProcessor.schedule(txreq4);
+
+ newBlock = newBlockEditor.prepare();
+ newBlockEditor.commit();
+
+ BytesValue v1_0 = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress()).getBytes("K1",
+ 0);
+ BytesValue v1_1 = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress()).getBytes("K1",
+ 1);
+ BytesValue v2 = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress()).getBytes("K2",
+ 0);
+ BytesValue v3 = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress()).getBytes("K3",
+ 0);
+
+ assertNotNull(v1_0);
+ assertNotNull(v1_1);
+ assertNotNull(v2);
+ assertNotNull(v3);
+
+ assertEquals("V-1-1", v1_0.getValue().toUTF8String());
+ assertEquals("V-1-2", v1_1.getValue().toUTF8String());
+ assertEquals("V-2-1", v2.getValue().toUTF8String());
+ assertEquals("V-3-1", v3.getValue().toUTF8String());
+
+ // 提交多笔数据写入的交易,包含存在数据版本冲突的交易,验证交易是否正确回滚;
+ // 先写一笔正确的交易; k3 的版本将变为 1 ;
+ TransactionRequest txreq5 = LedgerTestUtils.createTxRequest_DataAccountWrite(dataAccountKeypair.getAddress(),
+ "K3", "V-3-2", 0, ledgerHash, parti0, parti0);
+ // 指定冲突的版本号,正确的应该是版本1;
+ TransactionRequest txreq6 = LedgerTestUtils.createTxRequest_DataAccountWrite(dataAccountKeypair.getAddress(),
+ "K1", "V-1-3", 0, ledgerHash, parti0, parti0);
+
+ newBlockEditor = ledgerRepo.createNextBlock();
+ previousBlockDataset = ledgerRepo.getDataSet(ledgerRepo.getLatestBlock());
+ txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor, previousBlockDataset, opReg,
+ ledgerManager);
+
+ txbatchProcessor.schedule(txreq5);
+ // 预期会产生版本冲突异常; DataVersionConflictionException;
+ DataVersionConflictException versionConflictionException = null;
+ try {
+ txbatchProcessor.schedule(txreq6);
+ } catch (DataVersionConflictException e) {
+ versionConflictionException = e;
+ }
+ assertNotNull(versionConflictionException);
+
+ newBlock = newBlockEditor.prepare();
+ newBlockEditor.commit();
+
+ BytesValue v1 = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress()).getBytes("K1");
+ v3 = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress()).getBytes("K3");
+
+ // k1 的版本仍然为1,没有更新;
+ long k1_version = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress())
+ .getDataVersion("K1");
+ assertEquals(1, k1_version);
+
+ long k3_version = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress())
+ .getDataVersion("K3");
+ assertEquals(1, k3_version);
+
+ assertNotNull(v1);
+ assertNotNull(v3);
+ assertEquals("V-1-2", v1.getValue().toUTF8String());
+ assertEquals("V-3-2", v3.getValue().toUTF8String());
+
+// // 验证正确性;
+// ledgerManager = new LedgerManager();
+// ledgerRepo = ledgerManager.register(ledgerHash, STORAGE);
+//
+// LedgerBlock latestBlock = ledgerRepo.getLatestBlock();
+// assertEquals(newBlock.getHash(), latestBlock.getHash());
+// assertEquals(1, newBlock.getHeight());
+//
+// LedgerTransaction tx1 = ledgerRepo.getTransactionSet()
+// .get(transactionRequest1.getTransactionContent().getHash());
+//
+// assertNotNull(tx1);
+// assertEquals(TransactionState.SUCCESS, tx1.getExecutionState());
+
+ }
+
+ private HashDigest initLedger(MemoryKVStorage storage, BlockchainKeypair... partiKeys) {
+ // 创建初始化配置;
+ LedgerInitSetting initSetting = LedgerTestUtils.createLedgerInitSetting(partiKeys);
+
+ // 创建账本;
+ LedgerEditor ldgEdt = LedgerTransactionalEditor.createEditor(initSetting, LEDGER_KEY_PREFIX, storage, storage);
+
+ TransactionRequest genesisTxReq = LedgerTestUtils.createLedgerInitTxRequest(partiKeys);
+ LedgerTransactionContext genisisTxCtx = ldgEdt.newTransaction(genesisTxReq);
+ LedgerDataset ldgDS = genisisTxCtx.getDataset();
+
+ for (int i = 0; i < partiKeys.length; i++) {
+ UserAccount userAccount = ldgDS.getUserAccountSet().register(partiKeys[i].getAddress(),
+ partiKeys[i].getPubKey());
+ userAccount.setProperty("Name", "参与方-" + i, -1);
+ userAccount.setProperty("Share", "" + (10 + i), -1);
+ }
+
+ LedgerTransaction tx = genisisTxCtx.commit(TransactionState.SUCCESS);
+
+ assertEquals(genesisTxReq.getTransactionContent().getHash(), tx.getTransactionContent().getHash());
+ assertEquals(0, tx.getBlockHeight());
+
+ LedgerBlock block = ldgEdt.prepare();
+
+ assertEquals(0, block.getHeight());
+ assertNotNull(block.getHash());
+ assertNull(block.getPreviousHash());
+
+ // 创世区块的账本哈希为 null;
+ assertNull(block.getLedgerHash());
+ assertNotNull(block.getHash());
+
+ // 提交数据,写入存储;
+ ldgEdt.commit();
+
+ HashDigest ledgerHash = block.getHash();
+ return ledgerHash;
+ }
+
+}
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TransactionSetTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionSetTest.java
similarity index 97%
rename from source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TransactionSetTest.java
rename to source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionSetTest.java
index a4b719a7..47902dcb 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TransactionSetTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionSetTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger;
+package test.com.jd.blockchain.ledger.core;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -31,9 +31,9 @@ import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.ledger.TransactionRequestBuilder;
import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.ledger.UserRegisterOperation;
+import com.jd.blockchain.ledger.core.LedgerTransactionData;
import com.jd.blockchain.ledger.core.TransactionSet;
-import com.jd.blockchain.ledger.core.impl.LedgerTransactionData;
-import com.jd.blockchain.ledger.core.impl.TransactionStagedSnapshot;
+import com.jd.blockchain.ledger.core.TransactionStagedSnapshot;
import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
import com.jd.blockchain.transaction.TxBuilder;
import com.jd.blockchain.utils.io.BytesUtils;
@@ -102,8 +102,7 @@ public class TransactionSetTest {
txSnapshot.setContractAccountSetHash(contractAccountSetHash);
long blockHeight = 8922L;
- LedgerTransactionData tx = new LedgerTransactionData(blockHeight, txReq, TransactionState.SUCCESS, txSnapshot,
- null);
+ LedgerTransactionData tx = new LedgerTransactionData(blockHeight, txReq, TransactionState.SUCCESS, txSnapshot);
txset.add(tx);
assertTrue(txset.isUpdated());
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TransactionStagedSnapshotTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionStagedSnapshotTest.java
similarity index 94%
rename from source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TransactionStagedSnapshotTest.java
rename to source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionStagedSnapshotTest.java
index 3693f60d..9eebeafd 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TransactionStagedSnapshotTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionStagedSnapshotTest.java
@@ -6,7 +6,7 @@
* Date: 2018/8/30 上午10:49
* Description:
*/
-package test.com.jd.blockchain.ledger;
+package test.com.jd.blockchain.ledger.core;
import static org.junit.Assert.assertEquals;
@@ -18,7 +18,7 @@ import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
import com.jd.blockchain.ledger.LedgerDataSnapshot;
-import com.jd.blockchain.ledger.core.impl.TransactionStagedSnapshot;
+import com.jd.blockchain.ledger.core.TransactionStagedSnapshot;
/**
*
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/UserRoleDatasetTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/UserRoleDatasetTest.java
new file mode 100644
index 00000000..44046ee6
--- /dev/null
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/UserRoleDatasetTest.java
@@ -0,0 +1,62 @@
+package test.com.jd.blockchain.ledger.core;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.Test;
+
+import com.jd.blockchain.crypto.Crypto;
+import com.jd.blockchain.crypto.CryptoAlgorithm;
+import com.jd.blockchain.crypto.CryptoProvider;
+import com.jd.blockchain.crypto.service.classic.ClassicCryptoService;
+import com.jd.blockchain.crypto.service.sm.SMCryptoService;
+import com.jd.blockchain.ledger.BlockchainKeyGenerator;
+import com.jd.blockchain.ledger.BlockchainKeypair;
+import com.jd.blockchain.ledger.RolesPolicy;
+import com.jd.blockchain.ledger.UserRoles;
+import com.jd.blockchain.ledger.core.CryptoConfig;
+import com.jd.blockchain.ledger.core.UserRoleDataset;
+import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
+
+public class UserRoleDatasetTest {
+
+ private static final String[] SUPPORTED_PROVIDER_NAMES = { ClassicCryptoService.class.getName(),
+ SMCryptoService.class.getName() };
+
+ private static final CryptoAlgorithm HASH_ALGORITHM = Crypto.getAlgorithm("SHA256");
+
+ private static final CryptoProvider[] SUPPORTED_PROVIDERS = new CryptoProvider[SUPPORTED_PROVIDER_NAMES.length];
+ static {
+ for (int i = 0; i < SUPPORTED_PROVIDER_NAMES.length; i++) {
+ SUPPORTED_PROVIDERS[i] = Crypto.getProvider(SUPPORTED_PROVIDER_NAMES[i]);
+ }
+ }
+
+ @Test
+ public void testAddUserRoles() {
+ CryptoConfig cryptoConfig = new CryptoConfig();
+ cryptoConfig.setAutoVerifyHash(true);
+ cryptoConfig.setSupportedProviders(SUPPORTED_PROVIDERS);
+ cryptoConfig.setHashAlgorithm(HASH_ALGORITHM);
+
+ MemoryKVStorage testStorage = new MemoryKVStorage();
+ String prefix = "user-roles/";
+ UserRoleDataset userRolesDataset = new UserRoleDataset(cryptoConfig, prefix, testStorage, testStorage);
+
+ BlockchainKeypair bckp = BlockchainKeyGenerator.getInstance().generate();
+ String[] authRoles = { "DEFAULT", "MANAGER" };
+ userRolesDataset.addUserRoles(bckp.getAddress(), RolesPolicy.UNION, authRoles);
+
+ userRolesDataset.commit();
+
+ assertEquals(1, userRolesDataset.getUserCount());
+ UserRoles userRoles = userRolesDataset.getUserRoles(bckp.getAddress());
+ assertNotNull(userRoles);
+ String[] roles = userRoles.getRoles();
+ assertEquals(2, roles.length);
+ assertArrayEquals(authRoles, roles);
+ assertEquals(RolesPolicy.UNION, userRoles.getPolicy());
+ }
+
+}
diff --git a/source/ledger/ledger-core/src/test/resources/logback-test.xml b/source/ledger/ledger-core/src/test/resources/logback-test.xml
new file mode 100644
index 00000000..29013782
--- /dev/null
+++ b/source/ledger/ledger-core/src/test/resources/logback-test.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/source/ledger/ledger-model/pom.xml b/source/ledger/ledger-model/pom.xml
index ea21a207..6bfbf903 100644
--- a/source/ledger/ledger-model/pom.xml
+++ b/source/ledger/ledger-model/pom.xml
@@ -6,7 +6,7 @@
com.jd.blockchain
ledger
- 1.0.0.RELEASE
+ 1.1.0-SNAPSHOT
ledger-model
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/AuthorizationException.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/AuthorizationException.java
new file mode 100644
index 00000000..94a374a8
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/AuthorizationException.java
@@ -0,0 +1,17 @@
+package com.jd.blockchain.ledger;
+
+public class AuthorizationException extends LedgerException {
+
+ private static final long serialVersionUID = -4418553411943356320L;
+
+
+
+ public AuthorizationException(String message) {
+ super(message);
+ }
+
+ public AuthorizationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockBody.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockBody.java
index ff8f3705..7c82b214 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockBody.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockBody.java
@@ -20,4 +20,7 @@ public interface BlockBody extends LedgerDataSnapshot{
@DataField(order=5, primitiveType = PrimitiveType.BYTES)
HashDigest getTransactionSetHash();
+
+ @DataField(order=6, primitiveType = PrimitiveType.INT64)
+ long getTimestamp();
}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockRollbackException.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockRollbackException.java
new file mode 100644
index 00000000..c64f9e42
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockRollbackException.java
@@ -0,0 +1,33 @@
+package com.jd.blockchain.ledger;
+
+public class BlockRollbackException extends LedgerException {
+
+ private static final long serialVersionUID = 3583192000738807503L;
+
+ private TransactionState state;
+
+ public BlockRollbackException(String message) {
+ this(TransactionState.SYSTEM_ERROR, message);
+ }
+
+ public BlockRollbackException(TransactionState state, String message) {
+ super(message);
+ assert TransactionState.SUCCESS != state;
+ this.state = state;
+ }
+
+ public BlockRollbackException(String message, Throwable cause) {
+ this(TransactionState.SYSTEM_ERROR, message, cause);
+ }
+
+ public BlockRollbackException(TransactionState state, String message, Throwable cause) {
+ super(message, cause);
+ assert TransactionState.SUCCESS != state;
+ this.state = state;
+ }
+
+ public TransactionState getState() {
+ return state;
+ }
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValueEncoding.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValueEncoding.java
index af67719e..baee5868 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValueEncoding.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValueEncoding.java
@@ -1,32 +1,36 @@
package com.jd.blockchain.ledger;
-import com.jd.blockchain.binaryproto.BinaryProtocol;
-import com.jd.blockchain.binaryproto.DataContract;
-import com.jd.blockchain.ledger.resolver.*;
-
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import com.jd.blockchain.binaryproto.BinaryProtocol;
+import com.jd.blockchain.binaryproto.DataContract;
+import com.jd.blockchain.ledger.resolver.BooleanToBytesValueResolver;
+import com.jd.blockchain.ledger.resolver.BytesToBytesValueResolver;
+import com.jd.blockchain.ledger.resolver.BytesValueResolver;
+import com.jd.blockchain.ledger.resolver.IntegerToBytesValueResolver;
+import com.jd.blockchain.ledger.resolver.LongToBytesValueResolver;
+import com.jd.blockchain.ledger.resolver.ShortToBytesValueResolver;
+import com.jd.blockchain.ledger.resolver.StringToBytesValueResolver;
+
public class BytesValueEncoding {
private static final Map, BytesValueResolver> CLASS_RESOLVER_MAP = new ConcurrentHashMap<>();
private static final Map DATA_TYPE_RESOLVER_MAP = new ConcurrentHashMap<>();
+ private static final Object[] EMPTY_OBJECTS = {};
+
static {
init();
}
private static void init() {
- BytesValueResolver[] resolvers = new BytesValueResolver[]{
- new BytesToBytesValueResolver(),
- new IntegerToBytesValueResolver(),
- new LongToBytesValueResolver(),
- new ShortToBytesValueResolver(),
- new StringToBytesValueResolver()
- };
+ BytesValueResolver[] resolvers = new BytesValueResolver[] { new BooleanToBytesValueResolver(),
+ new BytesToBytesValueResolver(), new IntegerToBytesValueResolver(), new LongToBytesValueResolver(),
+ new ShortToBytesValueResolver(), new StringToBytesValueResolver() };
for (BytesValueResolver currResolver : resolvers) {
// 填充classMAP
@@ -47,7 +51,6 @@ public class BytesValueEncoding {
}
}
-
public static BytesValue encodeSingle(Object value, Class> type) {
if (value == null) {
return null;
@@ -60,7 +63,8 @@ public class BytesValueEncoding {
if (type.isInterface()) {
// 判断是否含有DataContract注解
if (!type.isAnnotationPresent(DataContract.class)) {
- throw new IllegalStateException(String.format("Interface[%s] can not be serialize !!!", type.getName()));
+ throw new IllegalStateException(
+ String.format("Interface[%s] can not be serialize !!!", type.getName()));
}
// 将对象序列化
byte[] serialBytes = BinaryProtocol.encode(value, type);
@@ -72,7 +76,7 @@ public class BytesValueEncoding {
}
return bytesValueResolver.encode(value, type);
}
-
+
public static BytesValueList encodeArray(Object[] values, Class>[] types) {
if (values == null || values.length == 0) {
return null;
@@ -101,11 +105,14 @@ public class BytesValueEncoding {
}
return type == null ? valueResolver.decode(value) : valueResolver.decode(value, type);
}
-
+
public static Object[] decode(BytesValueList values, Class>[] types) {
+ if (values == null) {
+ return EMPTY_OBJECTS;
+ }
BytesValue[] bytesValues = values.getValues();
if (bytesValues == null || bytesValues.length == 0) {
- return null;
+ return EMPTY_OBJECTS;
}
// 允许types为null,此时每个BytesValue按照当前的对象来处理
// 若types不为null,则types's长度必须和bytesValues一致
@@ -120,7 +127,8 @@ public class BytesValueEncoding {
DataType dataType = bytesValue.getType();
BytesValueResolver valueResolver = DATA_TYPE_RESOLVER_MAP.get(dataType);
if (valueResolver == null) {
- throw new IllegalStateException(String.format("DataType[%s] can not find encoder !!!", dataType.name()));
+ throw new IllegalStateException(
+ String.format("DataType[%s] can not find encoder !!!", dataType.name()));
}
resolveObjs[i] = valueResolver.decode(bytesValue);
}
@@ -132,7 +140,7 @@ public class BytesValueEncoding {
}
return resolveObjs;
}
-
+
public static Object getDefaultValue(Class> type) {
if (type == void.class || type == Void.class) {
return null;
@@ -174,14 +182,27 @@ public class BytesValueEncoding {
if (currParamType.isInterface()) {
// 接口序列化必须实现DataContract注解
if (!currParamType.isAnnotationPresent(DataContract.class)) {
- throw new IllegalStateException(String.format("Interface[%s] can not be serialize !!!", currParamType.getName()));
+ throw new IllegalStateException(
+ String.format("Interface[%s] can not be annotated as a DataContract!!!", currParamType.getName()));
}
return true;
}
+
+ if (currParamType.isArray() ) {
+ Class> componentType = currParamType.getComponentType();
+ if (componentType.isInterface()) {
+ // 接口序列化必须实现DataContract注解
+ if (!componentType.isAnnotationPresent(DataContract.class)) {
+ throw new IllegalStateException(
+ String.format("Interface[%s] can not be annotated as a DataContract!!!", currParamType.getName()));
+ }
+ return true;
+ }
+ }
+
return CLASS_RESOLVER_MAP.containsKey(currParamType);
}
-
public static class BytesValueListData implements BytesValueList {
private List bytesValues = new ArrayList<>();
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractDoesNotExistException.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractDoesNotExistException.java
new file mode 100644
index 00000000..687ef762
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractDoesNotExistException.java
@@ -0,0 +1,16 @@
+package com.jd.blockchain.ledger;
+
+public class ContractDoesNotExistException extends LedgerException {
+
+
+ private static final long serialVersionUID = 8685914012112243771L;
+
+ public ContractDoesNotExistException(String message) {
+ super(message);
+ }
+
+ public ContractDoesNotExistException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataAccountDoesNotExistException.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataAccountDoesNotExistException.java
new file mode 100644
index 00000000..428efffc
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataAccountDoesNotExistException.java
@@ -0,0 +1,16 @@
+package com.jd.blockchain.ledger;
+
+public class DataAccountDoesNotExistException extends LedgerException {
+
+
+ private static final long serialVersionUID = -1889587937401974215L;
+
+ public DataAccountDoesNotExistException(String message) {
+ super(message);
+ }
+
+ public DataAccountDoesNotExistException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataVersionConflictException.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataVersionConflictException.java
new file mode 100644
index 00000000..8af67d01
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataVersionConflictException.java
@@ -0,0 +1,27 @@
+package com.jd.blockchain.ledger;
+
+public class DataVersionConflictException extends BlockRollbackException {
+
+ private static final long serialVersionUID = 3583192000738807503L;
+
+ private TransactionState state;
+
+ public DataVersionConflictException() {
+ this(TransactionState.DATA_VERSION_CONFLICT, null);
+ }
+
+ public DataVersionConflictException(String message) {
+ this(TransactionState.DATA_VERSION_CONFLICT, message);
+ }
+
+ private DataVersionConflictException(TransactionState state, String message) {
+ super(message);
+ assert TransactionState.SUCCESS != state;
+ this.state = state;
+ }
+
+ public TransactionState getState() {
+ return state;
+ }
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/IllegalTransactionException.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/IllegalTransactionException.java
new file mode 100644
index 00000000..5a2bb5a1
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/IllegalTransactionException.java
@@ -0,0 +1,35 @@
+package com.jd.blockchain.ledger;
+
+public class IllegalTransactionException extends RuntimeException {
+
+ private static final long serialVersionUID = 6348921847690512944L;
+
+ private TransactionState txState;
+
+ public IllegalTransactionException(String message) {
+ super(message);
+ this.txState = TransactionState.SYSTEM_ERROR;
+ }
+
+ public IllegalTransactionException(String message, TransactionState txState) {
+ super(message);
+ assert TransactionState.SUCCESS != txState;
+ this.txState = txState;
+ }
+
+ public IllegalTransactionException(String message, Throwable cause) {
+ super(message, cause);
+ this.txState = TransactionState.SYSTEM_ERROR;
+ }
+
+ public IllegalTransactionException(String message, Throwable cause, TransactionState txState) {
+ super(message, cause);
+ assert TransactionState.SUCCESS != txState;
+ this.txState = txState;
+ }
+
+ public TransactionState getTxState() {
+ return txState;
+ }
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataObject.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataObject.java
index 2769631c..1e8247ee 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataObject.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataObject.java
@@ -79,6 +79,8 @@ public class KVDataObject implements KVDataEntry {
return BytesUtils.toLong(bytesValue.getValue().toBytes());
case JSON:
return bytesValue.getValue().toUTF8String();
+ case XML:
+ return bytesValue.getValue().toUTF8String();
default:
throw new IllegalStateException("Unsupported value type[" + getType() + "] to resolve!");
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerAdminInfo.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerAdminInfo.java
new file mode 100644
index 00000000..b666535e
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerAdminInfo.java
@@ -0,0 +1,17 @@
+package com.jd.blockchain.ledger;
+
+public interface LedgerAdminInfo {
+
+ LedgerMetadata_V2 getMetadata();
+
+ LedgerSettings getSettings();
+
+ long getParticipantCount();
+
+ ParticipantNode[] getParticipants();
+
+ UserRolesSettings getUserRoles();
+
+ RolePrivilegeSettings getRolePrivileges();
+
+}
\ No newline at end of file
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerException.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerException.java
index 9d0dd838..d0edef01 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerException.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerException.java
@@ -3,6 +3,8 @@ package com.jd.blockchain.ledger;
public class LedgerException extends RuntimeException {
private static final long serialVersionUID = -4090881296855827888L;
+
+
public LedgerException(String message) {
super(message);
diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitException.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerInitException.java
similarity index 75%
rename from source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitException.java
rename to source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerInitException.java
index 3695a19e..c3a31079 100644
--- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitException.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerInitException.java
@@ -1,6 +1,4 @@
-package com.jd.blockchain.tools.initializer;
-
-import com.jd.blockchain.ledger.LedgerException;
+package com.jd.blockchain.ledger;
public class LedgerInitException extends LedgerException{
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerInitProperties.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerInitProperties.java
new file mode 100644
index 00000000..e19977fe
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerInitProperties.java
@@ -0,0 +1,505 @@
+package com.jd.blockchain.ledger;
+
+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.Map;
+import java.util.Properties;
+import java.util.TreeMap;
+
+import com.jd.blockchain.consts.Global;
+import com.jd.blockchain.crypto.AddressEncoding;
+import com.jd.blockchain.crypto.KeyGenUtils;
+import com.jd.blockchain.crypto.PubKey;
+import com.jd.blockchain.ledger.LedgerInitProperties.CryptoProperties;
+import com.jd.blockchain.utils.Bytes;
+import com.jd.blockchain.utils.PropertiesUtils;
+import com.jd.blockchain.utils.StringUtils;
+import com.jd.blockchain.utils.codec.HexUtils;
+import com.jd.blockchain.utils.io.FileUtils;
+import com.jd.blockchain.utils.net.NetworkAddress;
+
+public class LedgerInitProperties {
+
+ // 账本种子;
+ public static final String LEDGER_SEED = "ledger.seed";
+
+ // 账本名称
+ public static final String LEDGER_NAME = "ledger.name";
+
+ // 声明的账本建立时间;
+ public static final String CREATED_TIME = "created-time";
+ // 创建时间的格式;
+ public static final String CREATED_TIME_FORMAT = Global.DEFAULT_TIME_FORMAT;
+
+ // 角色清单;
+ public static final String ROLES = "security.roles";
+ // 角色的账本权限;用角色名称替代占位符;
+ public static final String ROLE_LEDGER_PRIVILEGES_PATTERN = "security.role.%s.ledger-privileges";
+ // 角色的交易权限;用角色名称替代占位符;
+ public static final String ROLE_TX_PRIVILEGES_PATTERN = "security.role.%s.tx-privileges";
+
+ // 共识参与方的个数,后续以 part.id 分别标识每一个参与方的配置;
+ public static final String PART_COUNT = "cons_parti.count";
+ // 共识参与方的名称的模式;
+ public static final String PART_ID_PATTERN = "cons_parti.%s";
+ // 参与方的名称;
+ public static final String PART_NAME = "name";
+ // 参与方的公钥文件路径;
+ public static final String PART_PUBKEY_PATH = "pubkey-path";
+ // 参与方的公钥文件路径;
+ public static final String PART_PUBKEY = "pubkey";
+ // 参与方的角色清单;
+ public static final String PART_ROLES = "roles";
+ // 参与方的角色权限策略;
+ public static final String PART_ROLES_POLICY = "roles-policy";
+
+ // 共识参与方的账本初始服务的主机;
+ public static final String PART_INITIALIZER_HOST = "initializer.host";
+ // 共识参与方的账本初始服务的端口;
+ public static final String PART_INITIALIZER_PORT = "initializer.port";
+ // 共识参与方的账本初始服务是否开启安全连接;
+ public static final String PART_INITIALIZER_SECURE = "initializer.secure";
+
+ // 共识服务的参数配置;必须;
+ public static final String CONSENSUS_CONFIG = "consensus.conf";
+
+ // 共识服务提供者;必须;
+ public static final String CONSENSUS_SERVICE_PROVIDER = "consensus.service-provider";
+
+ // 密码服务提供者列表,以英文逗点“,”分隔;必须;
+ public static final String CRYPTO_SERVICE_PROVIDERS = "crypto.service-providers";
+ // 从存储中加载账本数据时,是否校验哈希;可选;
+ public static final String CRYPTO_VRIFY_HASH = "crypto.verify-hash";
+ // 哈希算法;
+ public static final String CRYPTO_HASH_ALGORITHM = "crypto.hash-algorithm";
+
+ public static final String CRYPTO_SERVICE_PROVIDERS_SPLITTER = ",";
+
+ private byte[] ledgerSeed;
+
+ private String ledgerName;
+
+ private RoleInitData[] roles;
+
+ private List consensusParticipants = new ArrayList<>();
+
+ private String consensusProvider;
+
+ private Properties consensusConfig;
+
+// private String[] cryptoProviders;
+
+ private CryptoProperties cryptoProperties = new CryptoProperties();
+
+ private long createdTime;
+
+ public byte[] getLedgerSeed() {
+ return ledgerSeed.clone();
+ }
+
+ public String getLedgerName() {
+ return ledgerName;
+ }
+
+ public long getCreatedTime() {
+ return createdTime;
+ }
+
+ public Properties getConsensusConfig() {
+ return consensusConfig;
+ }
+
+ public String getConsensusProvider() {
+ return consensusProvider;
+ }
+
+ public int getConsensusParticipantCount() {
+ return consensusParticipants.size();
+ }
+
+ public List getConsensusParticipants() {
+ return consensusParticipants;
+ }
+
+ public ParticipantNode[] getConsensusParticipantNodes() {
+ if (consensusParticipants.isEmpty()) {
+ return null;
+ }
+ ParticipantNode[] participantNodes = new ParticipantNode[consensusParticipants.size()];
+ return consensusParticipants.toArray(participantNodes);
+ }
+
+ public CryptoProperties getCryptoProperties() {
+ return cryptoProperties;
+ }
+
+ public void setCryptoProperties(CryptoProperties cryptoProperties) {
+ if (cryptoProperties == null) {
+ cryptoProperties = new CryptoProperties();
+ }
+ this.cryptoProperties = cryptoProperties;
+ }
+
+ /**
+ * 返回参与者;
+ *
+ * @param id 从 1 开始; 小于等于 {@link #getConsensusParticipantCount()};
+ * @return
+ */
+ public ParticipantProperties getConsensusParticipant(int id) {
+ for (ParticipantProperties p : consensusParticipants) {
+ if (p.getId() == id) {
+ return p;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 私有的构造器;
+ *
+ * @param ledgerSeed
+ */
+ private LedgerInitProperties(byte[] ledgerSeed) {
+ this.ledgerSeed = ledgerSeed;
+ }
+
+ public void addConsensusParticipant(ParticipantProperties participant) {
+ consensusParticipants.add(participant);
+ }
+
+ private static String getKeyOfParticipant(int partId, String partPropKey) {
+ String partAddrStr = String.format(PART_ID_PATTERN, partId);
+ return String.format("%s.%s", partAddrStr, partPropKey);
+ }
+
+ public static LedgerInitProperties resolve(String initSettingFile) {
+ Properties props = FileUtils.readProperties(initSettingFile, "UTF-8");
+ File realFile = new File(initSettingFile);
+ return resolve(realFile.getParentFile().getPath(), props);
+ }
+
+ public static LedgerInitProperties resolve(InputStream in) {
+ Properties props = FileUtils.readProperties(in, "UTF-8");
+ return resolve(props);
+ }
+
+ public static LedgerInitProperties resolve(Properties props) {
+ return resolve(null, props);
+ }
+
+ /**
+ * 从属性表解析账本初始化参数;
+ *
+ * @param baseDirectory 基础路径;属性中涉及文件位置的相对路径以此参数指定的目录为父目录;
+ * @param props 要解析的属性表;
+ * @return
+ */
+ public static LedgerInitProperties resolve(String baseDirectory, Properties props) {
+ String hexLedgerSeed = PropertiesUtils.getRequiredProperty(props, LEDGER_SEED).replace("-", "");
+ byte[] ledgerSeed = HexUtils.decode(hexLedgerSeed);
+ LedgerInitProperties initProps = new LedgerInitProperties(ledgerSeed);
+
+ // 解析账本信息;
+ // 账本名称
+ String ledgerName = PropertiesUtils.getRequiredProperty(props, LEDGER_NAME);
+ initProps.ledgerName = ledgerName;
+
+ // 创建时间;
+ 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);
+ }
+
+ // 解析角色清单;
+ String strRoleNames = PropertiesUtils.getOptionalProperty(props, ROLES);
+ String[] roles = StringUtils.splitToArray(strRoleNames, ",");
+
+ Map rolesInitSettingMap = new TreeMap();
+ // 解析角色权限表;
+ for (String role : roles) {
+ String ledgerPrivilegeKey = getKeyOfRoleLedgerPrivilege(role);
+ String strLedgerPermissions = PropertiesUtils.getOptionalProperty(props, ledgerPrivilegeKey);
+ LedgerPermission[] ledgerPermissions = resolveLedgerPermissions(strLedgerPermissions);
+
+ String txPrivilegeKey = getKeyOfRoleTxPrivilege(role);
+ String strTxPermissions = PropertiesUtils.getOptionalProperty(props, txPrivilegeKey);
+ TransactionPermission[] txPermissions = resolveTransactionPermissions(strTxPermissions);
+
+ if (ledgerPermissions.length > 0 || txPermissions.length > 0) {
+ RoleInitData rolesSettings = new RoleInitData(role, ledgerPermissions, txPermissions);
+ rolesInitSettingMap.put(role, rolesSettings);
+ }
+ }
+ RoleInitData[] rolesInitDatas = rolesInitSettingMap.values()
+ .toArray(new RoleInitData[rolesInitSettingMap.size()]);
+ initProps.setRoles(rolesInitDatas);
+
+ // 解析共识相关的属性;
+ initProps.consensusProvider = PropertiesUtils.getRequiredProperty(props, CONSENSUS_SERVICE_PROVIDER);
+ String consensusConfigFilePath = PropertiesUtils.getRequiredProperty(props, CONSENSUS_CONFIG);
+ try {
+ File consensusConfigFile = FileUtils.getFile(baseDirectory, consensusConfigFilePath);
+ initProps.consensusConfig = FileUtils.readProperties(consensusConfigFile);
+ } catch (FileNotFoundException e) {
+ throw new IllegalArgumentException(
+ String.format("Consensus config file[%s] doesn't exist! ", consensusConfigFilePath), e);
+ }
+
+ // 解析密码提供者列表;
+ String cryptoProviderNames = PropertiesUtils.getProperty(props, CRYPTO_SERVICE_PROVIDERS, true);
+ String[] cryptoProviders = cryptoProviderNames.split(CRYPTO_SERVICE_PROVIDERS_SPLITTER);
+ for (int i = 0; i < cryptoProviders.length; i++) {
+ cryptoProviders[i] = cryptoProviders[i].trim();
+ }
+ initProps.cryptoProperties.setProviders(cryptoProviders);
+ // 哈希校验选项;
+ boolean verifyHash = PropertiesUtils.getBooleanOptional(props, CRYPTO_VRIFY_HASH, false);
+ initProps.cryptoProperties.setVerifyHash(verifyHash);
+ // 哈希算法;
+ String hashAlgorithm = PropertiesUtils.getOptionalProperty(props, CRYPTO_HASH_ALGORITHM);
+ initProps.cryptoProperties.setHashAlgorithm(hashAlgorithm);
+
+
+ // 解析参与方节点列表;
+ int partCount = getInt(PropertiesUtils.getRequiredProperty(props, PART_COUNT));
+ if (partCount < 0) {
+ throw new IllegalArgumentException(String.format("Property[%s] is negative!", PART_COUNT));
+ }
+ if (partCount < 4) {
+ throw new IllegalArgumentException(String.format("Property[%s] is less than 4!", PART_COUNT));
+ }
+ for (int i = 0; i < partCount; i++) {
+ ParticipantProperties parti = new ParticipantProperties();
+
+ parti.setId(i);
+
+ String nameKey = getKeyOfParticipant(i, PART_NAME);
+ parti.setName(PropertiesUtils.getRequiredProperty(props, nameKey));
+
+ String pubkeyPathKey = getKeyOfParticipant(i, PART_PUBKEY_PATH);
+ String pubkeyPath = PropertiesUtils.getProperty(props, pubkeyPathKey, false);
+
+ String pubkeyKey = getKeyOfParticipant(i, PART_PUBKEY);
+ String base58PubKey = PropertiesUtils.getProperty(props, pubkeyKey, false);
+ if (base58PubKey != null) {
+ PubKey pubKey = KeyGenUtils.decodePubKey(base58PubKey);
+ parti.setPubKey(pubKey);
+ } else if (pubkeyPath != null) {
+ PubKey pubKey = KeyGenUtils.readPubKey(pubkeyPath);
+ parti.setPubKey(pubKey);
+ } else {
+ throw new IllegalArgumentException(
+ String.format("Property[%s] and property[%s] are all empty!", pubkeyKey, pubkeyPathKey));
+ }
+
+ // 解析参与方的角色权限配置;
+ String partiRolesKey = getKeyOfParticipant(i, PART_ROLES);
+ String strPartiRoles = PropertiesUtils.getOptionalProperty(props, partiRolesKey);
+ String[] partiRoles = StringUtils.splitToArray(strPartiRoles, ",");
+ parti.setRoles(partiRoles);
+
+ String partiRolePolicyKey = getKeyOfParticipant(i, PART_ROLES_POLICY);
+ String strPartiPolicy = PropertiesUtils.getOptionalProperty(props, partiRolePolicyKey);
+ RolesPolicy policy = strPartiPolicy == null ? RolesPolicy.UNION
+ : RolesPolicy.valueOf(strPartiPolicy.trim());
+ policy = policy == null ? RolesPolicy.UNION : policy;
+ parti.setRolesPolicy(policy);
+
+ // 解析参与方的网络配置参数;
+ String initializerHostKey = getKeyOfParticipant(i, PART_INITIALIZER_HOST);
+ String initializerHost = PropertiesUtils.getRequiredProperty(props, initializerHostKey);
+
+ String initializerPortKey = getKeyOfParticipant(i, PART_INITIALIZER_PORT);
+ int initializerPort = getInt(PropertiesUtils.getRequiredProperty(props, initializerPortKey));
+
+ String initializerSecureKey = getKeyOfParticipant(i, PART_INITIALIZER_SECURE);
+ boolean initializerSecure = Boolean
+ .parseBoolean(PropertiesUtils.getRequiredProperty(props, initializerSecureKey));
+ NetworkAddress initializerAddress = new NetworkAddress(initializerHost, initializerPort, initializerSecure);
+ parti.setInitializerAddress(initializerAddress);
+
+ initProps.addConsensusParticipant(parti);
+ }
+
+ return initProps;
+ }
+
+ private static TransactionPermission[] resolveTransactionPermissions(String strTxPermissions) {
+ String[] strPermissions = StringUtils.splitToArray(strTxPermissions, ",");
+ List permissions = new ArrayList();
+ if (strPermissions != null) {
+ for (String pm : strPermissions) {
+ TransactionPermission permission = TransactionPermission.valueOf(pm);
+ if (permission != null) {
+ permissions.add(permission);
+ }
+ }
+ }
+ return permissions.toArray(new TransactionPermission[permissions.size()]);
+ }
+
+ private static LedgerPermission[] resolveLedgerPermissions(String strLedgerPermissions) {
+ String[] strPermissions = StringUtils.splitToArray(strLedgerPermissions, ",");
+ List permissions = new ArrayList();
+ if (strPermissions != null) {
+ for (String pm : strPermissions) {
+ LedgerPermission permission = LedgerPermission.valueOf(pm);
+ if (permission != null) {
+ permissions.add(permission);
+ }
+ }
+ }
+ return permissions.toArray(new LedgerPermission[permissions.size()]);
+ }
+
+ private static String getKeyOfRoleLedgerPrivilege(String role) {
+ return String.format(ROLE_LEDGER_PRIVILEGES_PATTERN, role);
+ }
+
+ private static String getKeyOfRoleTxPrivilege(String role) {
+ return String.format(ROLE_TX_PRIVILEGES_PATTERN, role);
+ }
+
+ private static int getInt(String strInt) {
+ return Integer.parseInt(strInt.trim());
+ }
+
+ public RoleInitData[] getRoles() {
+ return roles;
+ }
+
+ public void setRoles(RoleInitData[] roles) {
+ this.roles = roles;
+ }
+
+ public static class CryptoProperties {
+
+ private String[] providers;
+
+ private boolean verifyHash;
+
+ private String hashAlgorithm;
+
+ public String[] getProviders() {
+ return providers;
+ }
+
+ public void setProviders(String[] providers) {
+ this.providers = providers;
+ }
+
+ public boolean isVerifyHash() {
+ return verifyHash;
+ }
+
+ public void setVerifyHash(boolean verifyHash) {
+ this.verifyHash = verifyHash;
+ }
+
+ public String getHashAlgorithm() {
+ return hashAlgorithm;
+ }
+
+ public void setHashAlgorithm(String hashAlgorithm) {
+ this.hashAlgorithm = hashAlgorithm;
+ }
+
+ }
+
+ /**
+ * 参与方配置信息;
+ *
+ * @author huanghaiquan
+ *
+ */
+ public static class ParticipantProperties implements ParticipantNode {
+
+ private int id;
+
+ private Bytes address;
+
+ private String name;
+
+ private PubKey pubKey;
+
+ private String[] roles;
+
+ private RolesPolicy rolesPolicy;
+
+ // private NetworkAddress consensusAddress;
+
+ private NetworkAddress initializerAddress;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ @Override
+ public Bytes getAddress() {
+ return address;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+// public String getPubKeyPath() {
+// return pubKeyPath;
+// }
+//
+// public void setPubKeyPath(String pubKeyPath) {
+// this.pubKeyPath = pubKeyPath;
+// }
+
+ public NetworkAddress getInitializerAddress() {
+ return initializerAddress;
+ }
+
+ public void setInitializerAddress(NetworkAddress initializerAddress) {
+ this.initializerAddress = initializerAddress;
+ }
+
+ public PubKey getPubKey() {
+ return pubKey;
+ }
+
+ public void setPubKey(PubKey pubKey) {
+ this.pubKey = pubKey;
+ this.address = AddressEncoding.generateAddress(pubKey);
+ }
+
+ public String[] getRoles() {
+ return roles;
+ }
+
+ public void setRoles(String[] roles) {
+ this.roles = roles;
+ }
+
+ public RolesPolicy getRolesPolicy() {
+ return rolesPolicy;
+ }
+
+ public void setRolesPolicy(RolesPolicy rolesPolicy) {
+ this.rolesPolicy = rolesPolicy;
+ }
+
+ }
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerMetadata.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerMetadata.java
index 4d7a57b0..f7108ff3 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerMetadata.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerMetadata.java
@@ -6,31 +6,37 @@ import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.consts.DataCodes;
import com.jd.blockchain.crypto.HashDigest;
-@DataContract(code = DataCodes.METADATA)
+/**
+ * 账本的元数据;
+ *
+ * @author huanghaiquan
+ *
+ */
+@DataContract(code = DataCodes.METADATA, name = "LEDGER-METADATA")
public interface LedgerMetadata {
- /**
- * 账本的初始化种子;
- *
- * @return
- */
- @DataField(order = 1, primitiveType = PrimitiveType.BYTES)
- byte[] getSeed();
+ /**
+ * 账本的初始化种子;
+ *
+ * @return
+ */
+ @DataField(order = 1, primitiveType = PrimitiveType.BYTES)
+ byte[] getSeed();
- /**
- * 共识参与方的默克尔树的根;
- *
- * @return
- */
- @DataField(order = 2, primitiveType = PrimitiveType.BYTES)
- HashDigest getParticipantsHash();
+ /**
+ * 共识参与方的默克尔树的根;
+ *
+ * @return
+ */
+ @DataField(order = 2, primitiveType = PrimitiveType.BYTES)
+ HashDigest getParticipantsHash();
- /**
- * 账本配置;
- *
- * @return
- */
- @DataField(order = 3, refContract = true)
- LedgerSetting getSetting();
+ /**
+ * 账本配置的哈希;
+ *
+ * @return
+ */
+ @DataField(order = 3, primitiveType = PrimitiveType.BYTES)
+ HashDigest getSettingsHash();
}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerMetadata_V2.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerMetadata_V2.java
new file mode 100644
index 00000000..228019b7
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerMetadata_V2.java
@@ -0,0 +1,35 @@
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.binaryproto.DataContract;
+import com.jd.blockchain.binaryproto.DataField;
+import com.jd.blockchain.binaryproto.PrimitiveType;
+import com.jd.blockchain.consts.DataCodes;
+import com.jd.blockchain.crypto.HashDigest;
+
+/**
+ * {@link LedgerMetadata_V2} 是 {@link LedgerMetadata} 的升级版本,新增加了
+ * {@link #getRolePrivilegesHash()} 属性;
+ *
+ * @author huanghaiquan
+ *
+ */
+@DataContract(code = DataCodes.METADATA_V2, name = "LEDGER-METADATA-V2")
+public interface LedgerMetadata_V2 extends LedgerMetadata {
+
+ /**
+ * 角色权限集合的根哈希;;
+ *
+ * @return
+ */
+ @DataField(order = 4, primitiveType = PrimitiveType.BYTES)
+ HashDigest getRolePrivilegesHash();
+
+ /**
+ * 用户角色授权集合的根哈希;
+ *
+ * @return
+ */
+ @DataField(order = 5, primitiveType = PrimitiveType.BYTES)
+ HashDigest getUserRolesHash();
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerPermission.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerPermission.java
new file mode 100644
index 00000000..a735a2da
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerPermission.java
@@ -0,0 +1,97 @@
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.binaryproto.EnumContract;
+import com.jd.blockchain.binaryproto.EnumField;
+import com.jd.blockchain.binaryproto.PrimitiveType;
+import com.jd.blockchain.consts.DataCodes;
+
+/**
+ * 账本相关的权限,这些权限属于全局性的;
+ *
+ * @author huanghaiquan
+ *
+ */
+@EnumContract(code = DataCodes.ENUM_LEDGER_PERMISSION)
+public enum LedgerPermission {
+
+ /**
+ * 配置角色的权限;
+ */
+ CONFIGURE_ROLES((byte) 0x01),
+
+ /**
+ * 授权用户角色;
+ */
+ AUTHORIZE_USER_ROLES((byte) 0x02),
+
+ /**
+ * 设置共识协议;
+ */
+ SET_CONSENSUS((byte) 0x03),
+
+ /**
+ * 设置密码体系;
+ */
+ SET_CRYPTO((byte) 0x04),
+
+ /**
+ * 注册参与方;
+ */
+ REGISTER_PARTICIPANT((byte) 0x05),
+
+ /**
+ * 注册用户;
+ *
+ * 如果不具备此项权限,则无法注册用户;
+ */
+ REGISTER_USER((byte) 0x11),
+
+ /**
+ * 注册数据账户;
+ */
+ REGISTER_DATA_ACCOUNT((byte) 0x12),
+
+ /**
+ * 注册合约;
+ */
+ REGISTER_CONTRACT((byte) 0x13),
+
+ /**
+ * 升级合约
+ */
+ UPGRADE_CONTRACT((byte) 0x14),
+
+ /**
+ * 设置用户属性;
+ */
+ SET_USER_ATTRIBUTES((byte) 0x15),
+
+ /**
+ * 写入数据账户;
+ */
+ WRITE_DATA_ACCOUNT((byte) 0x16),
+
+ /**
+ * 参与方核准交易;
+ *
+ * 如果不具备此项权限,则无法作为节点签署由终端提交的交易;
+ *
+ * 只对交易请求的节点签名列表{@link TransactionRequest#getNodeSignatures()}的用户产生影响;
+ */
+ APPROVE_TX((byte) 0x0C),
+
+ /**
+ * 参与方共识交易;
+ *
+ * 如果不具备此项权限,则无法作为共识节点接入并对交易进行共识;
+ */
+ CONSENSUS_TX((byte) 0x0D);
+
+ @EnumField(type = PrimitiveType.INT8)
+ public final byte CODE;
+
+ private LedgerPermission(byte code) {
+ this.CODE = code;
+ }
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerPrivilege.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerPrivilege.java
new file mode 100644
index 00000000..dad59a41
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerPrivilege.java
@@ -0,0 +1,29 @@
+package com.jd.blockchain.ledger;
+
+/**
+ * LedgerPrivilege 账本特权是授权给特定角色的权限代码序列;
+ *
+ * @author huanghaiquan
+ *
+ */
+public class LedgerPrivilege extends PrivilegeBitset {
+
+ private static final CodeIndexer CODE_INDEXER = new LedgerPermissionCodeIndexer();
+
+ public LedgerPrivilege() {
+ super(CODE_INDEXER);
+ }
+
+ public LedgerPrivilege(byte[] codeBytes) {
+ super(codeBytes, CODE_INDEXER);
+ }
+
+ private static class LedgerPermissionCodeIndexer implements CodeIndexer {
+
+ @Override
+ public int getCodeIndex(LedgerPermission permission) {
+ return permission.CODE & 0xFF;
+ }
+
+ }
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerSecurityException.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerSecurityException.java
new file mode 100644
index 00000000..0b3e98a8
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerSecurityException.java
@@ -0,0 +1,17 @@
+package com.jd.blockchain.ledger;
+
+public class LedgerSecurityException extends RuntimeException {
+
+ private static final long serialVersionUID = -4090881296855827888L;
+
+
+
+ public LedgerSecurityException(String message) {
+ super(message);
+ }
+
+ public LedgerSecurityException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerSetting.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerSettings.java
similarity index 87%
rename from source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerSetting.java
rename to source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerSettings.java
index 1a0441bd..fd77685a 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerSetting.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerSettings.java
@@ -8,7 +8,7 @@ import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.utils.Bytes;
@DataContract(code = DataCodes.METADATA_LEDGER_SETTING)
-public interface LedgerSetting {
+public interface LedgerSettings {
@DataField(order=0, primitiveType=PrimitiveType.TEXT)
String getConsensusProvider();
@@ -19,6 +19,4 @@ public interface LedgerSetting {
@DataField(order=2, refContract=true)
CryptoSetting getCryptoSetting();
-// PrivilegeModelSetting getPrivilegesModelSetting();
-
}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataNode.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/MerkleDataNode.java
similarity index 78%
rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataNode.java
rename to source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/MerkleDataNode.java
index 63db9103..c2014877 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataNode.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/MerkleDataNode.java
@@ -1,4 +1,4 @@
-package com.jd.blockchain.ledger.core;
+package com.jd.blockchain.ledger;
import com.jd.blockchain.utils.Bytes;
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleNode.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/MerkleNode.java
similarity index 86%
rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleNode.java
rename to source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/MerkleNode.java
index 185d5403..b8eba626 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleNode.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/MerkleNode.java
@@ -1,4 +1,4 @@
-package com.jd.blockchain.ledger.core;
+package com.jd.blockchain.ledger;
import com.jd.blockchain.crypto.HashDigest;
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleProof.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/MerkleProof.java
similarity index 97%
rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleProof.java
rename to source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/MerkleProof.java
index db9fe2f4..1463f736 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleProof.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/MerkleProof.java
@@ -1,4 +1,4 @@
-package com.jd.blockchain.ledger.core;
+package com.jd.blockchain.ledger;
import com.jd.blockchain.crypto.HashDigest;
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantDataQuery.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantDataQuery.java
new file mode 100644
index 00000000..6ba0668e
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantDataQuery.java
@@ -0,0 +1,29 @@
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.utils.Bytes;
+
+public interface ParticipantDataQuery {
+
+ HashDigest getRootHash();
+
+ MerkleProof getProof(Bytes key);
+
+ long getParticipantCount();
+
+ boolean contains(Bytes address);
+
+ /**
+ * 返回指定地址的参与方凭证;
+ *
+ *
+ * 如果不存在,则返回 null;
+ *
+ * @param address
+ * @return
+ */
+ ParticipantNode getParticipant(Bytes address);
+
+ ParticipantNode[] getParticipants();
+
+}
\ No newline at end of file
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantDoesNotExistException.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantDoesNotExistException.java
new file mode 100644
index 00000000..54994dc7
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantDoesNotExistException.java
@@ -0,0 +1,15 @@
+package com.jd.blockchain.ledger;
+
+public class ParticipantDoesNotExistException extends LedgerException {
+
+ private static final long serialVersionUID = 397450363050148898L;
+
+ public ParticipantDoesNotExistException(String message) {
+ super(message);
+ }
+
+ public ParticipantDoesNotExistException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantNode.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantNode.java
index dd2c62fa..efc55c12 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantNode.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantNode.java
@@ -5,6 +5,7 @@ import com.jd.blockchain.binaryproto.DataField;
import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.consts.DataCodes;
import com.jd.blockchain.crypto.PubKey;
+import com.jd.blockchain.utils.Bytes;
/**
* 参与方节点;
@@ -13,7 +14,7 @@ import com.jd.blockchain.crypto.PubKey;
*
*/
@DataContract(code = DataCodes.METADATA_CONSENSUS_PARTICIPANT)
-public interface ParticipantNode {// extends ConsensusNode, ParticipantInfo {
+public interface ParticipantNode {
/**
* 节点的顺序编号;
@@ -30,8 +31,8 @@ public interface ParticipantNode {// extends ConsensusNode, ParticipantInfo {
*
* @return
*/
- @DataField(order = 1, primitiveType = PrimitiveType.TEXT)
- String getAddress();
+ @DataField(order = 1, primitiveType = PrimitiveType.BYTES)
+ Bytes getAddress();
/**
* 参与者名称;
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Privilege.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Privilege.java
new file mode 100644
index 00000000..4a77e0b9
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Privilege.java
@@ -0,0 +1,5 @@
+package com.jd.blockchain.ledger;
+
+public interface Privilege> {
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/PrivilegeBitset.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/PrivilegeBitset.java
new file mode 100644
index 00000000..1282530d
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/PrivilegeBitset.java
@@ -0,0 +1,148 @@
+package com.jd.blockchain.ledger;
+
+import java.util.BitSet;
+
+import com.jd.blockchain.utils.io.BytesSerializable;
+
+/**
+ * PrivilegeBitset 定义了用位表示的权限码;
+ *
+ * @author huanghaiquan
+ *
+ */
+public class PrivilegeBitset> implements Privilege, BytesSerializable {
+ // 加入前缀位,可避免序列化时输出空的字节数组;
+ private static final boolean[] PREFIX = { false, false, false, true, false, false, false, true };
+ private static final int OFFSET = PREFIX.length;
+ private static final int MAX_SIZE = 256 - PREFIX.length;
+
+ private BitSet permissionBits;
+
+ private CodeIndexer codeIndexer;
+
+ public PrivilegeBitset(CodeIndexer codeIndexer) {
+ this.permissionBits = new BitSet();
+ this.codeIndexer = codeIndexer;
+ // 设置前缀;
+ for (int i = 0; i < PREFIX.length; i++) {
+ permissionBits.set(i, PREFIX[i]);
+ }
+ }
+
+ public PrivilegeBitset(byte[] codeBytes, CodeIndexer codeIndexer) {
+ if (codeBytes.length > MAX_SIZE) {
+ throw new IllegalArgumentException(
+ "The size of code bytes specified to PrivilegeBitset exceed the max size[" + MAX_SIZE + "]!");
+ }
+ this.permissionBits = BitSet.valueOf(codeBytes);
+ this.codeIndexer = codeIndexer;
+ // 校验前缀;
+ for (int i = 0; i < PREFIX.length; i++) {
+ if (permissionBits.get(i) != PREFIX[i]) {
+ throw new IllegalArgumentException("The code bytes is not match the privilege prefix code!");
+ }
+ }
+ }
+
+ private PrivilegeBitset(BitSet bits, CodeIndexer codeIndexer) {
+ this.permissionBits = bits;
+ this.codeIndexer = codeIndexer;
+ }
+
+ public boolean isEnable(E permission) {
+ return permissionBits.get(index(permission));
+ }
+
+ public void enable(E permission) {
+ permissionBits.set(index(permission));
+ }
+
+ public void disable(E permission) {
+ permissionBits.clear(index(permission));
+ }
+
+ @SuppressWarnings("unchecked")
+ public void enable(E... permissions) {
+ for (E p : permissions) {
+ permissionBits.set(index(p));
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public void disable(E... permissions) {
+ for (E p : permissions) {
+ permissionBits.clear(index(p));
+ }
+ }
+
+ @Override
+ public byte[] toBytes() {
+ return permissionBits.toByteArray();
+ }
+
+ /**
+ * 把指定的权限合并到当前的权限中;
+ *
+ * @param privileges
+ * @return
+ */
+ @SuppressWarnings("unchecked")
+ public Privilege union(PrivilegeBitset... privileges) {
+ return union(privileges, 0, privileges.length);
+ }
+
+ /**
+ * 把指定的权限合并到当前的权限中;
+ *
+ * @param privileges
+ * @param offset
+ * @param count
+ * @return
+ */
+ public Privilege union(PrivilegeBitset[] privileges, int offset, int count) {
+ BitSet bits = this.permissionBits;
+ for (int i = 0; i < count; i++) {
+ bits.or(privileges[i + offset].permissionBits);
+ }
+ return this;
+ }
+
+ /**
+ * 保留当前的权限与指定权限的共同生效的部分,同时清除其它的权限位;
+ *
+ * @param privileges
+ * @return
+ */
+ @SuppressWarnings("unchecked")
+ public Privilege intersect(PrivilegeBitset... privileges) {
+ return intersect(privileges, 0, privileges.length);
+ }
+
+ /**
+ * 保留当前的权限与指定权限的共同生效的部分,同时清除其它的权限位;
+ *
+ * @param privileges
+ * @param offset
+ * @param count
+ * @return
+ */
+ public Privilege intersect(PrivilegeBitset[] privileges, int offset, int count) {
+ BitSet bits = this.permissionBits;
+ for (int i = 0; i < count; i++) {
+ bits.and(privileges[i + offset].permissionBits);
+ }
+ return this;
+ }
+
+ public PrivilegeBitset clone() {
+ return new PrivilegeBitset((BitSet) permissionBits.clone(), codeIndexer);
+ }
+
+ private int index(E permission) {
+ return OFFSET + codeIndexer.getCodeIndex(permission);
+ }
+
+ static interface CodeIndexer> {
+ int getCodeIndex(E permission);
+ }
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/PrivilegeSet.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/PrivilegeSet.java
new file mode 100644
index 00000000..bf0d3da7
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/PrivilegeSet.java
@@ -0,0 +1,23 @@
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.binaryproto.DataContract;
+import com.jd.blockchain.binaryproto.DataField;
+import com.jd.blockchain.binaryproto.PrimitiveType;
+import com.jd.blockchain.consts.DataCodes;
+
+/**
+ * 表示赋予角色的特权码;
+ *
+ * @author huanghaiquan
+ *
+ */
+@DataContract(code = DataCodes.PRIVILEGE_SET, name = "PRIVILEGE-SET")
+public interface PrivilegeSet {
+
+ @DataField(order = 1, primitiveType = PrimitiveType.BYTES)
+ LedgerPrivilege getLedgerPrivilege();
+
+ @DataField(order = 2, primitiveType = PrimitiveType.BYTES)
+ TransactionPrivilege getTransactionPrivilege();
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Privileges.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Privileges.java
new file mode 100644
index 00000000..420cbf45
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Privileges.java
@@ -0,0 +1,65 @@
+package com.jd.blockchain.ledger;
+
+public class Privileges implements PrivilegeSet {
+
+ private LedgerPrivilege ledgerPrivilege;
+
+ private TransactionPrivilege txPrivilege;
+
+ protected Privileges() {
+ this.ledgerPrivilege = new LedgerPrivilege();
+ this.txPrivilege = new TransactionPrivilege();
+ }
+
+ protected Privileges(PrivilegeSet privilege) {
+ this.ledgerPrivilege = privilege.getLedgerPrivilege();
+ this.txPrivilege = privilege.getTransactionPrivilege();
+ }
+
+ protected Privileges(LedgerPrivilege ledgerPrivilege, TransactionPrivilege txPrivilege) {
+ this.ledgerPrivilege = ledgerPrivilege;
+ this.txPrivilege = txPrivilege;
+ }
+
+ @Override
+ public LedgerPrivilege getLedgerPrivilege() {
+ return ledgerPrivilege;
+ }
+
+ public void setLedgerPrivilege(LedgerPrivilege ledgerPrivilege) {
+ this.ledgerPrivilege = ledgerPrivilege;
+ }
+
+ @Override
+ public TransactionPrivilege getTransactionPrivilege() {
+ return txPrivilege;
+ }
+
+ public void setTransactionPrivilege(TransactionPrivilege txPrivilege) {
+ this.txPrivilege = txPrivilege;
+ }
+
+ public static Privileges configure() {
+ return new Privileges();
+ }
+
+ public Privileges enable(LedgerPermission...ledgerPermissions) {
+ this.ledgerPrivilege.enable(ledgerPermissions);
+ return this;
+ }
+
+ public Privileges disable(LedgerPermission...ledgerPermissions) {
+ this.ledgerPrivilege.disable(ledgerPermissions);
+ return this;
+ }
+
+ public Privileges enable(TransactionPermission...transactionPermissions) {
+ this.txPrivilege.enable(transactionPermissions);
+ return this;
+ }
+
+ public Privileges disable(TransactionPermission...transactionPermissions) {
+ this.txPrivilege.disable(transactionPermissions);
+ return this;
+ }
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RoleInitData.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RoleInitData.java
new file mode 100644
index 00000000..ea1822e2
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RoleInitData.java
@@ -0,0 +1,48 @@
+package com.jd.blockchain.ledger;
+
+public class RoleInitData implements RoleInitSettings {
+
+ private String roleName;
+
+ private LedgerPermission[] ledgerPermissions;
+
+ private TransactionPermission[] transactionPermissions;
+
+ public RoleInitData() {
+ }
+
+ public RoleInitData(String roleName, LedgerPermission[] ledgerPermissions,
+ TransactionPermission[] transactionPermissions) {
+ this.roleName = roleName;
+ this.ledgerPermissions = ledgerPermissions;
+ this.transactionPermissions = transactionPermissions;
+ }
+
+ @Override
+ public String getRoleName() {
+ return roleName;
+ }
+
+ @Override
+ public LedgerPermission[] getLedgerPermissions() {
+ return ledgerPermissions;
+ }
+
+ @Override
+ public TransactionPermission[] getTransactionPermissions() {
+ return transactionPermissions;
+ }
+
+ public void setRoleName(String roleName) {
+ this.roleName = roleName;
+ }
+
+ public void setLedgerPermissions(LedgerPermission[] ledgerPermissions) {
+ this.ledgerPermissions = ledgerPermissions;
+ }
+
+ public void setTransactionPermissions(TransactionPermission[] transactionPermissions) {
+ this.transactionPermissions = transactionPermissions;
+ }
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RoleInitSettings.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RoleInitSettings.java
new file mode 100644
index 00000000..71c6965b
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RoleInitSettings.java
@@ -0,0 +1,41 @@
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.binaryproto.DataContract;
+import com.jd.blockchain.binaryproto.DataField;
+import com.jd.blockchain.binaryproto.PrimitiveType;
+import com.jd.blockchain.consts.DataCodes;
+
+/**
+ * 角色参数设置;
+ *
+ * @author huanghaiquan
+ *
+ */
+@DataContract(code = DataCodes.SECURITY_ROLE_INIT_SETTING)
+public interface RoleInitSettings {
+
+ /**
+ * 角色名称;
+ *
+ * @return
+ */
+ @DataField(order = 0, primitiveType = PrimitiveType.TEXT)
+ String getRoleName();
+
+ /**
+ * 角色的账本权限;
+ *
+ * @return
+ */
+ @DataField(order = 1, refEnum = true, list = true)
+ LedgerPermission[] getLedgerPermissions();
+
+ /**
+ * 角色的交易权限;
+ *
+ * @return
+ */
+ @DataField(order = 2, refEnum = true, list = true)
+ TransactionPermission[] getTransactionPermissions();
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolePrivilegeSettings.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolePrivilegeSettings.java
new file mode 100644
index 00000000..cdaa99e8
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolePrivilegeSettings.java
@@ -0,0 +1,160 @@
+package com.jd.blockchain.ledger;
+
+public interface RolePrivilegeSettings {
+
+ /**
+ * 角色名称的最大 Unicode 字符数;
+ */
+ public static final int MAX_ROLE_NAME_LENGTH = 20;
+
+ /**
+ * 角色的数量;
+ *
+ * @return
+ */
+ long getRoleCount();
+
+ /**
+ * 查询角色权限;
+ *
+ *
+ * 如果不存在,则返回 null;
+ *
+ * @param address
+ * @return
+ */
+ RolePrivileges getRolePrivilege(String roleName);
+
+ /**
+ * 返回指定位置的角色权限;
+ *
+ * @param index
+ * @param count
+ * @return
+ */
+ RolePrivileges[] getRolePrivileges(int index, int count);
+
+ /**
+ * 返回所有的角色权限;
+ *
+ * @return
+ */
+ RolePrivileges[] getRolePrivileges();
+
+ /**
+ * 是否只读;
+ *
+ * @return
+ */
+ boolean isReadonly();
+
+ /**
+ * 加入新的角色权限;
+ *
+ * 如果指定的角色已经存在,则引发 {@link LedgerException} 异常;
+ *
+ * @param roleName 角色名称;不能超过 {@link #MAX_ROLE_NAME_LENGTH} 个 Unicode 字符;
+ * @param ledgerPrivilege
+ * @param txPrivilege
+ */
+ long addRolePrivilege(String roleName, Privileges privileges);
+
+ /**
+ * 加入新的角色权限;
+ *
+ * 如果指定的角色已经存在,则引发 {@link LedgerException} 异常;
+ *
+ * @param roleName 角色名称;不能超过 {@link #MAX_ROLE_NAME_LENGTH} 个 Unicode 字符;
+ * @param ledgerPrivilege
+ * @param txPrivilege
+ */
+ long addRolePrivilege(String roleName, LedgerPrivilege ledgerPrivilege, TransactionPrivilege txPrivilege);
+
+ /**
+ * 加入新的角色权限;
+ *
+ * 如果指定的角色已经存在,则引发 {@link LedgerException} 异常;
+ *
+ * @param roleName 角色名称;不能超过 {@link #MAX_ROLE_NAME_LENGTH} 个 Unicode
+ * 字符;
+ * @param ledgerPermissions 给角色授予的账本权限列表;
+ * @param txPermissions 给角色授予的交易权限列表;
+ * @return
+ */
+ long addRolePrivilege(String roleName, LedgerPermission[] ledgerPermissions, TransactionPermission[] txPermissions);
+
+ /**
+ * 更新角色权限;
+ * 如果指定的角色不存在,或者版本不匹配,则引发 {@link LedgerException} 异常;
+ *
+ * @param participant
+ */
+ void updateRolePrivilege(RolePrivileges roleAuth);
+
+ /**
+ * 授权角色指定的权限;
+ * 如果角色不存在,则返回 -1;
+ *
+ * @param roleName 角色;
+ * @param permissions 权限列表;
+ * @return
+ */
+ long enablePermissions(String roleName, LedgerPermission... permissions);
+
+ /**
+ * 授权角色指定的权限;
+ * 如果角色不存在,则返回 -1;
+ *
+ * @param roleName 角色;
+ * @param permissions 权限列表;
+ * @return
+ */
+ long enablePermissions(String roleName, TransactionPermission... permissions);
+
+ /**
+ * 禁止角色指定的权限;
+ * 如果角色不存在,则返回 -1;
+ *
+ * @param roleName 角色;
+ * @param permissions 权限列表;
+ * @return
+ */
+ long disablePermissions(String roleName, LedgerPermission... permissions);
+
+ /**
+ * 禁止角色指定的权限;
+ * 如果角色不存在,则返回 -1;
+ *
+ * @param roleName 角色;
+ * @param permissions 权限列表;
+ * @return
+ */
+ long disablePermissions(String roleName, TransactionPermission... permissions);
+
+ /**
+ * 授权角色指定的权限;
+ * 如果角色不存在,则返回 -1;
+ *
+ * @param roleName
+ * @param ledgerPermissions
+ * @param txPermissions
+ * @return
+ */
+ long enablePermissions(String roleName, LedgerPermission[] ledgerPermissions,
+ TransactionPermission[] txPermissions);
+
+ /**
+ * 禁用角色指定的权限;
+ * 如果角色不存在,则返回 -1;
+ *
+ * @param roleName
+ * @param ledgerPermissions
+ * @param txPermissions
+ * @return
+ */
+ long disablePermissions(String roleName, LedgerPermission[] ledgerPermissions,
+ TransactionPermission[] txPermissions);
+
+ boolean contains(String r);
+
+}
\ No newline at end of file
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolePrivileges.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolePrivileges.java
new file mode 100644
index 00000000..1b0b32ba
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolePrivileges.java
@@ -0,0 +1,41 @@
+package com.jd.blockchain.ledger;
+
+/**
+ * 对角色的授权;
+ *
+ * @author huanghaiquan
+ *
+ */
+public class RolePrivileges extends Privileges {
+
+ private String roleName;
+
+ private long version;
+
+ public RolePrivileges(String roleName, long version) {
+ this.roleName = roleName;
+ this.version = version;
+ }
+
+ public RolePrivileges(String roleName, long version, PrivilegeSet privilege) {
+ super(privilege);
+ this.roleName = roleName;
+ this.version = version;
+ }
+
+ public RolePrivileges(String roleName, long version, LedgerPrivilege ledgerPrivilege,
+ TransactionPrivilege txPrivilege) {
+ super(ledgerPrivilege, txPrivilege);
+ this.roleName = roleName;
+ this.version = version;
+ }
+
+ public String getRoleName() {
+ return roleName;
+ }
+
+ public long getVersion() {
+ return version;
+ }
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RoleSet.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RoleSet.java
new file mode 100644
index 00000000..a026c23f
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RoleSet.java
@@ -0,0 +1,23 @@
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.binaryproto.DataContract;
+import com.jd.blockchain.binaryproto.DataField;
+import com.jd.blockchain.binaryproto.PrimitiveType;
+import com.jd.blockchain.consts.DataCodes;
+
+/**
+ * 角色集;
+ *
+ * @author huanghaiquan
+ *
+ */
+@DataContract(code = DataCodes.ROLE_SET)
+public interface RoleSet {
+
+ @DataField(order = 1, refEnum = true)
+ RolesPolicy getPolicy();
+
+ @DataField(order = 2, primitiveType = PrimitiveType.TEXT, list = true)
+ String[] getRoles();
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolesConfigureOperation.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolesConfigureOperation.java
new file mode 100644
index 00000000..1e448740
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolesConfigureOperation.java
@@ -0,0 +1,39 @@
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.binaryproto.DataContract;
+import com.jd.blockchain.binaryproto.DataField;
+import com.jd.blockchain.binaryproto.PrimitiveType;
+import com.jd.blockchain.consts.DataCodes;
+
+/**
+ * 角色配置操作;
+ *
+ * @author huanghaiquan
+ *
+ */
+@DataContract(code = DataCodes.TX_OP_ROLE_CONFIGURE)
+public interface RolesConfigureOperation extends Operation {
+
+ @DataField(order = 2, refContract = true, list = true)
+ RolePrivilegeEntry[] getRoles();
+
+ @DataContract(code = DataCodes.TX_OP_ROLE_CONFIGURE_ENTRY)
+ public static interface RolePrivilegeEntry {
+
+ @DataField(order = 1, primitiveType = PrimitiveType.TEXT)
+ String getRoleName();
+
+ @DataField(order = 2, refEnum = true, list = true)
+ LedgerPermission[] getEnableLedgerPermissions();
+
+ @DataField(order = 3, refEnum = true, list = true)
+ LedgerPermission[] getDisableLedgerPermissions();
+
+ @DataField(order = 4, refEnum = true, list = true)
+ TransactionPermission[] getEnableTransactionPermissions();
+
+ @DataField(order = 5, refEnum = true, list = true)
+ TransactionPermission[] getDisableTransactionPermissions();
+
+ }
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolesPolicy.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolesPolicy.java
new file mode 100644
index 00000000..690d0be5
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolesPolicy.java
@@ -0,0 +1,40 @@
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.binaryproto.EnumContract;
+import com.jd.blockchain.binaryproto.EnumField;
+import com.jd.blockchain.binaryproto.PrimitiveType;
+import com.jd.blockchain.consts.DataCodes;
+
+/**
+ * 多角色策略;
+ *
+ * 表示如何处理一个对象被赋予多个角色时的综合权限;
+ *
+ * @author huanghaiquan
+ *
+ */
+@EnumContract(code = DataCodes.ENUM_MULTI_ROLES_POLICY, name = "USER-ROLE-POLICY")
+public enum RolesPolicy {
+
+ /**
+ * 合并权限;
+ *
+ * 综合权限是所有角色权限的并集,即任何一个角色的权限都被继承;
+ */
+ UNION((byte) 0),
+
+ /**
+ * 交叉权限;
+ *
+ * 综合权限是所有角色权限的交集,即只有全部角色共同拥有的权限才会被继承;
+ */
+ INTERSECT((byte) 1);
+
+ @EnumField(type = PrimitiveType.INT8)
+ public final byte CODE;
+
+ private RolesPolicy(byte code) {
+ this.CODE = code;
+ }
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/SecurityInitData.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/SecurityInitData.java
new file mode 100644
index 00000000..626adef1
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/SecurityInitData.java
@@ -0,0 +1,54 @@
+package com.jd.blockchain.ledger;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import com.jd.blockchain.utils.Bytes;
+
+public class SecurityInitData implements SecurityInitSettings {
+
+ private Map roles = new LinkedHashMap<>();
+
+ private Map userAuthentications = new LinkedHashMap<>();
+
+ @Override
+ public RoleInitData[] getRoles() {
+ return roles.values().toArray(new RoleInitData[roles.size()]);
+ }
+
+ public int getRolesCount() {
+ return roles.size();
+ }
+
+ public void setRoles(RoleInitData[] roles) {
+ Map newRoles = new LinkedHashMap<>();
+ for (RoleInitData r : roles) {
+ newRoles.put(r.getRoleName(), r);
+ }
+ this.roles = newRoles;
+ }
+
+ public boolean containsRole(String roleName) {
+ return roles.containsKey(roleName);
+ }
+
+ public void addRole(String roleName, LedgerPermission[] ledgerPermissions,
+ TransactionPermission[] transactionPermissions) {
+ RoleInitData roleInitData = new RoleInitData(roleName, ledgerPermissions, transactionPermissions);
+ roles.put(roleName, roleInitData);
+ }
+
+ @Override
+ public UserAuthInitData[] getUserAuthorizations() {
+ return userAuthentications.values().toArray(new UserAuthInitData[userAuthentications.size()]);
+ }
+
+ public void addUserAuthencation(Bytes address, String[] roles, RolesPolicy policy) {
+ UserAuthInitData userAuth = new UserAuthInitData();
+ userAuth.setUserAddress(address);
+ userAuth.setRoles(roles);
+ userAuth.setPolicy(policy);
+
+ userAuthentications.put(address, userAuth);
+ }
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/SecurityInitSettings.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/SecurityInitSettings.java
new file mode 100644
index 00000000..8ca64d79
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/SecurityInitSettings.java
@@ -0,0 +1,27 @@
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.binaryproto.DataContract;
+import com.jd.blockchain.binaryproto.DataField;
+import com.jd.blockchain.consts.DataCodes;
+
+/**
+ * 安全权限的初始化;
+ *
+ * @author huanghaiquan
+ *
+ */
+@DataContract(code = DataCodes.SECURITY_INIT_SETTING)
+public interface SecurityInitSettings {
+
+ /**
+ * 角色列表;
+ *
+ * @return
+ */
+ @DataField(order = 0, refContract = true, list = true)
+ RoleInitSettings[] getRoles();
+
+ @DataField(order = 1, refContract = true, list = true)
+ UserAuthInitSettings[] getUserAuthorizations();
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/SecurityUtils.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/SecurityUtils.java
new file mode 100644
index 00000000..b0175fc5
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/SecurityUtils.java
@@ -0,0 +1,28 @@
+package com.jd.blockchain.ledger;
+
+public class SecurityUtils {
+
+ public static final int MAX_ROLE_NAMES = 20;
+
+ /**
+ * 校验角色名称的有效性,并格式化角色名称:去掉两端空白字符,统一为大写字符;
+ *
+ * @param roleName
+ * @return
+ */
+ public static String formatRoleName(String roleName) {
+ if (roleName == null) {
+ throw new IllegalArgumentException("Role name is empty!");
+ }
+ roleName = roleName.trim();
+ if (roleName.length() > MAX_ROLE_NAMES) {
+ throw new IllegalArgumentException("Role name exceeds max length!");
+ }
+ if (roleName.length() == 0) {
+ throw new IllegalArgumentException("Role name is empty!");
+ }
+
+ return roleName.toUpperCase();
+ }
+
+}
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 5ffa8739..0c227ab5 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
@@ -40,6 +40,6 @@ public interface TransactionContentBody {
* @return
*/
@DataField(order = 3, primitiveType = PrimitiveType.INT64)
- long getTime();
+ long getTimestamp();
}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionException.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionException.java
deleted file mode 100644
index c88f0792..00000000
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionException.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.jd.blockchain.ledger;
-
-public class TransactionException extends Exception {
-
- private static final long serialVersionUID = 3583192000738807503L;
-
- private TransactionState state;
-
- public TransactionException(TransactionState state) {
- this.state = state;
- }
-
- public TransactionException(TransactionState state, String message) {
- super(message);
- this.state = state;
- }
-
- public TransactionState getState() {
- return state;
- }
-
-}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionPermission.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionPermission.java
new file mode 100644
index 00000000..b197820e
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionPermission.java
@@ -0,0 +1,34 @@
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.binaryproto.EnumContract;
+import com.jd.blockchain.binaryproto.EnumField;
+import com.jd.blockchain.binaryproto.PrimitiveType;
+import com.jd.blockchain.consts.DataCodes;
+
+/**
+ * TxPermission 交易权限表示一个用户可以发起的交易类型;
+ *
+ * @author huanghaiquan
+ *
+ */
+@EnumContract(code = DataCodes.ENUM_TX_PERMISSION)
+public enum TransactionPermission {
+
+ /**
+ * 交易中包含指令操作;
+ */
+ DIRECT_OPERATION((byte) 0x01),
+
+ /**
+ * 交易中包含合约操作;
+ */
+ CONTRACT_OPERATION((byte) 0x02);
+
+ @EnumField(type = PrimitiveType.INT8)
+ public final byte CODE;
+
+ private TransactionPermission(byte code) {
+ this.CODE = code;
+ }
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionPrivilege.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionPrivilege.java
new file mode 100644
index 00000000..755a75a7
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionPrivilege.java
@@ -0,0 +1,23 @@
+package com.jd.blockchain.ledger;
+
+public class TransactionPrivilege extends PrivilegeBitset {
+
+ private static final CodeIndexer CODE_INDEXER = new TransactionPermissionCodeIndexer();
+
+ public TransactionPrivilege() {
+ super(CODE_INDEXER);
+ }
+
+ public TransactionPrivilege(byte[] codeBytes) {
+ super(codeBytes, CODE_INDEXER);
+ }
+
+ private static class TransactionPermissionCodeIndexer implements CodeIndexer {
+
+ @Override
+ public int getCodeIndex(TransactionPermission permission) {
+ return permission.CODE & 0xFF;
+ }
+
+ }
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionRequestBuilder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionRequestBuilder.java
index 0818d865..87c445ad 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionRequestBuilder.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionRequestBuilder.java
@@ -60,7 +60,7 @@ public interface TransactionRequestBuilder extends HashObject {
* Base64格式的签名摘要;
* @return
*/
- void addEndpointSignature(DigitalSignature signature);
+ void addEndpointSignature(DigitalSignature... signature);
/**
* 加入签名;
@@ -71,7 +71,7 @@ public interface TransactionRequestBuilder extends HashObject {
* Base64格式的签名摘要;
* @return
*/
- void addNodeSignature(DigitalSignature signature);
+ void addNodeSignature(DigitalSignature... signatures);
/**
* 生成交易请求;
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionRollbackException.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionRollbackException.java
new file mode 100644
index 00000000..7694d898
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionRollbackException.java
@@ -0,0 +1,16 @@
+package com.jd.blockchain.ledger;
+
+public class TransactionRollbackException extends RuntimeException {
+
+
+ private static final long serialVersionUID = -1223140447229570029L;
+
+ public TransactionRollbackException(String message) {
+ super(message);
+ }
+
+ public TransactionRollbackException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionState.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionState.java
index e89d41b6..029ccbab 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionState.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionState.java
@@ -11,7 +11,7 @@ import com.jd.blockchain.consts.DataCodes;
* @author huanghaiquan
*
*/
-@EnumContract(code= DataCodes.ENUM_TYPE_TRANSACTION_STATE)
+@EnumContract(code = DataCodes.ENUM_TYPE_TRANSACTION_STATE)
public enum TransactionState {
/**
@@ -20,19 +20,73 @@ public enum TransactionState {
SUCCESS((byte) 0),
/**
- * 共识错误;
+ * 账本错误;
+ */
+ LEDGER_ERROR((byte) 0x01),
+
+ /**
+ * 数据账户不存在;
*/
- CONSENSUS_ERROR((byte) 1),
+ DATA_ACCOUNT_DOES_NOT_EXIST((byte) 0x02),
+
+ /**
+ * 用户不存在;
+ */
+ USER_DOES_NOT_EXIST((byte) 0x03),
+
+ /**
+ * 合约不存在;
+ */
+ CONTRACT_DOES_NOT_EXIST((byte) 0x04),
/**
- * 账本错误;
+ * 数据写入时版本冲突;
+ */
+ DATA_VERSION_CONFLICT((byte) 0x05),
+
+ /**
+ * 参与方不存在;
+ */
+ PARTICIPANT_DOES_NOT_EXIST((byte) 0x05),
+
+ /**
+ * 被安全策略拒绝;
*/
- LEDGER_ERROR((byte) 2),
+ REJECTED_BY_SECURITY_POLICY((byte) 0x10),
/**
- * 数据序列更新错误;
+ * 由于在错误的账本上执行交易而被丢弃;
*/
- DATA_SEQUENCE_UPDATE_ERROR((byte) 3),
+ IGNORED_BY_WRONG_LEDGER((byte) 0x40),
+
+ /**
+ * 由于交易内容的验签失败而丢弃;
+ */
+ IGNORED_BY_WRONG_CONTENT_SIGNATURE((byte) 0x41),
+
+ /**
+ * 由于交易内容的验签失败而丢弃;
+ */
+ IGNORED_BY_CONFLICTING_STATE((byte) 0x42),
+
+ /**
+ * 由于交易的整体回滚而丢弃;
+ *
+ *
+ * 注: “整体回滚”是指把交易引入的数据更改以及交易记录本身全部都回滚;
+ * “部分回滚”是指把交易引入的数据更改回滚了,但是交易记录本身以及相应的“交易结果({@link TransactionState})”都会提交;
+ */
+ IGNORED_BY_TX_FULL_ROLLBACK((byte) 0x43),
+
+ /**
+ * 由于区块的整体回滚而丢弃;
+ *
+ *
+ * 注: “整体回滚”是指把交易引入的数据更改以及交易记录本身全部都回滚;
+ *
+ * “部分回滚”是指把交易引入的数据更改回滚了,但是交易记录本身以及相应的“交易结果({@link TransactionState})”都会提交;
+ */
+ IGNORED_BY_BLOCK_FULL_ROLLBACK((byte) 0x44),
/**
* 系统错误;
@@ -42,9 +96,14 @@ public enum TransactionState {
/**
* 超时;
*/
- TIMEOUT((byte) 0x81);
+ TIMEOUT((byte) 0x81),
+
+ /**
+ * 共识错误;
+ */
+ CONSENSUS_ERROR((byte) 0x82);
- @EnumField(type= PrimitiveType.INT8)
+ @EnumField(type = PrimitiveType.INT8)
public final byte CODE;
private TransactionState(byte code) {
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserAuthInitData.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserAuthInitData.java
new file mode 100644
index 00000000..6866c991
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserAuthInitData.java
@@ -0,0 +1,40 @@
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.utils.Bytes;
+
+public class UserAuthInitData implements UserAuthInitSettings {
+
+ private Bytes userAddress;
+
+ private String[] roles;
+
+ private RolesPolicy policy;
+
+ public void setUserAddress(Bytes userAddress) {
+ this.userAddress = userAddress;
+ }
+
+ public void setRoles(String[] roles) {
+ this.roles = roles;
+ }
+
+ public void setPolicy(RolesPolicy policy) {
+ this.policy = policy;
+ }
+
+ @Override
+ public Bytes getUserAddress() {
+ return userAddress;
+ }
+
+ @Override
+ public String[] getRoles() {
+ return roles;
+ }
+
+ @Override
+ public RolesPolicy getPolicy() {
+ return policy;
+ }
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserAuthInitSettings.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserAuthInitSettings.java
new file mode 100644
index 00000000..31a6033a
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserAuthInitSettings.java
@@ -0,0 +1,21 @@
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.binaryproto.DataContract;
+import com.jd.blockchain.binaryproto.DataField;
+import com.jd.blockchain.binaryproto.PrimitiveType;
+import com.jd.blockchain.consts.DataCodes;
+import com.jd.blockchain.utils.Bytes;
+
+@DataContract(code = DataCodes.SECURITY_USER_AUTH_INIT_SETTING)
+public interface UserAuthInitSettings {
+
+ @DataField(order = 1, primitiveType = PrimitiveType.BYTES)
+ Bytes getUserAddress();
+
+ @DataField(order = 2, primitiveType = PrimitiveType.TEXT, list = true)
+ String[] getRoles();
+
+ @DataField(order = 3, refEnum = true)
+ RolesPolicy getPolicy();
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserAuthorizeOperation.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserAuthorizeOperation.java
new file mode 100644
index 00000000..67e37e17
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserAuthorizeOperation.java
@@ -0,0 +1,57 @@
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.binaryproto.DataContract;
+import com.jd.blockchain.binaryproto.DataField;
+import com.jd.blockchain.binaryproto.PrimitiveType;
+import com.jd.blockchain.consts.DataCodes;
+import com.jd.blockchain.utils.Bytes;
+
+/**
+ * 角色配置操作;
+ *
+ * @author huanghaiquan
+ *
+ */
+@DataContract(code = DataCodes.TX_OP_USER_ROLES_AUTHORIZE)
+public interface UserAuthorizeOperation extends Operation {
+
+ @DataField(order = 2, refContract = true, list = true)
+ UserRolesEntry[] getUserRolesAuthorizations();
+
+ @DataContract(code = DataCodes.TX_OP_USER_ROLE_AUTHORIZE_ENTRY)
+ public static interface UserRolesEntry {
+
+ /**
+ * 用户地址;
+ *
+ * @return
+ */
+ @DataField(order = 0, primitiveType = PrimitiveType.BYTES, list = true)
+ Bytes[] getUserAddresses();
+
+ /**
+ * 要更新的多角色权限策略;
+ *
+ * @return
+ */
+ @DataField(order = 2, refEnum = true)
+ RolesPolicy getPolicy();
+
+ /**
+ * 授权的角色清单;
+ *
+ * @return
+ */
+ @DataField(order = 3, primitiveType = PrimitiveType.TEXT, list = true)
+ String[] getAuthorizedRoles();
+
+ /**
+ * 取消授权的角色清单;
+ *
+ * @return
+ */
+ @DataField(order = 4, primitiveType = PrimitiveType.TEXT, list = true)
+ String[] getUnauthorizedRoles();
+
+ }
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserDoesNotExistException.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserDoesNotExistException.java
new file mode 100644
index 00000000..1775405f
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserDoesNotExistException.java
@@ -0,0 +1,15 @@
+package com.jd.blockchain.ledger;
+
+public class UserDoesNotExistException extends LedgerException {
+
+ private static final long serialVersionUID = 397450363050148898L;
+
+ public UserDoesNotExistException(String message) {
+ super(message);
+ }
+
+ public UserDoesNotExistException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserInfoSetOperation.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserInfoSetOperation.java
index b9a92317..c6372b78 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserInfoSetOperation.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserInfoSetOperation.java
@@ -1,33 +1,29 @@
-//package com.jd.blockchain.ledger;
-//
-//import com.jd.blockchain.binaryproto.DataContract;
-//
-///**
-// * @author huanghaiquan
-// *
-// */
-//@DataContract(code=LedgerCodes.TX_OP_USER_INFO_SET)
-//public interface UserInfoSetOperation extends Operation {
-//
-// @Override
-// default OperationType getType() {
-// return OperationType.SET_USER_INFO;
-// }
-//
-// String getUserAddress();
-//
-// KVEntry[] getPropertiesWriteSet();
-//
-//
-// @DataContract(code=LedgerCodes.TX_OP_USER_INFO_SET_KV)
-// public static interface KVEntry{
-//
-// String getKey();
-//
-// String getValue();
-//
-// long getExpectedVersion();
-// }
-//
-//
-//}
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.binaryproto.DataContract;
+import com.jd.blockchain.consts.DataCodes;
+
+/**
+ * @author huanghaiquan
+ *
+ */
+@DataContract(code=DataCodes.TX_OP_USER_INFO_SET)
+public interface UserInfoSetOperation extends Operation {
+
+ String getUserAddress();
+
+ KVEntry[] getPropertiesWriteSet();
+
+
+ @DataContract(code=DataCodes.TX_OP_USER_INFO_SET_KV)
+ public static interface KVEntry{
+
+ String getKey();
+
+ String getValue();
+
+ long getExpectedVersion();
+ }
+
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserRegisterOperation.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserRegisterOperation.java
index f325085e..caa642de 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserRegisterOperation.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserRegisterOperation.java
@@ -4,10 +4,10 @@ import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.binaryproto.DataField;
import com.jd.blockchain.consts.DataCodes;
-@DataContract(code= DataCodes.TX_OP_USER_REG)
+@DataContract(code = DataCodes.TX_OP_USER_REG)
public interface UserRegisterOperation extends Operation {
-
- @DataField(order=2, refContract = true)
- BlockchainIdentity getUserID();
+ @DataField(order = 2, refContract = true)
+ BlockchainIdentity getUserID();
+
}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserRoles.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserRoles.java
new file mode 100644
index 00000000..d73d67a2
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserRoles.java
@@ -0,0 +1,107 @@
+package com.jd.blockchain.ledger;
+
+import java.util.Collection;
+import java.util.Set;
+import java.util.TreeSet;
+
+import com.jd.blockchain.utils.Bytes;
+
+public class UserRoles implements RoleSet {
+
+ private Bytes userAddress;
+
+ private RolesPolicy policy;
+
+ private Set roles;
+
+ private long version;
+
+ public UserRoles(Bytes userAddress, long version, RolesPolicy policy) {
+ this.userAddress = userAddress;
+ this.version = version;
+ this.policy = policy;
+ this.roles = new TreeSet();
+ }
+
+ public UserRoles(Bytes userAddress, long version, RoleSet roleSet) {
+ this.userAddress = userAddress;
+ this.version = version;
+ this.policy = roleSet.getPolicy();
+ this.roles = initRoles(roleSet.getRoles());
+
+ }
+
+ private Set initRoles(String[] roles) {
+ TreeSet roleset = new TreeSet();
+ if (roles != null) {
+ for (String r : roles) {
+ roleset.add(r);
+ }
+ }
+ return roleset;
+ }
+
+ public Bytes getUserAddress() {
+ return userAddress;
+ }
+
+ @Override
+ public RolesPolicy getPolicy() {
+ return policy;
+ }
+
+ public void setPolicy(RolesPolicy policy) {
+ this.policy = policy;
+ }
+
+ public int getRoleCount() {
+ return roles.size();
+ }
+
+ @Override
+ public String[] getRoles() {
+ return roles.toArray(new String[roles.size()]);
+ }
+
+ public long getVersion() {
+ return version;
+ }
+
+ public void addRoles(String... roles) {
+ for (String r : roles) {
+ this.roles.add(r);
+ }
+ }
+
+ public void addRoles(Collection roles) {
+ for (String r : roles) {
+ this.roles.add(r);
+ }
+ }
+
+ public void removeRoles(String... roles) {
+ for (String r : roles) {
+ this.roles.remove(r);
+ }
+ }
+
+ public void removeRoles(Collection roles) {
+ for (String r : roles) {
+ this.roles.remove(r);
+ }
+ }
+
+ /**
+ * 设置角色集合;
+ * 注意,这不是追加;现有的不在参数指定范围的角色将被移除;
+ *
+ * @param roles
+ */
+ public void setRoles(String[] roles) {
+ TreeSet rs = new TreeSet();
+ for (String r : roles) {
+ rs.add(r);
+ }
+ this.roles = rs;
+ }
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserRolesSettings.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserRolesSettings.java
new file mode 100644
index 00000000..af822b82
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserRolesSettings.java
@@ -0,0 +1,87 @@
+package com.jd.blockchain.ledger;
+
+import java.util.Collection;
+
+import com.jd.blockchain.utils.Bytes;
+
+public interface UserRolesSettings {
+
+ /**
+ * 单一用户可被授权的角色数量的最大值;
+ */
+ public static final int MAX_ROLES_PER_USER = 20;
+
+ /**
+ * 进行了授权的用户的数量;
+ *
+ * @return
+ */
+ long getUserCount();
+
+ /**
+ * 查询角色授权;
+ *
+ *
+ * 如果不存在,则返回 null;
+ *
+ * @param address
+ * @return
+ */
+ UserRoles getUserRoles(Bytes userAddress);
+
+ /**
+ * 返回全部的用户授权;
+ *
+ * @return
+ */
+ UserRoles[] getUserRoles();
+
+ /**
+ * 是否只读;
+ *
+ * @return
+ */
+ boolean isReadonly();
+
+ /**
+ * 加入新的用户角色授权;
+ *
+ * 如果该用户的授权已经存在,则引发 {@link LedgerException} 异常;
+ *
+ * @param userAddress
+ * @param rolesPolicy
+ * @param roles
+ */
+ void addUserRoles(Bytes userAddress, RolesPolicy rolesPolicy, String... roles);
+
+ /**
+ * 加入新的用户角色授权;
+ *
+ * 如果该用户的授权已经存在,则引发 {@link LedgerException} 异常;
+ *
+ * @param userAddress
+ * @param rolesPolicy
+ * @param roles
+ */
+ void addUserRoles(Bytes userAddress, RolesPolicy rolesPolicy, Collection roles);
+
+ /**
+ * 更新用户角色授权;
+ * 如果指定用户的授权不存在,或者版本不匹配,则引发 {@link LedgerException} 异常;
+ *
+ * @param userRoles
+ */
+ void updateUserRoles(UserRoles userRoles);
+
+ /**
+ * 设置用户的角色;
+ * 如果用户的角色授权不存在,则创建新的授权;
+ *
+ * @param userAddress 用户;
+ * @param policy 角色策略;
+ * @param roles 角色列表;
+ * @return
+ */
+ long setRoles(Bytes userAddress, RolesPolicy policy, String... roles);
+
+}
\ No newline at end of file
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BooleanToBytesValueResolver.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BooleanToBytesValueResolver.java
new file mode 100644
index 00000000..0664fdb9
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BooleanToBytesValueResolver.java
@@ -0,0 +1,58 @@
+package com.jd.blockchain.ledger.resolver;
+
+import com.jd.blockchain.ledger.BytesData;
+import com.jd.blockchain.ledger.BytesValue;
+import com.jd.blockchain.ledger.DataType;
+import com.jd.blockchain.utils.Bytes;
+import com.jd.blockchain.utils.io.BytesUtils;
+
+import java.util.Set;
+
+public class BooleanToBytesValueResolver extends AbstractBytesValueResolver {
+
+ private final Class>[] supportClasses = { Boolean.class, boolean.class };
+
+ private final DataType[] supportDataTypes = { DataType.BOOLEAN };
+
+ private final Set> convertClasses = initBooleanConvertSet();
+
+ @Override
+ public BytesValue encode(Object value, Class> type) {
+ if (!isSupport(type)) {
+ throw new IllegalStateException(String.format("Un-support encode Class[%s] Object !!!", type.getName()));
+ }
+ return BytesData.fromBoolean((boolean) value);
+ }
+
+ @Override
+ public Class>[] supportClasses() {
+ return supportClasses;
+ }
+
+ @Override
+ public DataType[] supportDataTypes() {
+ return supportDataTypes;
+ }
+
+ @Override
+ protected Object decode(Bytes value) {
+ return BytesUtils.toInt(value.toBytes());
+ }
+
+ @Override
+ public Object decode(BytesValue value, Class> clazz) {
+ // 支持转换为short、int、long
+ int intVal = (int) decode(value);
+ if (convertClasses.contains(clazz)) {
+ // 对于short和Short需要强制类型转换
+ if (clazz.equals(short.class) || clazz.equals(Short.class)) {
+ return (short) intVal;
+ } else if (clazz.equals(long.class) || clazz.equals(Long.class)) {
+ return (long) intVal;
+ }
+ return intVal;
+ } else {
+ throw new IllegalStateException(String.format("Un-Support decode value to class[%s] !!!", clazz.getName()));
+ }
+ }
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BytesValueResolver.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BytesValueResolver.java
index 08e48658..4c659567 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BytesValueResolver.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BytesValueResolver.java
@@ -10,71 +10,79 @@ import java.util.Set;
public interface BytesValueResolver {
- /**
- * Int相关的可转换Class集合
- */
- Class>[] supportIntConvertClasses = {
- short.class, Short.class, int.class, Integer.class, long.class, Long.class};
+ /**
+ * Boolean相关的可转换Class集合
+ */
+ Class>[] supportBooleanConvertClasses = { boolean.class, Boolean.class };
- /**
- * 字节数组(字符串)相关可转换的Class集合
- */
- Class>[] supportByteConvertClasses = {
- String.class, Bytes.class, byte[].class};
+ /**
+ * Int相关的可转换Class集合
+ */
+ Class>[] supportIntConvertClasses = { short.class, Short.class, int.class, Integer.class, long.class,
+ Long.class };
- default Set> initIntConvertSet() {
- return new HashSet<>(Arrays.asList(supportIntConvertClasses));
- }
+ /**
+ * 字节数组(字符串)相关可转换的Class集合
+ */
+ Class>[] supportByteConvertClasses = { String.class, Bytes.class, byte[].class };
+
+ default Set> initBooleanConvertSet() {
+ return new HashSet<>(Arrays.asList(supportBooleanConvertClasses));
+ }
- default Set> initByteConvertSet() {
- return new HashSet<>(Arrays.asList(supportByteConvertClasses));
- }
+ default Set> initIntConvertSet() {
+ return new HashSet<>(Arrays.asList(supportIntConvertClasses));
+ }
- /**
- * 将对象转换为BytesValue
- *
- * @param value
- * @return
- */
- BytesValue encode(Object value);
+ default Set> initByteConvertSet() {
+ return new HashSet<>(Arrays.asList(supportByteConvertClasses));
+ }
- /**
- * 将对象转换为BytesValue
- *
- * @param value
- * @param type
- * @return
- */
- BytesValue encode(Object value, Class> type);
+ /**
+ * 将对象转换为BytesValue
+ *
+ * @param value
+ * @return
+ */
+ BytesValue encode(Object value);
- /**
- * 当前解析器支持的Class列表
- *
- * @return
- */
- Class>[] supportClasses();
+ /**
+ * 将对象转换为BytesValue
+ *
+ * @param value
+ * @param type
+ * @return
+ */
+ BytesValue encode(Object value, Class> type);
- /**
- * 当前解析器支持的DataType列表
- *
- * @return
- */
- DataType[] supportDataTypes();
+ /**
+ * 当前解析器支持的Class列表
+ *
+ * @return
+ */
+ Class>[] supportClasses();
- /**
- * 将BytesValue解析为对应的Object
- *
- * @param value
- * @return
- */
- Object decode(BytesValue value);
+ /**
+ * 当前解析器支持的DataType列表
+ *
+ * @return
+ */
+ DataType[] supportDataTypes();
- /**
- * 将BytesValue转换为指定Class的Object
- *
- * @param value
- * @param clazz
- * @return
- */
- Object decode(BytesValue value, Class> clazz);
+ /**
+ * 将BytesValue解析为对应的Object
+ *
+ * @param value
+ * @return
+ */
+ Object decode(BytesValue value);
+
+ /**
+ * 将BytesValue转换为指定Class的Object
+ *
+ * @param value
+ * @param clazz
+ * @return
+ */
+ Object decode(BytesValue value, Class> clazz);
}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainOperationFactory.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainOperationFactory.java
index 00d79f35..9838bef1 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainOperationFactory.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainOperationFactory.java
@@ -12,6 +12,8 @@ import java.util.List;
*
*/
public class BlockchainOperationFactory implements ClientOperator, LedgerInitOperator {
+
+ private static final SecurityOperationBuilderImpl SECURITY_OP_BUILDER = new SecurityOperationBuilderImpl();
private static final LedgerInitOperationBuilderImpl LEDGER_INIT_OP_BUILDER = new LedgerInitOperationBuilderImpl();
@@ -22,6 +24,8 @@ public class BlockchainOperationFactory implements ClientOperator, LedgerInitOpe
private static final ContractCodeDeployOperationBuilderImpl CONTRACT_CODE_DEPLOY_OP_BUILDER = new ContractCodeDeployOperationBuilderImpl();
// private static final ContractEventSendOperationBuilderImpl CONTRACT_EVENT_SEND_OP_BUILDER = new ContractEventSendOperationBuilderImpl();
+
+ private SecurityOperationBuilderFilter securityOpBuilder = new SecurityOperationBuilderFilter();
private LedgerInitOperationBuilder ledgerInitOpBuilder = new LedgerInitOperationBuilderFilter();
@@ -42,6 +46,11 @@ public class BlockchainOperationFactory implements ClientOperator, LedgerInitOpe
public LedgerInitOperationBuilder ledgers() {
return ledgerInitOpBuilder;
}
+
+ @Override
+ public SecurityOperationBuilder security() {
+ return securityOpBuilder;
+ }
@Override
public UserRegisterOperationBuilder users() {
@@ -146,6 +155,23 @@ public class BlockchainOperationFactory implements ClientOperator, LedgerInitOpe
}
}
+
+ private class SecurityOperationBuilderFilter implements SecurityOperationBuilder {
+
+ @Override
+ public RolesConfigurer roles() {
+ RolesConfigurer rolesConfigurer = SECURITY_OP_BUILDER.roles();
+ operationList.add(rolesConfigurer.getOperation());
+ return rolesConfigurer;
+ }
+
+ @Override
+ public UserAuthorizer authorziations() {
+ UserAuthorizer userAuthorizer = SECURITY_OP_BUILDER.authorziations();
+ operationList.add(userAuthorizer.getOperation());
+ return userAuthorizer;
+ }
+ }
private class DataAccountRegisterOperationBuilderFilter implements DataAccountRegisterOperationBuilder {
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java
index a9f47141..9710b50d 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java
@@ -1,7 +1,21 @@
package com.jd.blockchain.transaction;
+import org.springframework.cglib.core.Block;
+
import com.jd.blockchain.crypto.HashDigest;
-import com.jd.blockchain.ledger.*;
+import com.jd.blockchain.ledger.AccountHeader;
+import com.jd.blockchain.ledger.ContractInfo;
+import com.jd.blockchain.ledger.KVDataEntry;
+import com.jd.blockchain.ledger.KVInfoVO;
+import com.jd.blockchain.ledger.LedgerAdminInfo;
+import com.jd.blockchain.ledger.LedgerBlock;
+import com.jd.blockchain.ledger.LedgerInfo;
+import com.jd.blockchain.ledger.LedgerMetadata;
+import com.jd.blockchain.ledger.LedgerTransaction;
+import com.jd.blockchain.ledger.ParticipantNode;
+import com.jd.blockchain.ledger.Transaction;
+import com.jd.blockchain.ledger.TransactionState;
+import com.jd.blockchain.ledger.UserInfo;
/**
* 区块链查询器;
@@ -28,12 +42,20 @@ public interface BlockchainQueryService {
*/
LedgerInfo getLedger(HashDigest ledgerHash);
- /**
- * 返回当前账本的参与者信息列表
- *
- * @param ledgerHash
- * @return
- */
+ /**
+ * 获取账本信息;
+ *
+ * @param ledgerHash
+ * @return 账本对象;如果不存在,则返回 null;
+ */
+ LedgerAdminInfo getLedgerAdminInfo(HashDigest ledgerHash);
+
+ /**
+ * 返回当前账本的参与者信息列表
+ *
+ * @param ledgerHash
+ * @return
+ */
ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash);
/**
@@ -47,10 +69,8 @@ public interface BlockchainQueryService {
/**
* 返回指定账本序号的区块;
*
- * @param ledgerHash
- * 账本hash;
- * @param height
- * 高度;
+ * @param ledgerHash 账本hash;
+ * @param height 高度;
* @return
*/
LedgerBlock getBlock(HashDigest ledgerHash, long height);
@@ -58,10 +78,8 @@ public interface BlockchainQueryService {
/**
* 返回指定区块hash的区块;
*
- * @param ledgerHash
- * 账本hash;
- * @param blockHash
- * 区块hash;
+ * @param ledgerHash 账本hash;
+ * @param blockHash 区块hash;
* @return
*/
LedgerBlock getBlock(HashDigest ledgerHash, HashDigest blockHash);
@@ -84,125 +102,116 @@ public interface BlockchainQueryService {
*/
long getTransactionCount(HashDigest ledgerHash, HashDigest blockHash);
- /**
- * 返回当前账本的交易总数
- *
- * @param ledgerHash
- * @return
- */
+ /**
+ * 返回当前账本的交易总数
+ *
+ * @param ledgerHash
+ * @return
+ */
long getTransactionTotalCount(HashDigest ledgerHash);
- /**
- * 返回指定高度的区块中记录的数据账户总数
- *
- * @param ledgerHash
- * @param height
- * @return
- */
+ /**
+ * 返回指定高度的区块中记录的数据账户总数
+ *
+ * @param ledgerHash
+ * @param height
+ * @return
+ */
long getDataAccountCount(HashDigest ledgerHash, long height);
- /**
- * 返回指定的区块中记录的数据账户总数
- *
- * @param ledgerHash
- * @param blockHash
- * @return
- */
+ /**
+ * 返回指定的区块中记录的数据账户总数
+ *
+ * @param ledgerHash
+ * @param blockHash
+ * @return
+ */
long getDataAccountCount(HashDigest ledgerHash, HashDigest blockHash);
- /**
- * 返回当前账本的数据账户总数
- *
- * @param ledgerHash
- * @return
- */
- long getDataAccountTotalCount(HashDigest ledgerHash);
-
- /**
- * 返回指定高度区块中的用户总数
- *
- * @param ledgerHash
- * @param height
- * @return
- */
+ /**
+ * 返回当前账本的数据账户总数
+ *
+ * @param ledgerHash
+ * @return
+ */
+ long getDataAccountTotalCount(HashDigest ledgerHash);
+
+ /**
+ * 返回指定高度区块中的用户总数
+ *
+ * @param ledgerHash
+ * @param height
+ * @return
+ */
long getUserCount(HashDigest ledgerHash, long height);
- /**
- * 返回指定区块中的用户总数
- *
- * @param ledgerHash
- * @param blockHash
- * @return
- */
+ /**
+ * 返回指定区块中的用户总数
+ *
+ * @param ledgerHash
+ * @param blockHash
+ * @return
+ */
long getUserCount(HashDigest ledgerHash, HashDigest blockHash);
- /**
- * 返回当前账本的用户总数
- *
- * @param ledgerHash
- * @return
- */
- long getUserTotalCount(HashDigest ledgerHash);
-
- /**
- * 返回指定高度区块中的合约总数
- *
- * @param ledgerHash
- * @param height
- * @return
- */
- long getContractCount(HashDigest ledgerHash, long height);
-
- /**
- * 返回指定区块中的合约总数
- *
- * @param ledgerHash
- * @param blockHash
- * @return
- */
- long getContractCount(HashDigest ledgerHash, HashDigest blockHash);
-
- /**
- * 返回当前账本的合约总数
- *
- * @param ledgerHash
- * @return
- */
- long getContractTotalCount(HashDigest ledgerHash);
-
+ /**
+ * 返回当前账本的用户总数
+ *
+ * @param ledgerHash
+ * @return
+ */
+ long getUserTotalCount(HashDigest ledgerHash);
/**
- * 分页返回指定账本序号的区块中的交易列表;
+ * 返回指定高度区块中的合约总数
*
* @param ledgerHash
- * 账本hash;
* @param height
- * 账本高度;
- * @param fromIndex
- * 开始的记录数;
- * @param count
- * 本次返回的记录数;
- * 最小为1,最大值受到系统参数的限制;
- * 注:通过 {@link #getBlock(String, long)} 方法获得的区块信息中可以得到区块的总交易数
- * {@link Block#getTxCount()};
* @return
*/
- LedgerTransaction[] getTransactions(HashDigest ledgerHash, long height, int fromIndex, int count);
+ long getContractCount(HashDigest ledgerHash, long height);
/**
- * 分页返回指定账本序号的区块中的交易列表;
+ * 返回指定区块中的合约总数
*
* @param ledgerHash
- * 账本hash;
* @param blockHash
- * 账本高度;
- * @param fromIndex
- * 开始的记录数;
- * @param count
- * 本次返回的记录数;
- * 如果参数值为 -1,则返回全部的记录;
- * 注:通过 {@link #getBlock(String, String)} 方法获得的区块信息中可以得到区块的总交易数
- * {@link Block#getTxCount()};
+ * @return
+ */
+ long getContractCount(HashDigest ledgerHash, HashDigest blockHash);
+
+ /**
+ * 返回当前账本的合约总数
+ *
+ * @param ledgerHash
+ * @return
+ */
+ long getContractTotalCount(HashDigest ledgerHash);
+
+ /**
+ * 分页返回指定账本序号的区块中的交易列表;
+ *
+ * @param ledgerHash 账本hash;
+ * @param height 账本高度;
+ * @param fromIndex 开始的记录数;
+ * @param count 本次返回的记录数;
+ * 最小为1,最大值受到系统参数的限制;
+ * 注:通过 {@link #getBlock(String, long)} 方法获得的区块信息中可以得到区块的总交易数
+ * {@link Block#getTxCount()};
+ * @return
+ */
+ LedgerTransaction[] getTransactions(HashDigest ledgerHash, long height, int fromIndex, int count);
+
+ /**
+ * 分页返回指定账本序号的区块中的交易列表;
+ *
+ * @param ledgerHash 账本hash;
+ * @param blockHash 账本高度;
+ * @param fromIndex 开始的记录数;
+ * @param count 本次返回的记录数;
+ * 如果参数值为 -1,则返回全部的记录;
+ * 注:通过 {@link #getBlock(String, String)}
+ * 方法获得的区块信息中可以得到区块的总交易数 {@link Block#getTxCount()};
* @return
*/
LedgerTransaction[] getTransactions(HashDigest ledgerHash, HashDigest blockHash, int fromIndex, int count);
@@ -210,21 +219,17 @@ public interface BlockchainQueryService {
/**
* 根据交易内容的哈希获取对应的交易记录;
*
- * @param ledgerHash
- * 账本hash;
- * @param contentHash
- * 交易内容的hash,即交易的 {@link Transaction#getContentHash()} 属性的值;
+ * @param ledgerHash 账本hash;
+ * @param contentHash 交易内容的hash,即交易的 {@link Transaction#getContentHash()} 属性的值;
* @return
*/
LedgerTransaction getTransactionByContentHash(HashDigest ledgerHash, HashDigest contentHash);
-
+
/**
* 根据交易内容的哈希获取对应的交易状态;
*
- * @param ledgerHash
- * 账本hash;
- * @param contentHash
- * 交易内容的hash,即交易的 {@link Transaction#getContentHash()} 属性的值;
+ * @param ledgerHash 账本hash;
+ * @param contentHash 交易内容的hash,即交易的 {@link Transaction#getContentHash()} 属性的值;
* @return
*/
TransactionState getTransactionStateByContentHash(HashDigest ledgerHash, HashDigest contentHash);
@@ -273,18 +278,13 @@ public interface BlockchainQueryService {
long getDataEntriesTotalCount(HashDigest ledgerHash, String address);
/**
- * 返回数据账户中指定序号的最新值;
- * 返回结果的顺序与指定的序号的顺序是一致的;
+ * 返回数据账户中指定序号的最新值; 返回结果的顺序与指定的序号的顺序是一致的;
*
- * @param ledgerHash
- * 账本hash;
- * @param address
- * 数据账户地址;
- * @param fromIndex
- * 开始的记录数;
- * @param count
- * 本次返回的记录数;
- * 如果参数值为 -1,则返回全部的记录;
+ * @param ledgerHash 账本hash;
+ * @param address 数据账户地址;
+ * @param fromIndex 开始的记录数;
+ * @param count 本次返回的记录数;
+ * 如果参数值为 -1,则返回全部的记录;
* @return
*/
KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count);
@@ -300,6 +300,7 @@ public interface BlockchainQueryService {
/**
* get users by ledgerHash and its range;
+ *
* @param ledgerHash
* @param fromIndex
* @param count
@@ -309,6 +310,7 @@ public interface BlockchainQueryService {
/**
* get data accounts by ledgerHash and its range;
+ *
* @param ledgerHash
* @param fromIndex
* @param count
@@ -318,6 +320,7 @@ public interface BlockchainQueryService {
/**
* get contract accounts by ledgerHash and its range;
+ *
* @param ledgerHash
* @param fromIndex
* @param count
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ClientOperator.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ClientOperator.java
index 5e47ef89..2aec03bc 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ClientOperator.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ClientOperator.java
@@ -6,6 +6,7 @@ package com.jd.blockchain.transaction;
* @author huanghaiquan
*
*/
-public interface ClientOperator extends UserOperator, DataAccountOperator, ContractOperator, EventOperator {
+public interface ClientOperator
+ extends SecurityOperator, UserOperator, DataAccountOperator, ContractOperator, EventOperator {
}
\ No newline at end of file
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ConsensusParticipantData.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ConsensusParticipantData.java
index b4e64744..ed0130d1 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ConsensusParticipantData.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ConsensusParticipantData.java
@@ -2,13 +2,14 @@ package com.jd.blockchain.transaction;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.ParticipantNode;
+import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.net.NetworkAddress;
public class ConsensusParticipantData implements ParticipantNode {
private int id;
- private String address;
+ private Bytes address;
private String name;
@@ -48,11 +49,11 @@ public class ConsensusParticipantData implements ParticipantNode {
this.pubKey = pubKey;
}
- public String getAddress() {
+ public Bytes getAddress() {
return address;
}
- public void setAddress(String address) {
+ public void setAddress(Bytes address) {
this.address = address;
}
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/LedgerInitData.java
similarity index 89%
rename from source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LedgerInitSettingData.java
rename to source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LedgerInitData.java
index a6f6045a..6de96680 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/LedgerInitData.java
@@ -1,22 +1,22 @@
package com.jd.blockchain.transaction;
-import com.jd.blockchain.ledger.ParticipantNode;
-import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerInitSetting;
+import com.jd.blockchain.ledger.ParticipantNode;
+import com.jd.blockchain.utils.Bytes;
-public class LedgerInitSettingData implements LedgerInitSetting {
+public class LedgerInitData implements LedgerInitSetting {
private byte[] ledgerSeed;
private ParticipantNode[] consensusParticipants;
private CryptoSetting cryptoSetting;
-
+
private String consensusProvider;
private Bytes consensusSettings;
-
+
private long createdTime;
@Override
@@ -55,11 +55,15 @@ public class LedgerInitSettingData implements LedgerInitSetting {
this.consensusSettings = consensusSettings;
}
+ public void setConsensusSettings(byte[] consensusSettings) {
+ this.consensusSettings = new Bytes(consensusSettings);
+ }
+
@Override
public String getConsensusProvider() {
return consensusProvider;
}
-
+
public void setConsensusProvider(String consensusProvider) {
this.consensusProvider = consensusProvider;
}
@@ -68,7 +72,7 @@ public class LedgerInitSettingData implements LedgerInitSetting {
public long getCreatedTime() {
return createdTime;
}
-
+
public void setCreatedTime(long createdTime) {
this.createdTime = createdTime;
}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PreparedTx.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PreparedTx.java
index b2d0f107..bba464e3 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PreparedTx.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PreparedTx.java
@@ -7,13 +7,8 @@ import java.util.Comparator;
import org.springframework.cglib.proxy.UndeclaredThrowableException;
-import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.crypto.AsymmetricKeypair;
-import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.HashDigest;
-import com.jd.blockchain.crypto.PrivKey;
-import com.jd.blockchain.crypto.SignatureDigest;
-import com.jd.blockchain.crypto.SignatureFunction;
import com.jd.blockchain.ledger.DigitalSignature;
import com.jd.blockchain.ledger.OperationResult;
import com.jd.blockchain.ledger.PreparedTransaction;
@@ -68,11 +63,7 @@ public class PreparedTx implements PreparedTransaction {
@Override
public DigitalSignature sign(AsymmetricKeypair keyPair) {
- SignatureFunction signatureFunction = Crypto.getSignatureFunction(keyPair.getAlgorithm());
- PrivKey privKey = keyPair.getPrivKey();
- byte[] content = BinaryProtocol.encode(getTransactionContent(), TransactionContent.class);
- SignatureDigest signatureDigest = signatureFunction.sign(privKey, content);
- DigitalSignature signature = new DigitalSignatureBlob(keyPair.getPubKey(), signatureDigest);
+ DigitalSignature signature = SignatureUtils.sign(getTransactionContent(), keyPair);
addSignature(signature);
return signature;
}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/RolePrivilegeConfigurer.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/RolePrivilegeConfigurer.java
new file mode 100644
index 00000000..13539536
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/RolePrivilegeConfigurer.java
@@ -0,0 +1,18 @@
+package com.jd.blockchain.transaction;
+
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.TransactionPermission;
+
+public interface RolePrivilegeConfigurer extends RolesConfigure {
+
+ String getRoleName();
+
+ RolePrivilegeConfigurer disable(TransactionPermission... permissions);
+
+ RolePrivilegeConfigurer enable(TransactionPermission... permissions);
+
+ RolePrivilegeConfigurer disable(LedgerPermission... permissions);
+
+ RolePrivilegeConfigurer enable(LedgerPermission... permissions);
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/RolesConfigure.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/RolesConfigure.java
new file mode 100644
index 00000000..4626fa5a
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/RolesConfigure.java
@@ -0,0 +1,7 @@
+package com.jd.blockchain.transaction;
+
+public interface RolesConfigure {
+
+ RolePrivilegeConfigurer configure(String roleName);
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/RolesConfigureOpTemplate.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/RolesConfigureOpTemplate.java
new file mode 100644
index 00000000..5ff5fea0
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/RolesConfigureOpTemplate.java
@@ -0,0 +1,137 @@
+package com.jd.blockchain.transaction;
+
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.jd.blockchain.binaryproto.DataContractRegistry;
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.RolesConfigureOperation;
+import com.jd.blockchain.ledger.SecurityUtils;
+import com.jd.blockchain.ledger.TransactionPermission;
+import com.jd.blockchain.ledger.UserRegisterOperation;
+import com.jd.blockchain.utils.ArrayUtils;
+
+public class RolesConfigureOpTemplate implements RolesConfigurer, RolesConfigureOperation {
+
+ static {
+ DataContractRegistry.register(UserRegisterOperation.class);
+ }
+
+ private Map rolesMap = Collections
+ .synchronizedMap(new LinkedHashMap());
+
+ public RolesConfigureOpTemplate() {
+ }
+
+ boolean isEmpty() {
+ return rolesMap.isEmpty();
+ }
+
+ @Override
+ public RolePrivilegeEntry[] getRoles() {
+ return rolesMap.values().toArray(new RolePrivilegeEntry[rolesMap.size()]);
+ }
+
+ @Override
+ public RolesConfigureOperation getOperation() {
+ return this;
+ }
+
+ @Override
+ public RolePrivilegeConfigurer configure(String roleName) {
+ roleName = SecurityUtils.formatRoleName(roleName);
+
+ RolePrivilegeConfig roleConfig = rolesMap.get(roleName);
+ if (roleConfig == null) {
+ roleConfig = new RolePrivilegeConfig(roleName);
+ rolesMap.put(roleName, roleConfig);
+ }
+ return roleConfig;
+ }
+
+ private class RolePrivilegeConfig implements RolePrivilegeConfigurer, RolePrivilegeEntry {
+
+ private String roleName;
+
+ private Set enableLedgerPermissions = new LinkedHashSet();
+ private Set disableLedgerPermissions = new LinkedHashSet();
+
+ private Set enableTxPermissions = new LinkedHashSet();
+ private Set disableTxPermissions = new LinkedHashSet();
+
+ private RolePrivilegeConfig(String roleName) {
+ this.roleName = roleName;
+ }
+
+ @Override
+ public String getRoleName() {
+ return roleName;
+ }
+
+ @Override
+ public LedgerPermission[] getEnableLedgerPermissions() {
+ return ArrayUtils.toArray(enableLedgerPermissions, LedgerPermission.class);
+ }
+
+ @Override
+ public LedgerPermission[] getDisableLedgerPermissions() {
+ return ArrayUtils.toArray(disableLedgerPermissions, LedgerPermission.class);
+ }
+
+ @Override
+ public TransactionPermission[] getEnableTransactionPermissions() {
+ return ArrayUtils.toArray(enableTxPermissions, TransactionPermission.class);
+ }
+
+ @Override
+ public TransactionPermission[] getDisableTransactionPermissions() {
+ return ArrayUtils.toArray(disableTxPermissions, TransactionPermission.class);
+ }
+
+ @Override
+ public RolePrivilegeConfigurer enable(LedgerPermission... permissions) {
+ List permissionList = ArrayUtils.asList(permissions);
+ enableLedgerPermissions.addAll(permissionList);
+ disableLedgerPermissions.removeAll(permissionList);
+
+ return this;
+ }
+
+ @Override
+ public RolePrivilegeConfigurer disable(LedgerPermission... permissions) {
+ List permissionList = ArrayUtils.asList(permissions);
+ disableLedgerPermissions.addAll(permissionList);
+ enableLedgerPermissions.removeAll(permissionList);
+
+ return this;
+ }
+
+ @Override
+ public RolePrivilegeConfigurer enable(TransactionPermission... permissions) {
+ List permissionList = ArrayUtils.asList(permissions);
+ enableTxPermissions.addAll(permissionList);
+ disableTxPermissions.removeAll(permissionList);
+
+ return this;
+ }
+
+ @Override
+ public RolePrivilegeConfigurer disable(TransactionPermission... permissions) {
+ List permissionList = ArrayUtils.asList(permissions);
+ disableTxPermissions.addAll(permissionList);
+ enableTxPermissions.removeAll(permissionList);
+
+ return this;
+ }
+
+ @Override
+ public RolePrivilegeConfigurer configure(String roleName) {
+ return RolesConfigureOpTemplate.this.configure(roleName);
+ }
+
+ }
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/RolesConfigurer.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/RolesConfigurer.java
new file mode 100644
index 00000000..0621a626
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/RolesConfigurer.java
@@ -0,0 +1,9 @@
+package com.jd.blockchain.transaction;
+
+import com.jd.blockchain.ledger.RolesConfigureOperation;
+
+public interface RolesConfigurer extends RolesConfigure {
+
+ RolesConfigureOperation getOperation();
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/SecurityOperationBuilder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/SecurityOperationBuilder.java
new file mode 100644
index 00000000..f3b6622c
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/SecurityOperationBuilder.java
@@ -0,0 +1,19 @@
+package com.jd.blockchain.transaction;
+
+public interface SecurityOperationBuilder {
+
+ /**
+ * 配置角色;
+ *
+ * @return
+ */
+ RolesConfigurer roles();
+
+ /**
+ * 授权用户;
+ *
+ * @return
+ */
+ UserAuthorizer authorziations();
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/SecurityOperationBuilderImpl.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/SecurityOperationBuilderImpl.java
new file mode 100644
index 00000000..ce271fce
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/SecurityOperationBuilderImpl.java
@@ -0,0 +1,15 @@
+package com.jd.blockchain.transaction;
+
+public class SecurityOperationBuilderImpl implements SecurityOperationBuilder{
+
+ @Override
+ public RolesConfigurer roles() {
+ return new RolesConfigureOpTemplate();
+ }
+
+ @Override
+ public UserAuthorizer authorziations() {
+ return new UserAuthorizeOpTemplate();
+ }
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/SecurityOperator.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/SecurityOperator.java
new file mode 100644
index 00000000..a636c577
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/SecurityOperator.java
@@ -0,0 +1,23 @@
+package com.jd.blockchain.transaction;
+
+/**
+ * 与安全配置相关的操作门面;
+ *
+ *
+ *
+ * 只能通过客户端接口直接操作;不支持通过合约操作;
+ *
+ * @author huanghaiquan
+ *
+ */
+public interface SecurityOperator {
+
+ /**
+ * 注册账户操作;
+ *
+ * @return
+ */
+
+ SecurityOperationBuilder security();
+
+}
\ No newline at end of file
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/SignatureUtils.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/SignatureUtils.java
new file mode 100644
index 00000000..a0c99733
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/SignatureUtils.java
@@ -0,0 +1,28 @@
+package com.jd.blockchain.transaction;
+
+import com.jd.blockchain.crypto.*;
+import com.jd.blockchain.ledger.DigitalSignature;
+import com.jd.blockchain.ledger.TransactionContent;
+
+public class SignatureUtils {
+
+ public static DigitalSignature sign(TransactionContent txContent, AsymmetricKeypair keyPair) {
+ SignatureDigest signatureDigest = sign(txContent, keyPair.getPrivKey());
+ return new DigitalSignatureBlob(keyPair.getPubKey(), signatureDigest);
+ }
+
+ public static SignatureDigest sign(TransactionContent txContent, PrivKey privKey) {
+ return Crypto.getSignatureFunction(privKey.getAlgorithm()).sign(privKey, txContent.getHash().toBytes());
+ }
+
+ public static boolean verifySignature(TransactionContent txContent, SignatureDigest signDigest, PubKey pubKey) {
+ if (!TxBuilder.verifyTxContentHash(txContent, txContent.getHash())) {
+ return false;
+ }
+ return verifyHashSignature(txContent.getHash(), signDigest, pubKey);
+ }
+
+ public static boolean verifyHashSignature(HashDigest hash, SignatureDigest signDigest, PubKey pubKey) {
+ return Crypto.getSignatureFunction(pubKey.getAlgorithm()).verify(signDigest, pubKey, hash.toBytes());
+ }
+}
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 35e09d78..8c582333 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
@@ -55,16 +55,31 @@ public class TxBuilder implements TransactionBuilder {
txContent.addOperations(opFactory.getOperations());
txContent.setTime(time);
- byte[] contentBodyBytes = BinaryProtocol.encode(txContent, TransactionContentBody.class);
- HashDigest contentHash = Crypto.getHashFunction(DEFAULT_HASH_ALGORITHM).hash(contentBodyBytes);
+ HashDigest contentHash = computeTxContentHash(txContent);
txContent.setHash(contentHash);
return txContent;
}
+
+ public static HashDigest computeTxContentHash(TransactionContent txContent) {
+ byte[] contentBodyBytes = BinaryProtocol.encode(txContent, TransactionContentBody.class);
+ HashDigest contentHash = Crypto.getHashFunction(DEFAULT_HASH_ALGORITHM).hash(contentBodyBytes);
+ return contentHash;
+ }
+
+ public static boolean verifyTxContentHash(TransactionContent txContent, HashDigest verifiedHash) {
+ HashDigest hash = computeTxContentHash(txContent);
+ return hash.equals(verifiedHash);
+ }
public Collection getReturnValuehandlers() {
return opFactory.getReturnValuetHandlers();
}
+
+ @Override
+ public SecurityOperationBuilder security() {
+ return opFactory.security();
+ }
@Override
public LedgerInitOperationBuilder ledgers() {
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 c03f1cc7..7413a5ff 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
@@ -84,7 +84,7 @@ public class TxContentBlob implements TransactionContent {
}
@Override
- public long getTime() {
+ public long getTimestamp() {
return time;
}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxRequestBuilder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxRequestBuilder.java
index 7d6701a5..68653c0e 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxRequestBuilder.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxRequestBuilder.java
@@ -7,9 +7,6 @@ import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.crypto.AsymmetricKeypair;
import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.HashDigest;
-import com.jd.blockchain.crypto.PrivKey;
-import com.jd.blockchain.crypto.PubKey;
-import com.jd.blockchain.crypto.SignatureDigest;
import com.jd.blockchain.ledger.DigitalSignature;
import com.jd.blockchain.ledger.NodeRequest;
import com.jd.blockchain.ledger.TransactionContent;
@@ -42,42 +39,56 @@ public class TxRequestBuilder implements TransactionRequestBuilder {
@Override
public DigitalSignature signAsEndpoint(AsymmetricKeypair keyPair) {
- DigitalSignature signature = sign(txContent, keyPair);
+ DigitalSignature signature = SignatureUtils.sign(txContent, keyPair);
addEndpointSignature(signature);
return signature;
}
@Override
public DigitalSignature signAsNode(AsymmetricKeypair keyPair) {
- DigitalSignature signature = sign(txContent, keyPair);
+ DigitalSignature signature = SignatureUtils.sign(txContent, keyPair);
addNodeSignature(signature);
return signature;
}
@Override
- public void addNodeSignature(DigitalSignature signature) {
- nodeSignatures.add(signature);
+ public void addNodeSignature(DigitalSignature... signatures) {
+ if (signatures != null) {
+ for (DigitalSignature s : signatures) {
+ nodeSignatures.add(s);
+ }
+ }
}
@Override
- public void addEndpointSignature(DigitalSignature signature) {
- endpointSignatures.add(signature);
+ public void addEndpointSignature(DigitalSignature... signatures) {
+ if (signatures != null) {
+ for (DigitalSignature s : signatures) {
+ endpointSignatures.add(s);
+ }
+ }
}
- public static DigitalSignature sign(TransactionContent txContent, AsymmetricKeypair keyPair) {
- SignatureDigest signatureDigest = sign(txContent, keyPair.getPrivKey());
- DigitalSignature signature = new DigitalSignatureBlob(keyPair.getPubKey(), signatureDigest);
- return signature;
- }
-
- public static SignatureDigest sign(TransactionContent txContent, PrivKey privKey) {
- return Crypto.getSignatureFunction(privKey.getAlgorithm()).sign(privKey, txContent.getHash().toBytes());
- }
-
- public static boolean verifySignature(TransactionContent txContent, SignatureDigest signDigest, PubKey pubKey) {
- return Crypto.getSignatureFunction(pubKey.getAlgorithm()).verify(signDigest, pubKey,
- txContent.getHash().toBytes());
- }
+// public static DigitalSignature sign(TransactionContent txContent, AsymmetricKeypair keyPair) {
+// SignatureDigest signatureDigest = sign(txContent, keyPair.getPrivKey());
+// DigitalSignature signature = new DigitalSignatureBlob(keyPair.getPubKey(), signatureDigest);
+// return signature;
+// }
+//
+// public static SignatureDigest sign(TransactionContent txContent, PrivKey privKey) {
+// return Crypto.getSignatureFunction(privKey.getAlgorithm()).sign(privKey, txContent.getHash().toBytes());
+// }
+
+// public static boolean verifySignature(TransactionContent txContent, SignatureDigest signDigest, PubKey pubKey) {
+// if (!TxBuilder.verifyTxContentHash(txContent, txContent.getHash())) {
+// return false;
+// }
+// return verifyHashSignature(txContent.getHash(), signDigest, pubKey);
+// }
+//
+// public static boolean verifyHashSignature(HashDigest hash, SignatureDigest signDigest, PubKey pubKey) {
+// return Crypto.getSignatureFunction(pubKey.getAlgorithm()).verify(signDigest, pubKey, hash.toBytes());
+// }
@Override
public TransactionRequest buildRequest() {
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxTemplate.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxTemplate.java
index 9777d238..40d7d3cd 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxTemplate.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxTemplate.java
@@ -35,6 +35,12 @@ public class TxTemplate implements TransactionTemplate {
return new PreparedTx(stateManager, txReqBuilder, txService, txBuilder.getReturnValuehandlers());
}
+ @Override
+ public SecurityOperationBuilder security() {
+ stateManager.operate();
+ return txBuilder.security();
+ }
+
@Override
public UserRegisterOperationBuilder users() {
stateManager.operate();
@@ -80,9 +86,10 @@ public class TxTemplate implements TransactionTemplate {
@Override
public void close() throws IOException {
if (!stateManager.close()) {
- Collection handlers = txBuilder.getReturnValuehandlers();
+ Collection handlers = txBuilder.getReturnValuehandlers();
if (handlers.size() > 0) {
- TransactionCancelledExeption error = new TransactionCancelledExeption("Transaction template has been cancelled!");
+ TransactionCancelledExeption error = new TransactionCancelledExeption(
+ "Transaction template has been cancelled!");
for (OperationResultHandle handle : handlers) {
handle.complete(error);
}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserAuthorize.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserAuthorize.java
new file mode 100644
index 00000000..ecaaa7ef
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserAuthorize.java
@@ -0,0 +1,12 @@
+package com.jd.blockchain.transaction;
+
+import com.jd.blockchain.ledger.BlockchainIdentity;
+import com.jd.blockchain.utils.Bytes;
+
+public interface UserAuthorize {
+
+ UserRolesAuthorizer forUser(BlockchainIdentity... userId);
+
+ UserRolesAuthorizer forUser(Bytes... userAddress);
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserAuthorizeOpTemplate.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserAuthorizeOpTemplate.java
new file mode 100644
index 00000000..a8f44f87
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserAuthorizeOpTemplate.java
@@ -0,0 +1,128 @@
+package com.jd.blockchain.transaction;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import com.jd.blockchain.binaryproto.DataContractRegistry;
+import com.jd.blockchain.ledger.BlockchainIdentity;
+import com.jd.blockchain.ledger.RolesPolicy;
+import com.jd.blockchain.ledger.SecurityUtils;
+import com.jd.blockchain.ledger.UserAuthorizeOperation;
+import com.jd.blockchain.ledger.UserRegisterOperation;
+import com.jd.blockchain.utils.ArrayUtils;
+import com.jd.blockchain.utils.Bytes;
+
+public class UserAuthorizeOpTemplate implements UserAuthorizer, UserAuthorizeOperation {
+
+ static {
+ DataContractRegistry.register(UserRegisterOperation.class);
+ }
+
+ private Set userAuthMap = Collections
+ .synchronizedSet(new LinkedHashSet());
+
+ public UserAuthorizeOpTemplate() {
+ }
+
+ public UserAuthorizeOpTemplate(BlockchainIdentity userID) {
+ }
+
+ @Override
+ public UserRolesAuthorization[] getUserRolesAuthorizations() {
+ return ArrayUtils.toArray(userAuthMap, UserRolesAuthorization.class);
+ }
+
+ @Override
+ public UserAuthorizeOperation getOperation() {
+ return this;
+ }
+
+ @Override
+ public UserRolesAuthorizer forUser(Bytes... userAddresses) {
+ UserRolesAuthorization userRolesAuth = new UserRolesAuthorization(userAddresses);
+ userAuthMap.add(userRolesAuth);
+ return userRolesAuth;
+ }
+
+ @Override
+ public UserRolesAuthorizer forUser(BlockchainIdentity... userIds) {
+ Bytes[] addresses = Arrays.stream(userIds).map(p -> p.getAddress()).toArray(Bytes[]::new);
+ return forUser(addresses);
+ }
+
+ private class UserRolesAuthorization implements UserRolesAuthorizer, UserRolesEntry {
+
+ private Bytes[] userAddress;
+
+ private RolesPolicy policy = RolesPolicy.UNION;
+
+ private Set authRoles = new LinkedHashSet();
+ private Set unauthRoles = new LinkedHashSet();
+
+ private UserRolesAuthorization(Bytes[] userAddress) {
+ this.userAddress = userAddress;
+ }
+
+ @Override
+ public Bytes[] getUserAddresses() {
+ return userAddress;
+ }
+
+ @Override
+ public RolesPolicy getPolicy() {
+ return policy;
+ }
+
+ @Override
+ public String[] getAuthorizedRoles() {
+ return ArrayUtils.toArray(authRoles, String.class);
+ }
+
+ @Override
+ public String[] getUnauthorizedRoles() {
+ return ArrayUtils.toArray(unauthRoles, String.class);
+ }
+
+ @Override
+ public UserRolesAuthorizer setPolicy(RolesPolicy policy) {
+ this.policy = policy;
+ return this;
+ }
+
+ @Override
+ public UserRolesAuthorizer authorize(String... roles) {
+ String roleName;
+ for (String r : roles) {
+ roleName = SecurityUtils.formatRoleName(r);
+ authRoles.add(roleName);
+ unauthRoles.remove(roleName);
+ }
+
+ return this;
+ }
+
+ @Override
+ public UserRolesAuthorizer unauthorize(String... roles) {
+ String roleName;
+ for (String r : roles) {
+ roleName = SecurityUtils.formatRoleName(r);
+ unauthRoles.add(roleName);
+ authRoles.remove(roleName);
+ }
+
+ return this;
+ }
+
+ @Override
+ public UserRolesAuthorizer forUser(BlockchainIdentity... userIds) {
+ return UserAuthorizeOpTemplate.this.forUser(userIds);
+ }
+
+ @Override
+ public UserRolesAuthorizer forUser(Bytes... userAddresses) {
+ return UserAuthorizeOpTemplate.this.forUser(userAddresses);
+ }
+ }
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserAuthorizer.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserAuthorizer.java
new file mode 100644
index 00000000..66f083c7
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserAuthorizer.java
@@ -0,0 +1,9 @@
+package com.jd.blockchain.transaction;
+
+import com.jd.blockchain.ledger.UserAuthorizeOperation;
+
+public interface UserAuthorizer extends UserAuthorize {
+
+ UserAuthorizeOperation getOperation();
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserRolesAuthorizer.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserRolesAuthorizer.java
new file mode 100644
index 00000000..2a58858a
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserRolesAuthorizer.java
@@ -0,0 +1,13 @@
+package com.jd.blockchain.transaction;
+
+import com.jd.blockchain.ledger.RolesPolicy;
+
+public interface UserRolesAuthorizer extends UserAuthorize {
+
+ UserRolesAuthorizer authorize(String... roles);
+
+ UserRolesAuthorizer unauthorize(String... roles);
+
+ UserRolesAuthorizer setPolicy(RolesPolicy rolePolicy);
+
+}
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/AddressEncodingTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/AddressEncodingTest.java
similarity index 96%
rename from source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/AddressEncodingTest.java
rename to source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/AddressEncodingTest.java
index ae8dbef8..aab1dbef 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/AddressEncodingTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/AddressEncodingTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger.data;
+package test.com.jd.blockchain.ledger;
import java.util.Random;
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/BytesEncodingTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesEncodingTest.java
similarity index 95%
rename from source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/BytesEncodingTest.java
rename to source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesEncodingTest.java
index 07bd9c1e..32d48aba 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/BytesEncodingTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesEncodingTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger.data;
+package test.com.jd.blockchain.ledger;
import static org.junit.Assert.*;
@@ -6,6 +6,7 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import org.junit.Test;
+import org.mockito.Mockito;
import com.jd.blockchain.utils.io.BytesEncoding;
import com.jd.blockchain.utils.io.NumberMask;
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/BytesToBytesValueResolverTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesToBytesValueResolverTest.java
similarity index 96%
rename from source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/BytesToBytesValueResolverTest.java
rename to source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesToBytesValueResolverTest.java
index fb470200..3635743c 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/BytesToBytesValueResolverTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesToBytesValueResolverTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger.data;
+package test.com.jd.blockchain.ledger;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.DataType;
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/BytesValueEncodingTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesValueEncodingTest.java
similarity index 98%
rename from source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/BytesValueEncodingTest.java
rename to source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesValueEncodingTest.java
index 73d51d7b..e5b624c9 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/BytesValueEncodingTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesValueEncodingTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger.data;
+package test.com.jd.blockchain.ledger;
import com.jd.blockchain.ledger.*;
import com.jd.blockchain.utils.Bytes;
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/ContractCodeDeployOpTemplateTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ContractCodeDeployOpTemplateTest.java
similarity index 98%
rename from source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/ContractCodeDeployOpTemplateTest.java
rename to source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ContractCodeDeployOpTemplateTest.java
index a54ce94f..5c6b24d2 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/ContractCodeDeployOpTemplateTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ContractCodeDeployOpTemplateTest.java
@@ -6,7 +6,7 @@
* Date: 2018/8/30 上午10:53
* Description:
*/
-package test.com.jd.blockchain.ledger.data;
+package test.com.jd.blockchain.ledger;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/ContractEventSendOpTemplateTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ContractEventSendOpTemplateTest.java
similarity index 98%
rename from source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/ContractEventSendOpTemplateTest.java
rename to source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ContractEventSendOpTemplateTest.java
index bdfaaa80..d010ae6f 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/ContractEventSendOpTemplateTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ContractEventSendOpTemplateTest.java
@@ -6,7 +6,7 @@
* Date: 2018/8/30 上午10:56
* Description:
*/
-package test.com.jd.blockchain.ledger.data;
+package test.com.jd.blockchain.ledger;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/ContractTypeTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ContractTypeTest.java
similarity index 98%
rename from source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/ContractTypeTest.java
rename to source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ContractTypeTest.java
index beceb39c..d6a49c9c 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/ContractTypeTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ContractTypeTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger.data;
+package test.com.jd.blockchain.ledger;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/DataAccountKVSetOpTemplateTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/DataAccountKVSetOpTemplateTest.java
similarity index 98%
rename from source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/DataAccountKVSetOpTemplateTest.java
rename to source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/DataAccountKVSetOpTemplateTest.java
index a87919b4..d8b33048 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/DataAccountKVSetOpTemplateTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/DataAccountKVSetOpTemplateTest.java
@@ -6,7 +6,7 @@
* Date: 2018/8/30 上午10:59
* Description:
*/
-package test.com.jd.blockchain.ledger.data;
+package test.com.jd.blockchain.ledger;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/DataAccountRegisterOpTemplateTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/DataAccountRegisterOpTemplateTest.java
similarity index 98%
rename from source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/DataAccountRegisterOpTemplateTest.java
rename to source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/DataAccountRegisterOpTemplateTest.java
index fcca954f..e13bad09 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/DataAccountRegisterOpTemplateTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/DataAccountRegisterOpTemplateTest.java
@@ -6,7 +6,7 @@
* Date: 2018/8/30 上午11:03
* Description:
*/
-package test.com.jd.blockchain.ledger.data;
+package test.com.jd.blockchain.ledger;
import static org.junit.Assert.assertEquals;
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/DigitalSignatureBlobTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/DigitalSignatureBlobTest.java
similarity index 98%
rename from source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/DigitalSignatureBlobTest.java
rename to source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/DigitalSignatureBlobTest.java
index b3e73a0a..068a4040 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/DigitalSignatureBlobTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/DigitalSignatureBlobTest.java
@@ -6,7 +6,7 @@
* Date: 2018/8/30 下午2:12
* Description:
*/
-package test.com.jd.blockchain.ledger.data;
+package test.com.jd.blockchain.ledger;
import static org.junit.Assert.assertEquals;
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/ED25519SignatureTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ED25519SignatureTest.java
similarity index 97%
rename from source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/ED25519SignatureTest.java
rename to source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ED25519SignatureTest.java
index 11cc02d1..a9a187ab 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/ED25519SignatureTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ED25519SignatureTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger.data;
+package test.com.jd.blockchain.ledger;
import java.util.Random;
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/IntegerToBytesValueResolverTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/IntegerToBytesValueResolverTest.java
similarity index 97%
rename from source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/IntegerToBytesValueResolverTest.java
rename to source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/IntegerToBytesValueResolverTest.java
index 4b65ae16..8e39aa85 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/IntegerToBytesValueResolverTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/IntegerToBytesValueResolverTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger.data;
+package test.com.jd.blockchain.ledger;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.DataType;
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/KVDataTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/KVDataTest.java
similarity index 97%
rename from source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/KVDataTest.java
rename to source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/KVDataTest.java
index 229c308d..d1a6fcb9 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/KVDataTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/KVDataTest.java
@@ -6,7 +6,7 @@
* Date: 2018/8/30 上午11:08
* Description:
*/
-package test.com.jd.blockchain.ledger.data;
+package test.com.jd.blockchain.ledger;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/LedgerInitPropertiesTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/LedgerInitPropertiesTest.java
new file mode 100644
index 00000000..ea17f4d2
--- /dev/null
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/LedgerInitPropertiesTest.java
@@ -0,0 +1,203 @@
+package test.com.jd.blockchain.ledger;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TimeZone;
+
+import org.junit.Test;
+import org.springframework.core.io.ClassPathResource;
+
+import com.jd.blockchain.binaryproto.DataContractRegistry;
+import com.jd.blockchain.crypto.AddressEncoding;
+import com.jd.blockchain.crypto.KeyGenUtils;
+import com.jd.blockchain.crypto.PubKey;
+import com.jd.blockchain.ledger.LedgerInitOperation;
+import com.jd.blockchain.ledger.LedgerInitProperties;
+import com.jd.blockchain.ledger.LedgerInitProperties.ParticipantProperties;
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.RoleInitData;
+import com.jd.blockchain.ledger.RolesPolicy;
+import com.jd.blockchain.ledger.TransactionPermission;
+import com.jd.blockchain.ledger.UserRegisterOperation;
+import com.jd.blockchain.utils.codec.HexUtils;
+
+public class LedgerInitPropertiesTest {
+
+
+ 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" };
+
+
+ private static String expectedCreatedTimeStr = "2019-08-01 14:26:58.069+0800";
+
+ private static String expectedCreatedTimeStr1 = "2019-08-01 13:26:58.069+0700";
+
+ @Test
+ public void testTimeFormat() throws ParseException {
+ SimpleDateFormat timeFormat = new SimpleDateFormat(LedgerInitProperties.CREATED_TIME_FORMAT);
+ timeFormat.setTimeZone(TimeZone.getTimeZone("GMT+08:00"));
+ // 或者设置全局的默认时区;
+ // TimeZone.setDefault(TimeZone.getTimeZone("GMT+08:00"));
+
+ Date time = timeFormat.parse(expectedCreatedTimeStr);
+ String actualTimeStr = timeFormat.format(time);
+ assertEquals(expectedCreatedTimeStr, actualTimeStr);
+
+ Date time1 = timeFormat.parse(expectedCreatedTimeStr1);
+ String actualTimeStr1 = timeFormat.format(time1);
+ assertEquals(expectedCreatedTimeStr, actualTimeStr1);
+ }
+
+ @Test
+ public void testProperties() throws IOException, ParseException {
+ // 加载用于测试的账本初始化配置;
+ ClassPathResource ledgerInitSettingResource = new ClassPathResource("ledger.init");
+ InputStream in = ledgerInitSettingResource.getInputStream();
+ try {
+ LedgerInitProperties initProps = LedgerInitProperties.resolve(in);
+
+ // 验证账本信息;
+ String expectedLedgerSeed = "932dfe23-fe23232f-283f32fa-dd32aa76-8322ca2f-56236cda-7136b322-cb323ffe"
+ .replace("-", "");
+ String actualLedgerSeed = HexUtils.encode(initProps.getLedgerSeed());
+ assertEquals(expectedLedgerSeed, actualLedgerSeed);
+
+ SimpleDateFormat timeFormat = new SimpleDateFormat(LedgerInitProperties.CREATED_TIME_FORMAT);
+ timeFormat.setTimeZone(TimeZone.getTimeZone("GMT+08:00"));
+ long expectedTs = timeFormat.parse(expectedCreatedTimeStr).getTime();
+ assertEquals(expectedTs, initProps.getCreatedTime());
+
+ String createdTimeStr = timeFormat.format(new Date(initProps.getCreatedTime()));
+ assertEquals(expectedCreatedTimeStr, createdTimeStr);
+
+ // 验证角色配置;
+ RoleInitData[] roles = initProps.getRoles();
+ assertEquals(4, roles.length);
+ Map rolesInitDatas = new HashMap();
+ for (RoleInitData r : roles) {
+ rolesInitDatas.put(r.getRoleName(), r);
+ }
+ // 初始化配置的角色最终也是有序排列的,按照角色名称的自然顺序;
+ String[] expectedRolesNames = { "DEFAULT", "ADMIN", "MANAGER", "GUEST" };
+ Arrays.sort(expectedRolesNames);
+ assertEquals(expectedRolesNames[0], roles[0].getRoleName());
+ assertEquals(expectedRolesNames[1], roles[1].getRoleName());
+ assertEquals(expectedRolesNames[2], roles[2].getRoleName());
+ assertEquals(expectedRolesNames[3], roles[3].getRoleName());
+
+ RoleInitData roleDefault = rolesInitDatas.get("DEFAULT");
+ assertArrayEquals(
+ new LedgerPermission[] { LedgerPermission.REGISTER_USER, LedgerPermission.REGISTER_DATA_ACCOUNT },
+ roleDefault.getLedgerPermissions());
+ assertArrayEquals(new TransactionPermission[] { TransactionPermission.DIRECT_OPERATION,
+ TransactionPermission.CONTRACT_OPERATION }, roleDefault.getTransactionPermissions());
+
+ RoleInitData roleAdmin = rolesInitDatas.get("ADMIN");
+ assertArrayEquals(
+ new LedgerPermission[] { LedgerPermission.CONFIGURE_ROLES, LedgerPermission.AUTHORIZE_USER_ROLES,
+ LedgerPermission.SET_CONSENSUS, LedgerPermission.SET_CRYPTO,
+ LedgerPermission.REGISTER_PARTICIPANT, LedgerPermission.REGISTER_USER },
+ roleAdmin.getLedgerPermissions());
+ assertArrayEquals(new TransactionPermission[] { TransactionPermission.DIRECT_OPERATION },
+ roleAdmin.getTransactionPermissions());
+
+ RoleInitData roleManager = rolesInitDatas.get("MANAGER");
+ assertArrayEquals(
+ new LedgerPermission[] { LedgerPermission.CONFIGURE_ROLES, LedgerPermission.AUTHORIZE_USER_ROLES,
+ LedgerPermission.REGISTER_USER, LedgerPermission.REGISTER_DATA_ACCOUNT,
+ LedgerPermission.REGISTER_CONTRACT, LedgerPermission.UPGRADE_CONTRACT,
+ LedgerPermission.SET_USER_ATTRIBUTES, LedgerPermission.WRITE_DATA_ACCOUNT },
+ roleManager.getLedgerPermissions());
+ assertArrayEquals(new TransactionPermission[] { TransactionPermission.DIRECT_OPERATION,
+ TransactionPermission.CONTRACT_OPERATION }, roleManager.getTransactionPermissions());
+
+ RoleInitData roleGuest = rolesInitDatas.get("GUEST");
+ assertTrue(roleGuest.getLedgerPermissions() == null || roleGuest.getLedgerPermissions().length == 0);
+ assertArrayEquals(new TransactionPermission[] { TransactionPermission.CONTRACT_OPERATION },
+ roleGuest.getTransactionPermissions());
+
+ // 验证共识和密码配置;
+ assertEquals("com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider",
+ initProps.getConsensusProvider());
+
+ String[] cryptoProviders = initProps.getCryptoProperties().getProviders();
+ assertEquals(2, cryptoProviders.length);
+ assertEquals("com.jd.blockchain.crypto.service.classic.ClassicCryptoService", cryptoProviders[0]);
+ assertEquals("com.jd.blockchain.crypto.service.sm.SMCryptoService", cryptoProviders[1]);
+
+ // 验证参与方信息;
+ assertEquals(4, initProps.getConsensusParticipantCount());
+
+ ParticipantProperties part0 = initProps.getConsensusParticipant(0);
+ assertEquals("jd.com", part0.getName());
+ PubKey pubKey0 = KeyGenUtils.decodePubKey("3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9");
+ assertEquals(pubKey0, part0.getPubKey());
+ assertEquals("127.0.0.1", part0.getInitializerAddress().getHost());
+ assertEquals(8800, part0.getInitializerAddress().getPort());
+ assertEquals(true, part0.getInitializerAddress().isSecure());
+ assertArrayEquals(new String[] { "ADMIN", "MANAGER" }, part0.getRoles());
+ assertEquals(RolesPolicy.UNION, part0.getRolesPolicy());
+
+ ParticipantProperties part1 = initProps.getConsensusParticipant(1);
+ assertEquals(false, part1.getInitializerAddress().isSecure());
+ PubKey pubKey1 = KeyGenUtils.decodePubKey("3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX");
+ assertEquals(pubKey1, part1.getPubKey());
+ assertArrayEquals(new String[] { "MANAGER" }, part1.getRoles());
+ assertEquals(RolesPolicy.UNION, part1.getRolesPolicy());
+
+ ParticipantProperties part2 = initProps.getConsensusParticipant(2);
+ assertEquals("7VeRAr3dSbi1xatq11ZcF7sEPkaMmtZhV9shonGJWk9T4pLe", part2.getPubKey().toBase58());
+ assertArrayEquals(new String[] { "MANAGER" }, part2.getRoles());
+ assertEquals(RolesPolicy.UNION, part2.getRolesPolicy());
+
+ ParticipantProperties part3 = initProps.getConsensusParticipant(3);
+ PubKey pubKey3 = KeyGenUtils.decodePubKey("3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk");
+ assertEquals(pubKey3, part3.getPubKey());
+ assertArrayEquals(new String[] { "GUEST" }, part3.getRoles());
+ assertEquals(RolesPolicy.INTERSECT, part3.getRolesPolicy());
+
+ } finally {
+ in.close();
+ }
+ }
+
+ @Test
+ public void testPubKeyAddress() {
+ String[] pubKeys = PUB_KEYS;
+ int index = 0;
+ for (String pubKeyStr : pubKeys) {
+ System.out.println("[" + index + "][配置] = " + pubKeyStr);
+ PubKey pubKey = KeyGenUtils.decodePubKey(pubKeyStr);
+ System.out.println("[" + index + "][公钥Base58] = " + pubKey.toBase58());
+ System.out.println("[" + index + "][地址] = " + AddressEncoding.generateAddress(pubKey).toBase58());
+ System.out.println("--------------------------------------------------------------------");
+ index++;
+ }
+ }
+
+}
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/LongToBytesValueResolverTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/LongToBytesValueResolverTest.java
similarity index 97%
rename from source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/LongToBytesValueResolverTest.java
rename to source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/LongToBytesValueResolverTest.java
index 19cbdcbd..899a6415 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/LongToBytesValueResolverTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/LongToBytesValueResolverTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger.data;
+package test.com.jd.blockchain.ledger;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.DataType;
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/NormalContract.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/NormalContract.java
similarity index 96%
rename from source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/NormalContract.java
rename to source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/NormalContract.java
index 87dcd127..12324b42 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/NormalContract.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/NormalContract.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger.data;
+package test.com.jd.blockchain.ledger;
import com.jd.blockchain.contract.Contract;
import com.jd.blockchain.contract.ContractEvent;
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/NormalContractImpl.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/NormalContractImpl.java
similarity index 93%
rename from source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/NormalContractImpl.java
rename to source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/NormalContractImpl.java
index ad71598d..d2ba8714 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/NormalContractImpl.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/NormalContractImpl.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger.data;
+package test.com.jd.blockchain.ledger;
public class NormalContractImpl implements NormalContract{
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/OpBlobTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/OpBlobTest.java
similarity index 95%
rename from source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/OpBlobTest.java
rename to source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/OpBlobTest.java
index 0692a3e4..6ea6da45 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/OpBlobTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/OpBlobTest.java
@@ -1,3 +1,4 @@
+package test.com.jd.blockchain.ledger;
//package test.com.jd.blockchain.ledger.data;
//
//import static org.junit.Assert.*;
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/PrivilegesTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/PrivilegesTest.java
new file mode 100644
index 00000000..10f964c0
--- /dev/null
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/PrivilegesTest.java
@@ -0,0 +1,92 @@
+package test.com.jd.blockchain.ledger;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+import com.jd.blockchain.binaryproto.BinaryProtocol;
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.PrivilegeSet;
+import com.jd.blockchain.ledger.Privileges;
+import com.jd.blockchain.ledger.TransactionPermission;
+
+public class PrivilegesTest {
+
+ @Test
+ public void test() {
+ // 正常情形;
+ {
+ Privileges privileges = Privileges.configure()
+ .enable(LedgerPermission.REGISTER_USER, LedgerPermission.APPROVE_TX)
+ .enable(TransactionPermission.DIRECT_OPERATION);
+
+ byte[] bytes = BinaryProtocol.encode(privileges, PrivilegeSet.class);
+
+ PrivilegeSet decodePrivileges = BinaryProtocol.decode(bytes);
+
+ assertNotNull(decodePrivileges.getLedgerPrivilege());
+ assertNotNull(decodePrivileges.getTransactionPrivilege());
+
+ for (LedgerPermission p : LedgerPermission.values()) {
+ if (p == LedgerPermission.REGISTER_USER || p == LedgerPermission.APPROVE_TX) {
+ assertTrue(decodePrivileges.getLedgerPrivilege().isEnable(p));
+ } else {
+ assertFalse(decodePrivileges.getLedgerPrivilege().isEnable(p));
+ }
+ }
+ for (TransactionPermission p : TransactionPermission.values()) {
+ if (p == TransactionPermission.DIRECT_OPERATION) {
+ assertTrue(decodePrivileges.getTransactionPrivilege().isEnable(p));
+ } else {
+ assertFalse(decodePrivileges.getTransactionPrivilege().isEnable(p));
+ }
+ }
+ }
+ // 只定义账本权限的情形;
+ {
+ Privileges privileges = Privileges.configure().enable(LedgerPermission.REGISTER_USER,
+ LedgerPermission.APPROVE_TX);
+
+ byte[] bytes = BinaryProtocol.encode(privileges, PrivilegeSet.class);
+
+ PrivilegeSet decodePrivileges = BinaryProtocol.decode(bytes);
+
+ assertNotNull(decodePrivileges.getLedgerPrivilege());
+ assertNotNull(decodePrivileges.getTransactionPrivilege());
+
+ for (LedgerPermission p : LedgerPermission.values()) {
+ if (p == LedgerPermission.REGISTER_USER || p == LedgerPermission.APPROVE_TX) {
+ assertTrue(decodePrivileges.getLedgerPrivilege().isEnable(p));
+ } else {
+ assertFalse(decodePrivileges.getLedgerPrivilege().isEnable(p));
+ }
+ }
+ for (TransactionPermission p : TransactionPermission.values()) {
+ assertFalse(decodePrivileges.getTransactionPrivilege().isEnable(p));
+ }
+ }
+ // 只定义交易权限的情形;
+ {
+ Privileges privileges = Privileges.configure().enable(TransactionPermission.CONTRACT_OPERATION);
+
+ byte[] bytes = BinaryProtocol.encode(privileges, PrivilegeSet.class);
+
+ PrivilegeSet decodePrivileges = BinaryProtocol.decode(bytes);
+
+ assertNotNull(decodePrivileges.getLedgerPrivilege());
+ assertNotNull(decodePrivileges.getTransactionPrivilege());
+
+ for (LedgerPermission p : LedgerPermission.values()) {
+ assertFalse(decodePrivileges.getLedgerPrivilege().isEnable(p));
+ }
+ for (TransactionPermission p : TransactionPermission.values()) {
+ if (p == TransactionPermission.CONTRACT_OPERATION) {
+ assertTrue(decodePrivileges.getTransactionPrivilege().isEnable(p));
+ } else {
+ assertFalse(decodePrivileges.getTransactionPrivilege().isEnable(p));
+ }
+ }
+ }
+ }
+
+}
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/SecurityInitDataTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/SecurityInitDataTest.java
new file mode 100644
index 00000000..c573fcf6
--- /dev/null
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/SecurityInitDataTest.java
@@ -0,0 +1,94 @@
+package test.com.jd.blockchain.ledger;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.Test;
+
+import com.jd.blockchain.binaryproto.BinaryProtocol;
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.SecurityInitData;
+import com.jd.blockchain.ledger.SecurityInitSettings;
+import com.jd.blockchain.ledger.TransactionPermission;
+import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils;
+
+public class SecurityInitDataTest {
+
+ @Test
+ public void testEnumsSerialization() {
+ LedgerPermission[] permissions = JSONSerializeUtils.deserializeFromJSON("[\"REGISTER_USER\",\"REGISTER_DATA_ACCOUNT\"]", LedgerPermission[].class);
+ assertNotNull(permissions);
+ assertEquals(2, permissions.length);
+ assertEquals(LedgerPermission.REGISTER_USER, permissions[0]);
+ assertEquals(LedgerPermission.REGISTER_DATA_ACCOUNT, permissions[1]);
+
+ LedgerPermission[] permissions2 = JSONSerializeUtils.deserializeFromJSON("['REGISTER_USER', 'REGISTER_DATA_ACCOUNT']", LedgerPermission[].class);
+ assertNotNull(permissions2);
+ assertEquals(2, permissions2.length);
+ assertEquals(LedgerPermission.REGISTER_USER, permissions2[0]);
+ assertEquals(LedgerPermission.REGISTER_DATA_ACCOUNT, permissions2[1]);
+
+ LedgerPermission[] allLedgerPermissions = LedgerPermission.values();
+ String jsonLedgerPersioms = JSONSerializeUtils.serializeToJSON(allLedgerPermissions);
+
+ TransactionPermission[] allTransactionPermissions = TransactionPermission.values();
+ String jsonTransactionPersioms = JSONSerializeUtils.serializeToJSON(allTransactionPermissions);
+
+ System.out.println("----------- Ledger Permissions JSON ------------");
+ System.out.println(jsonLedgerPersioms);
+ System.out.println("-----------------------");
+ System.out.println("----------- Transaction Permissions JSON ------------");
+ System.out.println(jsonTransactionPersioms);
+ System.out.println("-----------------------");
+ }
+
+ @Test
+ public void testSecurityInitDataSerialization() {
+
+ SecurityInitData securityInitData = new SecurityInitData();
+
+ securityInitData.addRole("DEFAULT",
+ new LedgerPermission[] { LedgerPermission.REGISTER_USER, LedgerPermission.REGISTER_DATA_ACCOUNT },
+ new TransactionPermission[] { TransactionPermission.CONTRACT_OPERATION });
+ securityInitData.addRole("ADMIN",
+ new LedgerPermission[] { LedgerPermission.REGISTER_USER, LedgerPermission.REGISTER_DATA_ACCOUNT },
+ new TransactionPermission[] { TransactionPermission.DIRECT_OPERATION,
+ TransactionPermission.CONTRACT_OPERATION });
+ securityInitData.addRole("R1",
+ new LedgerPermission[] { LedgerPermission.REGISTER_USER, LedgerPermission.REGISTER_DATA_ACCOUNT },
+ null);
+ securityInitData.addRole("R2", null, new TransactionPermission[] { TransactionPermission.DIRECT_OPERATION,
+ TransactionPermission.CONTRACT_OPERATION });
+
+ String json = JSONSerializeUtils.serializeToJSON(securityInitData, true);
+ System.out.println("----------- JSON ------------");
+ System.out.println(json);
+ System.out.println("-----------------------");
+
+ SecurityInitData desSecurityInitData = JSONSerializeUtils.deserializeFromJSON(json, SecurityInitData.class);
+
+ String json2 = JSONSerializeUtils.serializeToJSON(desSecurityInitData, true);
+ System.out.println("----------- JSON2 ------------");
+ System.out.println(json2);
+ System.out.println("-----------------------");
+
+ assertEquals(json, json2);
+
+ byte[] bytes = BinaryProtocol.encode(securityInitData, SecurityInitSettings.class);
+
+ SecurityInitSettings securityInitData2 = BinaryProtocol.decode(bytes);
+
+ byte[] bytes2 = BinaryProtocol.encode(securityInitData2, SecurityInitSettings.class);
+
+ assertArrayEquals(bytes, bytes2);
+
+ assertEquals(4, securityInitData2.getRoles().length);
+ assertEquals(securityInitData.getRoles().length, securityInitData2.getRoles().length);
+ assertEquals(LedgerPermission.REGISTER_USER, securityInitData2.getRoles()[1].getLedgerPermissions()[0]);
+ assertEquals(securityInitData.getRoles()[1].getLedgerPermissions()[0], securityInitData2.getRoles()[1].getLedgerPermissions()[0]);
+ assertEquals(securityInitData.getRoles()[1].getLedgerPermissions()[1], securityInitData2.getRoles()[1].getLedgerPermissions()[1]);
+
+ }
+
+}
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/ShortToBytesValueResolverTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ShortToBytesValueResolverTest.java
similarity index 96%
rename from source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/ShortToBytesValueResolverTest.java
rename to source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ShortToBytesValueResolverTest.java
index 6c4ef0c8..b35cedd7 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/ShortToBytesValueResolverTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/ShortToBytesValueResolverTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger.data;
+package test.com.jd.blockchain.ledger;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.DataType;
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/SizeHeaderMaskTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/SizeHeaderMaskTest.java
similarity index 94%
rename from source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/SizeHeaderMaskTest.java
rename to source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/SizeHeaderMaskTest.java
index c1acfb00..b8e7875c 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/SizeHeaderMaskTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/SizeHeaderMaskTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger.data;
+package test.com.jd.blockchain.ledger;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/StringToBytesValueResolverTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/StringToBytesValueResolverTest.java
similarity index 97%
rename from source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/StringToBytesValueResolverTest.java
rename to source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/StringToBytesValueResolverTest.java
index 6538e88e..17dd0c04 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/StringToBytesValueResolverTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/StringToBytesValueResolverTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger.data;
+package test.com.jd.blockchain.ledger;
import com.alibaba.fastjson.JSON;
import com.jd.blockchain.ledger.BytesValue;
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/TxContentBlobTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/TxContentBlobTest.java
similarity index 97%
rename from source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/TxContentBlobTest.java
rename to source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/TxContentBlobTest.java
index fc4120d3..0404ee38 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/TxContentBlobTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/TxContentBlobTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger.data;
+package test.com.jd.blockchain.ledger;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/TxRequestMessageTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/TxRequestMessageTest.java
similarity index 99%
rename from source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/TxRequestMessageTest.java
rename to source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/TxRequestMessageTest.java
index 6083089f..533eb0b7 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/TxRequestMessageTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/TxRequestMessageTest.java
@@ -6,7 +6,7 @@
* Date: 2018/9/3 下午3:07
* Description:
*/
-package test.com.jd.blockchain.ledger.data;
+package test.com.jd.blockchain.ledger;
import static org.junit.Assert.assertEquals;
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/TxResponseMessageTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/TxResponseMessageTest.java
similarity index 97%
rename from source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/TxResponseMessageTest.java
rename to source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/TxResponseMessageTest.java
index c0a944de..bcd50191 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/TxResponseMessageTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/TxResponseMessageTest.java
@@ -6,7 +6,7 @@
* Date: 2018/9/6 上午11:00
* Description:
*/
-package test.com.jd.blockchain.ledger.data;
+package test.com.jd.blockchain.ledger;
import static org.junit.Assert.assertEquals;
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/UserRegisterOpTemplateTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/UserRegisterOpTemplateTest.java
similarity index 98%
rename from source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/UserRegisterOpTemplateTest.java
rename to source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/UserRegisterOpTemplateTest.java
index 27b455f3..95be8d5c 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/UserRegisterOpTemplateTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/UserRegisterOpTemplateTest.java
@@ -6,7 +6,7 @@
* Date: 2018/8/30 上午11:04
* Description:
*/
-package test.com.jd.blockchain.ledger.data;
+package test.com.jd.blockchain.ledger;
import static org.junit.Assert.assertEquals;
diff --git a/source/ledger/ledger-model/src/test/resources/bftsmart.config b/source/ledger/ledger-model/src/test/resources/bftsmart.config
new file mode 100644
index 00000000..df69caf5
--- /dev/null
+++ b/source/ledger/ledger-model/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/ledger/ledger-model/src/test/resources/keys/parti2.pub b/source/ledger/ledger-model/src/test/resources/keys/parti2.pub
new file mode 100644
index 00000000..dde44b8e
--- /dev/null
+++ b/source/ledger/ledger-model/src/test/resources/keys/parti2.pub
@@ -0,0 +1 @@
+3snPdw7i7PZi6TStiyc6mzjprnNhgs2atSGNS8wPYzhbKaUWGFJt7x
\ No newline at end of file
diff --git a/source/ledger/ledger-model/src/test/resources/ledger.init b/source/ledger/ledger-model/src/test/resources/ledger.init
new file mode 100644
index 00000000..9ff0a35c
--- /dev/null
+++ b/source/ledger/ledger-model/src/test/resources/ledger.init
@@ -0,0 +1,164 @@
+
+#账本的种子;一段16进制字符,最长可以包含64个字符;可以用字符“-”分隔,以便更容易读取;
+ledger.seed=932dfe23-fe23232f-283f32fa-dd32aa76-8322ca2f-56236cda-7136b322-cb323ffe
+
+#账本的描述名称;此属性不参与共识,仅仅在当前参与方的本地节点用于描述用途;
+ledger.name=test
+
+#声明账本的创建时间;格式为 “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=classpath: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=jd.com
+#第0个参与方的公钥文件路径;
+cons_parti.0.pubkey-path=keys/jd-com.pub
+#第0个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数;
+cons_parti.0.pubkey=3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9
+#第0个参与方的角色清单;可选项;
+cons_parti.0.roles=ADMIN, MANAGER
+#第0个参与方的角色权限策略,可选值有:UNION(并集),INTERSECT(交集);可选项;
+cons_parti.0.roles-policy=UNION
+#第0个参与方的共识服务的主机地址;
+cons_parti.0.consensus.host=127.0.0.1
+#第0个参与方的共识服务的端口;
+cons_parti.0.consensus.port=8900
+#第0个参与方的共识服务是否开启安全连接;
+cons_parti.0.consensus.secure=true
+#第0个参与方的账本初始服务的主机;
+cons_parti.0.initializer.host=127.0.0.1
+#第0个参与方的账本初始服务的端口;
+cons_parti.0.initializer.port=8800
+#第0个参与方的账本初始服务是否开启安全连接;
+cons_parti.0.initializer.secure=true
+
+#第1个参与方的名称;
+cons_parti.1.name=at.com
+#第1个参与方的公钥文件路径;
+cons_parti.1.pubkey-path=keys/at-com.pub
+#第1个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数;
+cons_parti.1.pubkey=3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX
+#第1个参与方的角色清单;可选项;
+cons_parti.1.roles=MANAGER
+#第1个参与方的角色权限策略,可选值有:UNION(并集),INTERSECT(交集);可选项;
+cons_parti.1.roles-policy=UNION
+#第1个参与方的共识服务的主机地址;
+cons_parti.1.consensus.host=127.0.0.1
+#第1个参与方的共识服务的端口;
+cons_parti.1.consensus.port=8910
+#第1个参与方的共识服务是否开启安全连接;
+cons_parti.1.consensus.secure=false
+#第1个参与方的账本初始服务的主机;
+cons_parti.1.initializer.host=127.0.0.1
+#第1个参与方的账本初始服务的端口;
+cons_parti.1.initializer.port=8810
+#第1个参与方的账本初始服务是否开启安全连接;
+cons_parti.1.initializer.secure=false
+
+#第2个参与方的名称;
+cons_parti.2.name=bt.com
+#第2个参与方的公钥文件路径;
+cons_parti.2.pubkey-path=classpath:keys/parti2.pub
+#第2个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数;
+cons_parti.2.pubkey=
+#第2个参与方的角色清单;可选项;
+cons_parti.2.roles=MANAGER
+#第2个参与方的角色权限策略,可选值有:UNION(并集),INTERSECT(交集);可选项;
+cons_parti.2.roles-policy=UNION
+#第2个参与方的共识服务的主机地址;
+cons_parti.2.consensus.host=127.0.0.1
+#第2个参与方的共识服务的端口;
+cons_parti.2.consensus.port=8920
+#第2个参与方的共识服务是否开启安全连接;
+cons_parti.2.consensus.secure=false
+#第2个参与方的账本初始服务的主机;
+cons_parti.2.initializer.host=127.0.0.1
+#第2个参与方的账本初始服务的端口;
+cons_parti.2.initializer.port=8820
+#第2个参与方的账本初始服务是否开启安全连接;
+cons_parti.2.initializer.secure=true
+
+#第3个参与方的名称;
+cons_parti.3.name=xt.com
+#第3个参与方的公钥文件路径;
+cons_parti.3.pubkey-path=keys/xt-com.pub
+#第3个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数;
+cons_parti.3.pubkey=3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk
+#第3个参与方的角色清单;可选项;
+cons_parti.3.roles=GUEST
+#第3个参与方的角色权限策略,可选值有:UNION(并集),INTERSECT(交集);可选项;
+cons_parti.3.roles-policy=INTERSECT
+#第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/ledger/ledger-rpc/pom.xml b/source/ledger/ledger-rpc/pom.xml
index 04e46715..765c837c 100644
--- a/source/ledger/ledger-rpc/pom.xml
+++ b/source/ledger/ledger-rpc/pom.xml
@@ -5,7 +5,7 @@
com.jd.blockchain
ledger
- 1.0.0.RELEASE
+ 1.1.0-SNAPSHOT
ledger-rpc
diff --git a/source/ledger/pom.xml b/source/ledger/pom.xml
index ec149ed1..4544f273 100644
--- a/source/ledger/pom.xml
+++ b/source/ledger/pom.xml
@@ -5,7 +5,7 @@
com.jd.blockchain
jdchain-root
- 1.0.0.RELEASE
+ 1.1.0-SNAPSHOT
ledger
pom
diff --git a/source/manager/pom.xml b/source/manager/pom.xml
new file mode 100644
index 00000000..9972ceaf
--- /dev/null
+++ b/source/manager/pom.xml
@@ -0,0 +1,18 @@
+
+ 4.0.0
+
+
+ com.jd.blockchain
+ jdchain-root
+ 1.1.0-SNAPSHOT
+
+ manager
+ pom
+
\ No newline at end of file
diff --git a/source/manager/ump-booter/pom.xml b/source/manager/ump-booter/pom.xml
new file mode 100644
index 00000000..392cb3b9
--- /dev/null
+++ b/source/manager/ump-booter/pom.xml
@@ -0,0 +1,132 @@
+
+
+
+
+ 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
+
+
+
+
+
+ com.jd.blockchain
+ ump-web
+ ${project.version}
+
+
+
+ com.jd.blockchain
+ ump-service
+ ${project.version}
+
+
+
+ com.jd.blockchain
+ ump-model
+ ${project.version}
+
+
+
+ com.jd.blockchain
+ ump-explorer
+
+
+
+ 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
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+
+
+ make-assembly
+ package
+
+ single
+
+
+ jump
+
+ src/main/resources/assembly.xml
+
+
+
+
+
+
+
+
+
+ ${project.basedir}/libs
+ BOOT-INF/lib/
+
+ *.jar
+
+
+
+ ${project.basedir}/src/main/resources
+ BOOT-INF/classes/
+
+ log4j2-jump.xml
+ *.txt
+ *.properties
+
+
+
+
+
+
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..4bf8d7ae
--- /dev/null
+++ b/source/manager/ump-booter/src/main/java/com/jd/blockchain/ump/UmpBooter.java
@@ -0,0 +1,128 @@
+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) {
+ startServer(server(args));
+ System.out.println("Unified Management Platform Server Start SUCCESS !!!");
+ }
+
+ private static void startServer(Server server) {
+
+ 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..b01c60cc
--- /dev/null
+++ b/source/manager/ump-service/pom.xml
@@ -0,0 +1,119 @@
+
+
+
+
+ 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
+
+
+
+ com.google.guava
+ guava
+
+
+
+ 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