diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 18634199..00000000 --- a/.travis.yml +++ /dev/null @@ -1,11 +0,0 @@ -language: java -jdk: - - openjdk8 - -before_install: - - cd ./tools - - mvn install:install-file -Dfile=core-0.1.4.jar -DgroupId=com.yahoo.ycsb -DartifactId=core -Dversion=0.1.4 -Dpackaging=jar -DgeneratePom=true -DcreateChecksum=true - - cd ../source - -script: - - mvn clean package \ No newline at end of file diff --git a/README.md b/README.md index 42b86d61..6b98db84 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,6 @@ [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) -[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.jd.blockchain/sdk-pack/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.jd.blockchain/sdk-pack/) -[![Build Status](https://travis-ci.com/blockchain-jd-com/jdchain.svg?branch=master)](https://travis-ci.org/blockchain-jd-com/jdchain) ------------------------------------------------------------------------ diff --git a/source/base/pom.xml b/source/base/pom.xml index 367d7c8a..0e0b7299 100644 --- a/source/base/pom.xml +++ b/source/base/pom.xml @@ -11,9 +11,8 @@ - org.slf4j - slf4j-api + org.springframework.boot + spring-boot-starter-log4j2 - \ No newline at end of file diff --git a/source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java b/source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java index e2f8d65b..e3e2506c 100644 --- a/source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java +++ b/source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java @@ -7,12 +7,14 @@ package com.jd.blockchain.consts; * */ public interface DataCodes { - - public static final int BYTES_VALUE = 0x80; - public static final int BYTES_VALUE_LIST = 0x81; + public static final int MERKLE_SNAPSHOT = 0x070; + + public static final int BYTES_VALUE = 0x080; + + public static final int BYTES_VALUE_LIST = 0x081; - public static final int BLOCK_CHAIN_IDENTITY = 0x90; + public static final int BLOCK_CHAIN_IDENTITY = 0x090; public static final int BLOCK = 0x100; @@ -22,6 +24,8 @@ public interface DataCodes { public static final int DATA_SNAPSHOT = 0x130; + public static final int LEDGER_ADMIN_INFO = 0x131; + public static final int TX = 0x200; public static final int TX_LEDGER = 0x201; @@ -49,15 +53,43 @@ public interface DataCodes { public static final int TX_OP_CONTRACT_EVENT_SEND = 0x340; - public static final int TX_RESPONSE = 0x350; + public static final int TX_OP_PARTICIPANT_REG = 0x350; + public static final int TX_OP_PARTICIPANT_STATE_UPDATE = 0x351; + + public static final int TX_RESPONSE = 0x360; + + public static final int TX_OP_RESULT = 0x370; + + public static final int TX_OP_ROLE_CONFIGURE = 0x371; + + public static final int TX_OP_ROLE_CONFIGURE_ENTRY = 0x372; + + public static final int TX_OP_USER_ROLES_AUTHORIZE = 0x373; + + public static final int TX_OP_USER_ROLE_AUTHORIZE_ENTRY = 0x374; + + // enum types of permissions; + public static final int ENUM_TX_PERMISSION = 0x401; + public static final int ENUM_LEDGER_PERMISSION = 0x402; + public static final int ENUM_MULTI_ROLES_POLICY = 0x403; - public static final int TX_OP_RESULT = 0x360; + public static final int PRIVILEGE_SET = 0x410; + public static final int ROLE_SET = 0x411; + + public static final int SECURITY_INIT_SETTING = 0x420; + + public static final int SECURITY_ROLE_INIT_SETTING = 0x421; + + public static final int SECURITY_USER_AUTH_INIT_SETTING = 0x422; + + // contract types of metadata; public static final int METADATA = 0x600; + public static final int METADATA_V2 = 0x601; public static final int METADATA_INIT_SETTING = 0x610; - public static final int METADATA_INIT_PERMISSION = 0x611; + public static final int METADATA_INIT_PROPOSAL = 0x611; public static final int METADATA_INIT_DECISION = 0x612; @@ -65,17 +97,27 @@ public interface DataCodes { public static final int METADATA_CONSENSUS_PARTICIPANT = 0x621; +// public static final int METADATA_CONSENSUS_NODE = 0x630; +// +// public static final int METADATA_CONSENSUS_SETTING = 0x631; +// +// public static final int METADATA_PARTICIPANT_INFO = 0x640; +// +// public static final int METADATA_CRYPTO_SETTING = 0x642; + // public static final int METADATA_CONSENSUS_NODE = 0x630; public static final int METADATA_CONSENSUS_SETTING = 0x631; - // public static final int METADATA_PARTICIPANT_INFO = 0x640; + public static final int METADATA_PARTICIPANT_INFO = 0x640; + + public static final int METADATA_PARTICIPANT_STATE_INFO = 0x641; public static final int METADATA_CRYPTO_SETTING = 0x642; - + public static final int METADATA_CRYPTO_SETTING_PROVIDER = 0x643; - // public static final int ACCOUNT = 0x700; +// public static final int ACCOUNT = 0x700; public static final int ACCOUNT_HEADER = 0x710; @@ -83,11 +125,10 @@ public interface DataCodes { public static final int DATA = 0x900; - //contract related; + // contract related; public static final int CONTRACT = 0xA00; - - //...0xA19 + // ...0xA19 public static final int HASH = 0xB00; public static final int HASH_OBJECT = 0xB10; @@ -100,6 +141,8 @@ public interface DataCodes { public static final int ENUM_TYPE_BYTES_VALUE_TYPE = 0xB23; + public static final int ENUM_TYPE_PARTICIPANT_NODE_STATE = 0xB24; + public static final int DIGITALSIGNATURE = 0xB30; public static final int DIGITALSIGNATURE_BODY = 0xB31; diff --git a/source/base/src/main/java/com/jd/blockchain/consts/Global.java b/source/base/src/main/java/com/jd/blockchain/consts/Global.java new file mode 100644 index 00000000..b508e833 --- /dev/null +++ b/source/base/src/main/java/com/jd/blockchain/consts/Global.java @@ -0,0 +1,19 @@ +package com.jd.blockchain.consts; + +import java.util.TimeZone; + +public class Global { + + public static final String DEFAULT_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss.SSSZ"; + + public static final String DEFAULT_TIME_ZONE = "GMT+08:00"; + + static { + initialize(); + } + + public static void initialize() { + TimeZone.setDefault(TimeZone.getTimeZone(DEFAULT_TIME_ZONE)); + } + +} diff --git a/source/base/src/main/resources/log4j2.xml b/source/base/src/main/resources/log4j2.xml deleted file mode 100644 index 26f090d7..00000000 --- a/source/base/src/main/resources/log4j2.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/source/binary-proto/pom.xml b/source/binary-proto/pom.xml index b0c94608..ace2ff38 100644 --- a/source/binary-proto/pom.xml +++ b/source/binary-proto/pom.xml @@ -15,9 +15,16 @@ utils-common ${project.version} + + + org.springframework.boot + spring-boot-starter-log4j2 + + junit junit + test \ No newline at end of file diff --git a/source/binary-proto/src/main/java/com/jd/blockchain/binaryproto/BinaryProtocol.java b/source/binary-proto/src/main/java/com/jd/blockchain/binaryproto/BinaryProtocol.java index ddf8e012..c06c6039 100644 --- a/source/binary-proto/src/main/java/com/jd/blockchain/binaryproto/BinaryProtocol.java +++ b/source/binary-proto/src/main/java/com/jd/blockchain/binaryproto/BinaryProtocol.java @@ -42,6 +42,10 @@ public class BinaryProtocol { long version = HeaderEncoder.resolveVersion(bytes); DataContractEncoder encoder = DataContractContext.ENCODER_LOOKUP.lookup(code, version); + if (encoder == null) { + throw new DataContractException( + String.format("No data contract was registered with code[%s] and version[%s]!", code, version)); + } return encoder.decode(bytes.getInputStream()); } diff --git a/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartConsensusSettingsBuilder.java b/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartConsensusSettingsBuilder.java index e72f866a..9d6637db 100644 --- a/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartConsensusSettingsBuilder.java +++ b/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/BftsmartConsensusSettingsBuilder.java @@ -2,11 +2,18 @@ package com.jd.blockchain.consensus.bftsmart; import java.io.IOException; import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; import java.util.Properties; +import com.jd.blockchain.consensus.ConsensusProviders; +import com.jd.blockchain.consensus.NodeSettings; +import com.jd.blockchain.ledger.ParticipantInfo; import com.jd.blockchain.ledger.ParticipantNode; import com.jd.blockchain.tools.keygen.KeyGenCommand; +import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.PropertiesUtils; +import com.jd.blockchain.utils.Property; import com.jd.blockchain.utils.codec.Base58Utils; import com.jd.blockchain.utils.io.BytesUtils; import com.jd.blockchain.utils.net.NetworkAddress; @@ -64,6 +71,8 @@ public class BftsmartConsensusSettingsBuilder implements ConsensusSettingsBuilde */ public static final String CONSENSUS_SECURE_PATTERN = "system.server.%s.network.secure"; + public static final String BFTSMART_PROVIDER = "com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider"; + private static Properties CONFIG_TEMPLATE; @@ -164,6 +173,30 @@ public class BftsmartConsensusSettingsBuilder implements ConsensusSettingsBuilde return config; } + @Override + public Bytes updateSettings(Bytes oldConsensusSettings, ParticipantInfo participantInfo) { + + //update consensus setting through node and system config two aspects + BftsmartConsensusSettings consensusSettings = (BftsmartConsensusSettings) ConsensusProviders.getProvider(BFTSMART_PROVIDER).getSettingsFactory().getConsensusSettingsEncoder().decode(oldConsensusSettings.toBytes()); + + Property[] systemConfigs = systemConfigs(consensusSettings.getSystemConfigs()); + + BftsmartNodeSettings[] nodeSettings = nodeSettings(consensusSettings.getNodes(), participantInfo); + + BftsmartConsensusConfig bftsmartConsensusConfig = new BftsmartConsensusConfig(nodeSettings, systemConfigs); + +// for(int i = 0 ;i < bftsmartConsensusConfig.getNodes().length; i++) { +// System.out.printf("id = %d, host = %s, port = %d\r\n", bftsmartConsensusConfig.getNodes()[i].getId(), bftsmartConsensusConfig.getNodes()[i].getNetworkAddress().getHost(), bftsmartConsensusConfig.getNodes()[i].getNetworkAddress().getPort()); +// } +// +// for(int i = 0 ;i < bftsmartConsensusConfig.getSystemConfigs().length; i++) { +// System.out.printf("property name = %s, property value = %s\r\n",bftsmartConsensusConfig.getSystemConfigs()[i].getName(), bftsmartConsensusConfig.getSystemConfigs()[i].getValue()); +// } + + return new Bytes(ConsensusProviders.getProvider(BFTSMART_PROVIDER).getSettingsFactory().getConsensusSettingsEncoder().encode(bftsmartConsensusConfig)); + + } + private static String keyOfNode(String pattern, int id) { return String.format(pattern, id); } @@ -224,4 +257,52 @@ public class BftsmartConsensusSettingsBuilder implements ConsensusSettingsBuilde PropertiesUtils.setValues(props, bftsmartSettings.getSystemConfigs()); } + /** + * + * update system.servers.num property + * + */ + private Property[] systemConfigs(Property[] systemConfigs) { + Map propertyMap = convert2Map(systemConfigs); + int serverNum = Integer.parseInt(propertyMap.get("system.servers.num").getValue()); + propertyMap.put("system.servers.num", new Property("system.servers.num", String.valueOf(serverNum + 1))); + return convert2Array(propertyMap); + + } + + private Map convert2Map(Property[] properties) { + Map propertyMap = new HashMap<>(); + for (Property property : properties) { + propertyMap.put(property.getName(), property); + } + return propertyMap; + } + + private Property[] convert2Array(Map map) { + Property[] properties = new Property[map.size()]; + int index = 0; + for (Map.Entry entry : map.entrySet()) { + properties[index++] = entry.getValue(); + } + return properties; + } + + /** + * + * update node setting + * + */ + private BftsmartNodeSettings[] nodeSettings(NodeSettings[] nodeSettings, ParticipantInfo participantInfo) { + + BftsmartNodeConfig bftsmartNodeConfig = new BftsmartNodeConfig(participantInfo.getPubKey(), nodeSettings.length, participantInfo.getNetworkAddress()); + + BftsmartNodeSettings[] bftsmartNodeSettings = new BftsmartNodeSettings[nodeSettings.length + 1]; + for (int i = 0; i < nodeSettings.length; i++) { + bftsmartNodeSettings[i] = (BftsmartNodeSettings)nodeSettings[i]; + } + bftsmartNodeSettings[nodeSettings.length] = bftsmartNodeConfig; + return bftsmartNodeSettings; + } + + } diff --git a/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServer.java b/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServer.java index e1773cc0..48c85f79 100644 --- a/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServer.java +++ b/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServer.java @@ -51,11 +51,13 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer private BftsmartConsensusManageService manageService; + private volatile BftsmartTopology topology; private volatile BftsmartConsensusSettings setting; private TOMConfiguration tomConfig; + private TOMConfiguration outerTomConfig; private HostsConfig hostsConfig; diff --git a/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/ConsensusSettingsBuilder.java b/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/ConsensusSettingsBuilder.java index c4f46776..4a58f024 100644 --- a/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/ConsensusSettingsBuilder.java +++ b/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/ConsensusSettingsBuilder.java @@ -1,6 +1,8 @@ package com.jd.blockchain.consensus; +import com.jd.blockchain.ledger.ParticipantInfo; import com.jd.blockchain.ledger.ParticipantNode; +import com.jd.blockchain.utils.Bytes; import java.util.Properties; @@ -16,6 +18,8 @@ public interface ConsensusSettingsBuilder { * @return */ ConsensusSettings createSettings(Properties props, ParticipantNode[] participantNodes); + + Bytes updateSettings(Bytes oldConsensusSettings, ParticipantInfo participantInfo); Properties createPropertiesTemplate(); diff --git a/source/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/MsgQueueConsensusSettingsBuilder.java b/source/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/MsgQueueConsensusSettingsBuilder.java index 85b1fbc3..448955c8 100644 --- a/source/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/MsgQueueConsensusSettingsBuilder.java +++ b/source/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/MsgQueueConsensusSettingsBuilder.java @@ -8,6 +8,7 @@ */ package com.jd.blockchain.consensus.mq; +import com.jd.blockchain.consensus.ConsensusProviders; import com.jd.blockchain.consensus.ConsensusSettings; import com.jd.blockchain.consensus.ConsensusSettingsBuilder; import com.jd.blockchain.consensus.NodeSettings; @@ -20,12 +21,14 @@ import com.jd.blockchain.consensus.mq.settings.MsgQueueConsensusSettings; import com.jd.blockchain.consensus.mq.settings.MsgQueueNetworkSettings; import com.jd.blockchain.consensus.mq.settings.MsgQueueNodeSettings; import com.jd.blockchain.crypto.AddressEncoding; +import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.ledger.ParticipantInfo; import com.jd.blockchain.ledger.ParticipantNode; -import com.jd.blockchain.tools.keygen.KeyGenCommand; import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.PropertiesUtils; import com.jd.blockchain.utils.codec.Base58Utils; +import com.jd.blockchain.utils.io.BytesEncoder; import com.jd.blockchain.utils.io.BytesUtils; import com.jd.blockchain.utils.io.FileUtils; import com.jd.blockchain.utils.net.NetworkAddress; @@ -82,6 +85,8 @@ public class MsgQueueConsensusSettingsBuilder implements ConsensusSettingsBuilde public static final String MSG_QUEUE_BLOCK_MAXDELAY = "system.msg.queue.block.maxdelay"; + public static final String MSG_QUEUE_PROVIDER = "com.jd.blockchain.consensus.mq.MsgQueueConsensusProvider"; + private static Properties CONFIG_TEMPLATE; static { @@ -129,7 +134,7 @@ public class MsgQueueConsensusSettingsBuilder implements ConsensusSettingsBuilde String keyOfPubkey = nodeKey(PUBKEY_PATTERN, id); String base58PubKey = PropertiesUtils.getRequiredProperty(resolvingProps, keyOfPubkey); - PubKey pubKey = KeyGenCommand.decodePubKey(base58PubKey); + PubKey pubKey = KeyGenUtils.decodePubKey(base58PubKey); // PubKey pubKey = new PubKey(Base58Utils.decode(base58PubKey)); resolvingProps.remove(keyOfPubkey); @@ -145,6 +150,48 @@ public class MsgQueueConsensusSettingsBuilder implements ConsensusSettingsBuilde return consensusConfig; } + private MsgQueueNodeSettings[] nodeSettings(NodeSettings[] nodeSettings, ParticipantInfo participantInfo) { + + MsgQueueNodeSettings msgQueueNodeSettings = new MsgQueueNodeConfig(); + ((MsgQueueNodeConfig) msgQueueNodeSettings).setAddress(AddressEncoding.generateAddress(participantInfo.getPubKey()).toBase58()); + ((MsgQueueNodeConfig) msgQueueNodeSettings).setPubKey(participantInfo.getPubKey()); + + MsgQueueNodeSettings[] msgQueuetNodeSettings = new MsgQueueNodeSettings[nodeSettings.length + 1]; + for (int i = 0; i < nodeSettings.length; i++) { + msgQueuetNodeSettings[i] = (MsgQueueNodeSettings)nodeSettings[i]; + } + msgQueuetNodeSettings[nodeSettings.length] = msgQueueNodeSettings; + + return msgQueuetNodeSettings; + } + + @Override + public Bytes updateSettings(Bytes oldConsensusSettings, ParticipantInfo participantInfo) { + + BytesEncoder consensusEncoder = ConsensusProviders.getProvider(MSG_QUEUE_PROVIDER).getSettingsFactory().getConsensusSettingsEncoder(); + + MsgQueueConsensusSettings consensusSettings = (MsgQueueConsensusSettings) consensusEncoder.decode(oldConsensusSettings.toBytes()); + + MsgQueueNodeSettings[] nodeSettings = nodeSettings(consensusSettings.getNodes(), participantInfo); + + MsgQueueConsensusConfig msgQueueConsensusConfig = new MsgQueueConsensusConfig(); + for (int i = 0; i < nodeSettings.length; i++) { + msgQueueConsensusConfig.addNodeSettings(nodeSettings[i]); + } + + msgQueueConsensusConfig.setBlockSettings(consensusSettings.getBlockSettings()); + + msgQueueConsensusConfig.setNetworkSettings(consensusSettings.getNetworkSettings()); + + +// for(int i = 0 ;i < msgQueueConsensusConfig.getNodes().length; i++) { +// System.out.printf("node addr = %s\r\n", msgQueueConsensusConfig.getNodes()[i].getAddress()); +// } + + return new Bytes(consensusEncoder.encode(msgQueueConsensusConfig)); + + } + @Override public Properties createPropertiesTemplate() { return PropertiesUtils.cloneFrom(CONFIG_TEMPLATE); diff --git a/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/InstantiatedContractCode.java b/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/InstantiatedContractCode.java new file mode 100644 index 00000000..94adc3a7 --- /dev/null +++ b/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/InstantiatedContractCode.java @@ -0,0 +1,25 @@ +package com.jd.blockchain.contract.jvm; + +import com.jd.blockchain.contract.ContractType; +import com.jd.blockchain.utils.Bytes; + +public class InstantiatedContractCode extends AbstractContractCode { + + private T instance; + + public InstantiatedContractCode(Bytes address, long version, Class delaredInterface, T instance) { + super(address, version, resolveContractDefinition(delaredInterface, instance.getClass())); + this.instance = instance; + } + + private static ContractDefinition resolveContractDefinition(Class declaredIntf, Class implementedClass) { + ContractType contractType = ContractType.resolve(declaredIntf); + return new ContractDefinition(contractType, implementedClass); + } + + @Override + protected T getContractInstance() { + return instance; + } + + } \ No newline at end of file diff --git a/source/contract/contract-maven-plugin/ReadME.MD b/source/contract/contract-maven-plugin/ReadME.MD new file mode 100644 index 00000000..1cc457b6 --- /dev/null +++ b/source/contract/contract-maven-plugin/ReadME.MD @@ -0,0 +1,274 @@ +# 合约编译插件使用教程 + +### 1、maven引入 + +在pom.xml文件中引入合约编译插件: +```xml + + com.jd.blockchain + contract-maven-plugin + 1.0.0.RELEASE + + + make-contract + package + + compile + + + + + + + com.jd.chain.contracts.ContractTestInfImpl + + + contract + + + +``` + +需要说明的几点如下: + + 1)version:请根据实际JDChain发布版本确认,不同版本会有区别; + + 2)executions->execution->id:该值请随意指定; + + 3)executions->execution->phase:建议使用package及其后续阶段(若不了解phase含义,请自行查阅相关信息); + + 4)executions->execution->goals->goal:必须使用compile; + + 5)mainClass:必填,该类为需要发布的合约执行类(注意此处是类,不是接口),必须正确配置; + + 6)finalName:必填,最终在编译正常的情况下,会产生{finalName}-JDChain-Contract.jar文件,只有该文件是可以发布到JDChain的合约包; + + +### 2、执行命令 +使用mvn执行命令,下面两种方式均可: + +方式一:只执行contract插件命令 +```shell + mvn clean compile contract:compile +``` + +方式二:直接执行打包命令: +```shell +mvn clean package +``` + + +### 3、合约编写要求 +合约的执行结果会对整条链产生比较深刻的影响,为了使用户能够更好、更合理的使用合约,目前JDChain约定合约编写规则包括以下几点: + +(违反其中任何一点都可能导致合约编译失败,但即使合约编译通过也不能保证合约可百分百运行正常) + + + 1)合约工程必须引入com.jd.blockchain:sdk-pack:该包中有合约正常编写需要使用的基本类; + + 2)com.jd.blockchain:sdk-pack的scope必须定义为provided; + + 3)合约发布必须通过合约编译插件进行打包:合约编译插件不但会对Jar包进行校验,同时也会加入JDChain独有的特征,只有具有该特征的Jar才能正常发布; + + 4)合约中严禁使用随机数、IO、NIO等操作; + + 5)合约打包时,请使用provided排除常用的工具包,例如FastJson、apache下的一些工具包等; + + 6)合约必须有一个接口和该接口的实现类,详细要求如下: + - a. 接口必须有@Contract注解; + - b. 接口的可调用方法上必须有@ContractEvent注解,且每个注解中的name属性不能重复; + - c. 合约方法支持入参和返回值,其主要包括所有基本类型; + + + +### 4、合约案例 + +#### 4.1、代码实例 +以下是一个可创建银行账户,指定具体金额,并可以转账的合约代码(逻辑较简单,仅供参考): + +合约接口代码如下: +```java +package com.jd.chain.contract; + + +@Contract +public interface TransferContract { + + @ContractEvent(name = "create") + String create(String address, String account, long money); + + @ContractEvent(name = "transfer") + String transfer(String address, String from, String to, long money); + + @ContractEvent(name = "read") + long read(String address, String account); + + @ContractEvent(name = "readAll") + String readAll(String address, String account); +} + +``` + +合约实现类代码如下: +```java +package com.jd.chain.contract; + +import com.alibaba.fastjson.JSON; +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.ledger.KVDataEntry; +import com.jd.blockchain.ledger.KVDataVO; +import com.jd.blockchain.ledger.KVInfoVO; + +public class TransferContractImpl implements EventProcessingAware, TransferContract { + + private ContractEventContext eventContext; + + private HashDigest ledgerHash; + + @Override + public String create(String address, String account, long money) { + KVDataEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, account); + // 肯定有返回值,但若不存在则返回version=-1 + if (kvDataEntries != null && kvDataEntries.length > 0) { + long currVersion = kvDataEntries[0].getVersion(); + if (currVersion > -1) { + throw new IllegalStateException(String.format("%s -> %s already have created !!!", address, account)); + } + eventContext.getLedger().dataAccount(address).setInt64(account, money, -1L); + } else { + throw new IllegalStateException(String.format("Ledger[%s] inner Error !!!", ledgerHash.toBase58())); + } + return String.format("DataAccountAddress[%s] -> Create(By Contract Operation) Account = %s and Money = %s Success!!! \r\n", + address, account, money); + } + + @Override + public String transfer(String address, String from, String to, long money) { + // 首先查询余额 + KVDataEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, from, to); + if (kvDataEntries == null || kvDataEntries.length != 2) { + throw new IllegalStateException(String.format("%s -> %s - %s may be not created !!!", address, from, to)); + } else { + // 判断from账号中钱数量是否足够 + long fromMoney = 0L, toMoney = 0L, fromVersion = 0L, toVersion = 0L; + for (KVDataEntry kvDataEntry : kvDataEntries) { + if (kvDataEntry.getKey().equals(from)) { + fromMoney = (long) kvDataEntry.getValue(); + fromVersion = kvDataEntry.getVersion(); + } else { + toMoney = (long) kvDataEntry.getValue(); + toVersion = kvDataEntry.getVersion(); + } + } + if (fromMoney < money) { + throw new IllegalStateException(String.format("%s -> %s not have enough money !!!", address, from)); + } + long fromNewMoney = fromMoney - money; + long toNewMoney = toMoney + money; + // 重新设置 + eventContext.getLedger().dataAccount(address).setInt64(from, fromNewMoney, fromVersion); + eventContext.getLedger().dataAccount(address).setInt64(to, toNewMoney, toVersion); + } + + return String.format("DataAccountAddress[%s] transfer from [%s] to [%s] and [money = %s] Success !!!", address, from, to, money); + } + + @Override + public long read(String address, String account) { + KVDataEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, account); + if (kvDataEntries == null || kvDataEntries.length == 0) { + return -1; + } + return (long)kvDataEntries[0].getValue(); + } + + @Override + public String readAll(String address, String account) { + KVDataEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, account); + // 获取最新的版本号 + if (kvDataEntries == null || kvDataEntries.length == 0) { + return ""; + } + long newestVersion = kvDataEntries[0].getVersion(); + if (newestVersion == -1) { + return ""; + } + KVDataVO[] kvDataVOS = new KVDataVO[1]; + long[] versions = new long[(int)newestVersion + 1]; + for (int i = 0; i < versions.length; i++) { + versions[i] = i; + } + KVDataVO kvDataVO = new KVDataVO(account, versions); + + kvDataVOS[0] = kvDataVO; + + KVInfoVO kvInfoVO = new KVInfoVO(kvDataVOS); + + KVDataEntry[] allEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, kvInfoVO); + + return JSON.toJSONString(allEntries); + } + + @Override + public void beforeEvent(ContractEventContext eventContext) { + this.eventContext = eventContext; + this.ledgerHash = eventContext.getCurrentLedgerHash(); + } + + @Override + public void postEvent(ContractEventContext eventContext, Exception error) { + + } +} +``` + + +#### 4.2、pom.xml文件实例 + +```xml + + + + + com.jd.chain + 1.0.0.RELEASE + 4.0.0 + + contract-samples + + contract-samples + + + + com.jd.blockchain + sdk-pack + 1.0.0.RELEASE + provided + + + + com.alibaba + fastjson + 1.2.32 + provided + + + + + + + com.jd.blockchain + contract-maven-plugin + 1.0.0.RELEASE + + + make-contract + package + + compile + + + + + + + com.jd.chain.contract.TransferContractImpl + + + contract + + + + + + +``` \ No newline at end of file diff --git a/source/contract/contract-maven-plugin/pom.xml b/source/contract/contract-maven-plugin/pom.xml index d8ec237f..47dab944 100644 --- a/source/contract/contract-maven-plugin/pom.xml +++ b/source/contract/contract-maven-plugin/pom.xml @@ -10,10 +10,6 @@ contract-maven-plugin maven-plugin - - 3.3.9 - - com.jd.blockchain @@ -39,59 +35,29 @@ ${project.version} - - com.github.javaparser - javaparser-core - ${javaparser.version} - - org.apache.maven maven-plugin-api 3.3.9 - - org.apache.maven - maven-core - 3.3.9 - - - org.apache.maven - maven-artifact - 3.3.9 - provided - - - org.apache.maven - maven-compat - 3.3.9 - - - junit - junit - 4.12 - test - - - org.apache.maven.plugin-testing - maven-plugin-testing-harness - test - 3.3.0 - - org.apache.maven.plugin-tools maven-plugin-annotations 3.6.0 - provided - org.apache.maven.shared - maven-invoker - 3.0.1 + org.apache.maven.plugins + maven-assembly-plugin + 2.6 + + + + org.ow2.asm + asm + 5.0.4 @@ -103,27 +69,6 @@ maven-plugin-plugin 3.5 - - - org.apache.maven.plugins - maven-compiler-plugin - - 1.8 - 1.8 - UTF-8 - false - true - false - false - - - - org.apache.maven.plugins - maven-surefire-plugin - - true - - - - + + diff --git a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/CheckImportsMojo.java b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/CheckImportsMojo.java deleted file mode 100644 index 461917a4..00000000 --- a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/CheckImportsMojo.java +++ /dev/null @@ -1,127 +0,0 @@ -package com.jd.blockchain; - -import com.github.javaparser.JavaParser; -import com.github.javaparser.ast.CompilationUnit; -import com.github.javaparser.ast.ImportDeclaration; -import com.github.javaparser.ast.NodeList; -import com.github.javaparser.ast.PackageDeclaration; -import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; -import com.github.javaparser.ast.body.MethodDeclaration; -import com.github.javaparser.ast.visitor.VoidVisitorAdapter; -import com.jd.blockchain.contract.ContractType; -import com.jd.blockchain.utils.IllegalDataException; -import org.apache.maven.plugin.AbstractMojo; -import org.apache.maven.plugin.MojoFailureException; -import org.apache.maven.plugins.annotations.Mojo; -import org.apache.maven.plugins.annotations.Parameter; -import org.apache.maven.project.MavenProject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.net.URLClassLoader; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.List; -import java.util.Properties; -import java.util.jar.Attributes; -import java.util.jar.JarFile; -import java.util.stream.Collectors; - -/** - * first step, we want to parse the source code by javaParse. But it's repeated and difficult to parse the source. - * This is a try of "from Initail to Abandoned". - * Since we are good at the class, why not? - * Now we change a way of thinking, first we pre-compile the source code, then parse the *.jar. - * - * by zhaogw - * date 2019-06-05 16:17 - */ -@Mojo(name = "checkImports") -public class CheckImportsMojo extends AbstractMojo { - Logger logger = LoggerFactory.getLogger(CheckImportsMojo.class); - - @Parameter(defaultValue = "${project}", required = true, readonly = true) - private MavenProject project; - - /** - * jar's name; - */ - @Parameter - private String finalName; - - @Override - public void execute() throws MojoFailureException { - List sources; - try { - InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("config.properties"); - Properties properties = new Properties(); - properties.load(inputStream); - String[] packageBlackList = properties.getProperty("blacklist").split(","); - Path baseDirPath = project.getBasedir().toPath(); - sources = Files.find(baseDirPath, Integer.MAX_VALUE, (file, attrs) -> (file.toString().endsWith(".java"))).collect(Collectors.toList()); - for (Path path : sources) { - CompilationUnit compilationUnit = JavaParser.parse(path); - - compilationUnit.accept(new MethodVisitor(), null); - - NodeList imports = compilationUnit.getImports(); - for (ImportDeclaration imp : imports) { - String importName = imp.getName().asString(); - for (String item : packageBlackList) { - if (importName.startsWith(item)) { - throw new MojoFailureException("在源码中不允许包含此引入包:" + importName); - } - } - } - - //now we parse the jar; - String jarPath = project.getBuild().getDirectory()+ File.separator+finalName+".jar"; - File jarFile = new File(jarPath); - URL jarURL = jarFile.toURI().toURL(); - ClassLoader classLoader = new URLClassLoader(new URL[]{jarURL},this.getClass().getClassLoader()); - Attributes m = new JarFile(jarFile).getManifest().getMainAttributes(); - String contractMainClass = m.getValue(Attributes.Name.MAIN_CLASS); - try { - Class mainClass = classLoader.loadClass(contractMainClass); - ContractType.resolve(mainClass); - } catch (ClassNotFoundException e) { - throw new IllegalDataException(e.getMessage()); - } - } - } catch (IOException exception) { - logger.error(exception.getMessage()); - throw new MojoFailureException("IO ERROR"); - } catch (NullPointerException e) { - logger.error(e.getMessage()); - } - } - - private class MethodVisitor extends VoidVisitorAdapter { - @Override - public void visit(MethodDeclaration n, Void arg) { - /* here you can access the attributes of the method. - this method will be called for all methods in this - CompilationUnit, including inner class methods */ - logger.info("method:"+n.getName()); - super.visit(n, arg); - } - - @Override - public void visit(ClassOrInterfaceDeclaration n, Void arg) { - logger.info("class:"+n.getName()+" extends:"+n.getExtendedTypes()+" implements:"+n.getImplementedTypes()); - - super.visit(n, arg); - } - - @Override - public void visit(PackageDeclaration n, Void arg) { - logger.info("package:"+n.getName()); - super.visit(n, arg); - } - - } -} diff --git a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractCheckMojo.java b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractCheckMojo.java deleted file mode 100644 index a47e4eb6..00000000 --- a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractCheckMojo.java +++ /dev/null @@ -1,221 +0,0 @@ -package com.jd.blockchain; - -import com.jd.blockchain.utils.ConsoleUtils; -import org.apache.maven.model.Model; -import org.apache.maven.model.Plugin; -import org.apache.maven.model.PluginExecution; -import org.apache.maven.model.io.xpp3.MavenXpp3Reader; -import org.apache.maven.model.io.xpp3.MavenXpp3Writer; -import org.apache.maven.plugin.AbstractMojo; -import org.apache.maven.plugins.annotations.Mojo; -import org.apache.maven.plugins.annotations.Parameter; -import org.apache.maven.project.MavenProject; -import org.apache.maven.shared.invoker.*; -import org.codehaus.plexus.util.xml.Xpp3Dom; -import org.codehaus.plexus.util.xml.pull.XmlPullParserException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.*; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - - -@Mojo(name = "contractCheck") -public class ContractCheckMojo extends AbstractMojo { - Logger logger = LoggerFactory.getLogger(ContractCheckMojo.class); - - @Parameter(defaultValue = "${project}", required = true, readonly = true) - private MavenProject project; - - /** - * jar's name; - */ - @Parameter - private String finalName; - - - /** - * mainClass; - */ - @Parameter - private String mainClass; - /** - * ledgerVersion; - */ - @Parameter - private String ledgerVersion; - - /** - * mvnHome; - */ - @Parameter - private String mvnHome; - - /** - * first compile the class, then parse it; - */ - @Override - public void execute() { - this.compileFiles(); - - } - - private void compileFiles(){ - // 获取当前项目pom.xml文件所在路径 -// URL targetClasses = this.getClass().getClassLoader().getResource(""); -// File file = new File(targetClasses.getPath()); -// String pomXmlPath = file.getParentFile().getParent() + File.separator + "pom.xml"; - - FileInputStream fis = null; - try { -// fis = new FileInputStream(new File(pomXmlPath)); - fis = new FileInputStream(project.getFile()); - MavenXpp3Reader reader = new MavenXpp3Reader(); - Model model = reader.read(fis); - - //delete this plugin(contractCheck) from destination pom.xml;then add the proper plugins; - Plugin plugin = model.getBuild().getPluginsAsMap().get("com.jd.blockchain:contract-maven-plugin"); - if(plugin == null){ - plugin = model.getBuild().getPluginsAsMap().get("org.apache.maven.plugins:contract-maven-plugin"); - } - - if(plugin == null) { - return; - } - - model.getBuild().removePlugin(plugin); -// model.getBuild().setPlugins(null); - -// ConsoleUtils.info("----- 不携带Plugin -----"); -// print(model); - - List plugins = new ArrayList<>(); - plugins.add(createAssembly()); - plugins.add(createCheckImports()); - - model.getBuild().setPlugins(plugins); - - ConsoleUtils.info("----- add Plugin -----"); - handle(model); - - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (XmlPullParserException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - private void invokeCompile(File file) { - InvocationRequest request = new DefaultInvocationRequest(); - - Invoker invoker = new DefaultInvoker(); - try { - request.setPomFile(file); - - request.setGoals( Collections.singletonList( "verify" ) ); -// request.setMavenOpts("-DmainClass="+mainClass); - invoker.setMavenHome(new File(mvnHome)); - invoker.execute(request); - } catch (MavenInvocationException e) { - e.printStackTrace(); - } - } - - private Plugin createCheckImports() { - Plugin plugin = new Plugin(); - plugin.setGroupId("com.jd.blockchain"); - plugin.setArtifactId("contract-maven-plugin"); - plugin.setVersion(ledgerVersion); - - Xpp3Dom finalNameNode = new Xpp3Dom("finalName"); - finalNameNode.setValue(finalName); - Xpp3Dom configuration = new Xpp3Dom("configuration"); - configuration.addChild(finalNameNode); - plugin.setConfiguration(configuration); - - PluginExecution pluginExecution = new PluginExecution(); - pluginExecution.setId("make-assembly"); - pluginExecution.setPhase("verify"); - List goals = new ArrayList<>(); - goals.add("checkImports"); - pluginExecution.setGoals(goals); - List pluginExecutions = new ArrayList<>(); - pluginExecutions.add(pluginExecution); - plugin.setExecutions(pluginExecutions); - - return plugin; - } - - private Plugin createAssembly() { - Plugin plugin = new Plugin(); - plugin.setArtifactId("maven-assembly-plugin"); - - Xpp3Dom configuration = new Xpp3Dom("configuration"); - - Xpp3Dom mainClassNode = new Xpp3Dom("mainClass"); - mainClassNode.setValue(mainClass); - - Xpp3Dom manifest = new Xpp3Dom("manifest"); - manifest.addChild(mainClassNode); - - Xpp3Dom archive = new Xpp3Dom("archive"); - archive.addChild(manifest); - - Xpp3Dom finalNameNode = new Xpp3Dom("finalName"); - finalNameNode.setValue(finalName); - - Xpp3Dom appendAssemblyId = new Xpp3Dom("appendAssemblyId"); - appendAssemblyId.setValue("false"); - - Xpp3Dom descriptorRef = new Xpp3Dom("descriptorRef"); - descriptorRef.setValue("jar-with-dependencies"); - Xpp3Dom descriptorRefs = new Xpp3Dom("descriptorRefs"); - descriptorRefs.addChild(descriptorRef); - - configuration.addChild(finalNameNode); - configuration.addChild(appendAssemblyId); - configuration.addChild(archive); - configuration.addChild(descriptorRefs); - plugin.setConfiguration(configuration); - - PluginExecution pluginExecution = new PluginExecution(); - pluginExecution.setId("make-assembly"); - pluginExecution.setPhase("package"); - List goals = new ArrayList<>(); - goals.add("single"); - pluginExecution.setGoals(goals); - List pluginExecutions = new ArrayList<>(); - pluginExecutions.add(pluginExecution); - plugin.setExecutions(pluginExecutions); - return plugin; - } - - private void handle(Model model) throws IOException { - MavenXpp3Writer mavenXpp3Writer = new MavenXpp3Writer(); - - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - - mavenXpp3Writer.write(outputStream, model); - - byte[] buffer = outputStream.toByteArray(); - - //输出文件 -// File fileOutput = new File("fileOut.xml"); -// File fileOutput = File.createTempFile("fileOut",".xml"); - File fileOutput = new File(project.getBasedir().getPath(),"fileOut.xml"); - fileOutput.createNewFile(); - - ConsoleUtils.info("fileOutput's path="+fileOutput.getPath()); - //创建文件输出流对象 - FileOutputStream fos = new FileOutputStream(fileOutput); - //将字节数组fileInput中的内容输出到文件fileOut.xml中; - ConsoleUtils.info(new String(buffer)); - fos.write(buffer); - invokeCompile(fileOutput); - fos.close(); - } -} diff --git a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractDeployExeUtil.java b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractDeployExeUtil.java index a206a854..b84cc712 100644 --- a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractDeployExeUtil.java +++ b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractDeployExeUtil.java @@ -7,29 +7,12 @@ import java.io.InputStream; import com.jd.blockchain.binaryproto.DataContractRegistry; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.ledger.BlockchainIdentity; -import com.jd.blockchain.ledger.BlockchainIdentityData; -import com.jd.blockchain.ledger.BlockchainKeyGenerator; -import com.jd.blockchain.ledger.BlockchainKeypair; -import com.jd.blockchain.ledger.ContractCodeDeployOperation; -import com.jd.blockchain.ledger.ContractEventSendOperation; -import com.jd.blockchain.ledger.DataAccountKVSetOperation; -import com.jd.blockchain.ledger.DataAccountRegisterOperation; -import com.jd.blockchain.ledger.EndpointRequest; -import com.jd.blockchain.ledger.NodeRequest; -import com.jd.blockchain.ledger.Operation; -import com.jd.blockchain.ledger.PreparedTransaction; -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.TransactionTemplate; -import com.jd.blockchain.ledger.UserRegisterOperation; +import com.jd.blockchain.ledger.*; import com.jd.blockchain.sdk.BlockchainService; import com.jd.blockchain.sdk.client.GatewayServiceFactory; -import com.jd.blockchain.tools.keygen.KeyGenCommand; import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.codec.Base58Utils; import com.jd.blockchain.utils.net.NetworkAddress; @@ -47,8 +30,8 @@ public enum ContractDeployExeUtil { PubKey pub = null; PrivKey prv = null; try { - prv = KeyGenCommand.readPrivKey(prvPath, KeyGenCommand.encodePassword(rawPassword)); - pub = KeyGenCommand.readPubKey(pubPath); + prv = KeyGenUtils.readPrivKey(prvPath, KeyGenUtils.encodePassword(rawPassword)); + pub = KeyGenUtils.readPubKey(pubPath); } catch (Exception e) { e.printStackTrace(); @@ -64,7 +47,7 @@ public enum ContractDeployExeUtil { BlockchainKeypair contractKeyPair = BlockchainKeyGenerator.getInstance().generate(); pub = contractKeyPair.getPubKey(); }else { - pub = KeyGenCommand.readPubKey(pubPath); + pub = KeyGenUtils.readPubKey(pubPath); } } catch (Exception e) { @@ -111,6 +94,8 @@ public enum ContractDeployExeUtil { DataContractRegistry.register(ContractEventSendOperation.class); DataContractRegistry.register(DataAccountRegisterOperation.class); DataContractRegistry.register(UserRegisterOperation.class); + DataContractRegistry.register(ParticipantRegisterOperation.class); + DataContractRegistry.register(ParticipantStateUpdateOperation.class); } public BlockchainService initBcsrv(String host, int port) { diff --git a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractDeployMojo.java b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractDeployMojo.java index 3eac13bb..427fe00f 100644 --- a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractDeployMojo.java +++ b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractDeployMojo.java @@ -1,10 +1,10 @@ package com.jd.blockchain; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.ledger.BlockchainKeypair; -import com.jd.blockchain.tools.keygen.KeyGenCommand; import com.jd.blockchain.utils.StringUtils; import com.jd.blockchain.utils.codec.Base58Utils; import com.jd.blockchain.utils.io.FileUtils; @@ -102,8 +102,8 @@ public class ContractDeployMojo extends AbstractMojo { byte[] contractBytes = FileUtils.readBytes(contractPath); - PrivKey prv = KeyGenCommand.decodePrivKeyWithRawPassword(prvKey, password); - PubKey pub = KeyGenCommand.decodePubKey(pubKey); + PrivKey prv = KeyGenUtils.decodePrivKeyWithRawPassword(prvKey, password); + PubKey pub = KeyGenUtils.decodePubKey(pubKey); BlockchainKeypair blockchainKeyPair = new BlockchainKeypair(pub, prv); HashDigest ledgerHash = new HashDigest(Base58Utils.decode(ledger)); diff --git a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/AbstractContract.java b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/AbstractContract.java new file mode 100644 index 00000000..389dd33a --- /dev/null +++ b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/AbstractContract.java @@ -0,0 +1,98 @@ +package com.jd.blockchain.contract.maven; + +import com.jd.blockchain.contract.maven.rule.BlackList; +import com.jd.blockchain.contract.maven.rule.WhiteList; + +import java.util.List; + +public abstract class AbstractContract { + + protected String className; + + public String getClassName() { + return className; + } + + public String getDotClassName() { + return className.replaceAll("/", "."); + } + + protected String format(final String inputFormat) { + String formatResult; + + String outputFormat = inputFormat; + if (inputFormat.endsWith(";")) { + outputFormat = inputFormat.substring(0, inputFormat.length() - 1); + } + if (outputFormat.startsWith("[L") && outputFormat.length() > 2) { + // 说明是数组,但不显示 + formatResult = outputFormat.substring(2); + } else if (outputFormat.startsWith("[") && outputFormat.length() > 1) { + // 说明是数组 + formatResult = outputFormat.substring(1); + } else if (outputFormat.startsWith("L") && outputFormat.length() > 1) { + // 说明是非基础类型 + formatResult = outputFormat.substring(1); + } else { + formatResult = outputFormat; + } + + return formatResult; + } + + public static BlackList initBlack(List blackList) { + BlackList contractBlack = new BlackList(); + if (blackList != null && !blackList.isEmpty()) { + for (String black : blackList) { + // 首先判断该black是package还是 + String packageName = isPackageAndReturn(black); + if (packageName != null) { + // 说明是包 + contractBlack.addBlackPackage(packageName); + } else { + String[] classAndMethod = black.split("-"); + if (classAndMethod.length == 1) { + // 说明只有ClassName + contractBlack.addBlack(classAndMethod[0], BlackList.COMMON_METHOD); + } else { + contractBlack.addBlack(classAndMethod[0], classAndMethod[1]); + } + } + } + } + + return contractBlack; + } + + public static WhiteList initWhite(List whiteList) { + WhiteList contractWhite = new WhiteList(); + + if (whiteList != null && !whiteList.isEmpty()) { + for (String white : whiteList) { + String packageName = isPackageAndReturn(white); + if (packageName != null) { + // 说明是包 + contractWhite.addWhite(packageName); + } else { + contractWhite.addWhite(white); + } + } + } + + return contractWhite; + } + + /** + * 获取配置的packageName + * + * @param config + * @return + * 假设为包,则返回其包名,否则返回NULL + */ + public static String isPackageAndReturn(String config) { + if (config.endsWith("*")) { + return config.substring(0, config.length() - 2); + } + return null; + } +} diff --git a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/ContractClass.java b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/ContractClass.java new file mode 100644 index 00000000..b9d3de7b --- /dev/null +++ b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/ContractClass.java @@ -0,0 +1,66 @@ +package com.jd.blockchain.contract.maven; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class ContractClass extends AbstractContract { + + // 若出现同名的方法则进行合并(将两个方法中涉及到的内容合并在一起) + private Map methods = new ConcurrentHashMap<>(); + + public ContractClass(String className) { + if (className.contains(".")) { + this.className = className.replaceAll("\\.", "/"); + } else { + this.className = className; + } + } + + /** + * 返回构造方法 + * + * @return + */ + public ContractMethod constructor() { + return methods.get(ContractConstant.METHOD_INIT); + } + + /** + * 返回该类的所有变量 + * + * @return + */ + public List fields() { + + List fields = new ArrayList<>(); + + // 构造方法 + ContractMethod initMethod = constructor(); + if (initMethod != null) { + fields.addAll(initMethod.getClassFieldList(className)); + } + // CLINIT方法 + ContractMethod clInitMethod = methods.get(ContractConstant.METHOD_CLINIT); + if (clInitMethod != null) { + fields.addAll(clInitMethod.getClassFieldList(className)); + } + return fields; + } + + public synchronized ContractMethod method(String methodName) { + if (methods.containsKey(methodName)) { + return methods.get(methodName); + } + ContractMethod method = new ContractMethod(this.className, methodName); + + methods.put(methodName, method); + + return method; + } + + public Map getMethods() { + return methods; + } +} diff --git a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/ContractCompileMojo.java b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/ContractCompileMojo.java new file mode 100644 index 00000000..a98eeca3 --- /dev/null +++ b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/ContractCompileMojo.java @@ -0,0 +1,288 @@ +package com.jd.blockchain.contract.maven; + +import com.jd.blockchain.contract.maven.rule.BlackList; +import com.jd.blockchain.contract.maven.rule.WhiteList; +import com.jd.blockchain.contract.maven.rule.DependencyExclude; +import com.jd.blockchain.contract.maven.verify.ResolveEngine; +import com.jd.blockchain.contract.maven.verify.VerifyEngine; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugin.assembly.mojos.SingleAssemblyMojo; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.project.MavenProject; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +import static com.jd.blockchain.contract.ContractJarUtils.BLACK_CONF; +import static com.jd.blockchain.contract.ContractJarUtils.WHITE_CONF; + +@Mojo(name = "compile") +public class ContractCompileMojo extends SingleAssemblyMojo { + + public static final String JAR_DEPENDENCE = "jar-with-dependencies"; + + public static final String SCOPE_PROVIDED = "provided"; + + public static final String SCOPE_COMPILE = "compile"; + + private DependencyExclude dependencyExclude = new DependencyExclude(); + + private static BlackList black; + + private static WhiteList white; + + static { + init(); + } + + @Override + public void execute() throws MojoExecutionException, MojoFailureException { + // 首先对MainClass进行校验,要求必须有MainClass + String mainClass = mainClassVerify(); + + // 排除所有依赖,只打包当前代码 +// excludeAllArtifactExclude(super.getProject().getDependencyArtifacts()); +// handleArtifactCompile(super.getProject().getDependencyArtifacts()); + handleArtifactExclude(super.getProject().getDependencyArtifacts()); + + // 此参数用于设置将所有第三方依赖的Jar包打散为.class,与主代码打包在一起,生成一个jar包 + super.setDescriptorRefs(new String[]{JAR_DEPENDENCE}); + + // 执行打包命令 + // 该命令生成的是只含有当前项目的实际代码的Jar包,该Jar包仅用于校验MainClass + super.execute(); + + // 生成解析引擎 + ResolveEngine resolveEngine = new ResolveEngine(getLog(), mainClass); + + // 获取本次生成的Jar文件 + File defaultJarFile; + try { + defaultJarFile = rename(getProject(), getFinalName()); + // 校验当前MainClass是否满足需求 + resolveEngine.verifyCurrentProjectMainClass(defaultJarFile); + // 校验完成后将该Jar删除 +// FileUtils.forceDelete(mainClassFile); + } catch (Exception e) { + getLog().error(e); + throw new MojoFailureException(e.getMessage()); + } + +// // 将JDChain本身之外的代码打包进Jar包,然后编译 +// handleArtifactExclude(super.getProject().getDependencyArtifacts()); +// +// // 此参数用于设置将所有第三方依赖的Jar包打散为.class,与主代码打包在一起,生成一个jar包 +// super.setDescriptorRefs(new String[]{JAR_DEPENDENCE}); +// +// // 生成Jar包(该Jar包中不包含JDChain内部的代码) +// super.execute(); +// +// File defaultJarFile; +// try { +// defaultJarFile = rename(getProject(), getFinalName()); +// } catch (Exception e) { +// getLog().error(e); +// throw new MojoFailureException(e.getMessage()); +// } + + // 校验该Jar包 + verify(defaultJarFile, mainClass); + + File deployJarFile = resolveEngine.verify(defaultJarFile); + + // 删除中间产生的临时文件 + try { + FileUtils.forceDelete(defaultJarFile); + } catch (Exception e) { + getLog().error(e); + } + + getLog().info(String.format("JDChain's Contract compile success, path = %s !", deployJarFile.getPath())); + + + +// // 将JDChain本身代码之外的代码移除(不打包进整个Jar) +// handleArtifactExclude(super.getProject().getDependencyArtifacts()); +// +// // 此参数用于设置将所有第三方依赖的Jar包打散为.class,与主代码打包在一起,生成一个jar包 +// super.setDescriptorRefs(new String[]{JAR_DEPENDENCE}); +// +// // 执行打包命令 +// super.execute(); + +// // 将本次打包好的文件重新命名,以便于后续重新打包需要 +// // 把文件改名,然后重新再生成一个文件 +// File dstFile; +// try { +// dstFile = rename(getProject(), getFinalName()); +// } catch (IOException e) { +// getLog().error(e); +// throw new MojoFailureException(e.getMessage()); +// } +// +// // dstFile理论上应该含有 +// +// // 首先校验该类的Jar包中是否包含不符合规范的命名,以及该类的代码中的部分解析 +// +// ResolveEngine resolveEngine = new ResolveEngine(getLog(), mainClass); +// +// // 校验mainClass +// resolveEngine.verifyCurrentProjectMainClass(dstFile); +// +// +// +// File finalJarFile = resolveEngine.verify(); +// +// // 将所有的依赖的jar包全部打包进一个包中,以便于进行ASM检查 +// handleArtifactCompile(super.getProject().getDependencyArtifacts()); +// +// // 然后再打包一次,本次打包完成后,其中的代码包含所有的class(JDK自身的除外) +// super.execute(); +// +// File jarFile = new File(jarPath(getProject(), getFinalName())); +// +// // 校验mainClass +// resolveEngine.verifyCurrentProjectMainClass(jarFile); +// +// // 对代码中的一些规则进行校验,主要是校验其是否包含一些不允许使用的类、包、方法等 +// verify(jarFile, mainClass); +// +// // 删除中间的一些文件 +//// try { +//// FileUtils.forceDelete(dstFile); +//// } catch (IOException e) { +//// throw new MojoFailureException(e.getMessage()); +//// } +// + // 若执行到此处没有异常则表明打包成功,打印打包成功消息 +// getLog().info(String.format("JDChain's Contract compile success, path = %s !", finalJarFile.getPath())); + } + + private String mainClassVerify() throws MojoFailureException { + // 要求必须有MainClass + String mainClass; + try { + mainClass = super.getJarArchiveConfiguration().getManifest().getMainClass(); + // 校验MainClass,要求MainClass必须不能为空 + if (mainClass == null || mainClass.length() == 0) { + throw new MojoFailureException("MainClass is NULL !!!"); + } + super.getLog().debug("MainClass is " + mainClass); + } catch (Exception e) { + throw new MojoFailureException("MainClass is null: " + e.getMessage(), e ); + } + return mainClass; + } + + private void handleArtifactExclude(Set artifacts) { + for (Artifact artifact : artifacts) { + String groupId = artifact.getGroupId(), artifactId = artifact.getArtifactId(); + if (dependencyExclude.isExclude(groupId, artifactId)) { + getLog().info(String.format("GroupId[%s] ArtifactId[%s] belongs to DependencyExclude !!!", groupId, artifactId)); + // 属于排除的名单之中 + artifact.setScope(SCOPE_PROVIDED); + } else { + getLog().info(String.format("GroupId[%s] ArtifactId[%s] not belongs to DependencyExclude !!!", groupId, artifactId)); + // 属于排除的名单之中 + artifact.setScope(SCOPE_COMPILE); + } + } + } + + private void excludeAllArtifactExclude(Set artifacts) { + for (Artifact artifact : artifacts) { + artifact.setScope(SCOPE_PROVIDED); + } + } + + private void handleArtifactCompile(Set artifacts) { + for (Artifact artifact : artifacts) { + if (artifact.getScope().equals(SCOPE_PROVIDED)) { + // 将所有的provided设置为compile,以便于后续编译 + artifact.setScope(SCOPE_COMPILE); + } + } + } + + private File rename(MavenProject project, String finalName) throws IOException { + String srcJarPath = jarPath(project, finalName); + String dstJarPath = project.getBuild().getDirectory() + + File.separator + finalName + ".jar"; + File dstFile = new File(dstJarPath); + FileUtils.copyFile(new File(srcJarPath), dstFile); + FileUtils.forceDelete(new File(srcJarPath)); + return dstFile; + } + + private String jarPath(MavenProject project, String finalName) { + return project.getBuild().getDirectory() + + File.separator + finalName + "-" + JAR_DEPENDENCE + ".jar"; + } + + private void verify(File jarFile, String mainClass) throws MojoFailureException { + try { + VerifyEngine verifyEngine = new VerifyEngine(getLog(), jarFile, mainClass, black, white); + + verifyEngine.verify(); + + // 校验完成后将该jar包删除 +// FileUtils.forceDelete(jarFile); + + } catch (Exception e) { + getLog().error(e); + throw new MojoFailureException(e.getMessage()); + } + } + + + + private static void init() { + try { + black = AbstractContract.initBlack(loadBlackConf()); + white = AbstractContract.initWhite(loadWhiteConf()); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + + private static List loadWhiteConf() { + + return resolveConfig(WHITE_CONF); + } + + private static List loadBlackConf() { + return resolveConfig(BLACK_CONF); + } + + private static List resolveConfig(String fileName) { + List configs = new ArrayList<>(); + + try { + List readLines = loadConfig(fileName); + if (!readLines.isEmpty()) { + for (String readLine : readLines) { + String[] lines = readLine.split(","); + configs.addAll(Arrays.asList(lines)); + } + } + } catch (Exception e) { + throw new IllegalStateException(e); + } + + return configs; + } + + public static List loadConfig(String fileName) throws Exception { + + return IOUtils.readLines( + ContractCompileMojo.class.getResourceAsStream("/" + fileName)); + } +} diff --git a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/ContractConstant.java b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/ContractConstant.java new file mode 100644 index 00000000..a94fb624 --- /dev/null +++ b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/ContractConstant.java @@ -0,0 +1,9 @@ +package com.jd.blockchain.contract.maven; + +public class ContractConstant { + + public static final String METHOD_INIT = ""; + + public static final String METHOD_CLINIT = ""; + +} diff --git a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/ContractField.java b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/ContractField.java new file mode 100644 index 00000000..f4b0f396 --- /dev/null +++ b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/ContractField.java @@ -0,0 +1,43 @@ +package com.jd.blockchain.contract.maven; + +public class ContractField extends AbstractContract { + + private String fieldName; + + private String fieldType; + + private boolean isStatic; + + public ContractField(String className, String fieldName, String fieldType) { + this(className, fieldName, fieldType, false); + } + + public ContractField(String className, String fieldName, String fieldType, boolean isStatic) { + this.className = format(className); + this.fieldName = fieldName; + this.fieldType = format(fieldType); + this.isStatic = isStatic; + } + + public String getFieldName() { + return fieldName; + } + + public String getFieldType() { + return fieldType; + } + + public boolean isStatic() { + return isStatic; + } + + @Override + public String toString() { + return "ContractField{" + + "className='" + className + '\'' + + ", fieldName='" + fieldName + '\'' + + ", fieldType='" + fieldType + '\'' + + ", isStatic=" + isStatic + + '}'; + } +} diff --git a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/ContractMethod.java b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/ContractMethod.java new file mode 100644 index 00000000..6dc2e3a7 --- /dev/null +++ b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/ContractMethod.java @@ -0,0 +1,81 @@ +package com.jd.blockchain.contract.maven; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class ContractMethod extends AbstractContract { + + private String methodName; + + private String[] paramTypes; + + private String[] returnTypes; + + private List fieldList = new ArrayList<>(); + + private List methodList = new ArrayList<>(); + + public ContractMethod(String className, String methodName) { + this(className, methodName, null, null); + } + + public ContractMethod(String className, String methodName, String[] paramTypes, String[] returnTypes) { + this.className = format(className); + this.methodName = methodName; + this.paramTypes = paramTypes; + this.returnTypes = returnTypes; + } + + public void addMethod(String className, String methodName, String[] paramTypes, String[] returnTypes) { + methodList.add(new ContractMethod(className, methodName, paramTypes, returnTypes)); + } + + public void addField(String className, String fieldName, String fieldType) { + this.fieldList.add(new ContractField(className, fieldName, fieldType)); + } + + public void addStaticField(String className, String fieldName, String fieldType) { + this.fieldList.add(new ContractField(className, fieldName, fieldType, true)); + } + + public String getMethodName() { + return methodName; + } + + public String[] getParamTypes() { + return paramTypes; + } + + public List getAllFieldList() { + return fieldList; + } + + public List getClassFieldList(String cName) { + List classFieldList = new ArrayList<>(); + if (!fieldList.isEmpty()) { + for (ContractField field : fieldList) { + if (field.getClassName().equals(cName)) { + classFieldList.add(field); + } + } + } + return classFieldList; + } + + public List getMethodList() { + return methodList; + } + + @Override + public String toString() { + return "ContractMethod{" + + "className='" + className + '\'' + + ", methodName='" + methodName + '\'' + + ", paramTypes=" + Arrays.toString(paramTypes) + + ", returnTypes=" + Arrays.toString(returnTypes) + + ", fieldList=" + fieldList + + ", methodList=" + methodList + + '}'; + } +} diff --git a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/asm/ASMClassVisitor.java b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/asm/ASMClassVisitor.java new file mode 100644 index 00000000..27bfeee4 --- /dev/null +++ b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/asm/ASMClassVisitor.java @@ -0,0 +1,22 @@ +package com.jd.blockchain.contract.maven.asm; + +import com.jd.blockchain.contract.maven.ContractClass; +import com.jd.blockchain.contract.maven.ContractMethod; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +public class ASMClassVisitor extends ClassVisitor { + + private ContractClass contractClass; + + public ASMClassVisitor(ContractClass contractClass) { + super(Opcodes.ASM5); + this.contractClass = contractClass; + } + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + MethodVisitor superMV = super.visitMethod(access, name, desc, signature, exceptions); + ContractMethod method = this.contractClass.method(name); + return new ASMMethodVisitor(superMV, method); + } +} \ No newline at end of file diff --git a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/asm/ASMMethodVisitor.java b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/asm/ASMMethodVisitor.java new file mode 100644 index 00000000..03488203 --- /dev/null +++ b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/asm/ASMMethodVisitor.java @@ -0,0 +1,108 @@ +package com.jd.blockchain.contract.maven.asm; + +import com.jd.blockchain.contract.maven.ContractMethod; +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.TypePath; + +import java.util.ArrayList; +import java.util.List; + +public class ASMMethodVisitor extends MethodVisitor { + + private ContractMethod method; + + public ASMMethodVisitor(MethodVisitor mv, ContractMethod method) { + super(Opcodes.ASM5, mv); + this.method = method; + } + + @Override + public void visitFieldInsn(int type, String cName, String fName, String fType) { + if (type == 178 || type == 179) { + this.method.addStaticField(cName, fName, fType); + } else { + this.method.addField(cName, fName, fType); + } + super.visitFieldInsn(type, cName, fName, fType); + } + + @Override + public void visitMethodInsn(int type, String cName, String mName, String params, boolean b) { + ParamsAndReturn paramsAndReturn = resolveParamsAndReturn(params); + this.method.addMethod(cName, mName, paramsAndReturn.paramTypes, paramsAndReturn.returnTypes); + super.visitMethodInsn(type, cName, mName, params, b); + } + + private ParamsAndReturn resolveParamsAndReturn(String params) { + // 格式: + // 1、(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + // 2、()I + // 3、(Ljava/lang/String;)V + // 4、()V + // 5、([Ljava/lang/Object;)Ljava/util/List; false + // 从上面分析可以得出:括号内的是入参,右括号后面的是返回值,其中V表示Void,即空; + String[] paramArray = params.split("\\)"); + String paramTypeChars = ""; + if (!paramArray[0].equals("(")) { + // 表明入参不为空 + paramTypeChars = paramArray[0].split("\\(")[1]; + } + String returnTypeChars = paramArray[1]; + return new ParamsAndReturn(paramTypeChars, returnTypeChars); + } + + static class ParamsAndReturn { + + String[] paramTypes; + + String[] returnTypes; + + public ParamsAndReturn(String paramsTypeChars, String returnTypeChars) { + initParamsType(paramsTypeChars); + initReturnType(returnTypeChars); + } + + private void initParamsType(String paramsTypeChars) { + List paramList = handleTypes(paramsTypeChars); + if (!paramList.isEmpty()) { + this.paramTypes = new String[paramList.size()]; + paramList.toArray(this.paramTypes); + } + } + + private void initReturnType(String returnTypeChar) { + // 按照分号分隔 + List returnList = handleTypes(returnTypeChar); + if (!returnList.isEmpty()) { + this.returnTypes = new String[returnList.size()]; + returnList.toArray(this.returnTypes); + } + } + + private List handleTypes(String typeChars) { + String[] types = typeChars.split(";"); + List typeList = new ArrayList<>(); + if (types.length > 0) { + for (String type : types) { + if (type.length() > 0) { + if (type.startsWith("[L") && type.length() > 2) { + // 说明是数组 + typeList.add(type.substring(2) + "[]"); + } else if (type.startsWith("[") && type.length() > 1) { + // 说明是数组 + typeList.add(type.substring(1)); + } else if (type.startsWith("L") && type.length() > 1) { + // 说明是非基础类型 + typeList.add(type.substring(1)); + } else { + typeList.add(type); + } + } + } + } + return typeList; + } + } +} \ No newline at end of file diff --git a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/rule/BlackList.java b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/rule/BlackList.java new file mode 100644 index 00000000..593093aa --- /dev/null +++ b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/rule/BlackList.java @@ -0,0 +1,155 @@ +package com.jd.blockchain.contract.maven.rule; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +public class BlackList { + + public static final String COMMON_METHOD = "*"; + + public static final String INIT_METHOD = "init"; + + // 合约黑名单 + private final Map blackClassMap = new ConcurrentHashMap<>(); + + private final List blackPackages = new ArrayList<>(); + + public synchronized BlackList addBlack(String className, String methodName) { + String trimClassName = className.trim(); + BlackClass blackClass = blackClassMap.get(trimClassName); + if (blackClass != null) { + blackClass.addMethod(methodName); + } else { + blackClass = new BlackClass(trimClassName); + blackClass.addMethod(methodName); + blackClassMap.put(trimClassName, blackClass); + } + return this; + } + + public synchronized BlackList addBlack(Class clazz, String methodName) { + return addBlack(clazz.getName(), methodName); + } + + public synchronized BlackList addBlack(Class clazz) { + return addBlack(clazz.getName(), COMMON_METHOD); + } + + public synchronized BlackList addBlackPackage(String packageName) { + blackPackages.add(packageName.trim() + "."); // 末尾增加一个点,防止后续判断是拼凑 + return this; + } + + public boolean isBlackClass(String className) { + if (isContainsPackage(className)) { + return true; + } + BlackClass blackClass = blackClassMap.get(className); + if (blackClass == null) { + return false; + } + return blackClass.isBlack(); + } + + public boolean isBlack(Class clazz, String methodName) { + + // 判断该Class是否属于黑名单 + if (isCurrentClassBlack(clazz, methodName)) { + return true; + } + // 当前Class不是黑名单的情况下,处理其对应的父类和接口 + // 获取该Class对应的接口和父类列表 + Set> superClassAndAllInterfaces = new HashSet<>(); + + loadSuperClassAndAllInterfaces(clazz, superClassAndAllInterfaces); + + // 循环判断每个父类和接口 + for (Class currClass : superClassAndAllInterfaces) { + if (isCurrentClassBlack(currClass, methodName)) { + return true; + } + } + return false; + } + + public boolean isCurrentClassBlack(Class clazz, String methodName) { + + String packageName = clazz.getPackage().getName(); + for (String bp : blackPackages) { + if ((packageName + ".").equals(bp) || packageName.startsWith(bp)) { + return true; + } + } + // 判断该类本身是否属于黑名单 + String className = clazz.getName(); + BlackClass blackClass = blackClassMap.get(className); + if (blackClass != null) { + // 判断其方法 + return blackClass.isBlack(methodName); + } + return false; + } + + public boolean isBlackField(Class clazz) { + return isBlack(clazz, INIT_METHOD); + } + + private boolean isContainsPackage(String className) { + for (String bp : blackPackages) { + if (className.equals(bp) || className.startsWith(bp)) { + return true; + } + } + return false; + } + + private void loadSuperClassAndAllInterfaces(Class currentClass, Set> allClassList) { + if (currentClass == null) { + return; + } + + if (!allClassList.contains(currentClass)) { + allClassList.add(currentClass); + // 处理其父类 + Class superClass = currentClass.getSuperclass(); + loadSuperClassAndAllInterfaces(superClass, allClassList); + + // 处理其所有接口 + Class[] allInterfaces = currentClass.getInterfaces(); + if (allInterfaces != null && allInterfaces.length > 0) { + for (Class intf : allInterfaces) { + loadSuperClassAndAllInterfaces(intf, allClassList); + } + } + } + } + + private static class BlackClass { + + String className; + + Set methods = new HashSet<>(); + + BlackClass(String className) { + this.className = className; + } + + void addMethod(String methodName) { + methods.add(methodName); + } + + boolean isBlack(String methodName) { + // 假设method为*则表示所有的方法 + if (methods.contains(COMMON_METHOD)) { + return true; + } + return methods.contains(methodName); + } + + boolean isBlack() { + return isBlack(COMMON_METHOD); + } + } +} + + diff --git a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/rule/DependencyExclude.java b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/rule/DependencyExclude.java new file mode 100644 index 00000000..c20ce777 --- /dev/null +++ b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/rule/DependencyExclude.java @@ -0,0 +1,93 @@ +package com.jd.blockchain.contract.maven.rule; + +import com.jd.blockchain.contract.maven.ContractCompileMojo; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class DependencyExclude { + + private static final String COMMON_ARTIFACTID = "*"; + + private static final String CONFIG = "providers.conf"; + + private static final Map> DEPENDENCYS = new ConcurrentHashMap<>(); + + static { + try { + init(); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + + private static void init() throws Exception { + List readLines = ContractCompileMojo.loadConfig(CONFIG); + if (!readLines.isEmpty()) { + for (String line : readLines) { + // groupId/artifactId + String[] lines = line.split(","); + if (lines.length > 0) { + for (String depend : lines) { + String[] depends = depend.split("/"); + if (depends.length == 2) { + String groupId = depends[0], artifactId = depends[1]; + Dependency dependency = new Dependency(groupId, artifactId); + addDependency(dependency); + } + } + } + } + } + } + + private synchronized static void addDependency(Dependency dependency) { + String groupId = dependency.groupId; + if (!DEPENDENCYS.containsKey(groupId)) { + List dependencies = new ArrayList<>(); + dependencies.add(dependency); + DEPENDENCYS.put(groupId, dependencies); + } else { + List dependencies = DEPENDENCYS.get(groupId); + dependencies.add(dependency); + } + } + + public boolean isExclude(String groupId, String artifactId) { + List dependencies = DEPENDENCYS.get(groupId); + + if (dependencies == null || dependencies.isEmpty()) { + return false; + } + + for (Dependency dependency : dependencies) { + if (dependency.isEqualArtifactId(artifactId)) { + return true; + } + } + + return false; + } + + + static class Dependency { + + String groupId; + + String artifactId; + + public Dependency(String groupId, String artifactId) { + this.groupId = groupId; + this.artifactId = artifactId; + } + + public boolean isEqualArtifactId(String artiId) { + if (artifactId.equals(COMMON_ARTIFACTID)) { + return true; + } + return artifactId.equals(artiId); + } + } +} diff --git a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/rule/WhiteList.java b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/rule/WhiteList.java new file mode 100644 index 00000000..eeb1e250 --- /dev/null +++ b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/rule/WhiteList.java @@ -0,0 +1,30 @@ +package com.jd.blockchain.contract.maven.rule; + +import java.util.ArrayList; +import java.util.List; + +public class WhiteList { + + // 合约白名单(白名单通常数量较少,主要是JDChain内部包) + private final List whiteClasses = new ArrayList<>(); + + public void addWhite(String className) { + whiteClasses.add(className.trim()); + } + + public boolean isWhite(Class clazz) { + String className = clazz.getName(); + return isWhite(className); + } + + public boolean isWhite(String className) { + for (String white : whiteClasses) { + if (white.equals(className) || className.startsWith(white)) { + return true; + } + } + return false; + } +} + + diff --git a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/verify/ResolveEngine.java b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/verify/ResolveEngine.java new file mode 100644 index 00000000..97744689 --- /dev/null +++ b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/verify/ResolveEngine.java @@ -0,0 +1,169 @@ +package com.jd.blockchain.contract.maven.verify; + +import com.alibaba.fastjson.JSON; +import com.jd.blockchain.contract.Contract; +import com.jd.blockchain.contract.ContractJarUtils; +import com.jd.blockchain.contract.ContractType; +import com.jd.blockchain.contract.EventProcessingAware; +import org.apache.commons.io.FileUtils; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugin.logging.Log; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +import static com.jd.blockchain.contract.ContractJarUtils.*; + +public class ResolveEngine { + + private Log LOGGER; + +// private File jarFile; + + private String mainClass; + +// public ResolveEngine(Log LOGGER, File jarFile, String mainClass) { + public ResolveEngine(Log LOGGER, String mainClass) { + this.LOGGER = LOGGER; +// this.jarFile = jarFile; + this.mainClass = mainClass; + } + + /** + * 校验当前项目中MainClass其是否满足JDChain合约写法 + * + * @param mainClassJarFile + * @throws MojoFailureException + */ + public void verifyCurrentProjectMainClass(File mainClassJarFile) throws MojoFailureException { + // 校验MainClass + try { + LOGGER.debug(String.format("Verify Jar [%s] 's MainClass start...", mainClassJarFile.getName())); + // 自定义ClassLoader,必须使用Thread.currentThread().getContextClassLoader() + // 保证其项目内部加载的Jar包无须再加载一次 + URLClassLoader classLoader = new URLClassLoader(new URL[]{mainClassJarFile.toURI().toURL()}, + Thread.currentThread().getContextClassLoader()); + + // 从MainClass作为入口进行MainClass代码校验 + Class mClass = classLoader.loadClass(mainClass); + ContractType.resolve(mClass); + + // 校验完成后需要释放,否则无法删除该Jar文件 + classLoader.close(); + + LOGGER.debug(String.format("Verify Jar [%s] 's MainClass end...", mainClassJarFile.getName())); + } catch (Exception e) { + throw new MojoFailureException(e.getMessage()); + } + } + + public File verify(File defaultJarFile) throws MojoFailureException { + try { + // 检查jar包中所有的class的命名,要求其包名不能为com.jd.blockchain.* + LinkedList totalClasses = loadAllClass(defaultJarFile); + + if (!totalClasses.isEmpty()) { + + for (String clazz : totalClasses) { + + String dotClassName = dotClassName(clazz); + + LOGGER.debug(String.format("Verify Dependency Class[%s] start......", dotClassName)); + // 获取其包名 + // 将class转换为包名 + String packageName = class2Package(dotClassName); + + if (ContractJarUtils.isJDChainPackage(packageName)) { + throw new IllegalStateException(String.format("Class[%s]'s package[%s] cannot start with %s !", + dotClassName, packageName, ContractJarUtils.JDCHAIN_PACKAGE)); + } + + LOGGER.debug(String.format("Verify Class[%s] end......", clazz)); + } + } + + // 处理完成之后,生成finalName-JDChain-Contract.jar + return compileCustomJar(defaultJarFile); + } catch (Exception e) { + LOGGER.error(e.getMessage()); + throw new MojoFailureException(e.getMessage()); + } + } + + private String class2Package(String dotClassName) { + + return dotClassName.substring(0, dotClassName.lastIndexOf(".")); + } + + private File compileCustomJar(File defaultJarFile) throws IOException { + + String fileParentPath = defaultJarFile.getParentFile().getPath(); + + String jarFileName = defaultJarFile.getName(); + + String fileName = jarFileName.substring(0, jarFileName.lastIndexOf(".")); + + // 首先将Jar包转换为指定的格式 + String dstJarPath = fileParentPath + File.separator + + fileName + "-temp-" + System.currentTimeMillis() + ".jar"; + + File srcJar = defaultJarFile, dstJar = new File(dstJarPath); + + LOGGER.debug(String.format("Jar from [%s] to [%s] Copying", defaultJarFile.getPath(), dstJarPath)); + // 首先进行Copy处理 + copy(srcJar, dstJar); + + LOGGER.debug(String.format("Jar from [%s] to [%s] Copied", defaultJarFile.getPath(), dstJarPath)); + + byte[] txtBytes = contractMF(FileUtils.readFileToByteArray(dstJar)).getBytes(StandardCharsets.UTF_8); + + String finalJarPath = fileParentPath + File.separator + fileName + "-JDChain-Contract.jar"; + + File finalJar = new File(finalJarPath); + + // 生成最终的Jar文件 + copy(dstJar, finalJar, contractMFJarEntry(), txtBytes, null); + + // 删除临时文件 + FileUtils.forceDelete(dstJar); + + return finalJar; + } + + private ClassLoader verifyMainClass(File jarFile) throws Exception { + // 加载main-class,开始校验类型 + LOGGER.debug(String.format("Verify Jar [%s] 's MainClass start...", jarFile.getName())); + URL jarURL = jarFile.toURI().toURL(); + ClassLoader classLoader = new URLClassLoader(new URL[]{jarURL}); + Class mClass = classLoader.loadClass(mainClass); + ContractType.resolve(mClass); + LOGGER.debug(String.format("Verify Jar [%s] 's MainClass end...", jarFile.getName())); + return classLoader; + } + + private LinkedList loadAllClass(File file) throws Exception { + JarFile jarFile = new JarFile(file); + LinkedList allClass = new LinkedList<>(); + Enumeration jarEntries = jarFile.entries(); + while (jarEntries.hasMoreElements()) { + JarEntry jarEntry = jarEntries.nextElement(); + String entryName = jarEntry.getName(); + if (entryName.endsWith(".class")) { + // 内部类,不需要处理 + if (!entryName.contains("$")) { + allClass.addLast(entryName.substring(0, entryName.length() - 6)); + } + } + } + // Jar文件使用完成后需要关闭,否则可能会产生无法删除的问题 + jarFile.close(); + + return allClass; + } +} diff --git a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/verify/VerifyEngine.java b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/verify/VerifyEngine.java new file mode 100644 index 00000000..7fd59c7e --- /dev/null +++ b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/contract/maven/verify/VerifyEngine.java @@ -0,0 +1,224 @@ +package com.jd.blockchain.contract.maven.verify; + +import com.jd.blockchain.contract.ContractJarUtils; +import com.jd.blockchain.contract.maven.ContractClass; +import com.jd.blockchain.contract.maven.ContractField; +import com.jd.blockchain.contract.maven.ContractMethod; +import com.jd.blockchain.contract.maven.asm.ASMClassVisitor; +import com.jd.blockchain.contract.maven.rule.BlackList; +import com.jd.blockchain.contract.maven.rule.WhiteList; +import org.apache.maven.plugin.logging.Log; +import org.objectweb.asm.ClassReader; + +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import static com.jd.blockchain.contract.ContractJarUtils.loadAllClasses; + + +public class VerifyEngine { + + private Log LOGGER; + + private File jarFile; + + private String mainClass; + + private BlackList black; + + private WhiteList white; + + // 代表的只是当前方法,不代表该方法中的内部方法 + private Set haveManagedMethods = new HashSet<>(); + + // 代表的是处理的参数 + private Set haveManagedFields = new HashSet<>(); + + public VerifyEngine(Log LOGGER, File jarFile, String mainClass, BlackList black, WhiteList white) { + this.LOGGER = LOGGER; + this.jarFile = jarFile; + this.mainClass = mainClass; + this.black = black; + this.white = white; + } + + public void verify() throws Exception { + // 加载所有的jar,然后ASM获取MAP + URL jarURL = jarFile.toURI().toURL(); + + URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{jarURL}, + Thread.currentThread().getContextClassLoader()); + + // 解析Jar包中所有的Class + Map allContractClasses = resolveClasses(jarClasses()); + + // 开始处理MainClass + verify(urlClassLoader, allContractClasses); + + // 校验完成后需要释放ClassLoader,否则无法删除该Jar包 + urlClassLoader.close(); + } + + public void verify(URLClassLoader urlClassLoader, Map allContractClasses) throws Exception { + // 获取MainClass + String mainClassKey = convertClassKey(mainClass); + ContractClass mainContractClass = allContractClasses.get(mainClassKey); + if (mainContractClass == null) { + LOGGER.error(String.format("Load Main Class = [%s] NULL !!!", mainClass)); + throw new IllegalStateException("MainClass is NULL !!!"); + } + // 校验该Class中所有方法 + Map methods = mainContractClass.getMethods(); + if (!methods.isEmpty()) { + for (Map.Entry entry : methods.entrySet()) { + ContractMethod method = entry.getValue(); + verify(urlClassLoader, allContractClasses, method); + } + } + } + + public void verify(URLClassLoader urlClassLoader, Map allContractClasses, ContractMethod method) throws Exception { + // 获取方法中涉及到的所有的Class及Method + // 首先判断该方法对应的Class是否由urlClassLoader加载 + // 首先判断该ClassName对应方法是否处理过 + String managedKey = managedKey(method); + if (haveManagedMethods.contains(managedKey)) { + return; + } + // 将该方法设置为已处理 + haveManagedMethods.add(managedKey); + String dotClassName = method.getDotClassName(); + + + Class dotClass = urlClassLoader.loadClass(dotClassName); + + if (dotClass == null) { + return; + } + String dotClassLoader = null; + ClassLoader classLoader = dotClass.getClassLoader(); + + if (classLoader != null) { + dotClassLoader = dotClass.getClassLoader().toString(); + } + + if (dotClassLoader != null && dotClassLoader.contains("URLClassLoader")) { + + // 说明是URLClassLoader,这个需要先从黑名单和白名单列表中操作 + // 首先判断是否是黑名单,黑名单优先级最高 + if (black.isBlack(dotClass, method.getMethodName())) { + throw new IllegalStateException(String.format("Class [%s] Method [%s] is Black !!!", dotClassName, method.getMethodName())); + } else { + // 不是黑名单的情况下,判断是否为白名单 + if (white.isWhite(dotClass)) { + return; + } + // 如果不属于白名单,则需要判断其子方法 + List innerMethods = method.getMethodList(); + if (!innerMethods.isEmpty()) { + for (ContractMethod innerMethod : innerMethods) { + // 需要重新从AllMap中获取,因为生成时并未处理其关联关系 + ContractClass innerClass = allContractClasses.get(innerMethod.getClassName()); + if (innerClass != null) { + ContractMethod verifyMethod = innerClass.method(innerMethod.getMethodName()); + verify(urlClassLoader, allContractClasses, verifyMethod); + } else { + verify(urlClassLoader, allContractClasses, innerMethod); + } + } + } + List innerFields = method.getAllFieldList(); + if (!innerFields.isEmpty()) { + for (ContractField innerField : innerFields) { + verify(urlClassLoader, innerField); + } + } + } + } else { + // 非URLClassLoader加载的类,只需要做判断即可 + // 对于系统加载的类,其白名单优先级高于黑名单 + // 1、不再需要获取其方法; + // 首先判断是否为白名单 + if (white.isWhite(dotClass)) { + return; + } + // 然后判断其是否为黑名单 + if (black.isBlack(dotClass, method.getMethodName())) { + throw new IllegalStateException(String.format("Class [%s] Method [%s] is Black !!!", dotClassName, method.getMethodName())); + } + } + } + + public void verify(URLClassLoader urlClassLoader, ContractField field) throws Exception { + // 获取方法中涉及到的所有的Class及Method + // 首先判断该方法对应的Class是否由urlClassLoader加载 + // 首先判断该ClassName对应方法是否处理过 + String managedKey = managedKey(field); + if (haveManagedFields.contains(managedKey)) { + return; + } + // 将该字段设置为已读 + haveManagedFields.add(managedKey); + + Class dotClass = urlClassLoader.loadClass(field.getDotClassName()); + + if (dotClass == null) { + return; + } + + if (black.isBlackField(dotClass)) { + throw new IllegalStateException(String.format("Class [%s] Field [%s] is Black !!!", field.getDotClassName(), field.getFieldName())); + } + } + + private Map jarClasses() throws Exception { + return loadAllClasses(jarFile); + } + + private Map resolveClasses(Map allClasses) { + + Map allContractClasses = new ConcurrentHashMap<>(); + + for (Map.Entry entry : allClasses.entrySet()) { + byte[] classContent = entry.getValue(); + if (classContent == null || classContent.length == 0) { + continue; + } + String className = entry.getKey().substring(0, entry.getKey().length() - 6); + + String dotClassName = ContractJarUtils.dotClassName(className); + if (white.isWhite(dotClassName) || black.isBlackClass(dotClassName)) { + continue; + } + + ContractClass contractClass = new ContractClass(className); + ClassReader cr = new ClassReader(classContent); + cr.accept(new ASMClassVisitor(contractClass), ClassReader.SKIP_DEBUG); + allContractClasses.put(className, contractClass); + } + return allContractClasses; + } + + private String convertClassKey(final String classKey) { + String newClassKey = classKey; + if (classKey.endsWith(".class")) { + newClassKey = classKey.substring(0, classKey.length() - 6); + } + newClassKey = newClassKey.replaceAll("\\.", "/"); + return newClassKey; + } + + private String managedKey(ContractMethod method) { + return method.getDotClassName() + "-" + method.getMethodName(); + } + + private String managedKey(ContractField field) { + return field.getDotClassName() + "--" + field.getFieldName(); + } +} diff --git a/source/contract/contract-maven-plugin/src/main/resources/blacks.conf b/source/contract/contract-maven-plugin/src/main/resources/blacks.conf new file mode 100644 index 00000000..caa20370 --- /dev/null +++ b/source/contract/contract-maven-plugin/src/main/resources/blacks.conf @@ -0,0 +1,19 @@ +java.io.File +java.io.InputStream +java.io.OutputStream +java.io.DataInput +java.io.DataOutput +java.io.Reader +java.io.Writer +java.io.Flushable +java.nio.channels.* +java.nio.file.* +java.net.* +java.sql.* +java.lang.reflect.* +java.lang.Class +java.lang.ClassLoader +java.util.Random +java.lang.System-currentTimeMillis +java.lang.System-nanoTime +com.jd.blockchain.ledger.BlockchainKeyGenerator-generate \ No newline at end of file diff --git a/source/contract/contract-maven-plugin/src/main/resources/config.properties b/source/contract/contract-maven-plugin/src/main/resources/config.properties deleted file mode 100644 index fdfca23e..00000000 --- a/source/contract/contract-maven-plugin/src/main/resources/config.properties +++ /dev/null @@ -1 +0,0 @@ -blacklist=java.io,java.net,java.util.Random \ No newline at end of file diff --git a/source/contract/contract-maven-plugin/src/main/resources/providers.conf b/source/contract/contract-maven-plugin/src/main/resources/providers.conf new file mode 100644 index 00000000..b2df66eb --- /dev/null +++ b/source/contract/contract-maven-plugin/src/main/resources/providers.conf @@ -0,0 +1,22 @@ +com.jd.blockchain/* +com.alibaba/fastjson +org.slf4j/* +org.apache.logging.log4j/* +org.aspectj/* +redis.clients/* +org.rocksdb/* +io.grpc/* +org.apache.commons/* +org.apache.httpcomponents/* +org.apache.logging.log4j/* +org.reflections/reflections +com.google.guava/guava +commons-cli/commons-cli +commons-codec/commons-codec +commons-httpclient/commons-httpclient +commons-io/commons-io +io.netty/* +org.slf4j/* +org.springframework.boot/* +org.springframework.security/* +org.springframework/* \ No newline at end of file diff --git a/source/contract/contract-maven-plugin/src/main/resources/sys-contract.properties b/source/contract/contract-maven-plugin/src/main/resources/sys-contract.properties deleted file mode 100644 index a7179906..00000000 --- a/source/contract/contract-maven-plugin/src/main/resources/sys-contract.properties +++ /dev/null @@ -1,19 +0,0 @@ -#PROJECT_BASE_DIR -PROJECT_BASE_DIR=E:\\gitCode\\block\\prototype\\ -#LEDGER_BASE_CLASS_PATH -LEDGER_BASE_CLASS_PATH=E:\\gitCode\\block\\prototype\\libs\\ - -#deploy and execute the contract; -cParam=com.jd.blockchain.contract.AssetContract3 -sParam=E:\\gitCode\\block\\prototype\\source\\sdk\\contract-sample\\src\\main\\java\\ -eParam=utf-8 -oParam=E:\\gitCode\\block\\prototype\\source\\contract\\contract-maven-plugin\\src\\test\\resources\\ -host=127.0.0.1 -port=8081 -event = issue-asset -ownerPassword=E:\\gitCode\\block\\prototype\\source\\contract\\contract-maven-plugin\\conf\\ownerPassword.txt -ownerPubPath=E:\\gitCode\\block\\prototype\\source\\contract\\contract-maven-plugin\\conf\\jd-com.pub -ownerPrvPath=E:\\gitCode\\block\\prototype\\source\\contract\\contract-maven-plugin\\conf\\jd-com.priv -chainCodePath=E:\\gitCode\\block\\prototype\\source\\contract\\contract-maven-plugin\\src\\test\\resources\\AssetContract3.contract -ledgerHash=6FEQDTQMnBGANpfX4haXuWHKHw5cZ6P1h2ocqwckYBxp4 -contractArgs=101##999##abc \ No newline at end of file diff --git a/source/contract/contract-maven-plugin/src/main/resources/whites.conf b/source/contract/contract-maven-plugin/src/main/resources/whites.conf new file mode 100644 index 00000000..08e7d754 --- /dev/null +++ b/source/contract/contract-maven-plugin/src/main/resources/whites.conf @@ -0,0 +1,3 @@ +com.jd.blockchain.* +java.nio.charset.Charset +com.alibaba.fastjson.* \ No newline at end of file diff --git a/source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/CheckImportsMojoTest.java b/source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/CheckImportsMojoTest.java deleted file mode 100644 index 66b194c0..00000000 --- a/source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/CheckImportsMojoTest.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.CheckImportsMojo; -import org.apache.maven.plugin.testing.AbstractMojoTestCase; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; - -/** - * @Author zhaogw - * @Date 2019/3/1 21:27 - */ -public class CheckImportsMojoTest extends AbstractMojoTestCase { - Logger logger = LoggerFactory.getLogger(CheckImportsMojoTest.class); - - @Test - public void test1() throws Exception { - File pom = getTestFile( "src/test/resources/project-to-test/pom.xml" ); - assertNotNull( pom ); - assertTrue( pom.exists() ); - - CheckImportsMojo myMojo = (CheckImportsMojo) lookupMojo( "checkImports", pom ); - assertNotNull( myMojo ); - myMojo.execute(); - } -} diff --git a/source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/ContractDeployMojoTest.java b/source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/ContractDeployMojoTest.java index 0d205758..bb907445 100644 --- a/source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/ContractDeployMojoTest.java +++ b/source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/ContractDeployMojoTest.java @@ -1,21 +1,21 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.ContractDeployMojo; - -import java.lang.reflect.Field; - -/** - * for contract deploy and exe; - * @Author zhaogw - * @Date 2018/11/02 09:06 - */ -public class ContractDeployMojoTest { - private ContractDeployMojo contractDeployMojo = new ContractDeployMojo(); - - private void fieldHandle(String fieldName,Object objValue) throws NoSuchFieldException, IllegalAccessException { - Field field = contractDeployMojo.getClass().getDeclaredField(fieldName);//name为类Instance中的private属性 - field.setAccessible(true);//=true,可访问私有变量。 - Class typeClass = field.getType(); - field.set(contractDeployMojo, objValue); - } -} +//package com.jd.blockchain.ledger; +// +//import com.jd.blockchain.contract.maven.ContractDeployMojo; +// +//import java.lang.reflect.Field; +// +///** +// * for contract deploy and exe; +// * @Author zhaogw +// * @Date 2018/11/02 09:06 +// */ +//public class ContractDeployMojoTest { +// private ContractDeployMojo contractDeployMojo = new ContractDeployMojo(); +// +// private void fieldHandle(String fieldName,Object objValue) throws NoSuchFieldException, IllegalAccessException { +// Field field = contractDeployMojo.getClass().getDeclaredField(fieldName);//name为类Instance中的private属性 +// field.setAccessible(true);//=true,可访问私有变量。 +// Class typeClass = field.getType(); +// field.set(contractDeployMojo, objValue); +// } +//} diff --git a/source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/ContractTestBase.java b/source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/ContractTestBase.java new file mode 100644 index 00000000..e3065766 --- /dev/null +++ b/source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/ContractTestBase.java @@ -0,0 +1,50 @@ +//package com.jd.blockchain.ledger; +// +//import org.apache.maven.model.Build; +//import org.apache.maven.project.MavenProject; +//import org.junit.Test; +//import org.springframework.core.io.ClassPathResource; +// +//import java.io.File; +// +//public class ContractTestBase { +// +// public static MavenProject mavenProjectInit() { +// MavenProject mavenProject = new MavenProject(); +// mavenProject.setBuild(buildInit()); +// mavenProject.setFile(file()); +// return mavenProject; +// } +// +// public static File file() { +// String resDir = resourceDir(); +// File file = new File(resDir); +// String path = file.getParentFile().getParentFile().getPath(); +// return new File(path + File.separator + "src"); +// } +// +// public static Build buildInit() { +// Build build = new Build(); +// build.setDirectory(resourceDir()); +// return build; +// } +// +// public static String resourceDir() { +// try { +// ClassPathResource classPathResource = new ClassPathResource("complex.jar"); +// return classPathResource.getFile().getParentFile().getPath(); +// } catch (Exception e) { +// throw new IllegalStateException(e); +// } +// } +// +// @Test +// public void testResourceDir() { +// System.out.println(resourceDir()); +// } +// +// @Test +// public void testFile() { +// System.out.println(file().getPath()); +// } +//} diff --git a/source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/ContractVerifyMojoTest.java b/source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/ContractVerifyMojoTest.java new file mode 100644 index 00000000..119f5cbf --- /dev/null +++ b/source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/ContractVerifyMojoTest.java @@ -0,0 +1,28 @@ +//package com.jd.blockchain.ledger; +// +//import com.jd.blockchain.contract.maven.ContractVerifyMojo; +//import org.apache.maven.plugin.testing.AbstractMojoTestCase; +//import org.junit.Test; +//import org.slf4j.Logger; +//import org.slf4j.LoggerFactory; +// +//import java.io.File; +// +///** +// * @Author zhaogw +// * @Date 2019/3/1 21:27 +// */ +//public class ContractVerifyMojoTest extends AbstractMojoTestCase { +// Logger logger = LoggerFactory.getLogger(ContractVerifyMojoTest.class); +// +// @Test +// public void test1() throws Exception { +// File pom = getTestFile( "src/test/resources/project-to-test/pom.xml" ); +// assertNotNull( pom ); +// assertTrue( pom.exists() ); +// +// ContractVerifyMojo myMojo = (ContractVerifyMojo) lookupMojo( "contractVerify", pom ); +// assertNotNull( myMojo ); +// myMojo.execute(); +// } +//} diff --git a/source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/ContractVerifyTest_.java b/source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/ContractVerifyTest_.java new file mode 100644 index 00000000..ea6828b6 --- /dev/null +++ b/source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/ContractVerifyTest_.java @@ -0,0 +1,47 @@ +//package com.jd.blockchain.ledger; +// +//import com.jd.blockchain.contract.maven.ContractVerifyMojo; +//import org.apache.maven.project.MavenProject; +//import org.junit.Before; +//import org.junit.Test; +// +//import java.lang.reflect.Field; +// +//import static com.jd.blockchain.ledger.ContractTestBase.mavenProjectInit; +// +//public class ContractVerifyTest_ { +// +// private MavenProject project; +// +// private String finalName; +// +// @Before +// public void testInit() { +// project = mavenProjectInit(); +// finalName = "complex"; +// } +// +// @Test +// public void test() throws Exception { +// ContractVerifyMojo contractVerifyMojo = contractVerifyMojoConf(); +// contractVerifyMojo.execute(); +// } +// +// private ContractVerifyMojo contractVerifyMojoConf() throws Exception { +// ContractVerifyMojo contractVerifyMojo = new ContractVerifyMojo(); +// // 为不影响其内部结构,通过反射进行私有变量赋值 +// Class clazz = contractVerifyMojo.getClass(); +// Field projectField = clazz.getDeclaredField("project"); +// Field finalNameField = clazz.getDeclaredField("finalName"); +// +// // 更新权限 +// projectField.setAccessible(true); +// finalNameField.setAccessible(true); +// +// // 设置具体值 +// projectField.set(contractVerifyMojo, project); +// finalNameField.set(contractVerifyMojo, finalName); +// +// return contractVerifyMojo; +// } +//} diff --git a/source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/MyProjectStub.java b/source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/MyProjectStub.java index 473115af..34614e30 100644 --- a/source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/MyProjectStub.java +++ b/source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/MyProjectStub.java @@ -1,67 +1,67 @@ -package com.jd.blockchain.ledger; - -import org.apache.maven.model.Build; -import org.apache.maven.model.Model; -import org.apache.maven.model.io.xpp3.MavenXpp3Reader; -import org.apache.maven.plugin.testing.stubs.MavenProjectStub; -import org.codehaus.plexus.util.ReaderFactory; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -/** - * @author zhaogw - * date 2019/6/4 18:33 - */ - -public class MyProjectStub extends MavenProjectStub -{ - /** - * Default constructor - */ - public MyProjectStub() - { - MavenXpp3Reader pomReader = new MavenXpp3Reader(); - Model model; - try - { - model = pomReader.read( ReaderFactory.newXmlReader( new File( getBasedir(), "pom.xml" ) ) ); - setModel( model ); - } - catch ( Exception e ) - { - throw new RuntimeException( e ); - } - - setGroupId( model.getGroupId() ); - setArtifactId( model.getArtifactId() ); - setVersion( model.getVersion() ); - setName( model.getName() ); - setUrl( model.getUrl() ); - setPackaging( model.getPackaging() ); - - Build build = new Build(); - build.setFinalName( model.getArtifactId() ); - build.setDirectory( getBasedir() + "/target" ); - build.setSourceDirectory( getBasedir() + "/src/main/java" ); - build.setOutputDirectory( getBasedir() + "/target/classes" ); - build.setTestSourceDirectory( getBasedir() + "/src/test/java" ); - build.setTestOutputDirectory( getBasedir() + "/target/test-classes" ); - setBuild( build ); - - List compileSourceRoots = new ArrayList(); - compileSourceRoots.add( getBasedir() + "/src/main/java" ); - setCompileSourceRoots( compileSourceRoots ); - - List testCompileSourceRoots = new ArrayList(); - testCompileSourceRoots.add( getBasedir() + "/src/test/java" ); - setTestCompileSourceRoots( testCompileSourceRoots ); - } - - /** {@inheritDoc} */ - public File getBasedir() - { - return new File( super.getBasedir() + "/src/test/resources/project-to-test/" ); - } -} +//package com.jd.blockchain.ledger; +// +//import org.apache.maven.model.Build; +//import org.apache.maven.model.Model; +//import org.apache.maven.model.io.xpp3.MavenXpp3Reader; +//import org.apache.maven.plugin.testing.stubs.MavenProjectStub; +//import org.codehaus.plexus.util.ReaderFactory; +// +//import java.io.File; +//import java.util.ArrayList; +//import java.util.List; +// +///** +// * @author zhaogw +// * date 2019/6/4 18:33 +// */ +// +//public class MyProjectStub extends MavenProjectStub +//{ +// /** +// * Default constructor +// */ +// public MyProjectStub() +// { +// MavenXpp3Reader pomReader = new MavenXpp3Reader(); +// Model model; +// try +// { +// model = pomReader.read( ReaderFactory.newXmlReader( new File( getBasedir(), "pom.xml" ) ) ); +// setModel( model ); +// } +// catch ( Exception e ) +// { +// throw new RuntimeException( e ); +// } +// +// setGroupId( model.getGroupId() ); +// setArtifactId( model.getArtifactId() ); +// setVersion( model.getVersion() ); +// setName( model.getName() ); +// setUrl( model.getUrl() ); +// setPackaging( model.getPackaging() ); +// +// Build build = new Build(); +// build.setFinalName( model.getArtifactId() ); +// build.setDirectory( getBasedir() + "/target" ); +// build.setSourceDirectory( getBasedir() + "/src/main/java" ); +// build.setOutputDirectory( getBasedir() + "/target/classes" ); +// build.setTestSourceDirectory( getBasedir() + "/src/test/java" ); +// build.setTestOutputDirectory( getBasedir() + "/target/test-classes" ); +// setBuild( build ); +// +// List compileSourceRoots = new ArrayList(); +// compileSourceRoots.add( getBasedir() + "/src/main/java" ); +// setCompileSourceRoots( compileSourceRoots ); +// +// List testCompileSourceRoots = new ArrayList(); +// testCompileSourceRoots.add( getBasedir() + "/src/test/java" ); +// setTestCompileSourceRoots( testCompileSourceRoots ); +// } +// +// /** {@inheritDoc} */ +// public File getBasedir() +// { +// return new File( super.getBasedir() + "/src/test/resources/project-to-test/" ); +// } +//} diff --git a/source/contract/contract-maven-plugin/src/test/resources/complex.jar b/source/contract/contract-maven-plugin/src/test/resources/complex.jar new file mode 100644 index 00000000..3c595b4d Binary files /dev/null and b/source/contract/contract-maven-plugin/src/test/resources/complex.jar differ diff --git a/source/contract/contract-samples/pom.xml b/source/contract/contract-samples/pom.xml index fc3a89b9..3935abe5 100644 --- a/source/contract/contract-samples/pom.xml +++ b/source/contract/contract-samples/pom.xml @@ -27,6 +27,12 @@ ${project.version} provided + + + com.alibaba + fastjson + + @@ -34,11 +40,11 @@ maven-assembly-plugin - random + complex false - com.jd.blockchain.contract.RandomContractImpl + com.jd.blockchain.contract.ComplexContractImpl diff --git a/source/contract/contract-samples/src/main/java/com/jd/blockchain/contract/ComplexContract.java b/source/contract/contract-samples/src/main/java/com/jd/blockchain/contract/ComplexContract.java new file mode 100644 index 00000000..b23511f3 --- /dev/null +++ b/source/contract/contract-samples/src/main/java/com/jd/blockchain/contract/ComplexContract.java @@ -0,0 +1,7 @@ +package com.jd.blockchain.contract; + +@Contract +public interface ComplexContract { + @ContractEvent(name = "read-key") + String read(String address, String key); +} diff --git a/source/contract/contract-samples/src/main/java/com/jd/blockchain/contract/ComplexContractImpl.java b/source/contract/contract-samples/src/main/java/com/jd/blockchain/contract/ComplexContractImpl.java new file mode 100644 index 00000000..15763954 --- /dev/null +++ b/source/contract/contract-samples/src/main/java/com/jd/blockchain/contract/ComplexContractImpl.java @@ -0,0 +1,12 @@ +package com.jd.blockchain.contract; + + +import com.alibaba.fastjson.JSON; + +public class ComplexContractImpl implements ComplexContract { + @Override + public String read(String address, String key) { + String json = JSON.toJSONString(address); + return System.currentTimeMillis() + "" + json; + } +} diff --git a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/ECDSAUtils.java b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/ECDSAUtils.java index 097ce957..73b9e7b3 100644 --- a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/ECDSAUtils.java +++ b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/ECDSAUtils.java @@ -7,6 +7,8 @@ import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.generators.ECKeyPairGenerator; import org.bouncycastle.crypto.params.*; import org.bouncycastle.crypto.signers.ECDSASigner; +import org.bouncycastle.jce.ECNamedCurveTable; +import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec; import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.math.ec.ECMultiplier; import org.bouncycastle.math.ec.ECPoint; @@ -28,12 +30,10 @@ public class ECDSAUtils { // p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1 // the curve equation is y^2 = x^3 + 7. - private static final X9ECParameters X9_PARAMS = SECNamedCurves.getByName("secp256k1"); - private static final ECCurve CURVE = X9_PARAMS.getCurve(); - private static final ECPoint ECDSA_G = X9_PARAMS.getG(); - private static final BigInteger ECDSA_H = X9_PARAMS.getH(); - private static final BigInteger ECDSA_N = X9_PARAMS.getN(); - private static final ECDomainParameters DOMAIN_PARAMS = new ECDomainParameters(CURVE, ECDSA_G,ECDSA_N,ECDSA_H); + private static final ECNamedCurveParameterSpec PARAMS = ECNamedCurveTable.getParameterSpec("secp256k1"); + private static final ECCurve CURVE = PARAMS.getCurve(); + private static final ECDomainParameters DOMAIN_PARAMS = new ECDomainParameters( + CURVE, PARAMS.getG(), PARAMS.getN(), PARAMS.getH()); //-----------------Key Generation Algorithm----------------- diff --git a/source/crypto/crypto-composite/src/test/java/com/jd/blockchain/AppTest.java b/source/crypto/crypto-composite/src/test/java/com/jd/blockchain/AppTest.java new file mode 100644 index 00000000..941b907f --- /dev/null +++ b/source/crypto/crypto-composite/src/test/java/com/jd/blockchain/AppTest.java @@ -0,0 +1,20 @@ +package com.jd.blockchain; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +/** + * Unit test for simple App. + */ +public class AppTest +{ + /** + * Rigorous Test :-) + */ + @Test + public void shouldAnswerWithTrue() + { + assertTrue( true ); + } +} diff --git a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/KeyGenUtils.java b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/KeyGenUtils.java new file mode 100644 index 00000000..717c813c --- /dev/null +++ b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/KeyGenUtils.java @@ -0,0 +1,187 @@ +package com.jd.blockchain.crypto; + +import java.util.Arrays; + +import javax.crypto.SecretKey; + +import com.jd.blockchain.utils.ConsoleUtils; +import com.jd.blockchain.utils.codec.Base58Utils; +import com.jd.blockchain.utils.io.BytesUtils; +import com.jd.blockchain.utils.io.FileUtils; +import com.jd.blockchain.utils.security.AESUtils; +import com.jd.blockchain.utils.security.DecryptionException; +import com.jd.blockchain.utils.security.ShaUtils; + +public class KeyGenUtils { + + private static final byte[] PUB_KEY_FILE_MAGICNUM = { (byte) 0xFF, 112, 117, 98 }; + + private static final byte[] PRIV_KEY_FILE_MAGICNUM = { (byte) 0x00, 112, 114, 118 }; + + /** + * 公钥编码输出为 Base58 字符; + * + * @param pubKey + * @return + */ + public static String encodePubKey(PubKey pubKey) { + byte[] pubKeyBytes = BytesUtils.concat(PUB_KEY_FILE_MAGICNUM, pubKey.toBytes()); + String base58PubKey = Base58Utils.encode(pubKeyBytes); + return base58PubKey; + } + + public static PubKey decodePubKey(String base58PubKey) { + byte[] keyBytes = Base58Utils.decode(base58PubKey); + return decodePubKey(keyBytes); + } + + public static String encodePrivKey(PrivKey privKey, String base58Pwd) { + byte[] pwdBytes = Base58Utils.decode(base58Pwd); + return encodePrivKey(privKey, pwdBytes); + } + + public static String encodePrivKey(PrivKey privKey, byte[] pwdBytes) { + byte[] encodedPrivKeyBytes = encryptPrivKey(privKey, pwdBytes); + String base58PrivKey = Base58Utils.encode(encodedPrivKeyBytes); + return base58PrivKey; + } + + public static byte[] encryptPrivKey(PrivKey privKey, byte[] pwdBytes) { + SecretKey userKey = AESUtils.generateKey128(pwdBytes); + byte[] encryptedPrivKeyBytes = AESUtils.encrypt(privKey.toBytes(), userKey); + return BytesUtils.concat(PRIV_KEY_FILE_MAGICNUM, encryptedPrivKeyBytes); + } + + /** + * @param encodedPubKeyBytes + * @return + */ + private static PubKey decodePubKeyBytes(byte[] encodedPubKeyBytes) { + byte[] pubKeyBytes = Arrays.copyOfRange(encodedPubKeyBytes, PUB_KEY_FILE_MAGICNUM.length, + encodedPubKeyBytes.length); + return new PubKey(pubKeyBytes); + } + + public static PrivKey decryptedPrivKeyBytes(byte[] encodedPrivKeyBytes, byte[] pwdBytes) { + // Read privKye; + SecretKey userKey = AESUtils.generateKey128(pwdBytes); + byte[] encryptedKeyBytes = Arrays.copyOfRange(encodedPrivKeyBytes, PRIV_KEY_FILE_MAGICNUM.length, + encodedPrivKeyBytes.length); + try { + byte[] plainKeyBytes = AESUtils.decrypt(encryptedKeyBytes, userKey); + return new PrivKey(plainKeyBytes); + } catch (DecryptionException e) { + throw new DecryptionException("Invalid password!", e); + } + } + + public static PubKey readPubKey(String keyFile) { + String base58KeyString = FileUtils.readText(keyFile); + return decodePubKey(base58KeyString); + } + + /** + * 解码公钥; + * + * @param encodedPubKeyBytes 从公钥; + * @return + */ + public static PubKey decodePubKey(byte[] encodedPubKeyBytes) { + if (BytesUtils.startsWith(encodedPubKeyBytes, PUB_KEY_FILE_MAGICNUM)) { + // Read pubKey; + return decodePubKeyBytes(encodedPubKeyBytes); + } + + throw new IllegalArgumentException("The specified bytes is not valid PubKey generated by the KeyGen tool!"); + } + + /** + * 从控制台读取加密口令,以二进制数组形式返回原始口令的一次SHA256的结果; + * + * @return + */ + public static byte[] readPassword() { + byte[] pwdBytes = ConsoleUtils.readPassword(); + return ShaUtils.hash_256(pwdBytes); + } + + /** + * 对指定的原始密码进行编码生成用于加解密的密码; + * + * @param rawPassword + * @return + */ + public static byte[] encodePassword(String rawPassword) { + byte[] pwdBytes = BytesUtils.toBytes(rawPassword, "UTF-8"); + return ShaUtils.hash_256(pwdBytes); + } + + /** + * 对指定的原始密码进行编码生成用于加解密的密码; + * + * @param rawPassword + * @return + */ + public static String encodePasswordAsBase58(String rawPassword) { + return Base58Utils.encode(encodePassword(rawPassword)); + } + + /** + * 从控制台读取加密口令,以Base58字符串形式返回口令的一次SHA256的结果; + * + * @return + */ + public static String readPasswordString() { + return Base58Utils.encode(readPassword()); + } + + public static PrivKey readPrivKey(String keyFile, String base58Pwd) { + return readPrivKey(keyFile, Base58Utils.decode(base58Pwd)); + } + + /** + * 从文件读取私钥; + * + * @param keyFile + * @param pwdBytes + * @return + */ + public static PrivKey readPrivKey(String keyFile, byte[] pwdBytes) { + String base58KeyString = FileUtils.readText(keyFile); + byte[] keyBytes = Base58Utils.decode(base58KeyString); + if (!BytesUtils.startsWith(keyBytes, PRIV_KEY_FILE_MAGICNUM)) { + throw new IllegalArgumentException("The specified file is not a private key file!"); + } + return decryptedPrivKeyBytes(keyBytes, pwdBytes); + } + + public static PrivKey decodePrivKey(String base58Key, String base58Pwd) { + byte[] decryptedKey = Base58Utils.decode(base58Pwd); + return decodePrivKey(base58Key, decryptedKey); + } + + public static PrivKey decodePrivKey(String base58Key, byte[] pwdBytes) { + byte[] keyBytes = Base58Utils.decode(base58Key); + if (!BytesUtils.startsWith(keyBytes, PRIV_KEY_FILE_MAGICNUM)) { + throw new IllegalArgumentException("The specified file is not a private key file!"); + } + return decryptedPrivKeyBytes(keyBytes, pwdBytes); + } + + public static PrivKey decodePrivKeyWithRawPassword(String base58Key, String rawPassword) { + byte[] pwdBytes = encodePassword(rawPassword); + byte[] keyBytes = Base58Utils.decode(base58Key); + if (!BytesUtils.startsWith(keyBytes, PRIV_KEY_FILE_MAGICNUM)) { + throw new IllegalArgumentException("The specified file is not a private key file!"); + } + return decryptedPrivKeyBytes(keyBytes, pwdBytes); + } + + public static boolean isPubKeyBytes(byte[] keyBytes) { + return BytesUtils.startsWith(keyBytes, PUB_KEY_FILE_MAGICNUM); + } + + public static boolean isPrivKeyBytes(byte[] keyBytes) { + return BytesUtils.startsWith(keyBytes, PRIV_KEY_FILE_MAGICNUM); + } +} diff --git a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CSRBuilder.java b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CSRBuilder.java index 790cb7db..3de606db 100644 --- a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CSRBuilder.java +++ b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CSRBuilder.java @@ -16,6 +16,9 @@ import org.bouncycastle.util.encoders.Base64; import java.io.IOException; import java.security.*; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; /** * @author zhanglin33 @@ -25,16 +28,18 @@ import java.security.*; */ public class CSRBuilder { - private String BC = BouncyCastleProvider.PROVIDER_NAME; + private final String BC = BouncyCastleProvider.PROVIDER_NAME; private PublicKey pubKey; private PrivateKey privKey; private String algoName; + private int keyLength; public void init() { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); algoName = "SHA1withRSA"; + keyLength = 2048; KeyPairGenerator generator; try { generator = KeyPairGenerator.getInstance("RSA", BC); @@ -47,10 +52,11 @@ public class CSRBuilder { } } - public void init(String algoName, int KeyLength) { + public void init(String algoName, int keyLength) { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); - this.algoName = algoName; + this.algoName = algoName; + this.keyLength = keyLength; KeyPairGenerator generator; KeyPair keyPair; @@ -60,34 +66,69 @@ public class CSRBuilder { switch (hashAndSignature[1]) { case "RSA": { generator = KeyPairGenerator.getInstance("RSA", BC); - generator.initialize(KeyLength); - keyPair = generator.generateKeyPair(); - pubKey = keyPair.getPublic(); - privKey = keyPair.getPrivate(); + generator.initialize(keyLength); break; } case "SM2": { generator = KeyPairGenerator.getInstance("EC", BC); - if (KeyLength != 256) { + if (keyLength != 256) { throw new CryptoException("SM3withSM2 with unsupported key length [" + - KeyLength +"] in CSR!"); + keyLength +"] in CSR!"); } generator.initialize(new ECNamedCurveGenParameterSpec("sm2p256v1")); - keyPair = generator.generateKeyPair(); - pubKey = keyPair.getPublic(); - privKey = keyPair.getPrivate(); break; } default: throw new CryptoException("Unsupported algorithm [" + algoName + "] with key length [" + - KeyLength +"] in CSR!"); + keyLength +"] in CSR!"); } + keyPair = generator.generateKeyPair(); + pubKey = keyPair.getPublic(); + privKey = keyPair.getPrivate(); } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) { throw new CryptoException(e.getMessage(), e); } } + public void init(String algoName, byte[] pubKeyBytes, byte[] privKeyBytes) { + + Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); + this.algoName = algoName; + String[] hashAndSignature = algoName.split("with"); + + X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(pubKeyBytes); + PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(privKeyBytes); + + KeyFactory keyFactory; + + try { + switch (hashAndSignature[1]) { + case "RSA": { + keyFactory = KeyFactory.getInstance("RSA"); + privKey = keyFactory.generatePrivate(privKeySpec); + pubKey = keyFactory.generatePublic(pubKeySpec); + keyLength = (pubKey.getEncoded().length < 4096 / 8)? 2048: 4096; + break; + } + + case "SM2": { + keyFactory = KeyFactory.getInstance("EC", BouncyCastleProvider.PROVIDER_NAME); + privKey = keyFactory.generatePrivate(privKeySpec); + pubKey = keyFactory.generatePublic(pubKeySpec); + keyLength = 256; + break; + } + + default: throw new CryptoException("Unsupported algorithm [" + algoName + "] with the given key pair!"); + } + } catch (InvalidKeySpecException | NoSuchAlgorithmException | NoSuchProviderException e) { + throw new CryptoException(e.getMessage(), e); + } + + + } + public String buildRequest(String countryName, String stateName, String cityName, String organizationName, String departmentName, String domainName, String emailName) { @@ -126,4 +167,12 @@ public class CSRBuilder { public PrivateKey getPrivKey() { return privKey; } + + public String getAlgoName() { + return algoName; + } + + public int getKeyLength() { + return keyLength; + } } diff --git a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CertParser.java b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CertParser.java index 8267d28b..e54c17db 100644 --- a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CertParser.java +++ b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CertParser.java @@ -25,6 +25,7 @@ public class CertParser { private String sigAlgName; private String userName; private String issuerName; + private int keyLength; private Date startTime; private Date endTime; @@ -71,6 +72,17 @@ public class CertParser { sigAlgName = userCert.getSigAlgName(); issuerName = userCert.getIssuerX500Principal().getName(); userName = userCert.getSubjectX500Principal().getName(); + + switch (sigAlgName) { + case "SM3WITHSM2": { + keyLength = 256; + break; + } + case "SHA1WITHRSA": { + keyLength = (pubKey.getEncoded().length < 4096 / 8)? 2048: 4096; + break; + } + } } // certificate string in Base64 format @@ -121,6 +133,10 @@ public class CertParser { return issuerName; } + public int getKeyLength() { + return keyLength; + } + public Date getStartTime() { return startTime; } diff --git a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunctionTest.java b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunctionTest.java index b7c7d831..64ca7eb5 100644 --- a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunctionTest.java +++ b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunctionTest.java @@ -1,9 +1,13 @@ package com.jd.blockchain.crypto.service.pki; import com.jd.blockchain.crypto.*; +import com.jd.blockchain.crypto.utils.CSRBuilder; +import com.jd.blockchain.crypto.utils.CertParser; import com.jd.blockchain.utils.io.BytesUtils; +import org.bouncycastle.util.encoders.Hex; import org.junit.Test; +import java.security.*; import java.util.Random; import static com.jd.blockchain.crypto.CryptoAlgorithm.*; @@ -125,4 +129,145 @@ public class SHA1WITHRSA2048SignatureFunctionTest { resolvedSignatureDigest.getAlgorithm()); assertArrayEquals(signatureDigestBytes, resolvedSignatureDigest.toBytes()); } + + @Test + public void testWithCSRAndCert() { + + String countryName = "CN"; + String stateName = "Beijing"; + String cityName = "Beijing"; + String organizationName = "JD.com"; + String departmentName = "Blockchain Department"; + String domainName = "ledger.jd.com"; + String emailName = "zhanglin33@jd.com"; + + + String publicKeyStr = "30820122300d06092a864886f70d01010105000382010f003082010a0282010100c91e978897a36b" + + "30a57d265807441b0eff40c5572ecf029cd0cb2999b715edd2d5345c7b60c003075b1352629d03b943d08b25bfc5245" + + "a400f9ecbc1757394eac452d6316bf90cfcff5edfc427e277aa5266e89b1b2daa2e69dad5575515f49417c9ff332c83" + + "0dcd5537381f08e00b11123ad947bb11b18666d264ab5d8cdc92d0967fd7e0e6677746e2f01270d0594f74cda4e9d77" + + "4c6f3824499896bfb6424684af260d71b57a1366b741104fc647d9e38de055568daad60c116686e4afa1e9c83e9e30c" + + "7216e61353da2f75b2dde2c0ae870cf0ccc90490d1e22ecccbf3985d30933689847e6faf946993f930f83ac5b816075" + + "793a9a6df20727552a21be30203010001"; + + String privateKeyStr = "308204bd020100300d06092a864886f70d0101010500048204a7308204a30201000282010100c91e" + + "978897a36b30a57d265807441b0eff40c5572ecf029cd0cb2999b715edd2d5345c7b60c003075b1352629d03b943d08" + + "b25bfc5245a400f9ecbc1757394eac452d6316bf90cfcff5edfc427e277aa5266e89b1b2daa2e69dad5575515f49417" + + "c9ff332c830dcd5537381f08e00b11123ad947bb11b18666d264ab5d8cdc92d0967fd7e0e6677746e2f01270d0594f7" + + "4cda4e9d774c6f3824499896bfb6424684af260d71b57a1366b741104fc647d9e38de055568daad60c116686e4afa1e" + + "9c83e9e30c7216e61353da2f75b2dde2c0ae870cf0ccc90490d1e22ecccbf3985d30933689847e6faf946993f930f83" + + "ac5b816075793a9a6df20727552a21be30203010001028201003975637e93300d8a2ee573e47762f6461117cca96d46" + + "982cfc1be6ed3318f142a845d6dc2ad680a703d69fd56b9d6a3b1d23fbeb6f63c4e303736f2bfca5c2585631825f494" + + "534783d6f3a07bd0b5efbcaa1faf7814ac9118c8d8820f4be9a8b0ac6db819fc86b538bf284369d9f009a667668a82d" + + "224f7122041eddb492ef5b02d462aa11bc550bf3785a5d7538043586cfb0cd5c313a4746f22a5d4a89a412b279a7517" + + "176b1858a9677a1a60605aa0b2a7d260cf2e9e23a0e67c4a23ac046c62973239e84874c3695cc3f34073a62bd50b597" + + "ee06092a93fa6e41303ab4d2293ffad4c8db06e6516ae0a26a4d681305c3b7d535b540a638ca6cff1ce483750281810" + + "0e39967c5b287bd319b448255a1033591c74f4d688eb71f89a674cdb1be999e9abcf40e6b7f0bb3054262d7625002da" + + "7d34e56055ee130b66d682a0b9f8ea240a7e2dd1ff3f4b32f3bd352ba0a5dffc0315da34922493c267597787222213b" + + "f87d99fbd2a809c2647a1937cd1e303d746373db7c409a2ef33f8c06bb838bc612702818100e2374c71db5f0b4a199f" + + "f9d646a1785a84383a14aceb506f515b380c69ff45b51d0e941f55f0a234d8a3ee30bed656142bb5b985e462c44d234" + + "cfd424ecd6ca5fc70503862978ffe42b45bd698a99091d6fc65e2d85652e0ef56c52e8e05a6c5e879922c1d794e22f3" + + "51998217b5c6637a6abb716bf90cd1f23a2eedcdfface50281805d28a872224e2f2183e539d7e4ccd47b73f240c4004" + + "e72493c69e8dbcd2141eb22565f249edee20ad00e770c95a5655b0470b2cad964d030eab293292bfa62802cff824a10" + + "d52de8d8545024346106dd186fb53ef05bcea1d0dbfce2fac1cc8ec583fdc0ccdd9d498a983cea081ac55dc734aae84" + + "1ed802d6caf0e285c88b6d702818068b2a752daf1364c6967bd3e0b1a98956c3489cd1feb19232c4847bc97226aa4d4" + + "79f6dc39ee51649c0fe321f471470db6dd38ac5b73caded8c3bd437f2d5c67c65a450693bb0a0de7d989d7dc783e4d0" + + "16f77c871d02233b1123bd8bc2aa97157934cafd6445a819a93ddb4743cd141215b5cbdb5f7629398c48d0bcb17d671" + + "028181009282554329b89bcb2236a7e2a5bff53627e3ca7cc792d65236085741bc62a3f5767654722af561eff175664" + + "1af60e3d3959f63f0fec00cb29443ffca4ff751a76ecc6fa192ebe08ec9f643b9bb0d11bc90c1e850f0528ef223ea5f" + + "e4b4c107cc3a9eb26e6b84d74d87acbf7cc760cd788cbc30f95f8399077b25cdd924604c01"; + + String expectedCSR = "MIIC4jCCAcoCAQAwgZwxCzAJBgNVBAYTAkNOMRAwDgYDVQQIDAdCZWlqaW5nMRAwDgYDVQQHDAdCZWlqaW" + + "5nMQ8wDQYDVQQKDAZKRC5jb20xHjAcBgNVBAsMFUJsb2NrY2hhaW4gRGVwYXJ0bWVudDEWMBQGA1UEAwwNbGVkZ2VyLmpkL" + + "mNvbTEgMB4GCSqGSIb3DQEJARYRemhhbmdsaW4zM0BqZC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJ" + + "HpeIl6NrMKV9JlgHRBsO/0DFVy7PApzQyymZtxXt0tU0XHtgwAMHWxNSYp0DuUPQiyW/xSRaQA+ey8F1c5TqxFLWMWv5DPz" + + "/Xt/EJ+J3qlJm6JsbLaouadrVV1UV9JQXyf8zLIMNzVU3OB8I4AsREjrZR7sRsYZm0mSrXYzcktCWf9fg5md3RuLwEnDQWU" + + "90zaTp13TG84JEmYlr+2QkaEryYNcbV6E2a3QRBPxkfZ443gVVaNqtYMEWaG5K+h6cg+njDHIW5hNT2i91st3iwK6HDPDMy" + + "QSQ0eIuzMvzmF0wkzaJhH5vr5Rpk/kw+DrFuBYHV5Oppt8gcnVSohvjAgMBAAGgADANBgkqhkiG9w0BAQUFAAOCAQEALKHw" + + "BrlppbN+CSJwHxO99rv2XVD7L8lwwiMqdMzoNHxZUoob4AcGS3Iyxy6obX8fZh7DCA4nN0AmvrJCmWD3hCLclWKlwXTwvFe" + + "WIeB4xEB9MVPV6/Hs/QaI9Rjhd+O/Alfzov8y+KyYHEWmwxHj2RtQm1ZeulELzMvRjsqP+m5tOM1hLnPMU+AF1tZ9Fc7Jbm" + + "7Dwh6TAPpmaH1aVbHsnlZyCp8K4nMozVogcXJqg3qsbeJ6c/TofL0fURqiTJxLKMC0aD0TwVcNwDWEmc8cpqGheG1g6UF5l" + + "QBpeR2Br4f3LXJgr1Op1RxRy6I+X7h1IL38Q3jAOoU4y04O/+an7g=="; + + String expectedUserCert = "MIIERjCCAy6gAwIBAgIFIChmYJgwDQYJKoZIhvcNAQEFBQAwWTELMAkGA1UEBhMCQ04xMDAuBgNVB" + + "AoTJ0NoaW5hIEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEYMBYGA1UEAxMPQ0ZDQSBURVNUIE9DQTExMB4X" + + "DTE5MDgyODA2MzEyNVoXDTIxMDgyODA2MzEyNVoweDELMAkGA1UEBhMCQ04xGDAWBgNVBAoTD0NGQ0EgVEVTVCBPQ0ExMTE" + + "RMA8GA1UECxMITG9jYWwgUkExFTATBgNVBAsTDEluZGl2aWR1YWwtMTElMCMGA1UEAxQcMDUxQHpoYW5nbGluIUBaMTg2MT" + + "IyMjkyOTVANTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMkel4iXo2swpX0mWAdEGw7/QMVXLs8CnNDLKZm3F" + + "e3S1TRce2DAAwdbE1JinQO5Q9CLJb/FJFpAD57LwXVzlOrEUtYxa/kM/P9e38Qn4neqUmbomxstqi5p2tVXVRX0lBfJ/zMs" + + "gw3NVTc4HwjgCxESOtlHuxGxhmbSZKtdjNyS0JZ/1+DmZ3dG4vAScNBZT3TNpOnXdMbzgkSZiWv7ZCRoSvJg1xtXoTZrdBE" + + "E/GR9njjeBVVo2q1gwRZobkr6HpyD6eMMchbmE1PaL3Wy3eLArocM8MzJBJDR4i7My/OYXTCTNomEfm+vlGmT+TD4OsW4Fg" + + "dXk6mm3yBydVKiG+MCAwEAAaOB9TCB8jAfBgNVHSMEGDAWgBT8C7xEmg4xoYOpgYcnHgVCxr9W+DBIBgNVHSAEQTA/MD0GC" + + "GCBHIbvKgECMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2ZjYS5jb20uY24vdXMvdXMtMTUuaHRtMDoGA1UdHwQzMDEw" + + "L6AtoCuGKWh0dHA6Ly8yMTAuNzQuNDIuMy9PQ0ExMS9SU0EvY3JsMjY2NTAuY3JsMAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQ" + + "UOTy45HymVDivPwA83lRoMpShasQwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMA0GCSqGSIb3DQEBBQUAA4IBAQ" + + "A7NFkDMV1mRV/07DJUdZJzvkm+QihhpLp7D2dUblCCEt0jjY5RdLiWG7HvJnlPTThiSkiejEO0Fy1cQzA5jYRhwp+70X8X9" + + "bt5jEBP/V4PyRXKKEvKZMdppLIeVI6rZk/gJzPh2FQYv3qWaINilxLOBP8Qa0kdMBwo6D6/MYwnSGv5zP4NLFUysLUJiKoM" + + "lAzEQSPNnkYRX6nogpkdN91/xgH3GA7fiihrjm5oxMAupCli9LQqvlUvRtv5EKIN9c+ixCAYFagG9IIjMDXbDne77n15i01" + + "420N8sjfTlr9v3W0v1gBSzjzFOT+TTTUtrjfO/Vm8iqq+z22QKIXgYjSF"; + + String issuerCert = + "-----BEGIN CERTIFICATE-----\n" + + "MIIDzzCCAregAwIBAgIKUalCR1Mt5ZSK8jANBgkqhkiG9w0BAQUFADBZMQswCQYD\n" + + "VQQGEwJDTjEwMC4GA1UEChMnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24g\n" + + "QXV0aG9yaXR5MRgwFgYDVQQDEw9DRkNBIFRFU1QgQ1MgQ0EwHhcNMTIwODI5MDU1\n" + + "NDM2WhcNMzIwODI0MDU1NDM2WjBZMQswCQYDVQQGEwJDTjEwMC4GA1UEChMnQ2hp\n" + + "bmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRgwFgYDVQQDEw9D\n" + + "RkNBIFRFU1QgT0NBMTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC8\n" + + "jn0n8Fp6hcRdACdn1+Y6GAkC6KGgNdKyHPrmsdmhCjnd/i4qUFwnG8cp3D4lFw1G\n" + + "jmjSO5yVYbik/NbS6lbNpRgTK3fDfMFvLJpRIC+IFhG9SdAC2hwjsH9qTpL9cK2M\n" + + "bSdrC6pBdDgnbzaM9AGBF4Y6vXhj5nah4ZMsBvDp19LzXjlGuTPLuAgv9ZlWknsd\n" + + "RN70PIAmvomd10uqX4GIJ4Jq/FdKXOLZ2DNK/NhRyN6Yq71L3ham6tutXeZow5t5\n" + + "0254AnUlo1u6SeH9F8itER653o/oMLFwp+63qXAcqrHUlOQPX+JI8fkumSqZ4F2F\n" + + "t/HfVMnqdtFNCnh5+eIBAgMBAAGjgZgwgZUwHwYDVR0jBBgwFoAUdN7FjQp9EBqq\n" + + "aYNbTSHOhpvMcTgwDAYDVR0TBAUwAwEB/zA4BgNVHR8EMTAvMC2gK6AphidodHRw\n" + + "Oi8vMjEwLjc0LjQyLjMvdGVzdHJjYS9SU0EvY3JsMS5jcmwwCwYDVR0PBAQDAgEG\n" + + "MB0GA1UdDgQWBBT8C7xEmg4xoYOpgYcnHgVCxr9W+DANBgkqhkiG9w0BAQUFAAOC\n" + + "AQEAb7W0K9fZPA+JPw6lRiMDaUJ0oh052yEXreMBfoPulxkBj439qombDiFggRLc\n" + + "3g8wIEKzMOzOKXTWtnzYwN3y/JQSuJb/M1QqOEEM2PZwCxI4AkBuH6jg03RjlkHg\n" + + "/kTtuIFp9ItBCC2/KkKlp0ENfn4XgVg2KtAjZ7lpyVU0LPnhEqqUVY/xthjlCSa7\n" + + "/XHNStRxsfCTIBUWJ8n2FZyQhfV/UkMNHDBIiJR0v6C4Ai0/290WvbPEIAq+03Si\n" + + "fsHzBeA0C8lP5VzfAr6wWePaZMCpStpLaoXNcAqReKxQllElOqAhRxC5VKH+rnIQ\n" + + "OMRZvB7FRyE9IfwKApngcZbA5g==\n" + + "-----END CERTIFICATE-----"; + + byte[] rawPublicKeyBytes = Hex.decode(publicKeyStr); + byte[] rawPrivateKeyBytes = Hex.decode(privateKeyStr); + + CSRBuilder builder = new CSRBuilder(); + builder.init("SHA1withRSA", rawPublicKeyBytes, rawPrivateKeyBytes); + + String csr = builder.buildRequest(countryName,stateName,cityName, + organizationName,departmentName,domainName, + emailName); + + assertEquals(expectedCSR,csr); + + CertParser parser = new CertParser(); + parser.parse(expectedUserCert,issuerCert); + + PublicKey rawPublicKeyInCert = parser.getPubKey(); + // check that the public key in inputs and the public key in certificate are consistent + assertArrayEquals(rawPublicKeyBytes, rawPublicKeyInCert.getEncoded()); + + String algoName = parser.getSigAlgName(); + int keyLength = parser.getKeyLength(); + String length = String.valueOf(keyLength); + String algo = (algoName.contains("RSA")? (algoName + length).toUpperCase(): algoName.toUpperCase()); + + CryptoAlgorithm algorithm = Crypto.getAlgorithm(algo); + assertNotNull(algorithm); + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + PubKey pubKey = new PubKey(algorithm, rawPublicKeyBytes); + PrivKey privKey = new PrivKey(algorithm, rawPrivateKeyBytes); + + // signTest + byte[] data = new byte[1024]; + Random random = new Random(); + random.nextBytes(data); + + SignatureDigest signature = signatureFunction.sign(privKey, data); + assertTrue(signatureFunction.verify(signature, pubKey, data)); + } } diff --git a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunctionTest.java b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunctionTest.java index 9444771b..466e245d 100644 --- a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunctionTest.java +++ b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunctionTest.java @@ -1,9 +1,13 @@ package com.jd.blockchain.crypto.service.pki; import com.jd.blockchain.crypto.*; +import com.jd.blockchain.crypto.utils.CSRBuilder; +import com.jd.blockchain.crypto.utils.CertParser; import com.jd.blockchain.utils.io.BytesUtils; +import org.bouncycastle.util.encoders.Hex; import org.junit.Test; +import java.security.PublicKey; import java.util.Random; import static com.jd.blockchain.crypto.CryptoAlgorithm.ASYMMETRIC_KEY; @@ -125,4 +129,186 @@ public class SHA1WITHRSA4096SignatureFunctionTest { resolvedSignatureDigest.getAlgorithm()); assertArrayEquals(signatureDigestBytes, resolvedSignatureDigest.toBytes()); } + + @Test + public void testWithCSRAndCert() { + + String countryName = "CN"; + String stateName = "Beijing"; + String cityName = "Beijing"; + String organizationName = "JD.com"; + String departmentName = "Blockchain Department"; + String domainName = "ledger.jd.com"; + String emailName = "zhanglin33@jd.com"; + + + String publicKeyStr = "30820222300d06092a864886f70d01010105000382020f003082020a0282020100b40edee83b609e" + + "aa001f2496f95d2f3302513306ec9a8e7fce0d2e141fce7ee357a7465314c3f5f4b08cb6c95803c368ddbfedba483cb" + + "5c45914037ceee5783fc971a12ef9b0e4158dc379b59499eee629324a9beb350c4c10e50837345be128b91f43a03381" + + "758bbefe41c45712e4b5fdd5bde780167283706b24e37dd753db65b4c6b3e49cd8be825665d9a29a24b77e76473df02" + + "2327873555aa33ba2ffcc766cbefedc46ec868d10f817822540eaf5754c074dd6d428355ce24a058a4c9ce41e48aad5" + + "92e7955cf93d779d03d3acf25ae271346a9e4255e4ed902ae016032b04efbee98f43cd767653e089b37540e537aede9" + + "dbc04f8f1a858b2764b9eedac80b6a8da5ff02aab4be94e071c70718fde7227cdefec31600a1c55bac16f4de9dea8ab" + + "7824c1ec783b818dfe005f040a3f6872b1c7a6c31a66c1b06eb8d872a23d1b4fdadf9eed58f93b2a2bc145638a79a81" + + "904d39b22128ced18a2556c21888ed1ec8ad59bd6764f1ea16eb7f3574c53166f0827b5072d23017bd725adeb63eeb2" + + "29a4e78d4d7426e936753902bb51e3cd90630314f4ab41272a9e36cb668b2ba9c2ebc02e9ef0c377c88482e839f2f4d" + + "5c8efcfbe1280e52c6bdf80aa487ae03ff9dd9fd981f78172bc1141ce6031b0b8915658d830c696662507d3cf4ddba8" + + "7daabf97c15cbef58b15e84f16f879328c7c65076d94fc6b4514549831850203010001"; + + String privateKeyStr = "30820942020100300d06092a864886f70d01010105000482092c308209280201000282020100b40e" + + "dee83b609eaa001f2496f95d2f3302513306ec9a8e7fce0d2e141fce7ee357a7465314c3f5f4b08cb6c95803c368ddb" + + "fedba483cb5c45914037ceee5783fc971a12ef9b0e4158dc379b59499eee629324a9beb350c4c10e50837345be128b9" + + "1f43a03381758bbefe41c45712e4b5fdd5bde780167283706b24e37dd753db65b4c6b3e49cd8be825665d9a29a24b77" + + "e76473df022327873555aa33ba2ffcc766cbefedc46ec868d10f817822540eaf5754c074dd6d428355ce24a058a4c9c" + + "e41e48aad592e7955cf93d779d03d3acf25ae271346a9e4255e4ed902ae016032b04efbee98f43cd767653e089b3754" + + "0e537aede9dbc04f8f1a858b2764b9eedac80b6a8da5ff02aab4be94e071c70718fde7227cdefec31600a1c55bac16f" + + "4de9dea8ab7824c1ec783b818dfe005f040a3f6872b1c7a6c31a66c1b06eb8d872a23d1b4fdadf9eed58f93b2a2bc14" + + "5638a79a81904d39b22128ced18a2556c21888ed1ec8ad59bd6764f1ea16eb7f3574c53166f0827b5072d23017bd725" + + "adeb63eeb229a4e78d4d7426e936753902bb51e3cd90630314f4ab41272a9e36cb668b2ba9c2ebc02e9ef0c377c8848" + + "2e839f2f4d5c8efcfbe1280e52c6bdf80aa487ae03ff9dd9fd981f78172bc1141ce6031b0b8915658d830c696662507" + + "d3cf4ddba87daabf97c15cbef58b15e84f16f879328c7c65076d94fc6b451454983185020301000102820200063fece" + + "3452a579f817513454d3efb842afcac077dbf689a4d89de13533e4cdfb1bb6be0b6dc0d65b29a13bf1dd7b598e67782" + + "b6204b4128e149a54c59136c6ed45c661296169a78180d54a46595c939c26ccd33a7c095de6f08b01610726ef885a26" + + "cebbad5efc14bbe1204d15be5c5de5b64a5cc279b4e6e20bded4a8126973b2ac0e9de11c6a1282f7d060693909a30e0" + + "c49cc500bedd38ed99c18830a26dd39f772aabf527410d54ed338db022d674f21f1332d3b5d5f67234a58a97300d130" + + "aed0d46effc2b4e4895665934188d0c75749e26ca5b97645957989530657b332b4ef202b3d70fe2e07d0d526240fbe1" + + "68e320357be0f54e18008a233a8137e23ca1c54074b31c57eebee49bf2f1c66ea97a2c846a8d26680b97e1240d6763e" + + "60bcd8d696c806362b18bf0504a39e4d465a9548091dbe97c36f6d8e038d95a72c0a88ff524dc81fe0ed2afd69f4251" + + "1a90687a4c632c812234a19a7312b2dea3fcd4515800eca700733b0f83509184fe8d3cd21385f0ef0cec37c433d354f" + + "aed61662a62902c8708c81e2af20898f649c1bafd600baa0409c943cf82bc90ea20a8972da7ab3a252f4f08df2509de" + + "e1dacfe787eef4d60c0c92ec7a3c6277d7be39deed7704ac721d8efd138a410d632a32535142cf977b09d9fb680bc96" + + "c538c00440d5e1ed71f8510e6524e564d69a24d03f1a9a0c326b421e32550801c890282010100e8d72f8f1fbeada724" + + "3e6df25337a2e7fc43e3d4f39877f89abb3b5e453f20f339a1f35e0a2847122f0bd835e6b43fd276f447da04f85cfca" + + "0fa8bf49b313239e36f9595ef1bfb9b8247bf01cc407dfc444421161a5b2e96d4d1d90cea185945e9447d21a2d8a461" + + "f43dff9ba58043feeb49552a3bf2472eea59b2aa8631048c76a15898065be0ef957d4802c827e30339d66ad7aed5851" + + "a5896f12d33f45800dcb10859531c590af7a75e9fa81f1d937a287fb6b066d58720584af2ae161e083681655ae77f48" + + "34bfe0accf1d12bbdd8c2644f78b207cfcb2dedf9fe7d29e1ae5c2a5623f5a1770db27d2636450c79fd39bce39f009b" + + "598e0298e1f77bf8d3d0282010100c5f7af9258a42da93204cecb71c544397bc16691cf0d41308fbd3b88eca7d101d1" + + "377dfe3b7e66707d3e5543b21033ab6c5b0de577740c6e335f512eeb2a839c3f2baeca4ce80e3fbd8fb93fa983e1719" + + "5c5fee63bc163df334a80f2767871e3434adc0bc7030dea44fce414a08da7e918e6f030cfb20b2d29033e9ef1be3e08" + + "ef1f50df0c9325a20ff01d0b7a06761403ae3498aea8bad93110d61a6386d470e630990029e2cb098de40fafa330911" + + "6c3c6de180b7fa41ae14553e891148ab53e970ce372b1777826983baaccac08290e343761d8daa2505f1dc45b8511a3" + + "6e2d0909237be9ae7ebbaa00b31de1224f32959e4e6f3428140ca8e1e5580789e902820100674075609c8d2be880940" + + "6a17cf1a1160ab1f8684895862e023fa0f60ef30da38e1d1914cca04bd3ee74ec2e0ade47a70705108fc7c0734bbbff" + + "1eed1b9cd74f00624d0d2df954bc032bd9b1ec6774f6d736f70d1c26ef2407bffee65130f6f59f99b57ba3013af40d2" + + "12926565fe8c734835276e61a6c228bddb6f3138acd1f94c3bbcbbe9623cb5a9931c3ba0aa60a9a2d5137cfd9f3aa59" + + "3aa63c8b5b8162f07ab8df1391f092827bffe400e3bb73d8a9f8e88495357f3482b2c9a7153bc01c9b88dca4e7b6975" + + "db73e2aa213daa7462cfa4c63afc67d30bcd0a1d2657da323dc0b06e45d09240cab3e0ac1436922a0ede8a79ca0519d" + + "375a7621d23269690282010100bbc1299716d2bf2b94f0d260494ada65da6596adfb3d8af24fa11d71c36175eccf4c5" + + "e065cce88c16f474afea546907aa88dc3243aa2a9976ac99fe96bc82a8269b738534d9558ce432ea87724829bb26a66" + + "1a56a99dc4e6cf727dd17762cc40ca759934e24e9747f49e14832bb2ade97960adb4dd86f2eaa5d719f10d3d6d00742" + + "9b33d98638671a9c40507f9775f4da41ff86a465c68b9ccbb371458086c3b9755c8064bb378f55ac94dc73a72b96869" + + "cd969e1f69b36e7af091a024d8e2a4faf3af999811904937f171c58fd028fd272786cf1a286180f074fee1fdd6b8b5a" + + "9a8c42e0f3b95ef4474fbace54dbc887865467b0524e64dfda3be7b117e34e1028201001a7e846231c34400c1f704e7" + + "fec6e46c87d61f269b71942bc9cc72005ba30eea3db5d0e5b0b754f7a00b96c883399982b5b3a9916765c5ed9129e44" + + "a791ce6892f85758c637bc040da132b8f0cd0ac36ba3aae9334414a77f0b50c0aa03643bfd59b9a621342a4807e46fc" + + "52a5a12fd3ff6762e181c40c2baf3653043c836b14700463af5d68a2a2897897edb5f217d655d5bcd24e7910062f40e" + + "00f19e2f94b45efbbf60cbf734830756baf72dcfca8d2858ca5df63336999474945f3744a96e4ce23f9067bbca849ef" + + "1048cba3a4aad73ed73b0fcd8c2e9f6d06aa768548d7107aa58d9d296f853543f6569e4dd33270540d983460773794f" + + "e9196fc5a54cd"; + + String expectedCSR = "MIIE4jCCAsoCAQAwgZwxCzAJBgNVBAYTAkNOMRAwDgYDVQQIDAdCZWlqaW5nMRAwDgYDVQQHDAdCZWlqaW" + + "5nMQ8wDQYDVQQKDAZKRC5jb20xHjAcBgNVBAsMFUJsb2NrY2hhaW4gRGVwYXJ0bWVudDEWMBQGA1UEAwwNbGVkZ2VyLmpkL" + + "mNvbTEgMB4GCSqGSIb3DQEJARYRemhhbmdsaW4zM0BqZC5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC0" + + "Dt7oO2CeqgAfJJb5XS8zAlEzBuyajn/ODS4UH85+41enRlMUw/X0sIy2yVgDw2jdv+26SDy1xFkUA3zu5Xg/yXGhLvmw5BW" + + "Nw3m1lJnu5ikySpvrNQxMEOUINzRb4Si5H0OgM4F1i77+QcRXEuS1/dW954AWcoNwayTjfddT22W0xrPknNi+glZl2aKaJL" + + "d+dkc98CIyeHNVWqM7ov/Mdmy+/txG7IaNEPgXgiVA6vV1TAdN1tQoNVziSgWKTJzkHkiq1ZLnlVz5PXedA9Os8lricTRqn" + + "kJV5O2QKuAWAysE777pj0PNdnZT4ImzdUDlN67enbwE+PGoWLJ2S57trIC2qNpf8CqrS+lOBxxwcY/ecifN7+wxYAocVbrB" + + "b03p3qireCTB7Hg7gY3+AF8ECj9ocrHHpsMaZsGwbrjYcqI9G0/a357tWPk7KivBRWOKeagZBNObIhKM7RiiVWwhiI7R7Ir" + + "Vm9Z2Tx6hbrfzV0xTFm8IJ7UHLSMBe9clretj7rIppOeNTXQm6TZ1OQK7UePNkGMDFPSrQScqnjbLZosrqcLrwC6e8MN3yI" + + "SC6Dny9NXI78++EoDlLGvfgKpIeuA/+d2f2YH3gXK8EUHOYDGwuJFWWNgwxpZmJQfTz03bqH2qv5fBXL71ixXoTxb4eTKMf" + + "GUHbZT8a0UUVJgxhQIDAQABoAAwDQYJKoZIhvcNAQEFBQADggIBAKowJTG9mZLbDHRndmDUd7PWrq1AiCdk6DStV39B/REF" + + "OrMYcW9X4Ak69fhXQDtD4gu2lKtumDY0oJ8xleM2FHUSzdooTWb7P/QtCIBy27sH6nvlefRWi7ngSTNJlDmwgr0l07UzZU1" + + "Yl/ZULn0XlNAFal+qt+4ZNdiulNwkL6IofXV/8vqOeQw5iICDBYHItyY/mqD8IIaClVd8yNpEuE/W9GdJIDNXQjpug+BxL/" + + "FbjAs6P3ZzJboedJE5urbru2jjb7atl3w/eDo4r6+XNSD8d1PgVmVhzN2WpUWsZNeH2jd9AA6436GjsBssgSRKEc3FTJ+lO" + + "0Jw2d8GewXXkIv8CT4L3BFwqZhGQt27wlb87+W4dIC05JIaJx52869dvu1ky1CL73GROXeS8rVYJsPwVmK2xy3QTaeHGEQh" + + "kiVNeV1cc3mll2z7fgbkjPD8zDNBWUdzSXQMzecY1CBD02iz6LaHfvkI7gXXoiIf1cJrnLtYhv3lG45jKr0E45/Wn7oXmYk" + + "RM4/zHO4KnY7Pp3b3QTgkRJaPnZiG7aiCrdnTIopDSGpTWSPWDLjgwgaCPPz5Pd2Fk+SAE98o7Cu8O0vxMASpd4liaedASE" + + "n6hnrvcTkFLLG2ecZzJZ0aEqPi4es0FqlqVZrLPH2UYpECgfhkGQQKAx4eRTAZFhz1GSkd"; + + String expectedUserCert = "MIIFRjCCBC6gAwIBAgIFIChmYWIwDQYJKoZIhvcNAQEFBQAwWTELMAkGA1UEBhMCQ04xMDAuBgNVB" + + "AoTJ0NoaW5hIEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEYMBYGA1UEAxMPQ0ZDQSBURVNUIE9DQTExMB4X" + + "DTE5MDgyODA4MDAxMVoXDTIxMDgyODA4MDAxMVoweDELMAkGA1UEBhMCQ04xGDAWBgNVBAoTD0NGQ0EgVEVTVCBPQ0ExMTE" + + "RMA8GA1UECxMITG9jYWwgUkExFTATBgNVBAsTDEluZGl2aWR1YWwtMTElMCMGA1UEAxQcMDUxQHpoYW5nbGluIUBaMTg2MT" + + "IyMjkyOTVANzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALQO3ug7YJ6qAB8klvldLzMCUTMG7JqOf84NLhQfz" + + "n7jV6dGUxTD9fSwjLbJWAPDaN2/7bpIPLXEWRQDfO7leD/JcaEu+bDkFY3DebWUme7mKTJKm+s1DEwQ5Qg3NFvhKLkfQ6Az" + + "gXWLvv5BxFcS5LX91b3ngBZyg3BrJON911PbZbTGs+Sc2L6CVmXZopokt352Rz3wIjJ4c1Vaozui/8x2bL7+3Ebsho0Q+Be" + + "CJUDq9XVMB03W1Cg1XOJKBYpMnOQeSKrVkueVXPk9d50D06zyWuJxNGqeQlXk7ZAq4BYDKwTvvumPQ812dlPgibN1QOU3rt" + + "6dvAT48ahYsnZLnu2sgLao2l/wKqtL6U4HHHBxj95yJ83v7DFgChxVusFvTeneqKt4JMHseDuBjf4AXwQKP2hyscemwxpmw" + + "bBuuNhyoj0bT9rfnu1Y+TsqK8FFY4p5qBkE05siEoztGKJVbCGIjtHsitWb1nZPHqFut/NXTFMWbwgntQctIwF71yWt62Pu" + + "simk541NdCbpNnU5ArtR482QYwMU9KtBJyqeNstmiyupwuvALp7ww3fIhILoOfL01cjvz74SgOUsa9+Aqkh64D/53Z/Zgfe" + + "BcrwRQc5gMbC4kVZY2DDGlmYlB9PPTduofaq/l8FcvvWLFehPFvh5Mox8ZQdtlPxrRRRUmDGFAgMBAAGjgfUwgfIwHwYDVR" + + "0jBBgwFoAU/Au8RJoOMaGDqYGHJx4FQsa/VvgwSAYDVR0gBEEwPzA9BghggRyG7yoBAjAxMC8GCCsGAQUFBwIBFiNodHRwO" + + "i8vd3d3LmNmY2EuY29tLmNuL3VzL3VzLTE1Lmh0bTA6BgNVHR8EMzAxMC+gLaArhilodHRwOi8vMjEwLjc0LjQyLjMvT0NB" + + "MTEvUlNBL2NybDI2NjU1LmNybDALBgNVHQ8EBAMCA+gwHQYDVR0OBBYEFBl1Gmb89bqbEKyFcTU3eOY/5NmKMB0GA1UdJQQ" + + "WMBQGCCsGAQUFBwMCBggrBgEFBQcDBDANBgkqhkiG9w0BAQUFAAOCAQEADEU//9rnWN1s3/ariMHIUmgzRUdz3fWYiDRzGC" + + "mcnnETlXDstGmoYmwCM+QwHw6cyKXkwkg9zV7c7CgM471ZuF00gq115d432Ps3RXGCpfQ2fn3gs+91ky/YqJOOyBb8KL0IP" + + "r/Zh56/y3XX0gORn4GLqaj+oVZrFcmKrPtVhySlXNiD5BRMq39mUbuLBweGsgNVQ9VxiWc8ZBGjlJ6OVsngbvWrtl3zgkKb" + + "X9lhr8Bxq3G+jOV8jvr1Dkn4a65g2TWcFquxmPvRc5UwN29CimbC7RViCL3Jp+zrGasqbjycuqu5eSXb6gG4/aV0/K9yn5k" + + "YlZMIBlbsXSEi5J26pg=="; + + String issuerCert = + "-----BEGIN CERTIFICATE-----\n" + + "MIIDzzCCAregAwIBAgIKUalCR1Mt5ZSK8jANBgkqhkiG9w0BAQUFADBZMQswCQYD\n" + + "VQQGEwJDTjEwMC4GA1UEChMnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24g\n" + + "QXV0aG9yaXR5MRgwFgYDVQQDEw9DRkNBIFRFU1QgQ1MgQ0EwHhcNMTIwODI5MDU1\n" + + "NDM2WhcNMzIwODI0MDU1NDM2WjBZMQswCQYDVQQGEwJDTjEwMC4GA1UEChMnQ2hp\n" + + "bmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRgwFgYDVQQDEw9D\n" + + "RkNBIFRFU1QgT0NBMTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC8\n" + + "jn0n8Fp6hcRdACdn1+Y6GAkC6KGgNdKyHPrmsdmhCjnd/i4qUFwnG8cp3D4lFw1G\n" + + "jmjSO5yVYbik/NbS6lbNpRgTK3fDfMFvLJpRIC+IFhG9SdAC2hwjsH9qTpL9cK2M\n" + + "bSdrC6pBdDgnbzaM9AGBF4Y6vXhj5nah4ZMsBvDp19LzXjlGuTPLuAgv9ZlWknsd\n" + + "RN70PIAmvomd10uqX4GIJ4Jq/FdKXOLZ2DNK/NhRyN6Yq71L3ham6tutXeZow5t5\n" + + "0254AnUlo1u6SeH9F8itER653o/oMLFwp+63qXAcqrHUlOQPX+JI8fkumSqZ4F2F\n" + + "t/HfVMnqdtFNCnh5+eIBAgMBAAGjgZgwgZUwHwYDVR0jBBgwFoAUdN7FjQp9EBqq\n" + + "aYNbTSHOhpvMcTgwDAYDVR0TBAUwAwEB/zA4BgNVHR8EMTAvMC2gK6AphidodHRw\n" + + "Oi8vMjEwLjc0LjQyLjMvdGVzdHJjYS9SU0EvY3JsMS5jcmwwCwYDVR0PBAQDAgEG\n" + + "MB0GA1UdDgQWBBT8C7xEmg4xoYOpgYcnHgVCxr9W+DANBgkqhkiG9w0BAQUFAAOC\n" + + "AQEAb7W0K9fZPA+JPw6lRiMDaUJ0oh052yEXreMBfoPulxkBj439qombDiFggRLc\n" + + "3g8wIEKzMOzOKXTWtnzYwN3y/JQSuJb/M1QqOEEM2PZwCxI4AkBuH6jg03RjlkHg\n" + + "/kTtuIFp9ItBCC2/KkKlp0ENfn4XgVg2KtAjZ7lpyVU0LPnhEqqUVY/xthjlCSa7\n" + + "/XHNStRxsfCTIBUWJ8n2FZyQhfV/UkMNHDBIiJR0v6C4Ai0/290WvbPEIAq+03Si\n" + + "fsHzBeA0C8lP5VzfAr6wWePaZMCpStpLaoXNcAqReKxQllElOqAhRxC5VKH+rnIQ\n" + + "OMRZvB7FRyE9IfwKApngcZbA5g==\n" + + "-----END CERTIFICATE-----"; + + byte[] rawPublicKeyBytes = Hex.decode(publicKeyStr); + byte[] rawPrivateKeyBytes = Hex.decode(privateKeyStr); + + CSRBuilder builder = new CSRBuilder(); + builder.init("SHA1withRSA", rawPublicKeyBytes, rawPrivateKeyBytes); + + String csr = builder.buildRequest(countryName,stateName,cityName, + organizationName,departmentName,domainName, + emailName); + + assertEquals(expectedCSR,csr); + + CertParser parser = new CertParser(); + parser.parse(expectedUserCert,issuerCert); + + PublicKey rawPublicKeyInCert = parser.getPubKey(); + // check that the public key in inputs and the public key in certificate are consistent + assertArrayEquals(rawPublicKeyBytes, rawPublicKeyInCert.getEncoded()); + + String algoName = parser.getSigAlgName(); + int keyLength = parser.getKeyLength(); + String length = String.valueOf(keyLength); + String algo = (algoName.contains("RSA")? (algoName + length).toUpperCase(): algoName.toUpperCase()); + + CryptoAlgorithm algorithm = Crypto.getAlgorithm(algo); + assertNotNull(algorithm); + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + PubKey pubKey = new PubKey(algorithm, rawPublicKeyBytes); + PrivKey privKey = new PrivKey(algorithm, rawPrivateKeyBytes); + + // signTest + byte[] data = new byte[1024]; + Random random = new Random(); + random.nextBytes(data); + + SignatureDigest signature = signatureFunction.sign(privKey, data); + assertTrue(signatureFunction.verify(signature, pubKey, data)); + } } diff --git a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SM3WITHSM2SignatureFunctionTest.java b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SM3WITHSM2SignatureFunctionTest.java index 0b8063a9..54969745 100644 --- a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SM3WITHSM2SignatureFunctionTest.java +++ b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SM3WITHSM2SignatureFunctionTest.java @@ -1,9 +1,13 @@ package com.jd.blockchain.crypto.service.pki; import com.jd.blockchain.crypto.*; +import com.jd.blockchain.crypto.utils.CSRBuilder; +import com.jd.blockchain.crypto.utils.CertParser; import com.jd.blockchain.utils.io.BytesUtils; +import org.bouncycastle.util.encoders.Hex; import org.junit.Test; +import java.security.PublicKey; import java.util.Random; import static com.jd.blockchain.crypto.CryptoAlgorithm.ASYMMETRIC_KEY; @@ -270,4 +274,80 @@ public class SM3WITHSM2SignatureFunctionTest { resolvedSignatureDigest.getAlgorithm()); assertArrayEquals(signatureDigestBytes, resolvedSignatureDigest.toBytes()); } + + + @Test + public void testWithCSRAndCert() { + + String publicKeyStr = "3059301306072a8648ce3d020106082a811ccf5501822d03420004aa6586478be879504fdd02892f" + + "b4cf2bdb3d96a316f41ff7bcadfabef4ea836678984f9ba6931a609391426ca7164592f5fccd062be56fc32b3eec3a5" + + "0400971"; + + String privateKeyStr = "308193020100301306072a8648ce3d020106082a811ccf5501822d0479307702010104207abd2953" + + "84f193abe4f3715c26bc15225061f007131755d94ca12c7e0ce0b3a0a00a06082a811ccf5501822da14403420004aa6" + + "586478be879504fdd02892fb4cf2bdb3d96a316f41ff7bcadfabef4ea836678984f9ba6931a609391426ca7164592f5" + + "fccd062be56fc32b3eec3a50400971"; + + String expectedUserCert = "MIICwjCCAmWgAwIBAgIFIChnMlIwDAYIKoEcz1UBg3UFADBdMQswCQYDVQQGEwJDTjEwMC4GA1UEC" + + "gwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRwwGgYDVQQDDBNDRkNBIFRFU1QgU00yIE9DQTEx" + + "MB4XDTE5MDgyODA4MTUzNloXDTIxMDgyODA4MTUzNloweDELMAkGA1UEBhMCQ04xGDAWBgNVBAoMD0NGQ0EgVEVTVCBPQ0E" + + "xMTERMA8GA1UECwwITG9jYWwgUkExFTATBgNVBAsMDEluZGl2aWR1YWwtMTElMCMGA1UEAwwcMDUxQHpoYW5nbGluIUBaMT" + + "g2MTIyMjkyOTVAODBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABKplhkeL6HlQT90CiS+0zyvbPZajFvQf97yt+r706oNme" + + "JhPm6aTGmCTkUJspxZFkvX8zQYr5W/DKz7sOlBACXGjgfQwgfEwHwYDVR0jBBgwFoAUvqZ+TT18j6BV5sEvCS4sIEOzQn8w" + + "SAYDVR0gBEEwPzA9BghggRyG7yoBAjAxMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmNmY2EuY29tLmNuL3VzL3VzLTE1Lmh" + + "0bTA5BgNVHR8EMjAwMC6gLKAqhihodHRwOi8vMjEwLjc0LjQyLjMvT0NBMTEvU00yL2NybDI0OTkuY3JsMAsGA1UdDwQEAw" + + "ID6DAdBgNVHQ4EFgQU07tMtbs5PWkwN33OQVH116xd1kowHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMAwGCCqBH" + + "M9VAYN1BQADSQAwRgIhAPuuInppVhugw6EIG4wgkouxX/MX2dTLe478wx7LFXSQAiEAneiz51vrurICNCfeecaBHgzaj7+3" + + "kmrdIZJBoxYGbso="; + + String issuerCert = + "-----BEGIN CERTIFICATE-----\n" + + "MIICTzCCAfOgAwIBAgIKJFSZ4SRVDndYUTAMBggqgRzPVQGDdQUAMF0xCzAJBgNV\n" + + "BAYTAkNOMTAwLgYDVQQKDCdDaGluYSBGaW5hbmNpYWwgQ2VydGlmaWNhdGlvbiBB\n" + + "dXRob3JpdHkxHDAaBgNVBAMME0NGQ0EgVEVTVCBDUyBTTTIgQ0EwHhcNMTIwODI5\n" + + "MDU0ODQ3WhcNMzIwODI0MDU0ODQ3WjBdMQswCQYDVQQGEwJDTjEwMC4GA1UECgwn\n" + + "Q2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRwwGgYDVQQD\n" + + "DBNDRkNBIFRFU1QgU00yIE9DQTExMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE\n" + + "L1mx4wriQUojGsIkNL14kslv9nwiqsiVpELOZauzghrbccNlPYKNYKZOCvXwIIqU\n" + + "9QY02d4weqKqo/JMcNsKEaOBmDCBlTAfBgNVHSMEGDAWgBS12JBvXPDYM9JjvX6y\n" + + "w43GTxJ6YTAMBgNVHRMEBTADAQH/MDgGA1UdHwQxMC8wLaAroCmGJ2h0dHA6Ly8y\n" + + "MTAuNzQuNDIuMy90ZXN0cmNhL1NNMi9jcmwxLmNybDALBgNVHQ8EBAMCAQYwHQYD\n" + + "VR0OBBYEFL6mfk09fI+gVebBLwkuLCBDs0J/MAwGCCqBHM9VAYN1BQADSAAwRQIh\n" + + "AKuk7s3eYCZDck5NWU0eNQmLhBN/1zmKs517qFrDrkJWAiAP4cVfLtdza/OkwU9P\n" + + "PrIDl+E4aL3FypntFXHG3T+Keg==\n" + + "-----END CERTIFICATE-----"; + + byte[] rawPublicKeyBytes = Hex.decode(publicKeyStr); + byte[] rawPrivateKeyBytes = Hex.decode(privateKeyStr); + + CSRBuilder builder = new CSRBuilder(); + builder.init("SM3withSM2", rawPublicKeyBytes, rawPrivateKeyBytes); + + CertParser parser = new CertParser(); + parser.parse(expectedUserCert,issuerCert); + + PublicKey rawPublicKeyInCert = parser.getPubKey(); + // check that the public key in inputs and the public key in certificate are consistent + assertArrayEquals(rawPublicKeyBytes, rawPublicKeyInCert.getEncoded()); + + String algoName = parser.getSigAlgName(); + int keyLength = parser.getKeyLength(); + String length = String.valueOf(keyLength); + String algo = (algoName.contains("RSA")? (algoName + length).toUpperCase(): algoName.toUpperCase()); + + CryptoAlgorithm algorithm = Crypto.getAlgorithm(algo); + assertNotNull(algorithm); + SignatureFunction signatureFunction = Crypto.getSignatureFunction(algorithm); + + PubKey pubKey = new PubKey(algorithm, rawPublicKeyBytes); + PrivKey privKey = new PrivKey(algorithm, rawPrivateKeyBytes); + + // signTest + byte[] data = new byte[1024]; + Random random = new Random(); + random.nextBytes(data); + + SignatureDigest signature = signatureFunction.sign(privKey, data); + assertTrue(signatureFunction.verify(signature, pubKey, data)); + } } diff --git a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CertParserTest.java b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CertParserTest.java index 24cdc414..263d3e88 100644 --- a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CertParserTest.java +++ b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CertParserTest.java @@ -43,7 +43,8 @@ public class CertParserTest { String userCert = "MIIEQDCCAyigAwIBAgIFICdVYzEwDQYJKoZIhvcNAQEFBQAwWTELMAkGA1UEBhMCQ04xMDAuBgNVBAoTJ0NoaW5hIEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEYMBYGA1UEAxMPQ0ZDQSBURVNUIE9DQTExMB4XDTE5MDUxMDExMjAyNFoXDTIxMDUxMDExMjAyNFowcjELMAkGA1UEBhMCQ04xGDAWBgNVBAoTD0NGQ0EgVEVTVCBPQ0ExMTERMA8GA1UECxMITG9jYWwgUkExFTATBgNVBAsTDEluZGl2aWR1YWwtMTEfMB0GA1UEAxQWMDUxQGFhYWFhQFpIMDkzNTgwMjhAMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJx3F2WD1dJPzK/nRHO7d1TJ1hTjzGTmv0PQ7ECsJAh3U3BtnGTpCB+b4+JMI4LO8nHkKIBQ3P9XnF+Bf1iXdWNAQ4aWCxa2nV7lCp4w0GliPu/EMgIfmsSDUtgqbM3cr8sR8r9m1xG3gt2TIQJ+jT7sAiguU/kyNzpjaccOUIgUFa8IDFq9UeB76MXtCuhlERRZQCl47e+9w7ZoxmE7e6IZORxPp7rQWVBHlR9ntWjJfNDTm3gMP5ehP+yIZnKx1LudxkBLQxpMmspzOyH1zqx5nkKe49AfWWpDxxRvYkriyYC3aE81qLsU/bhLwNEKOju7BGDF/mhJLZUedojM0gMCAwEAAaOB9TCB8jAfBgNVHSMEGDAWgBT8C7xEmg4xoYOpgYcnHgVCxr9W+DBIBgNVHSAEQTA/MD0GCGCBHIbvKgECMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2ZjYS5jb20uY24vdXMvdXMtMTUuaHRtMDoGA1UdHwQzMDEwL6AtoCuGKWh0dHA6Ly8yMTAuNzQuNDIuMy9PQ0ExMS9SU0EvY3JsMjU2OTMuY3JsMAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQU5oKGaQs7Jt5Gfbt1XhFTWAySEKswHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMA0GCSqGSIb3DQEBBQUAA4IBAQAlmPRaImZV51iKjtpMKuyLMw7dX8L0lY3tl+pVZZSxHuwsN4GCCtV0Ej50up+/6EbfL4NUTiuHVAjCroKKvb+94CrdEwdnQGM5IbGSjT78nQpeASXbIWuUwA+ImjvZOzvq/0b56AzonNzBxOMGko/bj5smM6X8jrgJ0NQppo2KNSVNC4JbuoNWI4FM94SE4DUi9H7EYl4JdOtDaDtCsq49o/A1CZyYrmoOPCgxpQQXmuB3lGq/jyoOlW2aW8uee/hYG1JJcSHLBjF0WBwdxssgbBotA5f1PebiIMSbFgjk57bd4M80hhU/rI4Hkn9pcp5R7NsX95TtyDIg90LboBnW"; parser.parse(userCert, issuerCert); - assertEquals("SHA1WITHRSA",parser.getSigAlgName()); + assertEquals("SHA1WITHRSA", parser.getSigAlgName()); + assertEquals(2048, parser.getKeyLength()); } @Test @@ -77,7 +78,8 @@ public class CertParserTest { String userCert = "MIIFRjCCBC6gAwIBAgIFICdWiDMwDQYJKoZIhvcNAQEFBQAwWTELMAkGA1UEBhMCQ04xMDAuBgNVBAoTJ0NoaW5hIEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEYMBYGA1UEAxMPQ0ZDQSBURVNUIE9DQTExMB4XDTE5MDUxNjA3MDcyMloXDTIxMDUxNjA3MDcyMloweDELMAkGA1UEBhMCQ04xGDAWBgNVBAoTD0NGQ0EgVEVTVCBPQ0ExMTERMA8GA1UECxMITG9jYWwgUkExFTATBgNVBAsTDEluZGl2aWR1YWwtMTElMCMGA1UEAxQcMDUxQHpoYW5nbGluIUBaMTg2MTIyMjkyOTVAMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL0rTOxd8rsjPtFJ0aGVh9bZPy5Xo0SADaP7BbJsG4+ykLQMZHg9hTf/6fv1OsD2HEKFoMpIkW2gwCJW2nvicHcVql/shCoktc6ZBW6Dr/DxOgbO9tpoGxZ50xdI4Q0NsrxqtbCldW4ozPHdjgRJ83i1KSFh7evNrVByN/mB+jchrVGLWyJ1uIRgUUgpRZmZPoOHaizVJqrqWJGGk6xbDLR2gUQ1hTzetQaz1OeKtelHDk9FY08XSmNGssSMpuSjrxn78S888VW5WIxyo4cwrXSXFk3J7LNTy70Oga16HZjJD/vLTM6a4riPa8+uivPinKxK38/++nlBPNwhx6n46uYkd9Zvw+SJiJgpnuPJLtMZpKpJx7V1BDVEydKPUthilTdsmJtkBFSlFw0G1aKfuciBGzzJ3SKngJF/JqJAWIonVAFBGb6Gokp1Sw+T4KqXrdbjxYxiyyjZ++8O1vydgFAkx/NjsuwJnpKETiRKFJmY7YawcUvC4ixF7XQc0luFWRDYcbxOppir+ieMqhGXyaFhLUuB4WXv+rFxfa3NmkBW8q5TPzt/PwWcXpITsYTZYla/E/grB+OeZLYgjigT5YlgytPHG6Gt1ySCCd8WXFWpkBbQfXzqcvtU27RCcAUgfXk5NLb7NZCQg7heGjgzOdYJCPsa1d3m7l04+VIKGCZdAgMBAAGjgfUwgfIwHwYDVR0jBBgwFoAU/Au8RJoOMaGDqYGHJx4FQsa/VvgwSAYDVR0gBEEwPzA9BghggRyG7yoBAjAxMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmNmY2EuY29tLmNuL3VzL3VzLTE1Lmh0bTA6BgNVHR8EMzAxMC+gLaArhilodHRwOi8vMjEwLjc0LjQyLjMvT0NBMTEvUlNBL2NybDI1NzE3LmNybDALBgNVHQ8EBAMCA+gwHQYDVR0OBBYEFMjh6AzDCuNkD+pqQfiS6bqPGpI4MB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDBDANBgkqhkiG9w0BAQUFAAOCAQEApZaLXS6/6FudPA3l2xom5U7nJUOpQ1E6DO/ic9dFGtLE0WgyAqB3JVPvXEntppX55x/dAV7rvvz9NaEdiAe8DAj7qyoPDvC8ZWQK8U4n9l8N78QwALOURxzQNs+CBatJQzbu2w1RKVwkfE6xEIVnu+wjiAtymfwdLHMagHxDIC/eOPbTnbbtITJk2ukFfoc0WJ6Awg5lW+x7nGokEn/XAjKyRHCpkRUFGQm4ww41zlrqCqQqnVGVABJtjbdtFf7nh33QHl0fkj19nfMox9eGuntPyM0bNA0XqPMA+FWSCqeDT6uLbyaOKWxlhv53U/NCJl76U3tssMEWsm9amEDDQg=="; parser.parse(userCert, issuerCert); - assertEquals("SHA1WITHRSA",parser.getSigAlgName()); + assertEquals("SHA1WITHRSA", parser.getSigAlgName()); + assertEquals(4096, parser.getKeyLength()); } @Test @@ -103,7 +105,8 @@ public class CertParserTest { String userCert = "MIICwDCCAmWgAwIBAgIFICdWkWgwDAYIKoEcz1UBg3UFADBdMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRwwGgYDVQQDDBNDRkNBIFRFU1QgU00yIE9DQTExMB4XDTE5MDUxNjA4MTA1MVoXDTIxMDUxNjA4MTA1MVoweDELMAkGA1UEBhMCQ04xGDAWBgNVBAoMD0NGQ0EgVEVTVCBPQ0ExMTERMA8GA1UECwwITG9jYWwgUkExFTATBgNVBAsMDEluZGl2aWR1YWwtMTElMCMGA1UEAwwcMDUxQHpoYW5nbGluIUBaMTg2MTIyMjkyOTVAMzBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABPvNXpdZ4/4g+wx5qKS94CPkMqpEDhlnXYYW7ZzsbNI4d28sVBz5Ji6dTT1Zx627Kvw4tdUaUt7BVMvZsu3BFlyjgfQwgfEwHwYDVR0jBBgwFoAUvqZ+TT18j6BV5sEvCS4sIEOzQn8wSAYDVR0gBEEwPzA9BghggRyG7yoBAjAxMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmNmY2EuY29tLmNuL3VzL3VzLTE1Lmh0bTA5BgNVHR8EMjAwMC6gLKAqhihodHRwOi8vMjEwLjc0LjQyLjMvT0NBMTEvU00yL2NybDIxMDkuY3JsMAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQUxR5C/VjASus5zrAAFS4ulMpRjKgwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMAwGCCqBHM9VAYN1BQADRwAwRAIgVBzVi/fgkknr+2BH2wXeGMXC+Pa6p7rbldUsYMOYoyUCIAmQ4KEk2U1xJZSBpOPy5jN9kmRb+0YH6x04O/2tqCgq"; parser.parse(userCert, issuerCert); - assertEquals("SM3WITHSM2",parser.getSigAlgName()); + assertEquals("SM3WITHSM2", parser.getSigAlgName()); + assertEquals(256, parser.getKeyLength()); } @Test @@ -141,6 +144,7 @@ public class CertParserTest { "PrIDl+E4aL3FypntFXHG3T+Keg==\n" + "-----END CERTIFICATE-----"; parser.parse(issuerCert, CACert); - assertEquals("SM3WITHSM2",parser.getSigAlgName()); + assertEquals("SM3WITHSM2", parser.getSigAlgName()); + assertEquals(256, parser.getKeyLength()); } } diff --git a/source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/utils/sm/SM2Utils.java b/source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/utils/sm/SM2Utils.java index 94c0cf32..b3a65b18 100644 --- a/source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/utils/sm/SM2Utils.java +++ b/source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/utils/sm/SM2Utils.java @@ -13,6 +13,8 @@ import org.bouncycastle.crypto.engines.SM2Engine; import org.bouncycastle.crypto.generators.ECKeyPairGenerator; import org.bouncycastle.crypto.params.*; import org.bouncycastle.crypto.signers.SM2Signer; +import org.bouncycastle.jce.ECNamedCurveTable; +import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec; import org.bouncycastle.math.ec.*; import java.io.IOException; @@ -29,19 +31,10 @@ public class SM2Utils { // The length of sm3 output is 32 bytes private static final int SM3DIGEST_LENGTH = 32; - private static final BigInteger SM2_P = new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", 16); - private static final BigInteger SM2_A = new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC", 16); - private static final BigInteger SM2_B = new BigInteger("28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", 16); - private static final BigInteger SM2_N = new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", 16); - private static final BigInteger SM2_H = ECConstants.ONE; - private static final BigInteger SM2_GX = new BigInteger("32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", 16); - private static final BigInteger SM2_GY = new BigInteger("BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", 16); - - // To get the curve from the equation y^2=x^3+ax+b according the coefficient a and b, - // with the big prime p, the order n, the cofactor h, and obtain the generator g and the domain's parameters - private static final ECCurve CURVE = new ECCurve.Fp(SM2_P, SM2_A, SM2_B, SM2_N, SM2_H); - private static final ECPoint G = CURVE.createPoint(SM2_GX, SM2_GY); - private static final ECDomainParameters DOMAIN_PARAMS = new ECDomainParameters(CURVE, G, SM2_N); + private static final ECNamedCurveParameterSpec PARAMS = ECNamedCurveTable.getParameterSpec("sm2p256v1"); + private static final ECCurve CURVE = PARAMS.getCurve(); + private static final ECDomainParameters DOMAIN_PARAMS = new ECDomainParameters( + CURVE, PARAMS.getG(), PARAMS.getN(), PARAMS.getH()); //-----------------Key Generation Algorithm----------------- diff --git a/source/deployment/deployment-autotest/src/test/java/com/jd/blockchain/AppTest.java b/source/deployment/deployment-autotest/src/test/java/com/jd/blockchain/AppTest.java new file mode 100644 index 00000000..941b907f --- /dev/null +++ b/source/deployment/deployment-autotest/src/test/java/com/jd/blockchain/AppTest.java @@ -0,0 +1,20 @@ +package com.jd.blockchain; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +/** + * Unit test for simple App. + */ +public class AppTest +{ + /** + * Rigorous Test :-) + */ + @Test + public void shouldAnswerWithTrue() + { + assertTrue( true ); + } +} diff --git a/source/deployment/deployment-gateway/conf/application-gw.properties b/source/deployment/deployment-gateway/conf/application-gw.properties new file mode 100644 index 00000000..e69de29b diff --git a/source/deployment/deployment-gateway/src/main/java/com/jd/blockchain/gateway/boot/GatewayBooter.java b/source/deployment/deployment-gateway/src/main/java/com/jd/blockchain/gateway/boot/GatewayBooter.java index 93ca75ff..4c9d5537 100644 --- a/source/deployment/deployment-gateway/src/main/java/com/jd/blockchain/gateway/boot/GatewayBooter.java +++ b/source/deployment/deployment-gateway/src/main/java/com/jd/blockchain/gateway/boot/GatewayBooter.java @@ -23,10 +23,7 @@ public class GatewayBooter { } private static final void writePID() throws Exception { - URL url = GatewayBooter.class - .getProtectionDomain() - .getCodeSource() - .getLocation(); + URL url = GatewayBooter.class.getProtectionDomain().getCodeSource().getLocation(); String currPath = java.net.URLDecoder.decode(url.getPath(), "UTF-8"); if (currPath.contains("!/")) { currPath = currPath.substring(5, currPath.indexOf("!/")); @@ -40,6 +37,10 @@ public class GatewayBooter { String pidFilePath = homeDir + File.separator + "bin" + File.separator + "PID.log"; File pidFile = new File(pidFilePath); if (!pidFile.exists()) { + File dir = pidFile.getParentFile(); + if (!dir.exists()) { + dir.mkdirs(); + } pidFile.createNewFile(); } String name = ManagementFactory.getRuntimeMXBean().getName(); diff --git a/source/deployment/deployment-gateway/src/main/resources/scripts/startup.sh b/source/deployment/deployment-gateway/src/main/resources/scripts/startup.sh index db75a6ad..44a1a528 100644 --- a/source/deployment/deployment-gateway/src/main/resources/scripts/startup.sh +++ b/source/deployment/deployment-gateway/src/main/resources/scripts/startup.sh @@ -5,5 +5,5 @@ GATEWAY=$(ls $HOME/lib | grep deployment-gateway-) if [ ! -n "$GATEWAY" ]; then echo "GateWay Is Null !!!" else - nohup java -jar -server $HOME/lib/$GATEWAY -c $HOME/config/gateway.conf $* > gw.out 2>&1 & + nohup java -jar -server -Dgateway.log=$HOME $HOME/lib/$GATEWAY -c $HOME/config/gateway.conf $* >$HOME/bin/gw.out 2>&1 & fi \ No newline at end of file diff --git a/source/deployment/deployment-peer/pom.xml b/source/deployment/deployment-peer/pom.xml index f9c3e56f..7d94202b 100644 --- a/source/deployment/deployment-peer/pom.xml +++ b/source/deployment/deployment-peer/pom.xml @@ -25,7 +25,11 @@ runtime-modular-booter ${project.version} - + com.jd.blockchain storage-composite diff --git a/source/deployment/deployment-peer/src/main/resources/assembly.xml b/source/deployment/deployment-peer/src/main/resources/assembly.xml index 5e64c93e..0fc4ddf5 100644 --- a/source/deployment/deployment-peer/src/main/resources/assembly.xml +++ b/source/deployment/deployment-peer/src/main/resources/assembly.xml @@ -55,6 +55,16 @@ com.jd.blockchain:deployment-peer + + + diff --git a/source/deployment/deployment-peer/src/main/resources/config/init/ledger.init b/source/deployment/deployment-peer/src/main/resources/config/init/ledger.init index 14a95134..e84f24f5 100644 --- a/source/deployment/deployment-peer/src/main/resources/config/init/ledger.init +++ b/source/deployment/deployment-peer/src/main/resources/config/init/ledger.init @@ -7,6 +7,48 @@ ledger.name= #声明的账本创建时间;格式为 “yyyy-MM-dd HH:mm:ss.SSSZ”,表示”年-月-日 时:分:秒:毫秒时区“;例如:“2019-08-01 14:26:58.069+0800”,其中,+0800 表示时区是东8区 created-time=2019-08-01 14:26:58.069+0800 + +#----------------------------------------------- +# 初始的角色名称列表;可选项; +# 角色名称不区分大小写,最长不超过20个字符;多个角色名称之间用半角的逗点“,”分隔; +# 系统会预置一个默认角色“DEFAULT”,所有未指定角色的用户都以赋予该角色的权限;若初始化时未配置默认角色的权限,则为默认角色分配所有权限; +# +# 注:如果声明了角色,但未声明角色对应的权限清单,这会忽略该角色的初始化; +# +#security.roles=DEFAULT, ADMIN, MANAGER, GUEST + +# 赋予角色的账本权限清单;可选项; +# 可选的权限如下; +# AUTHORIZE_ROLES, SET_CONSENSUS, SET_CRYPTO, REGISTER_PARTICIPANT, +# REGISTER_USER, REGISTER_DATA_ACCOUNT, REGISTER_CONTRACT, UPGRADE_CONTRACT, +# SET_USER_ATTRIBUTES, WRITE_DATA_ACCOUNT, +# APPROVE_TX, CONSENSUS_TX +# 多项权限之间用逗点“,”分隔; +# +#security.role.DEFAULT.ledger-privileges=REGISTER_USER, REGISTER_DATA_ACCOUNT + +# 赋予角色的交易权限清单;可选项; +# 可选的权限如下; +# DIRECT_OPERATION, CONTRACT_OPERATION +# 多项权限之间用逗点“,”分隔; +# +#security.role.DEFAULT.tx-privileges=DIRECT_OPERATION, CONTRACT_OPERATION + +# 其它角色的配置示例; +# 系统管理员角色:只能操作全局性的参数配置和用户注册,只能执行直接操作指令; +#security.role.ADMIN.ledger-privileges=CONFIGURE_ROLES, AUTHORIZE_USER_ROLES, SET_CONSENSUS, SET_CRYPTO, REGISTER_PARTICIPANT, REGISTER_USER +#security.role.ADMIN.tx-privileges=DIRECT_OPERATION + +# 业务主管角色:只能够执行账本数据相关的操作,包括注册用户、注册数据账户、注册合约、升级合约、写入数据等;能够执行直接操作指令和调用合约; +#security.role.MANAGER.ledger-privileges=CONFIGURE_ROLES, AUTHORIZE_USER_ROLES, REGISTER_USER, REGISTER_DATA_ACCOUNT, REGISTER_CONTRACT, UPGRADE_CONTRACT, SET_USER_ATTRIBUTES, WRITE_DATA_ACCOUNT, +#security.role.MANAGER.tx-privileges=DIRECT_OPERATION, CONTRACT_OPERATION + +# 访客角色:不具备任何的账本权限,只有数据读取的操作;也只能够通过调用合约来读取数据; +#security.role.GUEST.ledger-privileges= +#security.role.GUEST.tx-privileges=CONTRACT_OPERATION + + +#----------------------------------------------- #共识服务提供者;必须; consensus.service-provider=com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider @@ -17,16 +59,36 @@ consensus.conf=bftsmart.config crypto.service-providers=com.jd.blockchain.crypto.service.classic.ClassicCryptoService, \ com.jd.blockchain.crypto.service.sm.SMCryptoService +#从存储中加载账本数据时,是否校验哈希;可选; +crypto.verify-hash=true + +#哈希算法; +crypto.hash-algorithm=SHA256 + #参与方的个数,后续以 cons_parti.id 分别标识每一个参与方的配置; cons_parti.count=4 +#--------------------- #第0个参与方的名称; cons_parti.0.name= #第0个参与方的公钥文件路径; cons_parti.0.pubkey-path= #第0个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数; cons_parti.0.pubkey= + +#第0个参与方的角色清单;可选项; +#cons_parti.0.roles=ADMIN, MANAGER +#第0个参与方的角色权限策略,可选值有:UNION(并集),INTERSECT(交集);可选项; +#cons_parti.0.roles-policy=UNION + +#第0个参与方的共识服务的主机地址; +cons_parti.0.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个参与方的账本初始服务的端口; @@ -34,12 +96,27 @@ cons_parti.0.initializer.port=8800 #第0个参与方的账本初始服务是否开启安全连接; cons_parti.0.initializer.secure=false + +#--------------------- #第1个参与方的名称; cons_parti.1.name= #第1个参与方的公钥文件路径; cons_parti.1.pubkey-path= #第1个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数; cons_parti.1.pubkey= + +#第1个参与方的角色清单;可选项; +#cons_parti.1.roles=MANAGER +#第1个参与方的角色权限策略,可选值有:UNION(并集),INTERSECT(交集);可选项; +#cons_parti.1.roles-policy=UNION + +#第1个参与方的共识服务的主机地址; +cons_parti.1.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个参与方的账本初始服务的端口; @@ -47,12 +124,26 @@ cons_parti.1.initializer.port=8810 #第1个参与方的账本初始服务是否开启安全连接; cons_parti.1.initializer.secure=false +#--------------------- #第2个参与方的名称; cons_parti.2.name= #第2个参与方的公钥文件路径; cons_parti.2.pubkey-path= #第2个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数; cons_parti.2.pubkey= + +#第2个参与方的角色清单;可选项; +#cons_parti.2.roles=MANAGER +#第2个参与方的角色权限策略,可选值有:UNION(并集),INTERSECT(交集);可选项; +#cons_parti.2.roles-policy=UNION + +#第2个参与方的共识服务的主机地址; +cons_parti.2.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个参与方的账本初始服务的端口; @@ -60,12 +151,26 @@ cons_parti.2.initializer.port=8820 #第2个参与方的账本初始服务是否开启安全连接; cons_parti.2.initializer.secure=false +#--------------------- #第3个参与方的名称; cons_parti.3.name= #第3个参与方的公钥文件路径; cons_parti.3.pubkey-path= #第3个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数; cons_parti.3.pubkey= + +#第3个参与方的角色清单;可选项; +#cons_parti.3.roles=GUEST +#第3个参与方的角色权限策略,可选值有:UNION(并集),INTERSECT(交集);可选项; +#cons_parti.3.roles-policy=INTERSECT + +#第3个参与方的共识服务的主机地址; +cons_parti.3.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个参与方的账本初始服务的端口; diff --git a/source/deployment/deployment-peer/src/main/resources/scripts/keygen.sh b/source/deployment/deployment-peer/src/main/resources/scripts/keygen.sh index 0249e85d..f0844f4c 100644 --- a/source/deployment/deployment-peer/src/main/resources/scripts/keygen.sh +++ b/source/deployment/deployment-peer/src/main/resources/scripts/keygen.sh @@ -12,5 +12,5 @@ else else echo "keys file will be saved $HOME/config/keys" fi - java -jar $HOME/libs/$boot_file -o $HOME/config/keys -l $HOME/config/init/local.conf $* + java -jar $HOME/libs/$boot_file -o $HOME/config/keys $* fi \ No newline at end of file diff --git a/source/deployment/deployment-peer/src/main/resources/scripts/ledger-init.sh b/source/deployment/deployment-peer/src/main/resources/scripts/ledger-init.sh index d0c3f5f2..660676e8 100644 --- a/source/deployment/deployment-peer/src/main/resources/scripts/ledger-init.sh +++ b/source/deployment/deployment-peer/src/main/resources/scripts/ledger-init.sh @@ -5,5 +5,5 @@ boot_file=$(ls $HOME/libs | grep tools-initializer-booter-) if [ ! -n "$boot_file" ]; then echo "tools-initializer-booter is null" else - java -jar $HOME/libs/$boot_file -l $HOME/config/init/local.conf -i $HOME/config/init/ledger.init $* -fi + java -jar -server -Dinit.log=$HOME $HOME/libs/$boot_file -l $HOME/config/init/local.conf -i $HOME/config/init/ledger.init $* +fi \ No newline at end of file diff --git a/source/deployment/deployment-peer/src/main/resources/scripts/manager-start.sh b/source/deployment/deployment-peer/src/main/resources/scripts/manager-start.sh new file mode 100644 index 00000000..6c1f44af --- /dev/null +++ b/source/deployment/deployment-peer/src/main/resources/scripts/manager-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 -p 8000 $* >$HOME/bin/jump.out 2>&1 & +fi \ No newline at end of file diff --git a/source/deployment/deployment-peer/src/main/resources/scripts/manager-stop.sh b/source/deployment/deployment-peer/src/main/resources/scripts/manager-stop.sh new file mode 100644 index 00000000..b7155c88 --- /dev/null +++ b/source/deployment/deployment-peer/src/main/resources/scripts/manager-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/deployment/deployment-peer/src/main/resources/scripts/shutdown.sh b/source/deployment/deployment-peer/src/main/resources/scripts/peer-shutdown.sh similarity index 100% rename from source/deployment/deployment-peer/src/main/resources/scripts/shutdown.sh rename to source/deployment/deployment-peer/src/main/resources/scripts/peer-shutdown.sh diff --git a/source/deployment/deployment-peer/src/main/resources/scripts/peer-startup.sh b/source/deployment/deployment-peer/src/main/resources/scripts/peer-startup.sh new file mode 100644 index 00000000..c316ed7d --- /dev/null +++ b/source/deployment/deployment-peer/src/main/resources/scripts/peer-startup.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +HOME=$(cd `dirname $0`;cd ../; pwd) +PEER=$(ls $HOME/system | grep deployment-peer-) +if [ ! -n "$PEER" ]; then + echo "Peer Is Null !!!" +else + nohup java -jar -server -Xmx512m -Xms512m -Dpeer.log=$HOME $HOME/system/$PEER -home=$HOME -c $HOME/config/ledger-binding.conf -p 7080 $* >$HOME/bin/peer.out 2>&1 & +fi \ No newline at end of file diff --git a/source/deployment/deployment-peer/src/main/resources/scripts/startup.sh b/source/deployment/deployment-peer/src/main/resources/scripts/startup.sh deleted file mode 100644 index 371b8d78..00000000 --- a/source/deployment/deployment-peer/src/main/resources/scripts/startup.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -HOME=$(cd `dirname $0`;cd ../; pwd) -PEER=$(ls $HOME/system | grep deployment-peer-) -if [ ! -n "$PEER" ]; then - echo "Peer Is Null !!!" -else - nohup java -jar -server -Xmx2g -Xms2g $HOME/system/$PEER -home=$HOME -c $HOME/config/ledger-binding.conf -p 7080 $* & -fi \ No newline at end of file diff --git a/source/gateway/pom.xml b/source/gateway/pom.xml index 6bd8122c..2df3c7af 100644 --- a/source/gateway/pom.xml +++ b/source/gateway/pom.xml @@ -75,24 +75,6 @@ commons-io commons-io - ${commons-io.version} - - - - org.bitbucket.mstrobel - procyon-core - - - org.bitbucket.mstrobel - procyon-expressions - - - org.bitbucket.mstrobel - procyon-reflection - - - org.bitbucket.mstrobel - procyon-compilertools @@ -110,7 +92,7 @@ org.springframework.boot spring-boot-starter-log4j2 - + org.springframework.boot spring-boot-starter-security 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..bdc8e881 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 @@ -2,31 +2,36 @@ package com.jd.blockchain.gateway; import java.io.File; import java.io.InputStream; +import java.net.URL; 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 { + private static final String DEFAULT_GATEWAY_PROPS = "application-gw.properties"; + // 当前参与方在初始化配置中的参与方列表的编号; private static final String HOST_ARG = "-c"; + //sp;针对spring.config.location这个参数进行包装; private static final String SPRING_CF_LOCATION = BaseConstant.SPRING_CF_LOCATION; + // 是否输出调试信息; private static final String DEBUG_OPT = "-debug"; @@ -57,11 +62,20 @@ public class GatewayServerBooter { }else { //if no the config file, then should tip as follows. but it's not a good feeling, so we create it by inputStream; ConsoleUtils.info("no param:-sp, format: -sp /x/xx.properties, use the default application-gw.properties "); - ClassPathResource configResource = new ClassPathResource("application-gw.properties"); + ClassPathResource configResource = new ClassPathResource(DEFAULT_GATEWAY_PROPS); InputStream in = configResource.getInputStream(); - File targetFile = new File(System.getProperty("user.dir")+File.separator+"conf"+File.separator+"application-gw.properties"); + + // 将文件写入至config目录下 + String configPath = bootPath() + "config" + File.separator + DEFAULT_GATEWAY_PROPS; + File targetFile = new File(configPath); + + // 先将原来文件删除再Copy + if (targetFile.exists()) { + FileUtils.forceDelete(targetFile); + } + FileUtils.copyInputStreamToFile(in, targetFile); - springConfigLocation = "file:"+targetFile.getAbsolutePath(); + springConfigLocation = "file:" + targetFile.getAbsolutePath(); } // 启动服务器; @@ -88,19 +102,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); } @@ -147,4 +161,17 @@ public class GatewayServerBooter { return appCtx; } + private static String bootPath() throws Exception { + URL url = GatewayServerBooter.class.getProtectionDomain().getCodeSource().getLocation(); + String currPath = java.net.URLDecoder.decode(url.getPath(), "UTF-8"); + // 处理打包至SpringBoot问题 + if (currPath.contains("!/")) { + currPath = currPath.substring(5, currPath.indexOf("!/")); + } + if (currPath.endsWith(".jar")) { + currPath = currPath.substring(0, currPath.lastIndexOf("/") + 1); + } + System.out.printf("Current Project Boot Path = %s \r\n", currPath); + return new File(currPath).getParent() + File.separator; + } } \ No newline at end of file diff --git a/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayInterceptService.java b/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayInterceptService.java new file mode 100644 index 00000000..ca998b89 --- /dev/null +++ b/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayInterceptService.java @@ -0,0 +1,8 @@ +package com.jd.blockchain.gateway.service; + +import com.jd.blockchain.ledger.TransactionRequest; + +public interface GatewayInterceptService { + + void intercept(TransactionRequest txRequest); +} diff --git a/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayInterceptServiceHandler.java b/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayInterceptServiceHandler.java new file mode 100644 index 00000000..44f22aad --- /dev/null +++ b/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayInterceptServiceHandler.java @@ -0,0 +1,35 @@ +package com.jd.blockchain.gateway.service; + +import com.jd.blockchain.contract.ContractJarUtils; +import com.jd.blockchain.gateway.PeerService; +import com.jd.blockchain.ledger.ContractCodeDeployOperation; +import com.jd.blockchain.ledger.Operation; +import com.jd.blockchain.ledger.TransactionRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class GatewayInterceptServiceHandler implements GatewayInterceptService { + + @Autowired + private PeerService peerService; + + @Override + public void intercept(TransactionRequest txRequest) { + // 当前仅处理合约发布的请求 + Operation[] operations = txRequest.getTransactionContent().getOperations(); + if (operations != null && operations.length > 0) { + for (Operation op : operations) { + if (ContractCodeDeployOperation.class.isAssignableFrom(op.getClass())) { + // 发布合约请求 + contractCheck((ContractCodeDeployOperation)op); + } + } + } + } + + private void contractCheck(final ContractCodeDeployOperation contractOP) { + // 校验chainCode + ContractJarUtils.verify(contractOP.getChainCode()); + } +} 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..8a856953 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 @@ -3,8 +3,7 @@ package com.jd.blockchain.gateway.service; 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; +import com.jd.blockchain.sdk.LedgerBaseSettings; /** * queryService only for gateway; @@ -35,7 +34,7 @@ public interface GatewayQueryService { * 账本Hash * @return */ - LedgerInitSettings getLedgerInitSettings(HashDigest ledgerHash); + LedgerBaseSettings getLedgerBaseSettings(HashDigest ledgerHash); /** * 获取账本指定合约信息 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 4421dde1..aeedd64c 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 @@ -3,18 +3,17 @@ package com.jd.blockchain.gateway.service; import com.jd.blockchain.consensus.ConsensusProvider; import com.jd.blockchain.consensus.ConsensusProviders; import com.jd.blockchain.consensus.ConsensusSettings; -import com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider; -import com.jd.blockchain.consensus.mq.MsgQueueConsensusProvider; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.gateway.PeerService; -import com.jd.blockchain.gateway.decompiler.utils.DecompilerUtils; 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; -import com.jd.blockchain.sdk.LedgerInitSettings; +import com.jd.blockchain.sdk.LedgerBaseSettings; import com.jd.blockchain.utils.QueryUtil; import com.jd.blockchain.utils.codec.HexUtils; +import com.jd.blockchain.utils.decompiler.utils.DecompilerUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.Arrays; @@ -32,28 +31,26 @@ public class GatewayQueryServiceHandler implements GatewayQueryService { @Override public HashDigest[] getLedgersHash(int fromIndex, int count) { - HashDigest ledgersHash[] = peerService.getQueryService().getLedgerHashs(); - int indexAndCount[] = QueryUtil.calFromIndexAndCount(fromIndex,count,ledgersHash.length); - HashDigest ledgersHashNew[] = Arrays.copyOfRange(ledgersHash,indexAndCount[0],indexAndCount[0]+indexAndCount[1]); - return ledgersHashNew; + HashDigest[] ledgersHashs = peerService.getQueryService().getLedgerHashs(); + int[] indexAndCount = QueryUtil.calFromIndexAndCount(fromIndex, count, ledgersHashs.length); + return Arrays.copyOfRange(ledgersHashs, indexAndCount[0], indexAndCount[0] + indexAndCount[1]); } @Override public ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash, int fromIndex, 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; + ParticipantNode[] participantNodes = peerService.getQueryService().getConsensusParticipants(ledgerHash); + int[] indexAndCount = QueryUtil.calFromIndexAndCount(fromIndex, count, participantNodes.length); + ParticipantNode[] participantNodesNews = Arrays.copyOfRange(participantNodes, indexAndCount[0], + indexAndCount[0] + indexAndCount[1]); + return participantNodesNews; } @Override - public LedgerInitSettings getLedgerInitSettings(HashDigest ledgerHash) { - - ParticipantNode[] participantNodes = peerService.getQueryService().getConsensusParticipants(ledgerHash); + public LedgerBaseSettings getLedgerBaseSettings(HashDigest ledgerHash) { - LedgerMetadata ledgerMetadata = peerService.getQueryService().getLedgerMetadata(ledgerHash); + LedgerAdminInfo ledgerAdminInfo = peerService.getQueryService().getLedgerAdminInfo(ledgerHash); - return initLedgerInitSettings(participantNodes, ledgerMetadata); + return initLedgerBaseSettings(ledgerAdminInfo); } @Override @@ -72,36 +69,38 @@ public class GatewayQueryServiceHandler implements GatewayQueryService { } /** - * 初始化账本配置 + * 初始化账本的基本配置 + * + * @param ledgerAdminInfo + * 账本信息 * - * @param participantNodes - * 参与方列表 - * @param ledgerMetadata - * 账本元数据 * @return */ - private LedgerInitSettings initLedgerInitSettings(ParticipantNode[] participantNodes, LedgerMetadata ledgerMetadata) { - LedgerInitSettings ledgerInitSettings = new LedgerInitSettings(); + private LedgerBaseSettings initLedgerBaseSettings(LedgerAdminInfo ledgerAdminInfo) { + + LedgerMetadata ledgerMetadata = ledgerAdminInfo.getMetadata(); + + LedgerBaseSettings ledgerBaseSettings = new LedgerBaseSettings(); // 设置参与方 - ledgerInitSettings.setParticipantNodes(participantNodes); + ledgerBaseSettings.setParticipantNodes(ledgerAdminInfo.getParticipants()); // 设置共识设置 - ledgerInitSettings.setConsensusSettings(initConsensusSettings(ledgerMetadata)); + ledgerBaseSettings.setConsensusSettings(initConsensusSettings(ledgerAdminInfo)); // 设置参与方根Hash - ledgerInitSettings.setParticipantsHash(ledgerMetadata.getParticipantsHash()); + ledgerBaseSettings.setParticipantsHash(ledgerMetadata.getParticipantsHash()); // 设置算法配置 - ledgerInitSettings.setCryptoSetting(ledgerMetadata.getSetting().getCryptoSetting()); + ledgerBaseSettings.setCryptoSetting(ledgerAdminInfo.getSettings().getCryptoSetting()); // 设置种子 - ledgerInitSettings.setSeed(initSeed(ledgerMetadata.getSeed())); + ledgerBaseSettings.setSeed(initSeed(ledgerMetadata.getSeed())); // 设置共识协议 - ledgerInitSettings.setConsensusProtocol(ledgerMetadata.getSetting().getConsensusProvider()); + ledgerBaseSettings.setConsensusProtocol(ledgerAdminInfo.getSettings().getConsensusProvider()); - return ledgerInitSettings; + return ledgerBaseSettings; } /** @@ -131,14 +130,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..a6ef2f9b 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,586 @@ package com.jd.blockchain.gateway.web; +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; + +import com.jd.blockchain.gateway.service.GatewayQueryService; +import com.jd.blockchain.sdk.LedgerBaseSettings; +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; + private GatewayQueryService gatewayQueryService; - @Autowired - private GatewayQueryService gatewayQueryService; + @Autowired + 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") + @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(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) { + return peerService.getQueryService().getLedgerAdminInfo(ledgerHash); + } + + @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/participants") + @Override + public ParticipantNode[] getConsensusParticipants(@PathVariable(name = "ledgerHash") 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); - } + public LedgerBaseSettings getLedgerInitSettings(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) { + return gatewayQueryService.getLedgerBaseSettings(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..cfed9081 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,18 @@ public class GatewayWebServerConfigurer implements WebMvcConfigurer { JSONSerializeUtils.disableCircularReferenceDetect(); JSONSerializeUtils.configStringSerializer(ByteArray.class); DataContractRegistry.register(BftsmartNodeSettings.class); + + // 注册角色/权限相关接口 + DataContractRegistry.register(RolesConfigureOperation.class); + DataContractRegistry.register(RolesConfigureOperation.RolePrivilegeEntry.class); + DataContractRegistry.register(UserAuthorizeOperation.class); + DataContractRegistry.register(UserAuthorizeOperation.UserRolesEntry.class); + DataContractRegistry.register(PrivilegeSet.class); + DataContractRegistry.register(RoleSet.class); + DataContractRegistry.register(SecurityInitSettings.class); + DataContractRegistry.register(RoleInitSettings.class); + DataContractRegistry.register(UserAuthInitSettings.class); + DataContractRegistry.register(LedgerMetadata_V2.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 6ef3cacf..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,7 @@ 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; @@ -29,9 +30,15 @@ public class TxProcessingController implements TransactionService { @Autowired private PeerService peerService; + @Autowired + private GatewayInterceptService interceptService; + @RequestMapping(path = "rpc/tx", method = RequestMethod.POST, consumes = BinaryMessageConverter.CONTENT_TYPE_VALUE, produces = BinaryMessageConverter.CONTENT_TYPE_VALUE) @Override public @ResponseBody TransactionResponse process(@RequestBody TransactionRequest txRequest) { + // 拦截请求进行校验 + interceptService.intercept(txRequest); + // 检查交易请求的信息是否完整; HashDigest ledgerHash = txRequest.getTransactionContent().getLedgerHash(); if (ledgerHash == null) { diff --git a/source/gateway/src/main/resources/log4j2.xml b/source/gateway/src/main/resources/log4j2.xml index d81fe1dc..6b49c3e9 100644 --- a/source/gateway/src/main/resources/log4j2.xml +++ b/source/gateway/src/main/resources/log4j2.xml @@ -13,12 +13,12 @@ - + - + @@ -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 3938916c..e7bfe29e 100644 --- a/source/ledger/ledger-core/pom.xml +++ b/source/ledger/ledger-core/pom.xml @@ -40,6 +40,11 @@ contract-framework ${project.version} + + com.jd.blockchain + consensus-framework + ${project.version} + com.jd.blockchain contract-jvm 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/AccountQuery.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountQuery.java new file mode 100644 index 00000000..8f1f3cb0 --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountQuery.java @@ -0,0 +1,31 @@ +package com.jd.blockchain.ledger.core; + +import com.jd.blockchain.ledger.AccountHeader; +import com.jd.blockchain.utils.Bytes; + +public interface AccountQuery extends MerkleProvable { + + AccountHeader[] getHeaders(int fromIndex, int count); + + /** + * 返回总数; + * + * @return + */ + long getTotal(); + + boolean contains(Bytes address); + + /** + * 返回账户实例; + * + * @param address Base58 格式的账户地址; + * @return 账户实例,如果不存在则返回 null; + */ + T getAccount(String address); + + T getAccount(Bytes address); + + T getAccount(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/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/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..69dfac2c 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 { @@ -14,9 +14,9 @@ public class ContractAccount implements ContractInfo { private static final Bytes CHAIN_CODE_KEY = Bytes.fromString("CHAIN-CODE"); - private BaseAccount accBase; + private MerkleAccount accBase; - public ContractAccount(BaseAccount accBase) { + public ContractAccount(MerkleAccount accBase) { this.accBase = accBase; } @@ -57,7 +57,7 @@ public class ContractAccount implements ContractInfo { } public long getChaincodeVersion() { - return accBase.getKeyVersion(CHAIN_CODE_KEY); + return accBase.getVersion(CHAIN_CODE_KEY); } public long setProperty(Bytes key, String value, long version) { 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..3c1d52a5 --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccountQuery.java @@ -0,0 +1,5 @@ +package com.jd.blockchain.ledger.core; + +public interface ContractAccountQuery extends AccountQuery { + +} \ 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..5f4c7855 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,34 +5,40 @@ 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 Transactional, ContractAccountQuery { - private AccountSet accountSet; + private MerkleAccountSet accountSet; public ContractAccountSet(CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy) { - accountSet = new AccountSet(cryptoSetting, prefix, exStorage, verStorage, accessPolicy); + accountSet = new MerkleAccountSet(cryptoSetting, prefix, exStorage, verStorage, accessPolicy); } public ContractAccountSet(HashDigest dataRootHash, CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, AccountAccessPolicy accessPolicy) { - accountSet = new AccountSet(dataRootHash, cryptoSetting, prefix, exStorage, verStorage, readonly, accessPolicy); + accountSet = new MerkleAccountSet(dataRootHash, cryptoSetting, prefix, exStorage, verStorage, readonly, accessPolicy); } - public AccountHeader[] getAccounts(int fromIndex, int count) { - return accountSet.getAccounts(fromIndex,count); + @Override + public AccountHeader[] getHeaders(int fromIndex, int count) { + return accountSet.getHeaders(fromIndex, count); } public boolean isReadonly() { return accountSet.isReadonly(); } + void setReadonly() { + accountSet.setReadonly(); + } + @Override public HashDigest getRootHash() { return accountSet.getRootHash(); @@ -43,8 +49,9 @@ public class ContractAccountSet implements MerkleProvable, Transactional { * * @return */ - public long getTotalCount() { - return accountSet.getTotalCount(); + @Override + public long getTotal() { + return accountSet.getTotal(); } @Override @@ -52,36 +59,40 @@ public class ContractAccountSet implements MerkleProvable, Transactional { return accountSet.getProof(address); } + @Override public boolean contains(Bytes address) { return accountSet.contains(address); } - public ContractAccount getContract(Bytes address) { - BaseAccount accBase = accountSet.getAccount(address); + @Override + public ContractAccount getAccount(Bytes address) { + MerkleAccount accBase = accountSet.getAccount(address); return new ContractAccount(accBase); } - public ContractAccount getContract(Bytes address, long version) { - BaseAccount accBase = accountSet.getAccount(address, version); + @Override + public ContractAccount getAccount(String address) { + return getAccount(Bytes.fromBase58(address)); + } + + @Override + public ContractAccount getAccount(Bytes address, long version) { + MerkleAccount accBase = accountSet.getAccount(address, version); return new ContractAccount(accBase); } /** * 部署一项新的合约链码; * - * @param address - * 合约账户地址; - * @param pubKey - * 合约账户公钥; - * @param addressSignature - * 地址签名;合约账户的私钥对地址的签名; - * @param chaincode - * 链码内容; + * @param address 合约账户地址; + * @param pubKey 合约账户公钥; + * @param addressSignature 地址签名;合约账户的私钥对地址的签名; + * @param chaincode 链码内容; * @return 合约账户; */ public ContractAccount deploy(Bytes address, PubKey pubKey, DigitalSignature addressSignature, byte[] chaincode) { // TODO: 校验和记录合约地址签名; - BaseAccount accBase = accountSet.register(address, pubKey); + MerkleAccount accBase = accountSet.register(address, pubKey); ContractAccount contractAcc = new ContractAccount(accBase); contractAcc.setChaincode(chaincode, -1); return contractAcc; @@ -90,16 +101,13 @@ public class ContractAccountSet implements MerkleProvable, Transactional { /** * 更新指定账户的链码; * - * @param address - * 合约账户地址; - * @param chaincode - * 链码内容; - * @param version - * 链码版本; + * @param address 合约账户地址; + * @param chaincode 链码内容; + * @param version 链码版本; * @return 返回链码的新版本号; */ public long update(Bytes address, byte[] chaincode, long version) { - BaseAccount accBase = accountSet.getAccount(address); + MerkleAccount accBase = accountSet.getAccount(address); ContractAccount contractAcc = new ContractAccount(accBase); return contractAcc.setChaincode(chaincode, version); } 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..afaab416 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,21 +1,21 @@ 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 { - private BaseAccount baseAccount; + private MerkleAccount baseAccount; - public DataAccount(BaseAccount accBase) { + public DataAccount(MerkleAccount accBase) { this.baseAccount = accBase; } @@ -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); @@ -66,7 +135,7 @@ public class DataAccount implements AccountHeader, MerkleProvable { * @return */ public long getDataVersion(String key) { - return baseAccount.getKeyVersion(Bytes.fromString(key)); + return baseAccount.getVersion(Bytes.fromString(key)); } /** @@ -77,7 +146,7 @@ public class DataAccount implements AccountHeader, MerkleProvable { * @return */ public long getDataVersion(Bytes key) { - return baseAccount.getKeyVersion(key); + return baseAccount.getVersion(key); } /** @@ -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..c2bcb17d --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountQuery.java @@ -0,0 +1,5 @@ +package com.jd.blockchain.ledger.core; + +public interface DataAccountQuery extends AccountQuery { + +} \ 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 d44e9dbf..f693211b 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,41 +5,53 @@ 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 Transactional, DataAccountQuery { - private AccountSet accountSet; + private MerkleAccountSet accountSet; public DataAccountSet(CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy) { - accountSet = new AccountSet(cryptoSetting, prefix, exStorage, verStorage, accessPolicy); + accountSet = new MerkleAccountSet(cryptoSetting, prefix, exStorage, verStorage, accessPolicy); } public DataAccountSet(HashDigest dataRootHash, CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, AccountAccessPolicy accessPolicy) { - accountSet = new AccountSet(dataRootHash, cryptoSetting, prefix, exStorage, verStorage, readonly, accessPolicy); + accountSet = new MerkleAccountSet(dataRootHash, cryptoSetting, prefix, exStorage, verStorage, readonly, accessPolicy); } - public AccountHeader[] getAccounts(int fromIndex, int count) { - return accountSet.getAccounts(fromIndex, count); + @Override + public AccountHeader[] getHeaders(int fromIndex, int count) { + return accountSet.getHeaders(fromIndex, count); } public boolean isReadonly() { return accountSet.isReadonly(); } + void setReadonly() { + accountSet.setReadonly(); + } + @Override public HashDigest getRootHash() { return accountSet.getRootHash(); } - public long getTotalCount() { - return accountSet.getTotalCount(); + @Override + public long getTotal() { + return accountSet.getTotal(); + } + + @Override + public boolean contains(Bytes address) { + return accountSet.contains(address); } /** @@ -52,10 +64,15 @@ public class DataAccountSet implements MerkleProvable, Transactional { public DataAccount register(Bytes address, PubKey pubKey, DigitalSignature addressSignature) { // TODO: 未实现对地址签名的校验和记录; - BaseAccount accBase = accountSet.register(address, pubKey); + MerkleAccount accBase = accountSet.register(address, pubKey); return new DataAccount(accBase); } + @Override + public DataAccount getAccount(String address) { + return getAccount(Bytes.fromBase58(address)); + } + /** * 返回数据账户;
* 如果不存在,则返回 null; @@ -63,16 +80,18 @@ public class DataAccountSet implements MerkleProvable, Transactional { * @param address * @return */ - public DataAccount getDataAccount(Bytes address) { - BaseAccount accBase = accountSet.getAccount(address); + @Override + public DataAccount getAccount(Bytes address) { + MerkleAccount accBase = accountSet.getAccount(address); if (accBase == null) { return null; } return new DataAccount(accBase); } - public DataAccount getDataAccount(Bytes address, long version) { - BaseAccount accBase = accountSet.getAccount(address, version); + @Override + public DataAccount getAccount(Bytes address, long version) { + MerkleAccount 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..ae8ad40b --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DefaultOperationHandleRegisteration.java @@ -0,0 +1,122 @@ +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.ParticipantRegisterOperationHandle; +import com.jd.blockchain.ledger.core.handles.ParticipantStateUpdateOperationHandle; +import com.jd.blockchain.ledger.core.handles.RolesConfigureOperationHandle; +import com.jd.blockchain.ledger.core.handles.UserAuthorizeOperationHandle; +import com.jd.blockchain.ledger.core.handles.UserRegisterOperationHandle; + +@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()); + + registerDefaultHandle(new ParticipantRegisterOperationHandle()); + + registerDefaultHandle(new ParticipantStateUpdateOperationHandle()); + } + + 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 operationType) { + OperationHandle hdl = getRegisteredHandle(operationType); + if (hdl == null) { + throw new LedgerException("Unsupported operation type[" + operationType.getName() + "]!"); + } + return hdl; + } +} diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/EmptyAccountSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/EmptyAccountSet.java new file mode 100644 index 00000000..879bf702 --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/EmptyAccountSet.java @@ -0,0 +1,52 @@ +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 class EmptyAccountSet implements AccountQuery { + + private static final AccountHeader[] EMPTY = {}; + + @Override + public HashDigest getRootHash() { + return null; + } + + @Override + public MerkleProof getProof(Bytes key) { + return null; + } + + @Override + public AccountHeader[] getHeaders(int fromIndex, int count) { + return EMPTY; + } + + @Override + public long getTotal() { + return 0; + } + + @Override + public boolean contains(Bytes address) { + return false; + } + + @Override + public T getAccount(String address) { + return null; + } + + @Override + public T getAccount(Bytes address) { + return null; + } + + @Override + public T getAccount(Bytes address, long version) { + return null; + } + +} 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..958ef8aa --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/EmptyLedgerDataset.java @@ -0,0 +1,105 @@ +package com.jd.blockchain.ledger.core; + +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.ledger.LedgerAdminSettings; +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 LedgerAdminSettings 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 extends EmptyAccountSet implements UserAccountQuery{ + + } + + private static class EmptyDataAccountSet extends EmptyAccountSet implements DataAccountQuery{ + + } + + private static class EmptyContractAccountSet extends EmptyAccountSet implements ContractAccountQuery{ + + } + + +} 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..623a47b1 --- /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.LedgerAdminSettings; +import com.jd.blockchain.ledger.ParticipantDataQuery; + +public interface LedgerAdminDataQuery { + + LedgerAdminSettings 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..dfd06a1e --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminDataset.java @@ -0,0 +1,481 @@ +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.LedgerAdminSettings; +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.UserAuthorizationSettings; +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, LedgerAdminSettings { + + 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 UserAuthorizationSettings getAuthorizations() { + return userRoles; + } + + @Override + public LedgerAdminSettings 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 + */ + + @Override + 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); + } + + + /** + * 更新参与方的状态参数; + * + * @param participant + */ + public void updateParticipant(ParticipantNode participant) { + participants.updateConsensusParticipant(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/LedgerAdminInfoData.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminInfoData.java new file mode 100644 index 00000000..a0a74190 --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminInfoData.java @@ -0,0 +1,92 @@ +package com.jd.blockchain.ledger.core; + +import com.jd.blockchain.ledger.*; + +/** + * @author shaozhuguang + * @date 2019-09-16 + * + * LedgerAdminInfo的独立实现类,主要用于页面展示,区分 {@link LedgerAdminDataset} + */ +public class LedgerAdminInfoData implements LedgerAdminInfo { + + /** + * 元数据 + */ + private LedgerMetadata_V2 metadata; + + /** + * 账本配置 + * + */ + private LedgerSettings ledgerSettings; + + /** + * 参与方数量 + * + */ + private long participantCount; + + /** + * 参与方 + * + */ + private ParticipantNode[] participantNodes; + + /** + * 包装构造方法 + * + * @param ledgerAdminInfo + */ + public LedgerAdminInfoData(LedgerAdminInfo ledgerAdminInfo) { + this(ledgerAdminInfo.getMetadata(), ledgerAdminInfo.getSettings(), + ledgerAdminInfo.getParticipantCount(), ledgerAdminInfo.getParticipants()); + } + + public LedgerAdminInfoData(LedgerMetadata_V2 metadata, LedgerSettings ledgerSettings, long participantCount, ParticipantNode[] participantNodes) { + this.metadata = metadata; + this.ledgerSettings = ledgerSettings; + this.participantCount = participantCount; + this.participantNodes = participantNodes; + } + + /** + * 返回元数据配置信息 + * + * @return + */ + @Override + public LedgerMetadata_V2 getMetadata() { + return this.metadata; + } + + /** + * 返回当前设置的账本配置; + * + * @return + */ + @Override + public LedgerSettings getSettings() { + return this.ledgerSettings; + } + + /** + * 返回当前参与方的数量 + * + * @return + */ + @Override + public long getParticipantCount() { + return this.participantCount; + } + + /** + * 返回当前参与方列表 + * + * @return + */ + @Override + public ParticipantNode[] getParticipants() { + return this.participantNodes; + } +} 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 98% 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 1e8865b7..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; 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 46c21655..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 @@ -11,7 +11,7 @@ import com.jd.blockchain.ledger.TransactionRequest; *

* * {@link LedgerEditor} 以上一个区块作为数据编辑的起点;
- * 对账本数据({@link #getDataSet()})的批量更改可以作为一个交易({@link LedgerTransaction})整体提交暂存,形成暂存点; + * 对账本数据({@link #getDataset()})的批量更改可以作为一个交易({@link LedgerTransaction})整体提交暂存,形成暂存点; *
* * @author huanghaiquan @@ -33,11 +33,25 @@ public interface LedgerEditor { */ long getBlockHeight(); + /** + * 最新的账本数据集; + * + * @return + */ + LedgerDataset getLedgerDataset(); + + /** + * 最新的交易集合; + * + * @return + */ + TransactionSet getTransactionSet(); + /** * 开始新事务;
* * 方法返回之前,将会校验交易请求的用户签名列表和节点签名列表,并在后续对数据集 - * {@link LedgerTransactionContext#getDataSet()} 的操作时,校验这些用户和节点是否具备权限;
+ * {@link LedgerTransactionContext#getDataset()} 的操作时,校验这些用户和节点是否具备权限;
* * 校验失败将引发异常 {@link LedgerException}; *

@@ -52,7 +66,8 @@ public interface LedgerEditor { * * * - * 注:方法不解析、不执行交易中的操作;

+ * 注:方法不解析、不执行交易中的操作; + *

* * @param txRequest 交易请求; * @return 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..c8c04712 --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitializer.java @@ -0,0 +1,316 @@ +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.BlockchainKeypair; +import com.jd.blockchain.ledger.DigitalSignature; +import com.jd.blockchain.ledger.LedgerAdminInfo; +import com.jd.blockchain.ledger.LedgerAdminSettings; +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 LedgerQuery EMPTY_LEDGER =new EmptyLedgerQuery(); + + 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; + } + + 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); + } + + public DigitalSignature signTransaction(BlockchainKeypair key) { + return SignatureUtils.sign(initTxContent, key); + } + + /** + * 准备创建账本; + * + * @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, DEFAULT_OP_HANDLE_REG); + + txProcessor.schedule(txRequest); + + txResultsHandle = txProcessor.prepare(); + return txResultsHandle.getBlock(); + } + + private static class EmptyLedgerQuery implements LedgerQuery{ + + private EmptyLedgerDataset dataset; + + @Override + public HashDigest getHash() { + return null; + } + + @Override + public long getLatestBlockHeight() { + return 0; + } + + @Override + public HashDigest getLatestBlockHash() { + return null; + } + + @Override + public LedgerBlock getLatestBlock() { + return null; + } + + @Override + public HashDigest getBlockHash(long height) { + return null; + } + + @Override + public LedgerBlock getBlock(long height) { + return null; + } + + @Override + public LedgerAdminInfo getAdminInfo() { + return null; + } + + @Override + public LedgerAdminInfo getAdminInfo(LedgerBlock block) { + return null; + } + + @Override + public LedgerAdminSettings getAdminSettings() { + return null; + } + + @Override + public LedgerAdminSettings getAdminSettings(LedgerBlock block) { + return null; + } + + @Override + public LedgerBlock getBlock(HashDigest hash) { + return null; + } + + @Override + public LedgerDataQuery getLedgerData(LedgerBlock block) { + return dataset; + } + + @Override + public TransactionQuery getTransactionSet(LedgerBlock block) { + return null; + } + + @Override + public UserAccountQuery getUserAccountSet(LedgerBlock block) { + return dataset.getUserAccountSet(); + } + + @Override + public DataAccountQuery getDataAccountSet(LedgerBlock block) { + return dataset.getDataAccountSet(); + } + + @Override + public ContractAccountQuery getContractAccountSet(LedgerBlock block) { + return dataset.getContractAccountset(); + } + + @Override + public LedgerBlock retrieveLatestBlock() { + return null; + } + + @Override + public long retrieveLatestBlockHeight() { + return 0; + } + + @Override + public HashDigest retrieveLatestBlockHash() { + return null; + } + + } + +} 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..69cafb95 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 @@ -1,7 +1,6 @@ package com.jd.blockchain.ledger.core; import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.ledger.LedgerInitSetting; import com.jd.blockchain.storage.service.KVStorageService; /** @@ -12,19 +11,21 @@ import com.jd.blockchain.storage.service.KVStorageService; */ public interface LedgerManage extends LedgerService { - LedgerRepository register(HashDigest ledgerHash, KVStorageService storageService); + static final String LEDGER_PREFIX = "LDG://"; + + LedgerQuery 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 80% 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..715c68f3 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,16 +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; - // - // @Autowired - // private VersioningKVStorage versioningStorage; - - // private PrivilegeModelSetting privilegeModel = new PrivilegeModelConfig(); - private Map ledgers = new HashMap<>(); @Override @@ -69,7 +54,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 +127,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()); @@ -165,6 +150,7 @@ public class LedgerManager implements LedgerManage { public final LedgerRepository ledgerRepo; + @SuppressWarnings("unused") public final KVStorageService storageService; public LedgerRepositoryContext(LedgerRepository ledgerRepo, KVStorageService storageService) { diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerQuery.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerQuery.java new file mode 100644 index 00000000..75233ae5 --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerQuery.java @@ -0,0 +1,125 @@ +package com.jd.blockchain.ledger.core; + +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.ledger.LedgerAdminInfo; +import com.jd.blockchain.ledger.LedgerAdminSettings; +import com.jd.blockchain.ledger.LedgerBlock; + +public interface LedgerQuery { + + /** + * 账本哈希,这是账本的唯一标识; + * + * @return + */ + HashDigest getHash(); + + /** + * 最新区块高度; + * + * @return + */ + long getLatestBlockHeight(); + + /** + * 最新区块哈希; + * + * @return + */ + HashDigest getLatestBlockHash(); + + /** + * 最新区块; + * + * @return + */ + LedgerBlock getLatestBlock(); + + /** + * 指定高度的区块哈希; + * + * @param height + * @return + */ + HashDigest getBlockHash(long height); + + /** + * 指定高度的区块; + * + * @param height + * @return + */ + LedgerBlock getBlock(long height); + + LedgerAdminInfo getAdminInfo(); + + LedgerAdminInfo getAdminInfo(LedgerBlock block); + + LedgerAdminSettings getAdminSettings(); + + LedgerAdminSettings getAdminSettings(LedgerBlock block); + + LedgerBlock getBlock(HashDigest hash); + + /** + * 返回指定 + * @param block + * @return + */ + LedgerDataQuery getLedgerData(LedgerBlock block); + + /** + * 返回最新区块对应的账本数据; + * + * @return + */ + default LedgerDataQuery getLedgerData() { + return getLedgerData(getLatestBlock()); + } + + TransactionQuery getTransactionSet(LedgerBlock block); + + UserAccountQuery getUserAccountSet(LedgerBlock block); + + DataAccountQuery getDataAccountSet(LedgerBlock block); + + ContractAccountQuery getContractAccountSet(LedgerBlock block); + + default TransactionQuery getTransactionSet() { + return getTransactionSet(getLatestBlock()); + } + + default UserAccountQuery getUserAccountSet() { + return getUserAccountSet(getLatestBlock()); + } + + default DataAccountQuery getDataAccountSet() { + return getDataAccountSet(getLatestBlock()); + } + + default ContractAccountQuery getContractAccountset() { + return getContractAccountSet(getLatestBlock()); + } + + /** + * 重新检索最新区块,同时更新缓存; + * + * @return + */ + LedgerBlock retrieveLatestBlock(); + + /** + * 重新检索最新区块,同时更新缓存; + * + * @return + */ + long retrieveLatestBlockHeight(); + + /** + * 重新检索最新区块哈希,同时更新缓存; + * + * @return + */ + HashDigest retrieveLatestBlockHash(); + +} \ No newline at end of file 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 60% 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..55b989d5 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,169 +1,195 @@ -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.LedgerException; +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 LedgerService ledgerService; + private static final KVDataEntry[] EMPTY_ENTRIES = new KVDataEntry[0]; + + private HashDigest[] ledgerHashs; - public LedgerQueryService(LedgerService ledgerService) { - this.ledgerService = ledgerService; + private LedgerQuery ledger; + + public LedgerQueryService(LedgerQuery ledger) { + this.ledger = ledger; + this.ledgerHashs = new HashDigest[] {ledger.getHash()}; + } + + private void checkLedgerHash(HashDigest ledgerHash) { + if (!ledgerHashs[0].equals(ledgerHash)) { + throw new LedgerException("Unsupport cross chain query!"); + } } @Override public HashDigest[] getLedgerHashs() { - return ledgerService.getLedgerHashs(); + return ledgerHashs; } @Override public LedgerInfo getLedger(HashDigest ledgerHash) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + checkLedgerHash(ledgerHash); LedgerInfo ledgerInfo = new LedgerInfo(); ledgerInfo.setHash(ledger.getHash()); ledgerInfo.setLatestBlockHash(ledger.getLatestBlockHash()); ledgerInfo.setLatestBlockHeight(ledger.getLatestBlockHeight()); return ledgerInfo; } + + @Override + public LedgerAdminInfo getLedgerAdminInfo(HashDigest ledgerHash) { + checkLedgerHash(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 public LedgerBlock getBlock(HashDigest ledgerHash, long height) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + checkLedgerHash(ledgerHash); return ledger.getBlock(height); } @Override public LedgerBlock getBlock(HashDigest ledgerHash, HashDigest blockHash) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + checkLedgerHash(ledgerHash); return ledger.getBlock(blockHash); } @Override public long getTransactionCount(HashDigest ledgerHash, long height) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getBlock(height); - TransactionSet txset = ledger.getTransactionSet(block); + TransactionQuery txset = ledger.getTransactionSet(block); return txset.getTotalCount(); } @Override public long getTransactionCount(HashDigest ledgerHash, HashDigest blockHash) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getBlock(blockHash); - TransactionSet txset = ledger.getTransactionSet(block); + TransactionQuery txset = ledger.getTransactionSet(block); return txset.getTotalCount(); } @Override public long getTransactionTotalCount(HashDigest ledgerHash) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - TransactionSet txset = ledger.getTransactionSet(block); + TransactionQuery txset = ledger.getTransactionSet(block); return txset.getTotalCount(); } @Override public long getDataAccountCount(HashDigest ledgerHash, long height) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getBlock(height); - DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); - return dataAccountSet.getTotalCount(); + DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); + return dataAccountSet.getTotal(); } @Override public long getDataAccountCount(HashDigest ledgerHash, HashDigest blockHash) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getBlock(blockHash); - DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); - return dataAccountSet.getTotalCount(); + DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); + return dataAccountSet.getTotal(); } @Override public long getDataAccountTotalCount(HashDigest ledgerHash) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); - return dataAccountSet.getTotalCount(); + DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); + return dataAccountSet.getTotal(); } @Override public long getUserCount(HashDigest ledgerHash, long height) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getBlock(height); - UserAccountSet userAccountSet = ledger.getUserAccountSet(block); - return userAccountSet.getTotalCount(); + UserAccountQuery userAccountSet = ledger.getUserAccountSet(block); + return userAccountSet.getTotal(); } @Override public long getUserCount(HashDigest ledgerHash, HashDigest blockHash) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getBlock(blockHash); - UserAccountSet userAccountSet = ledger.getUserAccountSet(block); - return userAccountSet.getTotalCount(); + UserAccountQuery userAccountSet = ledger.getUserAccountSet(block); + return userAccountSet.getTotal(); } @Override public long getUserTotalCount(HashDigest ledgerHash) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - UserAccountSet userAccountSet = ledger.getUserAccountSet(block); - return userAccountSet.getTotalCount(); + UserAccountQuery userAccountSet = ledger.getUserAccountSet(block); + return userAccountSet.getTotal(); } @Override public long getContractCount(HashDigest ledgerHash, long height) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getBlock(height); - ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); - return contractAccountSet.getTotalCount(); + ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block); + return contractAccountSet.getTotal(); } @Override public long getContractCount(HashDigest ledgerHash, HashDigest blockHash) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getBlock(blockHash); - ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); - return contractAccountSet.getTotalCount(); + ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block); + return contractAccountSet.getTotal(); } @Override public long getContractTotalCount(HashDigest ledgerHash) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); - return contractAccountSet.getTotalCount(); + ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block); + return contractAccountSet.getTotal(); } @Override public LedgerTransaction[] getTransactions(HashDigest ledgerHash, long height, int fromIndex, int count) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + checkLedgerHash(ledgerHash); LedgerBlock ledgerBlock = ledger.getBlock(height); - TransactionSet transactionSet = ledger.getTransactionSet(ledgerBlock); + TransactionQuery transactionSet = ledger.getTransactionSet(ledgerBlock); int lastHeightTxTotalNums = 0; if (height > 0) { @@ -190,10 +216,10 @@ public class LedgerQueryService implements BlockchainQueryService { @Override public LedgerTransaction[] getTransactions(HashDigest ledgerHash, HashDigest blockHash, int fromIndex, int count) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + checkLedgerHash(ledgerHash); LedgerBlock ledgerBlock = ledger.getBlock(blockHash); long height = ledgerBlock.getHeight(); - TransactionSet transactionSet = ledger.getTransactionSet(ledgerBlock); + TransactionQuery transactionSet = ledger.getTransactionSet(ledgerBlock); int lastHeightTxTotalNums = 0; if (height > 0) { @@ -220,53 +246,53 @@ public class LedgerQueryService implements BlockchainQueryService { @Override public LedgerTransaction getTransactionByContentHash(HashDigest ledgerHash, HashDigest contentHash) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - TransactionSet txset = ledger.getTransactionSet(block); + TransactionQuery txset = ledger.getTransactionSet(block); return txset.get(contentHash); } @Override public TransactionState getTransactionStateByContentHash(HashDigest ledgerHash, HashDigest contentHash) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - TransactionSet txset = ledger.getTransactionSet(block); - return txset.getTxState(contentHash); + TransactionQuery txset = ledger.getTransactionSet(block); + return txset.getState(contentHash); } @Override public UserInfo getUser(HashDigest ledgerHash, String address) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - UserAccountSet userAccountSet = ledger.getUserAccountSet(block); - return userAccountSet.getUser(address); + UserAccountQuery userAccountSet = ledger.getUserAccountSet(block); + return userAccountSet.getAccount(address); } @Override public AccountHeader getDataAccount(HashDigest ledgerHash, String address) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); - return dataAccountSet.getDataAccount(Bytes.fromBase58(address)); + DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); + return dataAccountSet.getAccount(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); + checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); - DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address)); + DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); + DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address)); KVDataEntry[] entries = new KVDataEntry[keys.length]; long ver; 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); @@ -304,10 +330,10 @@ public class LedgerQueryService implements BlockchainQueryService { throw new ContractException("keys.length!=versions.length!"); } - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); - DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address)); + DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); + DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address)); KVDataEntry[] entries = new KVDataEntry[keys.length]; long ver = -1; @@ -334,11 +360,10 @@ public class LedgerQueryService implements BlockchainQueryService { @Override public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count) { - - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); - DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address)); + DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); + DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address)); int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccount.getDataEntriesTotalCount()); return dataAccount.getDataEntries(pages[0], pages[1]); @@ -346,54 +371,47 @@ public class LedgerQueryService implements BlockchainQueryService { @Override public long getDataEntriesTotalCount(HashDigest ledgerHash, String address) { - - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); - DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address)); + DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); + DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address)); return dataAccount.getDataEntriesTotalCount(); } @Override public ContractInfo getContract(HashDigest ledgerHash, String address) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); - return contractAccountSet.getContract(Bytes.fromBase58(address)); + ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block); + return contractAccountSet.getAccount(Bytes.fromBase58(address)); } @Override public AccountHeader[] getUsers(HashDigest ledgerHash, int fromIndex, int count) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - UserAccountSet userAccountSet = ledger.getUserAccountSet(block); - int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) userAccountSet.getTotalCount()); - return userAccountSet.getAccounts(pages[0], pages[1]); + UserAccountQuery userAccountSet = ledger.getUserAccountSet(block); + int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) userAccountSet.getTotal()); + return userAccountSet.getHeaders(pages[0], pages[1]); } @Override public AccountHeader[] getDataAccounts(HashDigest ledgerHash, int fromIndex, int count) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); - int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccountSet.getTotalCount()); - return dataAccountSet.getAccounts(pages[0], pages[1]); + DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); + int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccountSet.getTotal()); + return dataAccountSet.getHeaders(pages[0], pages[1]); } @Override public AccountHeader[] getContractAccounts(HashDigest ledgerHash, int fromIndex, int count) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + checkLedgerHash(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); - int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) contractAccountSet.getTotalCount()); - return contractAccountSet.getAccounts(pages[0], pages[1]); + ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block); + int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) contractAccountSet.getTotal()); + return contractAccountSet.getHeaders(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..e98ff376 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 @@ -2,115 +2,8 @@ package com.jd.blockchain.ledger.core; import java.io.Closeable; -import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.ledger.LedgerBlock; +public interface LedgerRepository extends Closeable, LedgerQuery { -public interface LedgerRepository extends Closeable { - - /** - * 账本哈希,这是账本的唯一标识; - * - * @return - */ - HashDigest getHash(); - - /** - * 最新区块高度; - * - * @return - */ - long getLatestBlockHeight(); - - /** - * 最新区块哈希; - * - * @return - */ - HashDigest getLatestBlockHash(); - - /** - * 最新区块; - * - * @return - */ - LedgerBlock getLatestBlock(); - - /** - * 指定高度的区块哈希; - * - * @param height - * @return - */ - HashDigest getBlockHash(long height); - - /** - * 指定高度的区块; - * - * @param height - * @return - */ - LedgerBlock getBlock(long height); - - LedgerAdministration getAdminInfo(); - - LedgerBlock getBlock(HashDigest hash); - - LedgerDataSet getDataSet(LedgerBlock block); - - TransactionSet getTransactionSet(LedgerBlock block); - - LedgerAdminAccount getAdminAccount(LedgerBlock block); - - UserAccountSet getUserAccountSet(LedgerBlock block); - - DataAccountSet getDataAccountSet(LedgerBlock block); - - ContractAccountSet getContractAccountSet(LedgerBlock block); - - default LedgerDataSet getDataSet() { - return getDataSet(getLatestBlock()); - } - - default TransactionSet getTransactionSet() { - return getTransactionSet(getLatestBlock()); - } - - default LedgerAdminAccount getAdminAccount() { - return getAdminAccount(getLatestBlock()); - } - - default UserAccountSet getUserAccountSet() { - return getUserAccountSet(getLatestBlock()); - } - - default DataAccountSet getDataAccountSet() { - return getDataAccountSet(getLatestBlock()); - } - - default ContractAccountSet getContractAccountSet() { - return getContractAccountSet(getLatestBlock()); - } - - /** - * 重新检索最新区块,同时更新缓存; - * - * @return - */ - LedgerBlock retrieveLatestBlock(); - - /** - * 重新检索最新区块,同时更新缓存; - * - * @return - */ - long retrieveLatestBlockHeight(); - - /** - * 重新检索最新区块哈希,同时更新缓存; - * - * @return - */ - HashDigest retrieveLatestBlockHash(); /** * 创建新区块的编辑器; 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 55% 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 1fe559b7..9734f880 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,23 +1,18 @@ -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.SettingContext; -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.LedgerAdminSettings; +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; @@ -36,7 +31,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); @@ -80,6 +75,8 @@ public class LedgerRepositoryImpl implements LedgerRepository { if (getLatestBlockHeight() < 0) { throw new RuntimeException("Ledger doesn't exist!"); } + + retrieveLatestState(); } /* @@ -110,25 +107,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); + TransactionQuery 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 @@ -187,7 +186,7 @@ public class LedgerRepositoryImpl implements LedgerRepository { if (height < 0) { return null; } - return innerGetBlock(getBlockHash(height)); + return innerGetBlock(innerGetBlockHash(height)); } @Override @@ -209,26 +208,18 @@ public class LedgerRepositoryImpl implements LedgerRepository { throw new RuntimeException("Block hash not equals to it's storage key!"); } - // verify hash; - // boolean requiredVerifyHash = - // adminAccount.getMetadata().getSetting().getCryptoSetting().getAutoVerifyHash(); - // TODO: 未实现从配置中加载是否校验 Hash 的设置; - if (SettingContext.queryingSettings().verifyHash()) { - 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 RuntimeException("Block hash verification fail!"); - } + // 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; @@ -243,9 +234,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 createAdminData(getLatestBlock()); } private LedgerBlock deserialize(byte[] blockBytes) { @@ -253,142 +253,125 @@ public class LedgerRepositoryImpl implements LedgerRepository { } @Override - public TransactionSet getTransactionSet(LedgerBlock block) { + public TransactionQuery 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 LedgerAdminInfo getAdminInfo(LedgerBlock block) { + return createAdminData(block); + } + + @Override + public LedgerAdminSettings getAdminSettings() { + return getAdminSettings(getLatestBlock()); + } + + @Override + public LedgerAdminSettings getAdminSettings(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); + } + + /** + * 生成LedgerAdminInfoData对象 + * 该对象主要用于页面展示 + * + * @param block + * @return + */ + private LedgerAdminInfoData createAdminData(LedgerBlock block) { + return new LedgerAdminInfoData(createAdminDataset(block)); + } + + /** + * 生成LedgerAdminDataset对象 + * + * @param block + * @return + */ + 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); + LedgerAdminSettings adminAccount = getAdminSettings(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); + LedgerAdminSettings adminAccount = getAdminSettings(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); + LedgerAdminSettings adminAccount = getAdminSettings(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 getLedgerData(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 @@ -401,9 +384,8 @@ public class LedgerRepositoryImpl implements LedgerRepository { "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(previousBlock, - getAdminInfo().getMetadata().getSetting(), keyPrefix, exPolicyStorage, - versioningStorage); + LedgerTransactionalEditor editor = LedgerTransactionalEditor.createEditor(previousBlock, getLatestSettings(), + keyPrefix, exPolicyStorage, versioningStorage); NewBlockCommittingMonitor committingMonitor = new NewBlockCommittingMonitor(editor, this); this.nextBlockEditor = committingMonitor; return committingMonitor; @@ -426,64 +408,39 @@ public class LedgerRepositoryImpl implements LedgerRepository { } 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, + static TransactionSet newTransactionSet(LedgerSettings 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)); String txsetKeyPrefix = keyPrefix + TRANSACTION_SET_PREFIX; @@ -492,13 +449,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 +463,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 +472,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 +481,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 +490,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 +498,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, @@ -586,6 +526,16 @@ public class LedgerRepositoryImpl implements LedgerRepository { 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); @@ -601,7 +551,8 @@ public class LedgerRepositoryImpl implements LedgerRepository { try { editor.commit(); LedgerBlock latestBlock = editor.getCurrentBlock(); - ledgerRepo.latestState = new LedgerState(latestBlock); + ledgerRepo.latestState = new LedgerState(latestBlock, editor.getLedgerDataset(), + editor.getTransactionSet()); } finally { ledgerRepo.nextBlockEditor = null; } @@ -628,20 +579,39 @@ public class LedgerRepositoryImpl implements LedgerRepository { private final LedgerBlock block; - private volatile LedgerAdminAccount adminAccount; + private final TransactionQuery transactionSet; + + private final LedgerDataset ledgerDataset; + + public LedgerState(LedgerBlock block, LedgerDataset ledgerDataset, TransactionQuery transactionSet) { + this.block = block; + this.ledgerDataset = ledgerDataset; + this.transactionSet = transactionSet; + + } - private volatile UserAccountSet userAccountSet; + public LedgerAdminDataset getAdminDataset() { + return ledgerDataset.getAdminDataset(); + } - private volatile DataAccountSet dataAccountSet; + public LedgerDataset getLedgerDataset() { + return ledgerDataset; + } - private volatile ContractAccountSet contractAccountSet; + public ContractAccountQuery getContractAccountSet() { + return ledgerDataset.getContractAccountset(); + } - private volatile TransactionSet transactionSet; + public DataAccountQuery getDataAccountSet() { + return ledgerDataset.getDataAccountSet(); + } - private volatile LedgerDataSet ledgerDataSet; + public UserAccountQuery getUserAccountSet() { + return ledgerDataset.getUserAccountSet(); + } - public LedgerState(LedgerBlock block) { - this.block = block; + public TransactionQuery 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..56daa556 --- /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.UserAuthorizationSettings; +import com.jd.blockchain.utils.Bytes; + +/** + * 账本安全管理器; + * + * @author huanghaiquan + * + */ +public class LedgerSecurityManagerImpl implements LedgerSecurityManager { + + private RolePrivilegeSettings rolePrivilegeSettings; + + private UserAuthorizationSettings 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, UserAuthorizationSettings 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/LedgerSetting.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerSetting.java deleted file mode 100644 index 6e9ad134..00000000 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerSetting.java +++ /dev/null @@ -1,24 +0,0 @@ -//package com.jd.blockchain.ledger.core; -// -//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.ledger.CryptoSetting; -//import com.jd.blockchain.utils.Bytes; -// -//@DataContract(code = DataCodes.METADATA_LEDGER_SETTING) -//public interface LedgerSetting { -// -// @DataField(order=0, primitiveType=PrimitiveType.TEXT) -// String getConsensusProvider(); -// -// @DataField(order=1, primitiveType=PrimitiveType.BYTES) -// Bytes getConsensusSetting(); -// -// @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/LedgerTransactionContext.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionContext.java index a4feb79e..5dccc736 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,11 +13,18 @@ import java.util.List; public interface LedgerTransactionContext { /** - * 账本数据; + * 账本数据集合; * * @return */ - LedgerDataSet getDataSet(); + LedgerDataset getDataset(); + + /** + * 事务集合; + * + * @return + */ + TransactionQuery getTransactionSet(); /** * 交易请求; 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 99% 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 432c24e1..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,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.DigitalSignature; 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/LedgerTransactionalEditor.java similarity index 84% rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionalEditor.java rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionalEditor.java index c4b696c0..ea7bb7ed 100644 --- 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/LedgerTransactionalEditor.java @@ -1,4 +1,4 @@ -package com.jd.blockchain.ledger.core.impl; +package com.jd.blockchain.ledger.core; import java.util.List; @@ -8,29 +8,19 @@ 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.DigitalSignature; 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.LedgerSetting; +import com.jd.blockchain.ledger.LedgerSettings; import com.jd.blockchain.ledger.LedgerTransaction; import com.jd.blockchain.ledger.OperationResult; -import com.jd.blockchain.ledger.TransactionContent; import com.jd.blockchain.ledger.TransactionRequest; import com.jd.blockchain.ledger.TransactionRollbackException; 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.LedgerTransactionContext; -import com.jd.blockchain.ledger.core.SettingContext; -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.transaction.SignatureUtils; -import com.jd.blockchain.transaction.TxBuilder; -import com.jd.blockchain.transaction.TxRequestBuilder; import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.codec.Base58Utils; @@ -70,10 +60,8 @@ public class LedgerTransactionalEditor implements LedgerEditor { private BufferedKVStorage baseStorage; /** - * 上一个交易的上下文; + * 上一个交易产生的账本快照; */ -// private LedgerTransactionContextImpl previousTxCtx; - private TxSnapshot previousTxSnapshot; /** @@ -81,6 +69,16 @@ public class LedgerTransactionalEditor implements LedgerEditor { */ private volatile LedgerTransactionContextImpl currentTxCtx; + /** + * 最后提交的账本数据集; + */ + private volatile LedgerDataset latestLedgerDataset; + + /** + * 最后提交的交易集合; + */ + private volatile TransactionSet latestTransactionSet; + /** * @param ledgerHash * @param cryptoSetting @@ -115,7 +113,7 @@ public class LedgerTransactionalEditor implements LedgerEditor { * @param verifyTx 是否校验交易请求;当外部调用者在调用前已经实施了验证时,将次参数设置为 false 能够提升性能; * @return */ - public static LedgerTransactionalEditor createEditor(LedgerBlock previousBlock, LedgerSetting ledgerSetting, + public static LedgerTransactionalEditor createEditor(LedgerBlock previousBlock, LedgerSettings ledgerSetting, String ledgerKeyPrefix, ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage) { // new block; HashDigest ledgerHash = previousBlock.getLedgerHash(); @@ -160,6 +158,10 @@ public class LedgerTransactionalEditor implements LedgerEditor { private void commitTxSnapshot(TxSnapshot snapshot) { previousTxSnapshot = snapshot; + latestLedgerDataset = currentTxCtx.getDataset(); + latestLedgerDataset.setReadonly(); + latestTransactionSet = currentTxCtx.getTransactionSet(); + latestTransactionSet.setReadonly(); currentTxCtx = null; } @@ -181,13 +183,23 @@ public class LedgerTransactionalEditor implements LedgerEditor { return ledgerHash; } + @Override + public LedgerDataset getLedgerDataset() { + return latestLedgerDataset; + } + + @Override + public TransactionSet getTransactionSet() { + return latestTransactionSet; + } + /** * 检查当前账本是否是指定交易请求的账本; * * @param txRequest * @return */ - private boolean isRequestedLedger(TransactionRequest txRequest) { + private boolean isRequestMatched(TransactionRequest txRequest) { HashDigest reqLedgerHash = txRequest.getTransactionContent().getLedgerHash(); if (ledgerHash == reqLedgerHash) { return true; @@ -198,49 +210,19 @@ public class LedgerTransactionalEditor implements LedgerEditor { return ledgerHash.equals(reqLedgerHash); } - private boolean verifyTxContent(TransactionRequest request) { - TransactionContent txContent = request.getTransactionContent(); - if (!TxBuilder.verifyTxContentHash(txContent, txContent.getHash())) { - return false; - } - DigitalSignature[] endpointSignatures = request.getEndpointSignatures(); - if (endpointSignatures != null) { - for (DigitalSignature signature : endpointSignatures) { - if (!SignatureUtils.verifyHashSignature(txContent.getHash(), signature.getDigest(), - signature.getPubKey())) { - return false; - } - } - } - DigitalSignature[] nodeSignatures = request.getNodeSignatures(); - if (nodeSignatures != null) { - for (DigitalSignature signature : nodeSignatures) { - if (!SignatureUtils.verifyHashSignature(txContent.getHash(), signature.getDigest(), - signature.getPubKey())) { - return false; - } - } - } - return true; - } - + /** + * 注:此方法不验证交易完整性和签名有效性,仅仅设计为进行交易记录的管理;调用者应在此方法之外进行数据完整性和签名有效性的检查; + */ @Override public synchronized LedgerTransactionContext newTransaction(TransactionRequest txRequest) { - if (SettingContext.txSettings().verifyLedger() && !isRequestedLedger(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); } - // TODO: 把验签和创建交易并行化; - if (SettingContext.txSettings().verifySignature() && !verifyTxContent(txRequest)) { - // 抛弃哈希和签名校验失败的交易请求; - throw new IllegalTransactionException( - "Wrong transaction signature! --[TxHash=" + txRequest.getTransactionContent().getHash() + "]!", - TransactionState.IGNORED_BY_WRONG_CONTENT_SIGNATURE); - } - if (currentTxCtx != null) { throw new IllegalStateException( "Unable to open another new transaction before the current transaction is completed! --[TxHash=" @@ -253,7 +235,7 @@ public class LedgerTransactionalEditor implements LedgerEditor { // init storage of new transaction; BufferedKVStorage txBufferedStorage = new BufferedKVStorage(baseStorage, baseStorage, false); - LedgerDataSetImpl txDataset = null; + LedgerDataset txDataset = null; TransactionSet txset = null; if (previousTxSnapshot == null) { // load the starting point of the new transaction; @@ -262,18 +244,18 @@ public class LedgerTransactionalEditor implements LedgerEditor { GenesisSnapshot snpht = (GenesisSnapshot) startingPoint; txDataset = LedgerRepositoryImpl.newDataSet(snpht.initSetting, ledgerKeyPrefix, txBufferedStorage, txBufferedStorage); - txset = LedgerRepositoryImpl.newTransactionSet(txDataset.getAdminAccount().getSetting(), + 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, ledgerKeyPrefix, txBufferedStorage, - txBufferedStorage, false); + txDataset = LedgerRepositoryImpl.loadDataSet(snpht.dataSnapshot, cryptoSetting, ledgerKeyPrefix, + txBufferedStorage, txBufferedStorage, false); // load txset; - txset = LedgerRepositoryImpl.loadTransactionSet(snpht.txsetHash, this.cryptoSetting, ledgerKeyPrefix, + txset = LedgerRepositoryImpl.loadTransactionSet(snpht.txsetHash, cryptoSetting, ledgerKeyPrefix, txBufferedStorage, txBufferedStorage, false); } else { // Unreachable; @@ -283,11 +265,11 @@ public class LedgerTransactionalEditor implements LedgerEditor { } else { // Reuse previous object to optimize performance; // load dataset; - txDataset = LedgerRepositoryImpl.loadDataSet(previousTxSnapshot.dataSnapshot, ledgerKeyPrefix, - txBufferedStorage, txBufferedStorage, false); + txDataset = LedgerRepositoryImpl.loadDataSet(previousTxSnapshot.dataSnapshot, cryptoSetting, + ledgerKeyPrefix, txBufferedStorage, txBufferedStorage, false); // load txset; - txset = LedgerRepositoryImpl.loadTransactionSet(previousTxSnapshot.txsetHash, this.cryptoSetting, + txset = LedgerRepositoryImpl.loadTransactionSet(previousTxSnapshot.txsetHash, cryptoSetting, ledgerKeyPrefix, txBufferedStorage, txBufferedStorage, false); } @@ -476,28 +458,6 @@ public class LedgerTransactionalEditor implements LedgerEditor { } -// /** -// * 账本的数据上下文; -// * -// * @author huanghaiquan -// * -// */ -// 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; -// } -// -// } - /** * 交易的上下文; * @@ -510,7 +470,7 @@ public class LedgerTransactionalEditor implements LedgerEditor { private TransactionRequest txRequest; - private LedgerDataSetImpl dataset; + private LedgerDataset dataset; private TransactionSet txset; @@ -524,7 +484,7 @@ public class LedgerTransactionalEditor implements LedgerEditor { private HashDigest txRootHash; - private LedgerTransactionContextImpl(TransactionRequest txRequest, LedgerDataSetImpl dataset, + private LedgerTransactionContextImpl(TransactionRequest txRequest, LedgerDataset dataset, TransactionSet txset, BufferedKVStorage storage, LedgerTransactionalEditor editor) { this.txRequest = txRequest; this.dataset = dataset; @@ -534,10 +494,15 @@ public class LedgerTransactionalEditor implements LedgerEditor { } @Override - public LedgerDataSet getDataSet() { + public LedgerDataset getDataset() { return dataset; } + @Override + public TransactionSet getTransactionSet() { + return txset; + } + @Override public TransactionRequest getTransactionRequest() { return txRequest; @@ -620,8 +585,8 @@ public class LedgerTransactionalEditor implements LedgerEditor { private TransactionStagedSnapshot takeDataSnapshot() { TransactionStagedSnapshot txDataSnapshot = new TransactionStagedSnapshot(); - txDataSnapshot.setAdminAccountHash(dataset.getAdminAccount().getHash()); - txDataSnapshot.setContractAccountSetHash(dataset.getContractAccountSet().getRootHash()); + txDataSnapshot.setAdminAccountHash(dataset.getAdminDataset().getHash()); + txDataSnapshot.setContractAccountSetHash(dataset.getContractAccountset().getRootHash()); txDataSnapshot.setDataAccountSetHash(dataset.getDataAccountSet().getRootHash()); txDataSnapshot.setUserAccountSetHash(dataset.getUserAccountSet().getRootHash()); return txDataSnapshot; 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/MerkleAccount.java similarity index 88% rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/BaseAccount.java rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccount.java index 9a57c6d0..49ef5753 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/MerkleAccount.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; @@ -19,7 +20,7 @@ import com.jd.blockchain.utils.Transactional; * @author huanghaiquan * */ -public class BaseAccount implements AccountHeader, MerkleProvable, Transactional { +public class MerkleAccount implements AccountHeader, MerkleProvable, Transactional { private BlockchainIdentity bcid; @@ -37,7 +38,7 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional * @param address * @param pubKey */ - public BaseAccount(Bytes address, PubKey pubKey, CryptoSetting cryptoSetting, String keyPrefix, + public MerkleAccount(Bytes address, PubKey pubKey, CryptoSetting cryptoSetting, String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage) { this(address, pubKey, null, cryptoSetting, keyPrefix, exStorage, verStorage, false); } @@ -57,33 +58,33 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional * @param verStorage * @param accessPolicy */ - public BaseAccount(BlockchainIdentity bcid, CryptoSetting cryptoSetting, String keyPrefix, + public MerkleAccount(BlockchainIdentity bcid, CryptoSetting cryptoSetting, String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage) { this(bcid, null, cryptoSetting, keyPrefix, exStorage, verStorage, false); } /** * 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 * @param readonly * @param accessPolicy */ - public BaseAccount(Bytes address, PubKey pubKey, HashDigest dataRootHash, CryptoSetting cryptoSetting, + public MerkleAccount(Bytes address, PubKey pubKey, HashDigest dataRootHash, CryptoSetting cryptoSetting, String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly) { this(new BlockchainIdentityData(address, pubKey), dataRootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly); } - public BaseAccount(BlockchainIdentity bcid, HashDigest dataRootHash, CryptoSetting cryptoSetting, String keyPrefix, + public MerkleAccount(BlockchainIdentity bcid, HashDigest dataRootHash, CryptoSetting cryptoSetting, String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly) { this.bcid = bcid; this.dataset = new MerkleDataSet(dataRootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly); @@ -168,7 +169,7 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional * @param key * @return */ - public long getKeyVersion(Bytes key) { + public long getVersion(Bytes key) { return dataset.getVersion(key); } 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/MerkleAccountSet.java similarity index 80% rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountSet.java rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccountSet.java index bb57cd3c..d3e507ba 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/MerkleAccountSet.java @@ -12,14 +12,17 @@ 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.ledger.MerkleSnapshot; 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 AccountSet implements Transactional, MerkleProvable { +public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQuery { static { + DataContractRegistry.register(MerkleSnapshot.class); DataContractRegistry.register(AccountHeader.class); } @@ -33,7 +36,7 @@ public class AccountSet implements Transactional, MerkleProvable { * */ // TODO:未考虑大数据量时,由于缺少过期策略,会导致内存溢出的问题; - private Map latestAccountsCache = new HashMap<>(); + private Map latestAccountsCache = new HashMap<>(); private ExPolicyKVStorage baseExStorage; @@ -49,13 +52,18 @@ public class AccountSet implements Transactional, MerkleProvable { return merkleDataset.isReadonly(); } - public AccountSet(CryptoSetting cryptoSetting, String keyPrefix, ExPolicyKVStorage exStorage, + void setReadonly() { + merkleDataset.setReadonly(); + } + + public MerkleAccountSet(CryptoSetting cryptoSetting, String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy) { this(null, cryptoSetting, keyPrefix, exStorage, verStorage, false, accessPolicy); } - public AccountSet(HashDigest rootHash, CryptoSetting cryptoSetting, String keyPrefix, ExPolicyKVStorage exStorage, - VersioningKVStorage verStorage, boolean readonly, AccountAccessPolicy accessPolicy) { + public MerkleAccountSet(HashDigest rootHash, CryptoSetting cryptoSetting, String keyPrefix, + ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, + AccountAccessPolicy accessPolicy) { this.keyPrefix = keyPrefix; this.cryptoSetting = cryptoSetting; this.baseExStorage = exStorage; @@ -65,10 +73,6 @@ public class AccountSet implements Transactional, MerkleProvable { this.accessPolicy = accessPolicy; } - // public HashDigest getAccountRootHash() { - // return merkleDataset.getRootHash(); - // } - @Override public HashDigest getRootHash() { return merkleDataset.getRootHash(); @@ -79,7 +83,7 @@ public class AccountSet implements Transactional, MerkleProvable { return merkleDataset.getProof(key); } - public AccountHeader[] getAccounts(int fromIndex, int count) { + public AccountHeader[] getHeaders(int fromIndex, int count) { byte[][] results = merkleDataset.getLatestValues(fromIndex, count); AccountHeader[] accounts = new AccountHeader[results.length]; @@ -109,17 +113,22 @@ public class AccountSet implements Transactional, MerkleProvable { * * @return */ - public long getTotalCount() { + public long getTotal() { return merkleDataset.getDataCount(); } + @Override + public MerkleAccount getAccount(String address) { + return getAccount(Bytes.fromBase58(address)); + } + /** * 返回最新版本的 Account; * * @param address * @return */ - public BaseAccount getAccount(Bytes address) { + public MerkleAccount getAccount(Bytes address) { return this.getAccount(address, -1); } @@ -148,7 +157,7 @@ public class AccountSet implements Transactional, MerkleProvable { * @return */ public long getVersion(Bytes address) { - VersioningAccount acc = latestAccountsCache.get(address); + InnerVersioningAccount acc = latestAccountsCache.get(address); if (acc != null) { // 已注册尚未提交,也返回 -1; return acc.version == -1 ? 0 : acc.version; @@ -162,15 +171,13 @@ public class AccountSet implements Transactional, MerkleProvable { * * 只有最新版本的账户才能可写的,其它都是只读; * - * @param address - * 账户地址; - * @param version - * 账户版本;如果指定为 -1,则返回最新版本; + * @param address 账户地址; + * @param version 账户版本;如果指定为 -1,则返回最新版本; * @return */ - public BaseAccount getAccount(Bytes address, long version) { + public MerkleAccount getAccount(Bytes address, long version) { version = version < 0 ? -1 : version; - VersioningAccount acc = latestAccountsCache.get(address); + InnerVersioningAccount acc = latestAccountsCache.get(address); if (acc != null && version == -1) { return acc; } else if (acc != null && acc.version == version) { @@ -232,14 +239,14 @@ public class AccountSet implements Transactional, MerkleProvable { * @param pubKey 公钥; * @return 注册成功的账户对象; */ - public BaseAccount register(Bytes address, PubKey pubKey) { + public MerkleAccount register(Bytes address, PubKey pubKey) { if (isReadonly()) { throw new IllegalArgumentException("This AccountSet is readonly!"); } verifyAddressEncoding(address, pubKey); - VersioningAccount cachedAcc = latestAccountsCache.get(address); + InnerVersioningAccount cachedAcc = latestAccountsCache.get(address); if (cachedAcc != null) { if (cachedAcc.version < 0) { // 同一个新账户已经注册,但尚未提交,所以重复注册不会引起任何变化; @@ -266,7 +273,7 @@ public class AccountSet implements Transactional, MerkleProvable { // accExStorage, accVerStorage); String prefix = keyPrefix + address; - VersioningAccount acc = createInstance(address, pubKey, cryptoSetting, prefix, baseExStorage, baseVerStorage, + InnerVersioningAccount acc = createInstance(address, pubKey, cryptoSetting, prefix, baseExStorage, baseVerStorage, -1); latestAccountsCache.put(address, acc); updated = true; @@ -281,15 +288,15 @@ public class AccountSet implements Transactional, MerkleProvable { } } - private VersioningAccount createInstance(Bytes address, PubKey pubKey, CryptoSetting cryptoSetting, + private InnerVersioningAccount createInstance(Bytes address, PubKey pubKey, CryptoSetting cryptoSetting, String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, long version) { - return new VersioningAccount(address, pubKey, cryptoSetting, keyPrefix, exStorage, verStorage, version); + return new InnerVersioningAccount(address, pubKey, cryptoSetting, keyPrefix, exStorage, verStorage, version); } - private VersioningAccount deserialize(byte[] bytes, CryptoSetting cryptoSetting, String keyPrefix, + private InnerVersioningAccount deserialize(byte[] bytes, CryptoSetting cryptoSetting, String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, long version) { AccountHeader accInfo = BinaryProtocol.decode(bytes); - return new VersioningAccount(accInfo.getAddress(), accInfo.getPubKey(), accInfo.getRootHash(), cryptoSetting, + return new InnerVersioningAccount(accInfo.getAddress(), accInfo.getPubKey(), accInfo.getRootHash(), cryptoSetting, keyPrefix, exStorage, verStorage, readonly, version); } @@ -308,7 +315,7 @@ public class AccountSet implements Transactional, MerkleProvable { return; } try { - for (VersioningAccount acc : latestAccountsCache.values()) { + for (InnerVersioningAccount acc : latestAccountsCache.values()) { // updated or new created; if (acc.isUpdated() || acc.version < 0) { // 提交更改,更新哈希; @@ -336,7 +343,7 @@ public class AccountSet implements Transactional, MerkleProvable { Bytes[] addresses = new Bytes[latestAccountsCache.size()]; latestAccountsCache.keySet().toArray(addresses); for (Bytes address : addresses) { - VersioningAccount acc = latestAccountsCache.remove(address); + InnerVersioningAccount acc = latestAccountsCache.remove(address); // cancel; if (acc.isUpdated()) { acc.cancel(); @@ -374,7 +381,7 @@ public class AccountSet implements Transactional, MerkleProvable { } - private class VersioningAccount extends BaseAccount { + private class InnerVersioningAccount extends MerkleAccount { // private final BaseAccount account; @@ -385,14 +392,14 @@ public class AccountSet implements Transactional, MerkleProvable { // this.version = version; // } - public VersioningAccount(Bytes address, PubKey pubKey, HashDigest rootHash, CryptoSetting cryptoSetting, + public InnerVersioningAccount(Bytes address, PubKey pubKey, HashDigest rootHash, CryptoSetting cryptoSetting, String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, long version) { super(address, pubKey, rootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly); this.version = version; } - public VersioningAccount(Bytes address, PubKey pubKey, CryptoSetting cryptoSetting, String keyPrefix, + public InnerVersioningAccount(Bytes address, PubKey pubKey, CryptoSetting cryptoSetting, String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, long version) { super(address, pubKey, cryptoSetting, keyPrefix, exStorage, verStorage); this.version = version; 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..b41e6856 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,11 +1,10 @@ package com.jd.blockchain.ledger.core; -import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.ledger.MerkleProof; +import com.jd.blockchain.ledger.MerkleSnapshot; import com.jd.blockchain.utils.Bytes; -public interface MerkleProvable { - - HashDigest getRootHash(); +public interface MerkleProvable extends MerkleSnapshot { /** * Get the merkle proof of the latest version of specified key;
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..ac3dbbec 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, + LedgerQuery ledger, OperationHandleContext handleContext); -// /** -// * 异步解析和执行操作; -// * 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 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..c9212bb2 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,8 @@ package com.jd.blockchain.ledger.core; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.ledger.ParticipantNode; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.ledger.ParticipantNodeState; /** * 参与方证书数据对象; @@ -12,9 +14,10 @@ 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; + private ParticipantNodeState participantNodeState; public ParticipantCertData() { } @@ -24,16 +27,18 @@ public class ParticipantCertData implements ParticipantNode { this.address = participantNode.getAddress(); this.name = participantNode.getName(); this.pubKey = participantNode.getPubKey(); + this.participantNodeState = participantNode.getParticipantNodeState(); } - public ParticipantCertData(String address, String name, PubKey pubKey) { + public ParticipantCertData(Bytes address, String name, PubKey pubKey, ParticipantNodeState participantNodeState) { this.address = address; this.name = name; this.pubKey = pubKey; + this.participantNodeState = participantNodeState; } @Override - public String getAddress() { + public Bytes getAddress() { return address; } @@ -47,6 +52,7 @@ public class ParticipantCertData implements ParticipantNode { return pubKey; } + @Override public int getId() { return id; } @@ -54,4 +60,14 @@ public class ParticipantCertData implements ParticipantNode { public void setId(int id) { this.id = id; } + + @Override + public ParticipantNodeState getParticipantNodeState() { + return participantNodeState; + } + + public void setParticipantNodeState(ParticipantNodeState participantNodeState) { + this.participantNodeState = participantNodeState; + } + } \ No newline at end of file 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 66% 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..dbc077a8 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,34 @@ public class ParticipantDataSet implements Transactional, MerkleProvable { } } - private Bytes encodeKey(String address) { - // return id + ""; - return Bytes.fromString(address); + /** + * 更新共识参与方的状态信息;
+ * + * @param participant + */ + public void updateConsensusParticipant(ParticipantNode participant) { + Bytes key = encodeKey(participant.getAddress()); + byte[] participantBytes = BinaryProtocol.encode(participant, ParticipantNode.class); + long version = dataset.getVersion(key); + if (version < 0) { + throw new LedgerException("Participant not exist, update failed!"); + } + + long nv = dataset.setValue(key, participantBytes, version); + if (nv < 0) { + throw new LedgerException("Participant update failed!"); + } + } + + 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 +115,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 +124,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 index 516b2acf..f464db7f 100644 --- 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 @@ -1,51 +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; - } - - } - -} +//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/impl/TransactionBatchProcessor.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionBatchProcessor.java similarity index 57% rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionBatchProcessor.java rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionBatchProcessor.java index aa8fcf93..ae62cdf7 100644 --- 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/TransactionBatchProcessor.java @@ -1,6 +1,7 @@ -package com.jd.blockchain.ledger.core.impl; +package com.jd.blockchain.ledger.core; import java.util.ArrayList; +import java.util.Collection; import java.util.Iterator; import java.util.List; @@ -15,37 +16,37 @@ 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.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.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; -import com.jd.blockchain.utils.Bytes; public class TransactionBatchProcessor implements TransactionBatchProcess { private static final Logger LOGGER = LoggerFactory.getLogger(TransactionBatchProcessor.class); - private LedgerService ledgerService; + private LedgerSecurityManager securityManager; private LedgerEditor newBlockEditor; - private LedgerDataSet previousBlockDataset; + private LedgerQuery ledger; - private OperationHandleRegisteration opHandles; + private OperationHandleRegisteration handlesRegisteration; // 新创建的交易; private LedgerBlock block; @@ -56,17 +57,53 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { private TransactionBatchResult batchResult; + public HashDigest getLedgerHash() { + return ledger.getHash(); + } + /** - * @param newBlockEditor 新区块的数据编辑器; - * @param previousBlockDataset 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集; - * @param opHandles 操作处理对象注册表; + * @param newBlockEditor 新区块的数据编辑器; + * @param ledgerQueryer 账本查询器,只包含新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集; + * @param opHandles 操作处理对象注册表; */ - public TransactionBatchProcessor(LedgerEditor newBlockEditor, LedgerDataSet previousBlockDataset, - OperationHandleRegisteration opHandles, LedgerService ledgerService) { + public TransactionBatchProcessor(LedgerSecurityManager securityManager, LedgerEditor newBlockEditor, + LedgerQuery ledger, OperationHandleRegisteration opHandles) { + this.securityManager = securityManager; this.newBlockEditor = newBlockEditor; - this.previousBlockDataset = previousBlockDataset; - this.opHandles = opHandles; - this.ledgerService = ledgerService; + this.ledger = ledger; + this.handlesRegisteration = opHandles; + } + + public TransactionBatchProcessor(LedgerRepository ledgerRepo, OperationHandleRegisteration handlesRegisteration) { + this.ledger = ledgerRepo; + this.handlesRegisteration = handlesRegisteration; + + LedgerBlock ledgerBlock = ledgerRepo.getLatestBlock(); + LedgerDataQuery ledgerDataQuery = ledgerRepo.getLedgerData(ledgerBlock); + LedgerAdminDataQuery previousAdminDataset = ledgerDataQuery.getAdminDataset(); + this.securityManager = new LedgerSecurityManagerImpl(previousAdminDataset.getAdminInfo().getRolePrivileges(), + previousAdminDataset.getAdminInfo().getAuthorizations(), previousAdminDataset.getParticipantDataset(), + ledgerDataQuery.getUserAccountSet()); + + this.newBlockEditor = ledgerRepo.createNextBlock(); + + } + + public static TransactionBatchProcess create(LedgerRepository ledgerRepo, + OperationHandleRegisteration handlesRegisteration) { + LedgerBlock ledgerBlock = ledgerRepo.getLatestBlock(); + LedgerEditor newBlockEditor = ledgerRepo.createNextBlock(); + LedgerDataQuery previousBlockDataset = ledgerRepo.getLedgerData(ledgerBlock); + + LedgerAdminDataQuery previousAdminDataset = previousBlockDataset.getAdminDataset(); + LedgerSecurityManager securityManager = new LedgerSecurityManagerImpl( + previousAdminDataset.getAdminInfo().getRolePrivileges(), + previousAdminDataset.getAdminInfo().getAuthorizations(), previousAdminDataset.getParticipantDataset(), + previousBlockDataset.getUserAccountSet()); + + TransactionBatchProcessor processor = new TransactionBatchProcessor(securityManager, newBlockEditor, ledgerRepo, + handlesRegisteration); + return processor; } /* @@ -82,12 +119,26 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { 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(request, txCtx); + resp = handleTx(reqExt, txCtx); LOGGER.debug("Complete handling transaction. --[BlockHeight={}][RequestHash={}][TxHash={}]", newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash()); @@ -99,10 +150,9 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { "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) { - // 抛弃发生处理异常的交易请求; -// resp = discard(request, TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK); + // 发生区块级别的处理异常,向上重新抛出异常进行处理,整个区块可能被丢弃; LOGGER.error(String.format( "Ignore transaction caused by BlockRollbackException! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s", newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(), @@ -116,12 +166,79 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { 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); + } + } + } + } + /** * 处理交易;
* @@ -131,23 +248,11 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { * @param txCtx * @return */ - private TransactionResponse handleTx(TransactionRequest request, LedgerTransactionContext txCtx) { + private TransactionResponse handleTx(TransactionRequestExtension request, LedgerTransactionContext txCtx) { 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!"); - } - } + LedgerDataset dataset = txCtx.getDataset(); // 执行操作; Operation[] ops = request.getTransactionContent().getOperations(); @@ -156,16 +261,15 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { 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 hdl = handlesRegisteration.getHandle(operation.getClass()); + hdl.process(operation, dataset, request, ledger, this); } }; OperationHandle opHandle; int opIndex = 0; for (Operation op : ops) { - opHandle = opHandles.getHandle(op.getClass()); - BytesValue opResult = opHandle.process(op, dataset, reqCtx, previousBlockDataset, handleContext, - ledgerService); + opHandle = handlesRegisteration.getHandle(op.getClass()); + BytesValue opResult = opHandle.process(op, dataset, request, ledger, handleContext); if (opResult != null) { operationResults.add(new OperationResultData(opIndex, opResult)); } @@ -183,6 +287,7 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(), e.getMessage()), e); } catch (BlockRollbackException e) { + // 回滚整个区块; result = TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK; txCtx.rollback(); LOGGER.error( @@ -201,17 +306,27 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { 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 the transaction will be rolled back and the results of the transaction will be committed! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s", + "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 the transaction will be rolled back and the results of the transaction will be committed! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s", + "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); } @@ -252,8 +367,8 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { if (batchResult != null) { throw new IllegalStateException("Batch result has already been prepared or canceled!"); } - block = newBlockEditor.prepare(); - batchResult = new TransactionBatchResultHandleImpl(); + this.block = newBlockEditor.prepare(); + this.batchResult = new TransactionBatchResultHandleImpl(); return (TransactionBatchResultHandle) batchResult; } @@ -278,10 +393,12 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { @Override public long blockHeight() { - if (block != null) { - return block.getHeight(); - } - return 0; +// if (block != null) { +// return block.getHeight(); +// } +// return 0; + + return ledger.getLatestBlockHeight(); } private void commitSuccess() { 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 52% 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..2d0fb55a 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,11 @@ -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.service.TransactionBatchProcess; import com.jd.blockchain.service.TransactionEngine; @@ -42,11 +37,8 @@ public class TransactionEngineImpl implements TransactionEngine { LedgerRepository ledgerRepo = ledgerService.getLedger(ledgerHash); - LedgerBlock ledgerBlock = ledgerRepo.getLatestBlock(); - LedgerEditor newBlockEditor = ledgerRepo.createNextBlock(); - LedgerDataSet previousBlockDataset = ledgerRepo.getDataSet(ledgerBlock); - batch = new InnerTransactionBatchProcessor(ledgerHash, newBlockEditor, previousBlockDataset, opHdlRegs, - ledgerService, ledgerBlock.getHeight()); + batch = new InnerTransactionBatchProcessor(ledgerRepo, + opHdlRegs); batchs.put(ledgerHash, batch); return batch; } @@ -62,45 +54,32 @@ public class TransactionEngineImpl implements TransactionEngine { private class InnerTransactionBatchProcessor extends TransactionBatchProcessor { - private HashDigest ledgerHash; - - private long blockHeight; +// private HashDigest ledgerHash; /** * 创建交易批处理器; * - * @param ledgerHash - * 账本哈希; - * @param newBlockEditor - * 新区块的数据编辑器; - * @param previousBlockDataset - * 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集; - * @param opHandles - * 操作处理对象注册表; + * @param ledgerRepo 账本; + * @param handlesRegisteration 操作处理对象注册表; + * */ - public InnerTransactionBatchProcessor(HashDigest ledgerHash, LedgerEditor newBlockEditor, - LedgerDataSet previousBlockDataset, OperationHandleRegisteration opHandles, - LedgerService ledgerService, long blockHeight) { - super(newBlockEditor, previousBlockDataset, opHandles, ledgerService); - this.ledgerHash = ledgerHash; - this.blockHeight = blockHeight; + public InnerTransactionBatchProcessor(LedgerRepository ledgerRepo, + OperationHandleRegisteration handlesRegisteration) { + super(ledgerRepo, handlesRegisteration); +// ledgerHash = ledgerRepo.getHash(); } @Override protected void onCommitted() { super.onCommitted(); - finishBatch(ledgerHash); + finishBatch(getLedgerHash()); } @Override protected void onCanceled() { super.onCanceled(); - finishBatch(ledgerHash); + finishBatch(getLedgerHash()); } - @Override - public long blockHeight() { - return this.blockHeight; - } } } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionQuery.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionQuery.java new file mode 100644 index 00000000..887782d4 --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionQuery.java @@ -0,0 +1,24 @@ +package com.jd.blockchain.ledger.core; + +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.ledger.LedgerTransaction; +import com.jd.blockchain.ledger.TransactionState; + +public interface TransactionQuery extends MerkleProvable { + + LedgerTransaction[] getTxs(int fromIndex, int count); + + byte[][] getValuesByIndex(int fromIndex, int count); + + long getTotalCount(); + + /** + * @param txContentHash + * Base58 编码的交易内容的哈希; + * @return + */ + LedgerTransaction get(HashDigest txContentHash); + + TransactionState getState(HashDigest txContentHash); + +} \ No newline at end of file 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..28c6bff4 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,13 +6,14 @@ 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; import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.Transactional; -public class TransactionSet implements Transactional, MerkleProvable { +public class TransactionSet implements Transactional, TransactionQuery { static { DataContractRegistry.register(LedgerTransaction.class); @@ -24,6 +25,7 @@ public class TransactionSet implements Transactional, MerkleProvable { private MerkleDataSet txSet; + @Override public LedgerTransaction[] getTxs(int fromIndex, int count) { if (count > LedgerConsts.MAX_LIST_COUNT) { throw new IllegalArgumentException("Count exceed the upper limit[" + LedgerConsts.MAX_LIST_COUNT + "]!"); @@ -37,6 +39,7 @@ public class TransactionSet implements Transactional, MerkleProvable { return ledgerTransactions; } + @Override public byte[][] getValuesByIndex(int fromIndex, int count) { byte[][] values = new byte[count][]; for (int i = 0; i < count; i++) { @@ -56,6 +59,7 @@ public class TransactionSet implements Transactional, MerkleProvable { return txSet.getProof(key); } + @Override public long getTotalCount() { // 每写入一个交易,同时写入交易内容Hash与交易结果的索引,因此交易记录数为集合总记录数除以 2; return txSet.getDataCount() / 2; @@ -112,10 +116,10 @@ public class TransactionSet implements Transactional, MerkleProvable { } /** - * @param txContentHash - * Base58 编码的交易内容的哈希; + * @param txContentHash Base58 编码的交易内容的哈希; * @return */ + @Override public LedgerTransaction get(HashDigest txContentHash) { // transaction has only one version; Bytes key = new Bytes(txContentHash.toBytes()); @@ -128,7 +132,8 @@ public class TransactionSet implements Transactional, MerkleProvable { return tx; } - public TransactionState getTxState(HashDigest txContentHash) { + @Override + public TransactionState getState(HashDigest txContentHash) { Bytes resultKey = encodeTxStateKey(txContentHash); // transaction has only one version; byte[] bytes = txSet.getValue(resultKey, 0); @@ -154,6 +159,10 @@ public class TransactionSet implements Transactional, MerkleProvable { return txSet.isReadonly(); } + void setReadonly() { + txSet.setReadonly(); + } + @Override public boolean isUpdated() { return txSet.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/UserAccount.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccount.java index b9cc88fd..49743f90 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccount.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccount.java @@ -19,7 +19,7 @@ public class UserAccount implements UserInfo { private static final Bytes DATA_PUB_KEY = Bytes.fromString("DATA-PUBKEY"); - private BaseAccount baseAccount; + private MerkleAccount baseAccount; @Override public Bytes getAddress() { @@ -36,7 +36,7 @@ public class UserAccount implements UserInfo { return baseAccount.getRootHash(); } - public UserAccount(BaseAccount baseAccount) { + public UserAccount(MerkleAccount baseAccount) { this.baseAccount = baseAccount; } 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..44e85b03 --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccountQuery.java @@ -0,0 +1,5 @@ +package com.jd.blockchain.ledger.core; + +public interface UserAccountQuery extends AccountQuery { + +} \ 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..a2e25356 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,24 +15,25 @@ import com.jd.blockchain.utils.Transactional; * @author huanghaiquan * */ -public class UserAccountSet implements Transactional, MerkleProvable { +public class UserAccountSet implements Transactional, UserAccountQuery { - private AccountSet accountSet; + private MerkleAccountSet accountSet; public UserAccountSet(CryptoSetting cryptoSetting, String keyPrefix, ExPolicyKVStorage simpleStorage, VersioningKVStorage versioningStorage, AccountAccessPolicy accessPolicy) { - accountSet = new AccountSet(cryptoSetting, keyPrefix, simpleStorage, versioningStorage, accessPolicy); + accountSet = new MerkleAccountSet(cryptoSetting, keyPrefix, simpleStorage, versioningStorage, accessPolicy); } public UserAccountSet(HashDigest dataRootHash, CryptoSetting cryptoSetting, String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, AccountAccessPolicy accessPolicy) { - accountSet = new AccountSet(dataRootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly, + accountSet = new MerkleAccountSet(dataRootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly, accessPolicy); } - public AccountHeader[] getAccounts(int fromIndex, int count) { - return accountSet.getAccounts(fromIndex,count); + @Override + public AccountHeader[] getHeaders(int fromIndex, int count) { + return accountSet.getHeaders(fromIndex,count); } /** @@ -39,13 +41,18 @@ public class UserAccountSet implements Transactional, MerkleProvable { * * @return */ - public long getTotalCount() { - return accountSet.getTotalCount(); + @Override + public long getTotal() { + return accountSet.getTotal(); } public boolean isReadonly() { return accountSet.isReadonly(); } + + void setReadonly() { + accountSet.setReadonly(); + } @Override public HashDigest getRootHash() { @@ -57,21 +64,25 @@ public class UserAccountSet implements Transactional, MerkleProvable { return accountSet.getProof(key); } - public UserAccount getUser(String address) { - return getUser(Bytes.fromBase58(address)); + @Override + public UserAccount getAccount(String address) { + return getAccount(Bytes.fromBase58(address)); } - public UserAccount getUser(Bytes address) { - BaseAccount baseAccount = accountSet.getAccount(address); + @Override + public UserAccount getAccount(Bytes address) { + MerkleAccount baseAccount = accountSet.getAccount(address); return new UserAccount(baseAccount); } + @Override public boolean contains(Bytes address) { return accountSet.contains(address); } - public UserAccount getUser(Bytes address, long version) { - BaseAccount baseAccount = accountSet.getAccount(address, version); + @Override + public UserAccount getAccount(Bytes address, long version) { + MerkleAccount baseAccount = accountSet.getAccount(address, version); return new UserAccount(baseAccount); } @@ -89,7 +100,7 @@ public class UserAccountSet implements Transactional, MerkleProvable { * @return 注册成功的用户对象; */ public UserAccount register(Bytes address, PubKey pubKey) { - BaseAccount baseAccount = accountSet.register(address, pubKey); + MerkleAccount baseAccount = accountSet.register(address, pubKey); 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..25ecd85a --- /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.UserAuthorizationSettings; +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, UserAuthorizationSettings { + + 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..dee7fb48 --- /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 LedgerPrivilege ledgerPrivileges; + + private TransactionPrivilege 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..2b259d4a --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/AbstractLedgerOperationHandle.java @@ -0,0 +1,63 @@ +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.LedgerDataset; +import com.jd.blockchain.ledger.core.LedgerQuery; +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, LedgerQuery ledger, OperationHandleContext handleContext) { + // 权限校验; + SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy(); + securityPolicy.checkEndpointPermission(TransactionPermission.DIRECT_OPERATION, MultiIDsPolicy.AT_LEAST_ONE); + + // 操作账本; + @SuppressWarnings("unchecked") + T concretedOp = (T) op; + doProcess(concretedOp, newBlockDataset, requestContext, ledger, handleContext); + + // 账本操作没有返回值; + return null; + } + + protected abstract void doProcess(T op, LedgerDataset newBlockDataset, TransactionRequestExtension requestContext, + LedgerQuery ledger, OperationHandleContext handleContext); +} diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/AbtractContractEventHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/AbtractContractEventSendOperationHandle.java similarity index 53% rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/AbtractContractEventHandle.java rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/AbtractContractEventSendOperationHandle.java index 40f6e2c2..5cd6dcfb 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/AbtractContractEventHandle.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,41 +8,56 @@ 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.LedgerService; +import com.jd.blockchain.ledger.core.ContractAccountQuery; +import com.jd.blockchain.ledger.core.LedgerDataset; +import com.jd.blockchain.ledger.core.LedgerQuery; +import com.jd.blockchain.ledger.core.LedgerQueryService; +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 AbtractContractEventHandle 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, + LedgerQuery ledger, OperationHandleContext opHandleContext) { + // 权限校验; + SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy(); + securityPolicy.checkEndpointPermission(TransactionPermission.CONTRACT_OPERATION, MultiIDsPolicy.AT_LEAST_ONE); + + // 操作账本; ContractEventSendOperation contractOP = (ContractEventSendOperation) op; + + return doProcess(requestContext, contractOP, newBlockDataset, ledger, opHandleContext); + } + + private BytesValue doProcess(TransactionRequestExtension request, ContractEventSendOperation contractOP, + LedgerDataset newBlockDataset, LedgerQuery ledger, OperationHandleContext opHandleContext) { // 先从账本校验合约的有效性; // 注意:必须在前一个区块的数据集中进行校验,因为那是经过共识的数据;从当前新区块链数据集校验则会带来攻击风险:未经共识的合约得到执行; - ContractAccountSet contractSet = previousBlockDataset.getContractAccountSet(); + ContractAccountQuery contractSet = ledger.getContractAccountset(); if (!contractSet.contains(contractOP.getContractAddress())) { throw new LedgerException(String.format("Contract was not registered! --[ContractAddress=%s]", contractOP.getContractAddress())); } // 创建合约的账本上下文实例; - LedgerQueryService queryService = new LedgerQueryService(ledgerService); + LedgerQueryService queryService = new LedgerQueryService(ledger); ContractLedgerContext ledgerContext = new ContractLedgerContext(queryService, opHandleContext); // 先检查合约引擎是否已经加载合约;如果未加载,再从账本中读取合约代码并装载到引擎中执行; - ContractAccount contract = contractSet.getContract(contractOP.getContractAddress()); + ContractAccount contract = contractSet.getAccount(contractOP.getContractAddress()); if (contract == null) { throw new LedgerException(String.format("Contract was not registered! --[ContractAddress=%s]", contractOP.getContractAddress())); @@ -50,19 +65,17 @@ public abstract class AbtractContractEventHandle 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..b4e1cac3 --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ContractCodeDeployOperationHandle.java @@ -0,0 +1,39 @@ +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.*; + +public class ContractCodeDeployOperationHandle extends AbstractLedgerOperationHandle { + + public ContractCodeDeployOperationHandle() { + super(ContractCodeDeployOperation.class); + } + + @Override + protected void doProcess(ContractCodeDeployOperation op, LedgerDataset newBlockDataset, + TransactionRequestExtension requestContext, LedgerQuery ledger, + OperationHandleContext handleContext) { + + + // 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..0f9fdb2b --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/DataAccountKVSetOperationHandle.java @@ -0,0 +1,47 @@ +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.LedgerDataset; +import com.jd.blockchain.ledger.core.LedgerQuery; +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, LedgerQuery ledger, + OperationHandleContext handleContext) { + // 权限校验; + SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy(); + securityPolicy.checkEndpointPermission(LedgerPermission.WRITE_DATA_ACCOUNT, MultiIDsPolicy.AT_LEAST_ONE); + + // 操作账本; + DataAccount account = newBlockDataset.getDataAccountSet().getAccount(kvWriteOp.getAccountAddress()); + if (account == null) { + throw new DataAccountDoesNotExistException("DataAccount doesn't exist!"); + } + KVWriteEntry[] writeSet = kvWriteOp.getWriteSet(); + long v = -1L; + 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..ab852255 --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/DataAccountRegisterOperationHandle.java @@ -0,0 +1,35 @@ +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.LedgerDataset; +import com.jd.blockchain.ledger.core.LedgerQuery; +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, LedgerQuery ledger, OperationHandleContext handleContext) { + // 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 55% 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 da4da430..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,16 +1,21 @@ -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; import com.jd.blockchain.contract.engine.ContractServiceProviders; import com.jd.blockchain.ledger.core.ContractAccount; -import static com.jd.blockchain.utils.BaseConstant.CONTRACT_SERVICE_PROVIDER; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; -public class JVMContractEventSendOperationHandle extends AbtractContractEventHandle { +public class JVMContractEventSendOperationHandle extends AbtractContractEventSendOperationHandle { private static final ContractEngine JVM_ENGINE; + private static final Lock JVM_LOAD_LOCK = new ReentrantLock(); + static { JVM_ENGINE = ContractServiceProviders.getProvider(CONTRACT_SERVICE_PROVIDER).getEngine(); } @@ -19,19 +24,19 @@ public class JVMContractEventSendOperationHandle extends AbtractContractEventHan protected ContractCode loadContractCode(ContractAccount contract) { ContractCode contractCode = JVM_ENGINE.getContract(contract.getAddress(), contract.getChaincodeVersion()); if (contractCode == null) { - // 装载合约; - contractCode = JVM_ENGINE.setupContract(contract.getAddress(), contract.getChaincodeVersion(), - contract.getChainCode()); + JVM_LOAD_LOCK.lock(); + try { + // Double Check + contractCode = JVM_ENGINE.getContract(contract.getAddress(), contract.getChaincodeVersion()); + if (contractCode == null) { + // 装载合约; + contractCode = JVM_ENGINE.setupContract(contract.getAddress(), contract.getChaincodeVersion(), + contract.getChainCode()); + } + } finally { + JVM_LOAD_LOCK.unlock(); + } } return contractCode; } - -// @Override -// public AsyncFuture asyncProcess(Operation op, LedgerDataSet newBlockDataset, -// TransactionRequestContext requestContext, LedgerDataSet previousBlockDataset, -// OperationHandleContext handleContext, LedgerService ledgerService) { -// // TODO Auto-generated method stub -// return null; -// } - } 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..ff22f777 --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/LedgerInitOperationHandle.java @@ -0,0 +1,26 @@ +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.LedgerDataset; +import com.jd.blockchain.ledger.core.LedgerQuery; +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, + LedgerQuery ledger,OperationHandleContext handleContext) { + // 对初始化操作不需要做任何处理; + return null; + } + +} diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ParticipantRegisterOperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ParticipantRegisterOperationHandle.java new file mode 100644 index 00000000..e02c2220 --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ParticipantRegisterOperationHandle.java @@ -0,0 +1,101 @@ +package com.jd.blockchain.ledger.core.handles; + +import com.jd.blockchain.crypto.AddressEncoding; +import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.ledger.LedgerPermission; +import com.jd.blockchain.ledger.ParticipantInfo; +import com.jd.blockchain.ledger.ParticipantInfoData; +import com.jd.blockchain.ledger.ParticipantNode; +import com.jd.blockchain.ledger.ParticipantNodeState; +import com.jd.blockchain.ledger.ParticipantRegisterOperation; +import com.jd.blockchain.ledger.UserRegisterOperation; +import com.jd.blockchain.ledger.core.LedgerAdminDataset; +import com.jd.blockchain.ledger.core.LedgerDataset; +import com.jd.blockchain.ledger.core.LedgerQuery; +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.transaction.UserRegisterOpTemplate; +import com.jd.blockchain.utils.Bytes; + + +public class ParticipantRegisterOperationHandle extends AbstractLedgerOperationHandle { + public ParticipantRegisterOperationHandle() { + super(ParticipantRegisterOperation.class); + } + + @Override + protected void doProcess(ParticipantRegisterOperation op, LedgerDataset newBlockDataset, + TransactionRequestExtension requestContext, LedgerQuery previousBlockDataset, + OperationHandleContext handleContext) { + + // 权限校验; + SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy(); + securityPolicy.checkEndpointPermission(LedgerPermission.REGISTER_PARTICIPANT, MultiIDsPolicy.AT_LEAST_ONE); + + ParticipantRegisterOperation participantRegOp = (ParticipantRegisterOperation) op; + + LedgerAdminDataset adminAccountDataSet = newBlockDataset.getAdminDataset(); + + ParticipantInfo participantInfo = new ParticipantInfoData(participantRegOp.getParticipantName(), participantRegOp.getParticipantRegisterIdentity().getPubKey(), participantRegOp.getNetworkAddress()); + + ParticipantNode participantNode = new PartNode((int)(adminAccountDataSet.getParticipantCount()), participantInfo.getName(), participantInfo.getPubKey(), ParticipantNodeState.REGISTERED); + + //add new participant as consensus node + adminAccountDataSet.addParticipant(participantNode); + + // Build UserRegisterOperation, reg participant as user + UserRegisterOperation userRegOp = new UserRegisterOpTemplate(participantRegOp.getParticipantRegisterIdentity()); + handleContext.handle(userRegOp); + } + + private static class PartNode implements ParticipantNode { + + private int id; + + private Bytes address; + + private String name; + + private PubKey pubKey; + + private ParticipantNodeState participantNodeState; + + public PartNode(int id, String name, PubKey pubKey, ParticipantNodeState participantNodeState) { + this.id = id; + this.name = name; + this.pubKey = pubKey; + this.address = AddressEncoding.generateAddress(pubKey); + this.participantNodeState = participantNodeState; + } + + @Override + public int getId() { + return id; + } + + @Override + public Bytes getAddress() { + return address; + } + + @Override + public String getName() { + return name; + } + + @Override + public PubKey getPubKey() { + return pubKey; + } + + @Override + public ParticipantNodeState getParticipantNodeState() { + return participantNodeState; + } + } + + +} diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ParticipantStateUpdateOperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ParticipantStateUpdateOperationHandle.java new file mode 100644 index 00000000..094a2e1a --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ParticipantStateUpdateOperationHandle.java @@ -0,0 +1,117 @@ +package com.jd.blockchain.ledger.core.handles; + +import com.jd.blockchain.consensus.ConsensusProvider; +import com.jd.blockchain.consensus.ConsensusProviders; +import com.jd.blockchain.crypto.AddressEncoding; +import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.ledger.LedgerPermission; +import com.jd.blockchain.ledger.LedgerSettings; +import com.jd.blockchain.ledger.ParticipantInfo; +import com.jd.blockchain.ledger.ParticipantInfoData; +import com.jd.blockchain.ledger.ParticipantNode; +import com.jd.blockchain.ledger.ParticipantNodeState; +import com.jd.blockchain.ledger.ParticipantStateUpdateOperation; +import com.jd.blockchain.ledger.core.LedgerAdminDataset; +import com.jd.blockchain.ledger.core.LedgerConfiguration; +import com.jd.blockchain.ledger.core.LedgerDataset; +import com.jd.blockchain.ledger.core.LedgerQuery; +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 ParticipantStateUpdateOperationHandle extends AbstractLedgerOperationHandle { + public ParticipantStateUpdateOperationHandle() { + super(ParticipantStateUpdateOperation.class); + } + + @Override + protected void doProcess(ParticipantStateUpdateOperation op, LedgerDataset newBlockDataset, + TransactionRequestExtension requestContext, LedgerQuery previousBlockDataset, + OperationHandleContext handleContext) { + + // 权限校验; + SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy(); + securityPolicy.checkEndpointPermission(LedgerPermission.REGISTER_PARTICIPANT, MultiIDsPolicy.AT_LEAST_ONE); + + ParticipantStateUpdateOperation stateUpdateOperation = (ParticipantStateUpdateOperation) op; + + LedgerAdminDataset adminAccountDataSet = newBlockDataset.getAdminDataset(); + + ConsensusProvider provider = ConsensusProviders.getProvider(adminAccountDataSet.getSettings().getConsensusProvider()); + + ParticipantNode[] participants = adminAccountDataSet.getParticipants(); + + ParticipantNode participantNode = null; + + for(int i = 0; i < participants.length; i++) { + if (stateUpdateOperation.getStateUpdateIdentity().getPubKey().equals(participants[i].getPubKey())) { + participantNode = new PartNode(participants[i].getId(), participants[i].getName(), participants[i].getPubKey(), ParticipantNodeState.ACTIVED); + break; + } + } + + //update consensus setting + ParticipantInfo participantInfo = new ParticipantInfoData(participantNode.getName(), participantNode.getPubKey(), stateUpdateOperation.getNetworkAddress()); + + Bytes newConsensusSettings = provider.getSettingsFactory().getConsensusSettingsBuilder().updateSettings(adminAccountDataSet.getSettings().getConsensusSetting(), participantInfo); + + LedgerSettings ledgerSetting = new LedgerConfiguration(adminAccountDataSet.getSettings().getConsensusProvider(), + newConsensusSettings, adminAccountDataSet.getPreviousSetting().getCryptoSetting()); + + adminAccountDataSet.setLedgerSetting(ledgerSetting); + + adminAccountDataSet.updateParticipant(participantNode); + + } + + private static class PartNode implements ParticipantNode { + + private int id; + + private Bytes address; + + private String name; + + private PubKey pubKey; + + private ParticipantNodeState participantNodeState; + + public PartNode(int id, String name, PubKey pubKey, ParticipantNodeState participantNodeState) { + this.id = id; + this.name = name; + this.pubKey = pubKey; + this.address = AddressEncoding.generateAddress(pubKey); + this.participantNodeState = participantNodeState; + } + + @Override + public int getId() { + return id; + } + + @Override + public Bytes getAddress() { + return address; + } + + @Override + public String getName() { + return name; + } + + @Override + public PubKey getPubKey() { + return pubKey; + } + + @Override + public ParticipantNodeState getParticipantNodeState() { + return participantNodeState; + } + } + +} 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..1d3c472c --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/RolesConfigureOperationHandle.java @@ -0,0 +1,49 @@ +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.LedgerDataset; +import com.jd.blockchain.ledger.core.LedgerQuery; +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, LedgerQuery ledger, OperationHandleContext handleContext) { + // 权限校验; + 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..295cb0fb --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/UserAuthorizeOperationHandle.java @@ -0,0 +1,78 @@ +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.UserAuthorizationSettings; +import com.jd.blockchain.ledger.core.LedgerDataset; +import com.jd.blockchain.ledger.core.LedgerQuery; +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, LedgerQuery ledger, + OperationHandleContext handleContext) { + // 权限校验; + SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy(); + securityPolicy.checkEndpointPermission(LedgerPermission.CONFIGURE_ROLES, MultiIDsPolicy.AT_LEAST_ONE); + + // 操作账本; + + UserRolesEntry[] urcfgs = operation.getUserRolesAuthorizations(); + UserAuthorizationSettings urSettings = newBlockDataset.getAdminDataset().getAuthorizations(); + 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..a5573019 --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/UserRegisterOperationHandle.java @@ -0,0 +1,37 @@ +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.LedgerDataset; +import com.jd.blockchain.ledger.core.LedgerQuery; +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, LedgerQuery ledger, OperationHandleContext handleContext) { + // 权限校验; + 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/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/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 e18c9304..00000000 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractCodeDeployOperationHandle.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.jd.blockchain.ledger.core.impl.handles; - -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: 请求者应该提供合约账户的公钥签名,已确定注册的地址的唯一性; - - dataset.getContractAccountSet().deploy(contractOP.getContractID().getAddress(), - contractOP.getContractID().getPubKey(), contractOP.getAddressSignature(), contractOP.getChainCode()); - - 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 2745a377..00000000 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/DataAccountKVSetOperationHandle.java +++ /dev/null @@ -1,50 +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.DataAccountDoesNotExistException; -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()); - if (account == null) { - throw new DataAccountDoesNotExistException("DataAccount doesn't exist!"); - } - KVWriteEntry[] writeSet = kvWriteOp.getWriteSet(); - for (KVWriteEntry kvw : writeSet) { - 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 c0a31321..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.AbtractContractEventHandle; +import com.jd.blockchain.ledger.core.handles.AbtractContractEventSendOperationHandle; import com.jd.blockchain.utils.Bytes; -public class ContractInvokingHandle extends AbtractContractEventHandle { +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 fd9df2d4..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,196 +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 org.junit.Test; -import org.mockito.Mockito; - -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(); - - @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); - TestContract contractProxy1 = 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.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() { - byte[] chainCode = new byte[1024]; - new Random().nextBytes(chainCode); - return chainCode; - } -} +//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/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 77% 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..812a8758 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; @@ -14,10 +14,10 @@ import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; import com.jd.blockchain.crypto.service.sm.SMCryptoService; import com.jd.blockchain.ledger.BlockchainKeyGenerator; import com.jd.blockchain.ledger.BlockchainKeypair; -import com.jd.blockchain.ledger.core.AccountSet; -import com.jd.blockchain.ledger.core.BaseAccount; +import com.jd.blockchain.ledger.core.MerkleAccountSet; +import com.jd.blockchain.ledger.core.MerkleAccount; 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 { @@ -43,12 +43,12 @@ public class AccountSetTest { cryptoConf.setHashAlgorithm(ClassicAlgorithm.SHA256); String keyPrefix = ""; - AccountSet accset = new AccountSet(cryptoConf, keyPrefix, storage, storage, accessPolicy); + MerkleAccountSet accset = new MerkleAccountSet(cryptoConf, keyPrefix, storage, storage, accessPolicy); BlockchainKeypair userKey = BlockchainKeyGenerator.getInstance().generate(); accset.register(userKey.getAddress(), userKey.getPubKey()); - BaseAccount userAcc = accset.getAccount(userKey.getAddress()); + MerkleAccount userAcc = accset.getAccount(userKey.getAddress()); assertNotNull(userAcc); assertTrue(accset.contains(userKey.getAddress())); @@ -56,8 +56,8 @@ public class AccountSetTest { HashDigest rootHash = accset.getRootHash(); assertNotNull(rootHash); - AccountSet reloadAccSet = new AccountSet(rootHash, cryptoConf, keyPrefix, storage, storage, true, accessPolicy); - BaseAccount reloadUserAcc = reloadAccSet.getAccount(userKey.getAddress()); + MerkleAccountSet reloadAccSet = new MerkleAccountSet(rootHash, cryptoConf, keyPrefix, storage, storage, true, accessPolicy); + MerkleAccount reloadUserAcc = reloadAccSet.getAccount(userKey.getAddress()); assertNotNull(reloadUserAcc); assertTrue(reloadAccSet.contains(userKey.getAddress())); 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 92% 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..51c8232b 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; @@ -13,7 +13,7 @@ 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.BytesData; -import com.jd.blockchain.ledger.core.BaseAccount; +import com.jd.blockchain.ledger.core.MerkleAccount; import com.jd.blockchain.ledger.core.CryptoConfig; import com.jd.blockchain.storage.service.utils.MemoryKVStorage; import com.jd.blockchain.utils.Bytes; @@ -48,7 +48,7 @@ public class BaseAccountTest { BlockchainKeypair bck = BlockchainKeyGenerator.getInstance().generate(); // 新建账户; - BaseAccount baseAccount = new BaseAccount(bck.getIdentity(), cryptoConf, keyPrefix, testStorage, testStorage); + MerkleAccount baseAccount = new MerkleAccount(bck.getIdentity(), cryptoConf, keyPrefix, testStorage, testStorage); assertFalse(baseAccount.isUpdated());// 空的账户; assertFalse(baseAccount.isReadonly()); 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..3232c385 --- /dev/null +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/ContractInvokingTest.java @@ -0,0 +1,484 @@ +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 com.jd.blockchain.ledger.*; +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.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); + DataContractRegistry.register(ParticipantNode.class); + DataContractRegistry.register(ParticipantRegisterOperation.class); + DataContractRegistry.register(ParticipantStateUpdateOperation.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.getLedgerData(preBlock); + + // 加载合约 + LedgerEditor newBlockEditor = ledgerRepo.createNextBlock(); + LedgerSecurityManager securityManager = getSecurityManager(); + TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor, + ledgerRepo, opReg); + + // 构建基于接口调用合约的交易请求,用于测试合约调用; + 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.getLedgerData(preBlock); + + // 加载合约 + LedgerEditor newBlockEditor = ledgerRepo.createNextBlock(); + TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(getSecurityManager(), newBlockEditor, + ledgerRepo, opReg); + + 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().getAccount(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().getAccount(kpDataAccount.getAddress()).getDataEntry("K1", + 0); + KVDataEntry kv2 = ledgerRepo.getDataAccountSet().getAccount(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().getAccount(kpDataAccount.getAddress()).getDataEntry("K1", 1); + kv2 = ledgerRepo.getDataAccountSet().getAccount(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().getAccount(kpDataAccount.getAddress()).getDataEntry("K1", 1); + assertEquals(1, kv1.getVersion()); + assertEquals("V1-1", kv1.getValue()); + kv1 = ledgerRepo.getDataAccountSet().getAccount(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.getLedgerData(preBlock); + LedgerEditor newBlockEditor = ledgerRepo.createNextBlock(); + TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(getSecurityManager(), newBlockEditor, + ledgerRepo, opReg); + + 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.getLedgerData(preBlock); + + // 加载合约 + LedgerEditor newBlockEditor = ledgerRepo.createNextBlock(); + TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(getSecurityManager(), newBlockEditor, + ledgerRepo, opReg); + + // 注册数据账户; + 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.getLedgerData(preBlock); + + // 加载合约 + LedgerEditor newBlockEditor = ledgerRepo.createNextBlock(); + LedgerSecurityManager securityManager = getSecurityManager(); + TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor, + ledgerRepo, opReg); + + // 构建基于接口调用合约的交易请求,用于测试合约调用; + 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 89% 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..a50cd41e 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; @@ -15,7 +15,7 @@ import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm; import com.jd.blockchain.crypto.service.sm.SMAlgorithm; import com.jd.blockchain.ledger.AccountHeader; import com.jd.blockchain.ledger.UserInfo; -import com.jd.blockchain.ledger.core.AccountSet; +import com.jd.blockchain.ledger.core.MerkleAccountSet; import com.jd.blockchain.utils.Bytes; /** @@ -44,7 +44,7 @@ public class LedgerAccountTest { String address = "xxxxxxxxxxxx"; PubKey pubKey = new PubKey(SMAlgorithm.SM2, rawDigestBytes); HashDigest hashDigest = new HashDigest(ClassicAlgorithm.SHA256, rawDigestBytes); - AccountSet.AccountHeaderData accountHeaderData = new AccountSet.AccountHeaderData(Bytes.fromString(address), + MerkleAccountSet.AccountHeaderData accountHeaderData = new MerkleAccountSet.AccountHeaderData(Bytes.fromString(address), pubKey, hashDigest); // encode and decode 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..e7fd2c27 --- /dev/null +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerAdminDatasetTest.java @@ -0,0 +1,308 @@ +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.LedgerAdminSettings; +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.ParticipantNodeState; +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.UserRoles; +import com.jd.blockchain.ledger.UserAuthorizationSettings; +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()); + parties[i].setParticipantState(ParticipantNodeState.ACTIVED); + } + 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.getAuthorizations().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.getAuthorizations()); + + // -------------- + // 重新加载,并进行修改; + 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.getAuthorizations().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(LedgerAdminSettings actualAccount, + RolePrivilegeSettings expRolePrivilegeSettings, UserAuthorizationSettings 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()); + } + + UserAuthorizationSettings actualUserRoleSettings = actualAccount.getAuthorizations(); + UserRoles[] expUserRoles = expUserRoleSettings.getUserRoles(); + assertEquals(expUserRoles.length, actualUserRoleSettings.getUserCount()); + + for (UserRoles expUR : expUserRoles) { + UserRoles actualUR = actualAccount.getAuthorizations().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/LedgerEditorTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerEditorTest.java similarity index 94% rename from source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerEditorTest.java rename to source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerEditorTest.java index 0779204e..97979205 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerEditorTest.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; @@ -27,14 +27,14 @@ 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; @@ -95,7 +95,7 @@ public class LedgerEditorTest { public void testWriteDataAccoutKvOp() { LedgerEditor ldgEdt = createLedgerInitEditor(); LedgerTransactionContext genisisTxCtx = createGenisisTx(ldgEdt, participants); - LedgerDataSet ldgDS = genisisTxCtx.getDataSet(); + LedgerDataset ldgDS = genisisTxCtx.getDataset(); AsymmetricKeypair cryptoKeyPair = signatureFunction.generateKeypair(); BlockchainKeypair dataKP = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey()); @@ -128,7 +128,7 @@ public class LedgerEditorTest { public void testGennesisBlockCreation() { LedgerEditor ldgEdt = createLedgerInitEditor(); LedgerTransactionContext genisisTxCtx = createGenisisTx(ldgEdt, participants); - LedgerDataSet ldgDS = genisisTxCtx.getDataSet(); + LedgerDataset ldgDS = genisisTxCtx.getDataset(); AsymmetricKeypair cryptoKeyPair = signatureFunction.generateKeypair(); BlockchainKeypair userKP = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey()); 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 92% 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..e916cc66 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; @@ -6,6 +6,7 @@ import static org.junit.Assert.assertEquals; import java.util.Arrays; import java.util.Random; +import com.jd.blockchain.ledger.*; import org.junit.Before; import org.junit.Test; @@ -17,15 +18,11 @@ import com.jd.blockchain.crypto.CryptoProvider; import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm; import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; import com.jd.blockchain.crypto.service.sm.SMCryptoService; -import com.jd.blockchain.ledger.BlockchainKeyGenerator; -import com.jd.blockchain.ledger.BlockchainKeypair; -import com.jd.blockchain.ledger.LedgerInitOperation; -import com.jd.blockchain.ledger.LedgerInitSetting; 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 +33,7 @@ public class LedgerInitOperationTest { byte[] seed = null; byte[] csSysSettingBytes = null; - LedgerInitSettingData ledgerInitSettingData = new LedgerInitSettingData(); + LedgerInitData ledgerInitSettingData = new LedgerInitData(); @Before public void initCfg() { @@ -76,10 +73,11 @@ 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()); + parties[i].setParticipantState(ParticipantNodeState.ACTIVED); } ConsensusParticipantData[] parties1 = Arrays.copyOf(parties, 4); @@ -117,8 +115,8 @@ 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(), - "Participant[" + i + "]", keys[i].getPubKey()); + parties[i] = new ParticipantCertData(AddressEncoding.generateAddress(keys[i].getPubKey()), + "Participant[" + i + "]", keys[i].getPubKey(), ParticipantNodeState.ACTIVED); } ParticipantCertData[] parties1 = Arrays.copyOf(parties, 4); 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 93% 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..3884186e 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; @@ -6,6 +6,7 @@ import static org.junit.Assert.assertEquals; import java.util.Arrays; import java.util.Random; +import com.jd.blockchain.ledger.ParticipantNodeState; import org.junit.Before; import org.junit.Test; @@ -24,14 +25,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,15 +77,16 @@ 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()); + parties[i].setParticipantState(ParticipantNodeState.ACTIVED); } ConsensusParticipantData[] parties1 = Arrays.copyOf(parties, 4); ledgerInitSettingData.setConsensusParticipants(parties1); - + byte[] encode = BinaryProtocol.encode(ledgerInitSettingData, LedgerInitSetting.class); LedgerInitSetting decode = BinaryProtocol.decode(encode); @@ -121,8 +123,8 @@ 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(), - "Participant[" + i + "]", keys[i].getPubKey()); + parties[i] = new ParticipantCertData(AddressEncoding.generateAddress(keys[i].getPubKey()), + "Participant[" + i + "]", keys[i].getPubKey(), ParticipantNodeState.ACTIVED); } ParticipantCertData[] parties1 = Arrays.copyOf(parties, 4); 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 83% 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 dfc17f24..225bd16d 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; @@ -6,6 +6,7 @@ import static org.junit.Assert.assertNull; import java.util.stream.Stream; +import com.jd.blockchain.ledger.*; import org.junit.Before; import org.junit.Test; @@ -19,32 +20,20 @@ import com.jd.blockchain.crypto.SignatureFunction; import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm; import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; import com.jd.blockchain.crypto.service.sm.SMCryptoService; -import com.jd.blockchain.ledger.BlockBody; -import com.jd.blockchain.ledger.BlockchainKeyGenerator; -import com.jd.blockchain.ledger.BlockchainKeypair; -import com.jd.blockchain.ledger.DataAccountRegisterOperation; -import com.jd.blockchain.ledger.DigitalSignature; -import com.jd.blockchain.ledger.LedgerBlock; -import com.jd.blockchain.ledger.LedgerInitSetting; -import com.jd.blockchain.ledger.LedgerTransaction; -import com.jd.blockchain.ledger.TransactionContent; -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; @@ -56,6 +45,9 @@ public class LedgerManagerTest { DataContractRegistry.register(TransactionContent.class); DataContractRegistry.register(UserRegisterOperation.class); DataContractRegistry.register(DataAccountRegisterOperation.class); + DataContractRegistry.register(ParticipantNode.class); + DataContractRegistry.register(ParticipantRegisterOperation.class); + DataContractRegistry.register(ParticipantStateUpdateOperation.class); DataContractRegistry.register(BlockBody.class); DataContractRegistry.register(CryptoProvider.class); } @@ -81,20 +73,19 @@ 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.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()); @@ -121,6 +112,9 @@ public class LedgerManagerTest { // 提交数据,写入存储; ldgEdt.commit(); + + assertNull(genesisBlock.getLedgerHash()); + assertNotNull(genesisBlock.getHash()); // 重新加载并校验结果; LedgerManager reloadLedgerManager = new LedgerManager(); @@ -145,7 +139,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(); @@ -167,9 +161,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); } @@ -199,7 +193,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); @@ -209,32 +203,36 @@ 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[0].setParticipantState(ParticipantNodeState.ACTIVED); parties[1] = new ConsensusParticipantData(); parties[1].setId(1); 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[1].setParticipantState(ParticipantNodeState.ACTIVED); parties[2] = new ConsensusParticipantData(); parties[2].setId(2); 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[2].setParticipantState(ParticipantNodeState.ACTIVED); parties[3] = new ConsensusParticipantData(); parties[3].setId(3); 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)); + parties[3].setParticipantState(ParticipantNodeState.ACTIVED); 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..51254613 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; @@ -7,8 +7,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.*; import org.junit.Before; import org.junit.Test; @@ -16,16 +15,15 @@ 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; import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm; import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; import com.jd.blockchain.crypto.service.sm.SMCryptoService; -import com.jd.blockchain.ledger.CryptoSetting; -import com.jd.blockchain.ledger.ParticipantNode; import com.jd.blockchain.ledger.core.CryptoConfig; -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 +72,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 +91,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 +119,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,8 +185,8 @@ public class LedgerMetaDataTest { String name = "John"; // NetworkAddress consensusAddress = new NetworkAddress("192.168.1.1", 9001, // false); - String address = AddressEncoding.generateAddress(pubKey).toBase58(); - ParticipantCertData participantCertData = new ParticipantCertData(address, name, pubKey); + Bytes address = AddressEncoding.generateAddress(pubKey); + ParticipantCertData participantCertData = new ParticipantCertData(address, name, pubKey, ParticipantNodeState.ACTIVED); // encode and decode byte[] encodeBytes = BinaryProtocol.encode(participantCertData, ParticipantNode.class); 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 89% 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 6101cdba..d3595755 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; @@ -11,17 +11,11 @@ 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.CryptoSetting; -import com.jd.blockchain.ledger.LedgerInitSetting; -import com.jd.blockchain.ledger.TransactionRequest; -import com.jd.blockchain.ledger.TransactionRequestBuilder; -import com.jd.blockchain.ledger.TransactionResponse; +import com.jd.blockchain.ledger.*; 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; @@ -62,7 +56,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); @@ -72,8 +66,9 @@ 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)); + parties[i].setParticipantState(ParticipantNodeState.ACTIVED); } @@ -125,13 +120,13 @@ public class LedgerTestUtils { return txReqBuilder.buildRequest(); } - - public static TransactionRequest createTxRequest_DataAccountReg(BlockchainKeypair dataAccountID, HashDigest ledgerHash, - BlockchainKeypair nodeKeypair, BlockchainKeypair... signers) { + + 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) { @@ -141,16 +136,17 @@ public class LedgerTestUtils { 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) { + + 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) { @@ -160,7 +156,7 @@ public class LedgerTestUtils { 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 89% 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 ce571d71..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)); + } /** * 测试存储的增长; @@ -58,7 +90,20 @@ public class MerkleDataSetTest { mds.setValue("C", "C".getBytes(), -1); 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 项; 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/TransactionBatchProcessorTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionBatchProcessorTest.java similarity index 76% rename from source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TransactionBatchProcessorTest.java rename to source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionBatchProcessorTest.java index f857a6ad..06bf987d 100644 --- 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/core/TransactionBatchProcessorTest.java @@ -1,12 +1,15 @@ -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; 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; @@ -14,28 +17,34 @@ 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.LedgerDataSet; +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.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 { @@ -75,8 +84,8 @@ public class TransactionBatchProcessorTest { LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, STORAGE); // 验证参与方账户的存在; - LedgerDataSet previousBlockDataset = ledgerRepo.getDataSet(ledgerRepo.getLatestBlock()); - UserAccount user0 = previousBlockDataset.getUserAccountSet().getUser(parti0.getAddress()); + LedgerDataQuery previousBlockDataset = ledgerRepo.getLedgerData(ledgerRepo.getLatestBlock()); + UserAccount user0 = previousBlockDataset.getUserAccountSet().getAccount(parti0.getAddress()); assertNotNull(user0); boolean partiRegistered = previousBlockDataset.getUserAccountSet().contains(parti0.getAddress()); assertTrue(partiRegistered); @@ -85,8 +94,9 @@ public class TransactionBatchProcessorTest { LedgerEditor newBlockEditor = ledgerRepo.createNextBlock(); OperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration(); - TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(newBlockEditor, previousBlockDataset, - opReg, ledgerManager); + LedgerSecurityManager securityManager = getSecurityManager(); + TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor, + ledgerRepo, opReg); // 注册新用户; BlockchainKeypair userKeypair = BlockchainKeyGenerator.getInstance().generate(); @@ -108,6 +118,20 @@ public class TransactionBatchProcessorTest { 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(); @@ -120,8 +144,8 @@ public class TransactionBatchProcessorTest { LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, STORAGE); // 验证参与方账户的存在; - LedgerDataSet previousBlockDataset = ledgerRepo.getDataSet(ledgerRepo.getLatestBlock()); - UserAccount user0 = previousBlockDataset.getUserAccountSet().getUser(parti0.getAddress()); + LedgerDataQuery previousBlockDataset = ledgerRepo.getLedgerData(ledgerRepo.getLatestBlock()); + UserAccount user0 = previousBlockDataset.getUserAccountSet().getAccount(parti0.getAddress()); assertNotNull(user0); boolean partiRegistered = previousBlockDataset.getUserAccountSet().contains(parti0.getAddress()); assertTrue(partiRegistered); @@ -130,8 +154,9 @@ public class TransactionBatchProcessorTest { LedgerEditor newBlockEditor = ledgerRepo.createNextBlock(); OperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration(); - TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(newBlockEditor, previousBlockDataset, - opReg, ledgerManager); + LedgerSecurityManager securityManager = getSecurityManager(); + TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor, + ledgerRepo, opReg); // 注册新用户; BlockchainKeypair userKeypair1 = BlockchainKeyGenerator.getInstance().generate(); @@ -158,7 +183,7 @@ public class TransactionBatchProcessorTest { assertEquals(newBlock.getHash(), latestBlock.getHash()); assertEquals(1, newBlock.getHeight()); - LedgerDataSet ledgerDS = ledgerRepo.getDataSet(latestBlock); + LedgerDataQuery ledgerDS = ledgerRepo.getLedgerData(latestBlock); boolean existUser1 = ledgerDS.getUserAccountSet().contains(userKeypair1.getAddress()); boolean existUser2 = ledgerDS.getUserAccountSet().contains(userKeypair2.getAddress()); assertTrue(existUser1); @@ -177,8 +202,8 @@ public class TransactionBatchProcessorTest { LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, STORAGE); // 验证参与方账户的存在; - LedgerDataSet previousBlockDataset = ledgerRepo.getDataSet(ledgerRepo.getLatestBlock()); - UserAccount user0 = previousBlockDataset.getUserAccountSet().getUser(parti0.getAddress()); + LedgerDataQuery previousBlockDataset = ledgerRepo.getLedgerData(ledgerRepo.getLatestBlock()); + UserAccount user0 = previousBlockDataset.getUserAccountSet().getAccount(parti0.getAddress()); assertNotNull(user0); boolean partiRegistered = previousBlockDataset.getUserAccountSet().contains(parti0.getAddress()); assertTrue(partiRegistered); @@ -187,8 +212,9 @@ public class TransactionBatchProcessorTest { LedgerEditor newBlockEditor = ledgerRepo.createNextBlock(); OperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration(); - TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(newBlockEditor, previousBlockDataset, - opReg, ledgerManager); + LedgerSecurityManager securityManager = getSecurityManager(); + TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor, + ledgerRepo, opReg); // 注册新用户; BlockchainKeypair userKeypair1 = BlockchainKeyGenerator.getInstance().generate(); @@ -235,7 +261,7 @@ public class TransactionBatchProcessorTest { assertNotNull(tx3); assertEquals(TransactionState.SUCCESS, tx3.getExecutionState()); - LedgerDataSet ledgerDS = ledgerRepo.getDataSet(latestBlock); + LedgerDataQuery ledgerDS = ledgerRepo.getLedgerData(latestBlock); boolean existUser1 = ledgerDS.getUserAccountSet().contains(userKeypair1.getAddress()); boolean existUser2 = ledgerDS.getUserAccountSet().contains(userKeypair2.getAddress()); boolean existUser3 = ledgerDS.getUserAccountSet().contains(userKeypair3.getAddress()); @@ -245,7 +271,7 @@ public class TransactionBatchProcessorTest { } @Test - public void testTxRollbackByVersionsConfliction() { + public void testTxRollbackByVersionsConflict() { final MemoryKVStorage STORAGE = new MemoryKVStorage(); // 初始化账本到指定的存储库; @@ -256,8 +282,8 @@ public class TransactionBatchProcessorTest { LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, STORAGE); // 验证参与方账户的存在; - LedgerDataSet previousBlockDataset = ledgerRepo.getDataSet(ledgerRepo.getLatestBlock()); - UserAccount user0 = previousBlockDataset.getUserAccountSet().getUser(parti0.getAddress()); + LedgerDataQuery previousBlockDataset = ledgerRepo.getLedgerData(ledgerRepo.getLatestBlock()); + UserAccount user0 = previousBlockDataset.getUserAccountSet().getAccount(parti0.getAddress()); assertNotNull(user0); boolean partiRegistered = previousBlockDataset.getUserAccountSet().contains(parti0.getAddress()); assertTrue(partiRegistered); @@ -267,8 +293,9 @@ public class TransactionBatchProcessorTest { LedgerEditor newBlockEditor = ledgerRepo.createNextBlock(); OperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration(); - TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(newBlockEditor, previousBlockDataset, - opReg, ledgerManager); + LedgerSecurityManager securityManager = getSecurityManager(); + TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor, + ledgerRepo, opReg); BlockchainKeypair dataAccountKeypair = BlockchainKeyGenerator.getInstance().generate(); TransactionRequest transactionRequest1 = LedgerTestUtils.createTxRequest_DataAccountReg(dataAccountKeypair, @@ -278,7 +305,7 @@ public class TransactionBatchProcessorTest { newBlockEditor.commit(); assertEquals(TransactionState.SUCCESS, txResp1.getExecutionState()); - DataAccount dataAccount = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress()); + DataAccount dataAccount = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()); assertNotNull(dataAccount); // 正确写入 KV 数据; @@ -288,12 +315,14 @@ public class TransactionBatchProcessorTest { "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(newBlockEditor, previousBlockDataset, opReg, ledgerManager); + previousBlockDataset = ledgerRepo.getLedgerData(ledgerRepo.getLatestBlock()); + txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor, ledgerRepo, opReg); txbatchProcessor.schedule(txreq1); txbatchProcessor.schedule(txreq2); @@ -303,27 +332,27 @@ public class TransactionBatchProcessorTest { newBlock = newBlockEditor.prepare(); newBlockEditor.commit(); - BytesValue v1_0 = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress()).getBytes("K1", + BytesValue v1_0 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getBytes("K1", 0); - BytesValue v1_1 = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress()).getBytes("K1", + BytesValue v1_1 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getBytes("K1", 1); - BytesValue v2 = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress()).getBytes("K2", + BytesValue v2 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getBytes("K2", 0); - BytesValue v3 = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress()).getBytes("K3", + BytesValue v3 = ledgerRepo.getDataAccountSet().getAccount(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; @@ -331,23 +360,34 @@ public class TransactionBatchProcessorTest { "K1", "V-1-3", 0, ledgerHash, parti0, parti0); newBlockEditor = ledgerRepo.createNextBlock(); - previousBlockDataset = ledgerRepo.getDataSet(ledgerRepo.getLatestBlock()); - txbatchProcessor = new TransactionBatchProcessor(newBlockEditor, previousBlockDataset, opReg, ledgerManager); + previousBlockDataset = ledgerRepo.getLedgerData(ledgerRepo.getLatestBlock()); + txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor, ledgerRepo, opReg); txbatchProcessor.schedule(txreq5); - txbatchProcessor.schedule(txreq6); + // 预期会产生版本冲突异常; 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"); + BytesValue v1 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getBytes("K1"); + v3 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getBytes("K3"); - long k1_version = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress()).getDataVersion("K1"); + // k1 的版本仍然为1,没有更新; + long k1_version = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()) + .getDataVersion("K1"); assertEquals(1, k1_version); - long k3_version = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress()).getDataVersion("K3"); + + long k3_version = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()) + .getDataVersion("K3"); assertEquals(1, k3_version); - + assertNotNull(v1); assertNotNull(v3); assertEquals("V-1-2", v1.getValue().toUTF8String()); @@ -378,7 +418,7 @@ public class TransactionBatchProcessorTest { TransactionRequest genesisTxReq = LedgerTestUtils.createLedgerInitTxRequest(partiKeys); LedgerTransactionContext genisisTxCtx = ldgEdt.newTransaction(genesisTxReq); - LedgerDataSet ldgDS = genisisTxCtx.getDataSet(); + LedgerDataset ldgDS = genisisTxCtx.getDataset(); for (int i = 0; i < partiKeys.length; i++) { UserAccount userAccount = ldgDS.getUserAccountSet().register(partiKeys[i].getAddress(), 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 88% 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 f023a987..cd5ebc9f 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; @@ -9,31 +9,17 @@ import static org.junit.Assert.assertTrue; import java.util.Random; +import com.jd.blockchain.ledger.*; import org.junit.Test; 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.BytesDataList; -import com.jd.blockchain.ledger.BytesValueList; -import com.jd.blockchain.ledger.ContractCodeDeployOperation; -import com.jd.blockchain.ledger.ContractEventSendOperation; -import com.jd.blockchain.ledger.CryptoSetting; -import com.jd.blockchain.ledger.DataAccountKVSetOperation; import com.jd.blockchain.ledger.DataAccountKVSetOperation.KVWriteEntry; -import com.jd.blockchain.ledger.DataAccountRegisterOperation; -import com.jd.blockchain.ledger.DigitalSignature; -import com.jd.blockchain.ledger.LedgerTransaction; -import com.jd.blockchain.ledger.Operation; -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.TransactionQuery; 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; @@ -51,6 +37,8 @@ public class TransactionSetTest { DataContractRegistry.register(DataAccountKVSetOperation.class); DataContractRegistry.register(ContractCodeDeployOperation.class); DataContractRegistry.register(ContractEventSendOperation.class); + DataContractRegistry.register(ParticipantRegisterOperation.class); + DataContractRegistry.register(ParticipantStateUpdateOperation.class); CryptoSetting defCryptoSetting = LedgerTestUtils.createDefaultCryptoSetting(); MemoryKVStorage testStorage = new MemoryKVStorage(); @@ -116,7 +104,7 @@ public class TransactionSetTest { assertEquals(5, tx.getTransactionContent().getOperations().length); // Reload ; - TransactionSet reloadTxset = new TransactionSet(txsetRootHash, defCryptoSetting, keyPrefix, testStorage, + TransactionQuery reloadTxset = new TransactionSet(txsetRootHash, defCryptoSetting, keyPrefix, testStorage, testStorage, true); assertEquals(1, reloadTxset.getTotalCount()); 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/contract-JDChain-Contract.jar b/source/ledger/ledger-core/src/test/resources/contract-JDChain-Contract.jar new file mode 100644 index 00000000..fd926b15 Binary files /dev/null and b/source/ledger/ledger-core/src/test/resources/contract-JDChain-Contract.jar differ 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 7b976e30..6bfbf903 100644 --- a/source/ledger/ledger-model/pom.xml +++ b/source/ledger/ledger-model/pom.xml @@ -37,7 +37,6 @@ com.jd.blockchain crypto-classic ${project.version} - test diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractJarUtils.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractJarUtils.java new file mode 100644 index 00000000..775d0ec5 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractJarUtils.java @@ -0,0 +1,228 @@ +package com.jd.blockchain.contract; + +import com.jd.blockchain.crypto.Crypto; +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.HashFunction; +import com.jd.blockchain.utils.io.BytesUtils; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; + +import java.io.*; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.jar.JarOutputStream; + +public class ContractJarUtils { + + public static final String BLACK_CONF = "blacks.conf"; + + public static final String WHITE_CONF = "whites.conf"; + + private static final String CONTRACT_MF = "META-INF/CONTRACT.MF"; + + private static final HashFunction HASH_FUNCTION = Crypto.getHashFunction("SHA256"); + + private static final Random FILE_RANDOM = new Random(); + + private static final byte[] JDCHAIN_MARK = "JDChain".getBytes(StandardCharsets.UTF_8); + + public static final String JDCHAIN_PACKAGE = "com.jd.blockchain"; + + public static boolean isJDChainPackage(String packageName) { + if (packageName.equals(JDCHAIN_PACKAGE)) { + return true; + } + return packageName.startsWith(JDCHAIN_PACKAGE + "."); + } + + public static List loadWhiteConf() { + + return resolveConfig(WHITE_CONF); + } + + public static List loadBlackConf() { + return resolveConfig(BLACK_CONF); + } + + public static List resolveConfig(String fileName) { + List configs = new ArrayList<>(); + + try { + List readLines = loadConfig(fileName); + if (!readLines.isEmpty()) { + for (String readLine : readLines) { + String[] lines = readLine.split(","); + configs.addAll(Arrays.asList(lines)); + } + } + } catch (Exception e) { + throw new IllegalStateException(e); + } + + return configs; + } + + public static List loadConfig(String fileName) throws Exception { + + return IOUtils.readLines( + ContractJarUtils.class.getResourceAsStream(File.separator + fileName)); + } + + public static Map loadAllClasses(final File jar) throws Exception { + Map allClasses = new HashMap<>(); + JarFile jarFile = new JarFile(jar); + Enumeration jarEntries = jarFile.entries(); + while(jarEntries.hasMoreElements()){ + JarEntry jarEntry = jarEntries.nextElement(); + String entryName = jarEntry.getName(); + if (verify(entryName)) { + byte[] classContent = readStream(jarFile.getInputStream(jarEntry)); + if (classContent != null && classContent.length > 0) { + allClasses.put(entryName, classContent); + } + } + } + jarFile.close(); + + return allClasses; + } + + private static boolean verify(String entryName) { + + if (entryName.endsWith(".class") + && !entryName.startsWith("META-INF") + && !entryName.contains("-") + && entryName.contains("/")) { + return true; + } + return false; + } + + public static String dotClassName(String className) { + String dotClassName = className; + if (className.endsWith(".class")) { + dotClassName = className.substring(0, className.length() - 6); + } + dotClassName = dotClassName.replaceAll("/", "."); + return dotClassName; + } + + public static void verify(byte[] chainCode) { + if (chainCode == null || chainCode.length == 0) { + throw new IllegalStateException("Contract's chaincode is empty !!!"); + } + // 首先生成合约文件 + File jarFile = newJarFile(); + try { + FileUtils.writeByteArrayToFile(jarFile, chainCode); + // 校验合约文件 + verify(jarFile); + } catch (Exception e) { + throw new IllegalStateException(e); + } finally { + // 删除文件 + try { + FileUtils.forceDelete(jarFile); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + } + + private static void verify(File jarFile) throws Exception { + // 首先判断jarFile中是否含有META-INF/JDCHAIN.TXT,并将其读出 + URL jarUrl = new URL("jar:file:" + jarFile.getPath() + "!/" + CONTRACT_MF); + InputStream inputStream = jarUrl.openStream(); + if (inputStream == null) { + throw new IllegalStateException(CONTRACT_MF + " IS NULL !!!"); + } + byte[] bytes = IOUtils.toByteArray(inputStream); + if (bytes == null || bytes.length == 0) { + throw new IllegalStateException(CONTRACT_MF + " IS Illegal !!!"); + } + // 获取对应的Hash内容 + String txt = new String(bytes, StandardCharsets.UTF_8); + + // 生成新的Jar包文件,该文件路径与JarFile基本一致 + File tempJar = newJarFile(); + + // 复制除JDCHAIN.TXT之外的部分 + copy(jarFile, tempJar, null, null, CONTRACT_MF); + + // 生成新Jar包对应的Hash内容 + String verifyTxt = contractMF(FileUtils.readFileToByteArray(tempJar)); + + // 删除临时文件 + FileUtils.forceDelete(tempJar); + + // 校验Jar包内容 + if (!txt.equals(verifyTxt)) { + throw new IllegalStateException(String.format("Jar [%s] verify Illegal !!!", jarFile.getName())); + } + } + + public static void copy(File srcJar, File dstJar) throws IOException { + copy(srcJar, dstJar, null, null, null); + } + + public static void copy(File srcJar, File dstJar, JarEntry addEntry, byte[] addBytes, String filter) throws IOException { + JarFile jarFile = new JarFile(srcJar); + Enumeration jarEntries = jarFile.entries(); + JarOutputStream jarOut = new JarOutputStream(new BufferedOutputStream(new FileOutputStream(dstJar))); + + while(jarEntries.hasMoreElements()){ + JarEntry jarEntry = jarEntries.nextElement(); + String entryName = jarEntry.getName(); + if (filter != null && filter.equals(entryName)) { + continue; + } + jarOut.putNextEntry(jarEntry); + jarOut.write(readStream(jarFile.getInputStream(jarEntry))); + jarOut.closeEntry(); + } + if (addEntry != null) { + jarOut.putNextEntry(addEntry); + jarOut.write(addBytes); + jarOut.closeEntry(); + } + + jarOut.flush(); + jarOut.finish(); + jarOut.close(); + jarFile.close(); + } + + public static String contractMF(byte[] content) { + HashDigest hashDigest = HASH_FUNCTION.hash(BytesUtils.concat(content, JDCHAIN_MARK)); + return "hash:" + hashDigest.toBase58(); + } + + public static JarEntry contractMFJarEntry() { + return new JarEntry(CONTRACT_MF); + } + + private static byte[] readStream(InputStream inputStream) { + try (ByteArrayOutputStream outSteam = new ByteArrayOutputStream()) { + byte[] buffer = new byte[1024]; + int len; + while ((len = inputStream.read(buffer)) != -1) { + outSteam.write(buffer, 0, len); + } + inputStream.close(); + return outSteam.toByteArray(); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + + private static File newJarFile() { + return new File("contract-" + + System.currentTimeMillis() + "-" + + System.nanoTime() + "-" + + FILE_RANDOM.nextInt(1024) + + ".jar"); + } +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/EventHandle.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/EventHandle.java index 9b301460..ac193ab9 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/EventHandle.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/EventHandle.java @@ -5,12 +5,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -/** - * HTTP 服务方法; - * - * @author haiq - * - */ + @Target({ ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) public @interface EventHandle { diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/AccountHeader.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/AccountHeader.java index 42dc25a0..16f2794b 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/AccountHeader.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/AccountHeader.java @@ -4,20 +4,17 @@ 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; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.utils.Bytes; @DataContract(code= DataCodes.ACCOUNT_HEADER) -public interface AccountHeader { +public interface AccountHeader extends MerkleSnapshot{ @DataField(order=1, primitiveType = PrimitiveType.BYTES) Bytes getAddress(); @DataField(order=2, primitiveType = PrimitiveType.BYTES) PubKey getPubKey(); - - @DataField(order=3, primitiveType = PrimitiveType.BYTES) - HashDigest getRootHash(); + } 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/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/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/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..62a2aa2f --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerAdminInfo.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; + +@DataContract(code=DataCodes.LEDGER_ADMIN_INFO) +public interface LedgerAdminInfo { + + @DataField(order=1, refContract = true) + LedgerMetadata_V2 getMetadata(); + + @DataField(order=2, refContract = true) + LedgerSettings getSettings(); + + @DataField(order=3, refContract = true, list = true) + ParticipantNode[] getParticipants(); + + @DataField(order=4, primitiveType = PrimitiveType.INT64) + long getParticipantCount(); + +} \ No newline at end of file diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerAdminSettings.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerAdminSettings.java new file mode 100644 index 00000000..2f4420fe --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerAdminSettings.java @@ -0,0 +1,8 @@ +package com.jd.blockchain.ledger; + +public interface LedgerAdminSettings extends LedgerAdminInfo { + + UserAuthorizationSettings getAuthorizations(); + + RolePrivilegeSettings getRolePrivileges(); +} 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..120f6730 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerInitProperties.java @@ -0,0 +1,520 @@ +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.ledger.ParticipantNodeState; +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); + parti.setParticipantNodeState(ParticipantNodeState.ACTIVED); + 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 ParticipantNodeState participantNodeState; + + private NetworkAddress initializerAddress; + + @Override + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + @Override + public Bytes getAddress() { + return address; + } + + @Override + 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; +// } + + @Override + public ParticipantNodeState getParticipantNodeState() { + return participantNodeState; + } + + public void setParticipantNodeState(ParticipantNodeState participantNodeState) { + this.participantNodeState = participantNodeState; + } + + public NetworkAddress getInitializerAddress() { + return initializerAddress; + } + + public void setInitializerAddress(NetworkAddress initializerAddress) { + this.initializerAddress = initializerAddress; + } + + @Override + 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..799354f1 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerPermission.java @@ -0,0 +1,103 @@ +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; +import com.jd.blockchain.utils.Int8Code; + +/** + * 账本相关的权限,这些权限属于全局性的; + * + * @author huanghaiquan + * + */ +@EnumContract(code = DataCodes.ENUM_LEDGER_PERMISSION) +public enum LedgerPermission implements Int8Code{ + + /** + * 配置角色的权限;
+ */ + CONFIGURE_ROLES((byte) 0x01), + + /** + * 授权用户角色;
+ */ + AUTHORIZE_USER_ROLES((byte) 0x02), + + /** + * 设置共识协议;
+ */ + SET_CONSENSUS((byte) 0x03), + + /** + * 设置密码体系;
+ */ + SET_CRYPTO((byte) 0x04), + + /** + * 注册参与方;
+ */ + REGISTER_PARTICIPANT((byte) 0x05), + + /** + * 注册用户;
+ * + * 如果不具备此项权限,则无法注册用户; + */ + REGISTER_USER((byte) 0x06), + + /** + * 注册数据账户;
+ */ + REGISTER_DATA_ACCOUNT((byte) 0x07), + + /** + * 注册合约;
+ */ + REGISTER_CONTRACT((byte) 0x08), + + /** + * 升级合约 + */ + UPGRADE_CONTRACT((byte) 0x14), + + /** + * 设置用户属性;
+ */ + SET_USER_ATTRIBUTES((byte) 0x09), + + /** + * 写入数据账户;
+ */ + WRITE_DATA_ACCOUNT((byte) 0x0A), + + /** + * 参与方核准交易;
+ * + * 如果不具备此项权限,则无法作为节点签署由终端提交的交易; + *

+ * 只对交易请求的节点签名列表{@link TransactionRequest#getNodeSignatures()}的用户产生影响; + */ + APPROVE_TX((byte) 0x0B), + + /** + * 参与方共识交易;
+ * + * 如果不具备此项权限,则无法作为共识节点接入并对交易进行共识; + */ + CONSENSUS_TX((byte) 0x0C); + + @EnumField(type = PrimitiveType.INT8) + public final byte CODE; + + private LedgerPermission(byte code) { + this.CODE = code; + } + + @Override + public byte getCode() { + return 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..01261cc2 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerPrivilege.java @@ -0,0 +1,23 @@ +package com.jd.blockchain.ledger; + +/** + * LedgerPrivilege 账本特权是授权给特定角色的权限代码序列; + * + * @author huanghaiquan + * + */ +public class LedgerPrivilege extends PrivilegeBitset { + + public LedgerPrivilege() { + } + + public LedgerPrivilege(byte[] codeBytes) { + super(codeBytes); + } + + @Override + public LedgerPrivilege clone() { + return (LedgerPrivilege) super.clone(); + } + +} 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/MerkleSnapshot.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/MerkleSnapshot.java new file mode 100644 index 00000000..1e195559 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/MerkleSnapshot.java @@ -0,0 +1,15 @@ +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; + +@DataContract(code = DataCodes.MERKLE_SNAPSHOT) +public interface MerkleSnapshot { + + @DataField(order = 0, primitiveType = PrimitiveType.BYTES) + HashDigest getRootHash(); + +} 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/ParticipantInfo.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantInfo.java index 903cabfd..c366fdd3 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantInfo.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantInfo.java @@ -1,35 +1,52 @@ -//package com.jd.blockchain.ledger; -// -//import com.jd.blockchain.base.data.TypeCodes; -//import com.jd.blockchain.binaryproto.DataContract; -//import com.jd.blockchain.binaryproto.DataField; -//import com.jd.blockchain.crypto.asymmetric.PubKey; -// -//import my.utils.ValueType; -// -///** -// * 参与方信息; -// * -// * @author huanghaiquan -// * -// */ -//@DataContract(code = TypeCodes.METADATA_PARTICIPANT_INFO) -//public interface ParticipantInfo { -// -// /** -// * 参与者名称; -// * -// * @return -// */ -// @DataField(order = 1, primitiveType = ValueType.TEXT) -// String getName(); -// -// /** -// * 公钥; -// * -// * @return -// */ -// @DataField(order = 2, primitiveType = ValueType.BYTES) -// PubKey getPubKey(); -// -//} \ No newline at end of file +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.PubKey; +import com.jd.blockchain.utils.net.NetworkAddress; + + +/** + * 参与方信息; + * + * @author huanghaiquan + * + */ +@DataContract(code = DataCodes.METADATA_PARTICIPANT_INFO) +public interface ParticipantInfo { + + /** + * regist or unregist, temporarily not available to users + * + * @return + */ +// @DataField(order = 0, primitiveType = PrimitiveType.TEXT) +// String getFlag(); + + /** + * 参与者名称; + * + * @return + */ + @DataField(order = 1, primitiveType = PrimitiveType.TEXT) + String getName(); + + /** + * 公钥; + * + * @return + */ + @DataField(order = 2, primitiveType = PrimitiveType.BYTES) + PubKey getPubKey(); + + /** + * 共识协议的网络地址; + * + * @return + */ + @DataField(order = 3, primitiveType = PrimitiveType.BYTES) + NetworkAddress getNetworkAddress(); + +} \ No newline at end of file diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantInfoData.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantInfoData.java new file mode 100644 index 00000000..27eaa098 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantInfoData.java @@ -0,0 +1,56 @@ +package com.jd.blockchain.ledger; + +import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.utils.net.NetworkAddress; +import org.omg.CORBA.PUBLIC_MEMBER; + +/** + * 即将要注册的参与方的信息 + * @author zhangshuang + * @create 2019/7/8 + * @since 1.0.0 + */ +public class ParticipantInfoData implements ParticipantInfo { + + + private String name; + + private PubKey pubKey; + + private NetworkAddress networkAddress; + +// private String flag;//代表注册参与方或者删除参与方 + + public ParticipantInfoData(String name, PubKey pubKey, NetworkAddress networkAddress) { + this.name = name; + this.pubKey = pubKey; + this.networkAddress = networkAddress; + } + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public PubKey getPubKey() { + return pubKey; + } + + public void setPubKey(PubKey pubKey) { + this.pubKey = pubKey; + } + + @Override + public NetworkAddress getNetworkAddress() { + return networkAddress; + } + + public void setNetworkAddress(NetworkAddress networkAddress) { + this.networkAddress = networkAddress; + } +} 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..9be89492 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(); /** * 参与者名称; @@ -48,4 +49,12 @@ public interface ParticipantNode {// extends ConsensusNode, ParticipantInfo { */ @DataField(order = 3, primitiveType = PrimitiveType.BYTES) PubKey getPubKey(); + + /** + * 节点的状态:已注册/已参与共识 + * + * @return + */ + @DataField(order = 4, refEnum = true) + ParticipantNodeState getParticipantNodeState(); } \ No newline at end of file diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantNodeState.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantNodeState.java new file mode 100644 index 00000000..f7b97fd1 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantNodeState.java @@ -0,0 +1,43 @@ +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 zhangshuang + * @create 2019/7/8 + * @since 1.0.0 + */ +@EnumContract(code= DataCodes.ENUM_TYPE_PARTICIPANT_NODE_STATE) +public enum ParticipantNodeState { + + /** + * 已注册; + */ + REGISTERED((byte) 0), + + /** + * 已激活; + */ + ACTIVED((byte) 1); + + @EnumField(type= PrimitiveType.INT8) + public final byte CODE; + + private ParticipantNodeState(byte code) { + this.CODE = code; + } + + public static ParticipantNodeState valueOf(byte code) { + for (ParticipantNodeState tr : values()) { + if (tr.CODE == code) { + return tr; + } + } + throw new IllegalArgumentException("Unsupported participant node state code!"); + } +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantRegisterOperation.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantRegisterOperation.java new file mode 100644 index 00000000..ec946593 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantRegisterOperation.java @@ -0,0 +1,20 @@ +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.net.NetworkAddress; + +@DataContract(code= DataCodes.TX_OP_PARTICIPANT_REG) +public interface ParticipantRegisterOperation extends Operation { + + @DataField(order = 0, primitiveType=PrimitiveType.TEXT) + String getParticipantName(); + + @DataField(order = 1, refContract = true) + BlockchainIdentity getParticipantRegisterIdentity(); + + @DataField(order = 2, primitiveType = PrimitiveType.BYTES) + NetworkAddress getNetworkAddress(); +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantStateUpdateInfo.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantStateUpdateInfo.java new file mode 100644 index 00000000..70c89f3f --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantStateUpdateInfo.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; +import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.utils.net.NetworkAddress; + +/** + * 参与方状态更新信息; + * + * + */ +@DataContract(code = DataCodes.METADATA_PARTICIPANT_STATE_INFO) +public interface ParticipantStateUpdateInfo { + + /** + * 公钥; + * + * @return + */ + @DataField(order = 1, primitiveType = PrimitiveType.BYTES) + PubKey getPubKey(); + + /** + * 共识协议的网络地址; + * + * @return + */ + @DataField(order = 2, primitiveType = PrimitiveType.BYTES) + NetworkAddress getNetworkAddress(); + + /** + * 参与方状态; + * + * @return + */ + @DataField(order = 3, refEnum = true) + ParticipantNodeState getState(); +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantStateUpdateInfoData.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantStateUpdateInfoData.java new file mode 100644 index 00000000..5e11c178 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantStateUpdateInfoData.java @@ -0,0 +1,43 @@ +package com.jd.blockchain.ledger; + +import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.utils.net.NetworkAddress; + +public class ParticipantStateUpdateInfoData implements ParticipantStateUpdateInfo { + private PubKey pubKey; + private ParticipantNodeState state; + private NetworkAddress networkAddress; + + public ParticipantStateUpdateInfoData(PubKey pubKey, ParticipantNodeState state, NetworkAddress networkAddress) { + this.pubKey = pubKey; + this.state = state; + this.networkAddress = networkAddress; + } + + public void setPubKey(PubKey pubKey) { + this.pubKey = pubKey; + } + + @Override + public PubKey getPubKey() { + return pubKey; + } + + public void setNetworkAddress(NetworkAddress networkAddress) { + this.networkAddress = networkAddress; + } + + @Override + public NetworkAddress getNetworkAddress() { + return networkAddress; + } + + public void setState(ParticipantNodeState state) { + this.state = state; + } + + @Override + public ParticipantNodeState getState() { + return state; + } +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantStateUpdateOperation.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantStateUpdateOperation.java new file mode 100644 index 00000000..fa2791a7 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantStateUpdateOperation.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.net.NetworkAddress; + +@DataContract(code= DataCodes.TX_OP_PARTICIPANT_STATE_UPDATE) +public interface ParticipantStateUpdateOperation extends Operation { + + @DataField(order = 0, refContract = true) + BlockchainIdentity getStateUpdateIdentity(); + + @DataField(order = 1, primitiveType = PrimitiveType.BYTES) + NetworkAddress getNetworkAddress(); + + @DataField(order = 2, refEnum = true) + ParticipantNodeState getState(); + +} 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..3b038fbb --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/PrivilegeBitset.java @@ -0,0 +1,166 @@ +package com.jd.blockchain.ledger; + +import java.util.BitSet; + +import com.jd.blockchain.utils.Int8Code; +import com.jd.blockchain.utils.io.BytesSerializable; + +/** + * PrivilegeBitset 定义了用位表示的权限码; + * + * @author huanghaiquan + * + */ +public abstract class PrivilegeBitset & Int8Code> implements Privilege, BytesSerializable, Cloneable { + // 加入1个字节的前缀位 0xF1,可避免序列化时输出空的字节数组; + private static final byte PREFIX = (byte) 0xF1; + private static final byte[] PREFIX_BYTES = { PREFIX }; + private static final int OFFSET = 8; + private static final int MAX_SIZE = 32; + + // 前缀中置为 1 的位数,值 0xF1 有 5 个比特位为 1; + private static final int PREFIX_CARDINALITY = 5; + + private BitSet permissionBits; + + public PrivilegeBitset() { + // 设置前缀; + this.permissionBits = BitSet.valueOf(PREFIX_BYTES); + } + + /** + * @param codeBytes 权限的字节位; + * @param codeIndexer + */ + public PrivilegeBitset(byte[] codeBytes) { + // 检查长度; + if (codeBytes.length == 0) { + throw new IllegalArgumentException("Empty code bytes!"); + } + if (codeBytes.length > MAX_SIZE) { + throw new IllegalArgumentException( + "The size of code bytes specified to PrivilegeBitset exceed the max size[" + MAX_SIZE + "]!"); + } + // 校验前缀; + if (codeBytes[0] != PREFIX) { + throw new IllegalArgumentException("The code bytes is not match the privilege prefix code!"); + } + + this.permissionBits = BitSet.valueOf(codeBytes); + } + + protected PrivilegeBitset(BitSet bits) { + this.permissionBits = bits; + } + + 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; + } + + @Override + public Privilege clone() { + try { + BitSet bitSet = (BitSet) permissionBits.clone(); + @SuppressWarnings("unchecked") + PrivilegeBitset privilege = (PrivilegeBitset) super.clone(); + privilege.permissionBits = bitSet; + return privilege; + } catch (CloneNotSupportedException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + protected BitSet cloneBitSet() { + return (BitSet) permissionBits.clone(); + } + + private int index(E permission) { + return OFFSET + permission.getCode(); + } + + public int getPermissionCount() { + return permissionBits.cardinality() - PREFIX_CARDINALITY; + } + +} 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..090b19f8 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RoleInitData.java @@ -0,0 +1,54 @@ +package com.jd.blockchain.ledger; + +import com.jd.blockchain.binaryproto.DataContractRegistry; + +public class RoleInitData implements RoleInitSettings { + + static { + DataContractRegistry.register(RoleInitSettings.class); + } + + 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..90f51869 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/SecurityInitData.java @@ -0,0 +1,60 @@ +package com.jd.blockchain.ledger; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.utils.Bytes; + +public class SecurityInitData implements SecurityInitSettings { + + static { + DataContractRegistry.register(SecurityInitSettings.class); + } + + + 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/TransactionPermission.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionPermission.java new file mode 100644 index 00000000..e251fac4 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionPermission.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; +import com.jd.blockchain.utils.Int8Code; + +/** + * TxPermission 交易权限表示一个用户可以发起的交易类型; + * + * @author huanghaiquan + * + */ +@EnumContract(code = DataCodes.ENUM_TX_PERMISSION) +public enum TransactionPermission implements Int8Code { + + /** + * 交易中包含指令操作; + */ + DIRECT_OPERATION((byte) 0x01), + + /** + * 交易中包含合约操作; + */ + CONTRACT_OPERATION((byte) 0x02); + + @EnumField(type = PrimitiveType.INT8) + public final byte CODE; + + private TransactionPermission(byte code) { + this.CODE = code; + } + + @Override + public byte getCode() { + return 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..dddd76d6 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionPrivilege.java @@ -0,0 +1,17 @@ +package com.jd.blockchain.ledger; + +public class TransactionPrivilege extends PrivilegeBitset { + + public TransactionPrivilege() { + } + + public TransactionPrivilege(byte[] codeBytes) { + super(codeBytes); + } + + @Override + public TransactionPrivilege clone() { + return (TransactionPrivilege) super.clone(); + } + +} 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/TransactionState.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionState.java index 518d793e..f7ef4a4e 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 @@ -38,6 +38,21 @@ public enum TransactionState { * 合约不存在; */ CONTRACT_DOES_NOT_EXIST((byte) 0x04), + + /** + * 数据写入时版本冲突; + */ + DATA_VERSION_CONFLICT((byte) 0x05), + + /** + * 参与方不存在; + */ + PARTICIPANT_DOES_NOT_EXIST((byte) 0x05), + + /** + * 被安全策略拒绝; + */ + REJECTED_BY_SECURITY_POLICY((byte) 0x10), /** * 由于在错误的账本上执行交易而被丢弃; 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..81dd5587 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserAuthInitData.java @@ -0,0 +1,45 @@ +package com.jd.blockchain.ledger; + +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.utils.Bytes; + +public class UserAuthInitData implements UserAuthInitSettings { + + static { + DataContractRegistry.register(UserAuthInitSettings.class); + } + + 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/UserAuthorizationSettings.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserAuthorizationSettings.java new file mode 100644 index 00000000..95e8755e --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserAuthorizationSettings.java @@ -0,0 +1,87 @@ +package com.jd.blockchain.ledger; + +import java.util.Collection; + +import com.jd.blockchain.utils.Bytes; + +public interface UserAuthorizationSettings { + + /** + * 单一用户可被授权的角色数量的最大值; + */ + 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/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/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..19f86ed8 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserRoles.java @@ -0,0 +1,117 @@ +package com.jd.blockchain.ledger; + +import java.util.Collection; +import java.util.Collections; +import java.util.Set; +import java.util.TreeSet; + +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.utils.Bytes; + +public class UserRoles implements RoleSet { + + static { + DataContractRegistry.register(RoleSet.class); + } + + 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 Set getRoleSet(){ + return Collections.unmodifiableSet(roles); + } + + 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/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 ef9b138a..66cec3b8 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 @@ -1,27 +1,24 @@ package com.jd.blockchain.transaction; +import com.jd.blockchain.ledger.*; +import com.jd.blockchain.utils.Bytes; + import java.util.ArrayList; import java.util.Collection; import java.util.List; -import com.jd.blockchain.ledger.BlockchainIdentity; -import com.jd.blockchain.ledger.BytesValue; -import com.jd.blockchain.ledger.BytesValueList; -import com.jd.blockchain.ledger.ContractCodeDeployOperation; -import com.jd.blockchain.ledger.ContractEventSendOperation; -import com.jd.blockchain.ledger.DataAccountKVSetOperation; -import com.jd.blockchain.ledger.DataAccountRegisterOperation; -import com.jd.blockchain.ledger.LedgerInitOperation; -import com.jd.blockchain.ledger.LedgerInitSetting; -import com.jd.blockchain.ledger.Operation; -import com.jd.blockchain.ledger.UserRegisterOperation; +import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.ledger.*; import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.net.NetworkAddress; /** * @author huanghaiquan * */ 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(); @@ -32,6 +29,12 @@ 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 static final ParticipantRegisterOperationBuilderImpl PARTICIPANT_REG_OP_BUILDER = new ParticipantRegisterOperationBuilderImpl(); + + private static final ParticipantStateUpdateOperationBuilderImpl PARTICIPANT_STATE_UPDATE_OP_BUILDER = new ParticipantStateUpdateOperationBuilderImpl(); private LedgerInitOperationBuilder ledgerInitOpBuilder = new LedgerInitOperationBuilderFilter(); @@ -45,6 +48,10 @@ public class BlockchainOperationFactory implements ClientOperator, LedgerInitOpe private ContractInvocationProxyBuilder contractInvoProxyBuilder = new ContractInvocationProxyBuilder(); + private ParticipantRegisterOperationBuilder participantRegOpBuilder = new ParticipantRegisterOperationBuilderFilter(); + + private ParticipantStateUpdateOperationBuilder participantStateModifyOpBuilder = new ParticipantStateUpdateOperationBuilderFilter(); + // TODO: 暂时只支持单线程情形,未考虑多线程; private List operationList = new ArrayList<>(); @@ -52,6 +59,11 @@ public class BlockchainOperationFactory implements ClientOperator, LedgerInitOpe public LedgerInitOperationBuilder ledgers() { return ledgerInitOpBuilder; } + + @Override + public SecurityOperationBuilder security() { + return securityOpBuilder; + } @Override public UserRegisterOperationBuilder users() { @@ -82,6 +94,12 @@ public class BlockchainOperationFactory implements ClientOperator, LedgerInitOpe return contractEventSendOpBuilder; } + @Override + public ParticipantRegisterOperationBuilder participants() {return participantRegOpBuilder;} + + @Override + public ParticipantStateUpdateOperationBuilder states() {return participantStateModifyOpBuilder;} + @Override public T contract(String address, Class contractIntf) { return contractInvoProxyBuilder.create(address, contractIntf, contractEventSendOpBuilder); @@ -156,6 +174,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 { @@ -256,6 +291,24 @@ public class BlockchainOperationFactory implements ClientOperator, LedgerInitOpe } } + private class ParticipantRegisterOperationBuilderFilter implements ParticipantRegisterOperationBuilder { + @Override + public ParticipantRegisterOperation register(String participantName, BlockchainIdentity participantIdentity, NetworkAddress networkAddress) { + ParticipantRegisterOperation op = PARTICIPANT_REG_OP_BUILDER.register(participantName, participantIdentity, networkAddress); + operationList.add(op); + return op; + } + } + + private class ParticipantStateUpdateOperationBuilderFilter implements ParticipantStateUpdateOperationBuilder { + @Override + public ParticipantStateUpdateOperation update(BlockchainIdentity blockchainIdentity, NetworkAddress networkAddress, ParticipantNodeState participantNodeState) { + ParticipantStateUpdateOperation op = PARTICIPANT_STATE_UPDATE_OP_BUILDER.update(blockchainIdentity, networkAddress, participantNodeState); + operationList.add(op); + return op; + } + } + private class ContractEventSendOperationBuilderFilter implements ContractEventSendOperationBuilder { @Override 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..cba4569e 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, ParticipantOperator { } \ 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..e182ced1 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,15 @@ 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; +import com.jd.blockchain.ledger.ParticipantNodeState; public class ConsensusParticipantData implements ParticipantNode { private int id; - private String address; + private Bytes address; private String name; @@ -16,6 +18,9 @@ public class ConsensusParticipantData implements ParticipantNode { private NetworkAddress hostAddress; + private ParticipantNodeState participantNodeState; + + @Override public int getId() { return id; } @@ -24,6 +29,7 @@ public class ConsensusParticipantData implements ParticipantNode { this.id = id; } + @Override public String getName() { return name; } @@ -32,7 +38,7 @@ public class ConsensusParticipantData implements ParticipantNode { this.name = name; } - public NetworkAddress getConsensusAddress() { + public NetworkAddress getHostAddress() { return hostAddress; } @@ -40,6 +46,7 @@ public class ConsensusParticipantData implements ParticipantNode { this.hostAddress = hostAddress; } + @Override public PubKey getPubKey() { return pubKey; } @@ -48,12 +55,22 @@ public class ConsensusParticipantData implements ParticipantNode { this.pubKey = pubKey; } - public String getAddress() { + @Override + public Bytes getAddress() { return address; } - public void setAddress(String address) { + public void setAddress(Bytes address) { this.address = address; } + @Override + public ParticipantNodeState getParticipantNodeState() { + return participantNodeState; + } + + public void setParticipantState(ParticipantNodeState participantNodeState) { + this.participantNodeState = participantNodeState; + } + } \ No newline at end of file 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 80% 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..656b4aa3 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,28 @@ package com.jd.blockchain.transaction; -import com.jd.blockchain.ledger.ParticipantNode; -import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.binaryproto.DataContractRegistry; import com.jd.blockchain.ledger.CryptoSetting; import com.jd.blockchain.ledger.LedgerInitSetting; +import com.jd.blockchain.ledger.ParticipantNode; +import com.jd.blockchain.ledger.UserAuthInitSettings; +import com.jd.blockchain.utils.Bytes; + +public class LedgerInitData implements LedgerInitSetting { -public class LedgerInitSettingData implements LedgerInitSetting { + static { + DataContractRegistry.register(LedgerInitSetting.class); + } private byte[] ledgerSeed; private ParticipantNode[] consensusParticipants; private CryptoSetting cryptoSetting; - + private String consensusProvider; private Bytes consensusSettings; - + private long createdTime; @Override @@ -55,11 +61,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 +78,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/ParticipantOperator.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantOperator.java new file mode 100644 index 00000000..83c1524a --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantOperator.java @@ -0,0 +1,18 @@ +package com.jd.blockchain.transaction; + +public interface ParticipantOperator { + + /** + * 注册参与方操作; + * + * @return + */ + ParticipantRegisterOperationBuilder participants(); + + /** + * 参与方状态更新操作; + * + * @return + */ + ParticipantStateUpdateOperationBuilder states(); +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantRegisterOpTemplate.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantRegisterOpTemplate.java new file mode 100644 index 00000000..925b8338 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantRegisterOpTemplate.java @@ -0,0 +1,41 @@ +package com.jd.blockchain.transaction; + +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.ParticipantInfo; +import com.jd.blockchain.ledger.ParticipantRegisterOperation; +import com.jd.blockchain.utils.net.NetworkAddress; + +public class ParticipantRegisterOpTemplate implements ParticipantRegisterOperation { + + static { + DataContractRegistry.register(ParticipantRegisterOperation.class); + } + + private String participantName; + private BlockchainIdentity participantRegisterIdentity; + private NetworkAddress networkAddress; + + public ParticipantRegisterOpTemplate(String participantName, BlockchainIdentity participantRegisterIdentity, NetworkAddress networkAddress) { + this.participantName = participantName; + this.participantRegisterIdentity = participantRegisterIdentity; + this.networkAddress = networkAddress; + + } + + @Override + public String getParticipantName() { + return participantName; + } + + @Override + public BlockchainIdentity getParticipantRegisterIdentity() { + return participantRegisterIdentity; + } + + @Override + public NetworkAddress getNetworkAddress() { + return networkAddress; + } +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantRegisterOperationBuilder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantRegisterOperationBuilder.java new file mode 100644 index 00000000..26f54c5b --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantRegisterOperationBuilder.java @@ -0,0 +1,23 @@ +package com.jd.blockchain.transaction; + +import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.ParticipantInfo; +import com.jd.blockchain.ledger.ParticipantRegisterOperation; +import com.jd.blockchain.utils.net.NetworkAddress; + +public interface ParticipantRegisterOperationBuilder { + + /** + * 注册; + * + * @param + * + * @param + * + * @return + */ + ParticipantRegisterOperation register(String participantName, BlockchainIdentity participantPubKey, NetworkAddress networkAddress); + + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantRegisterOperationBuilderImpl.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantRegisterOperationBuilderImpl.java new file mode 100644 index 00000000..34b126d1 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantRegisterOperationBuilderImpl.java @@ -0,0 +1,14 @@ +package com.jd.blockchain.transaction; + +import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.ParticipantInfo; +import com.jd.blockchain.ledger.ParticipantRegisterOperation; +import com.jd.blockchain.utils.net.NetworkAddress; + +public class ParticipantRegisterOperationBuilderImpl implements ParticipantRegisterOperationBuilder { + @Override + public ParticipantRegisterOperation register(String participantName, BlockchainIdentity participantPubKey, NetworkAddress networkAddress) { + return new ParticipantRegisterOpTemplate(participantName, participantPubKey, networkAddress); + } +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantStateOperator.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantStateOperator.java new file mode 100644 index 00000000..22554031 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantStateOperator.java @@ -0,0 +1,10 @@ +package com.jd.blockchain.transaction; + +public interface ParticipantStateOperator { + /** + * 参与方状态更新操作; + * + * @return + */ + ParticipantStateUpdateOperationBuilder states(); +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantStateUpdateOpTemplate.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantStateUpdateOpTemplate.java new file mode 100644 index 00000000..ff91eba5 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantStateUpdateOpTemplate.java @@ -0,0 +1,41 @@ +package com.jd.blockchain.transaction; + +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.ParticipantNodeState; +import com.jd.blockchain.ledger.ParticipantStateUpdateOperation; +import com.jd.blockchain.utils.net.NetworkAddress; + +public class ParticipantStateUpdateOpTemplate implements ParticipantStateUpdateOperation { + + static { + DataContractRegistry.register(ParticipantStateUpdateOperation.class); + } + + private BlockchainIdentity stateUpdateIdentity; + private NetworkAddress networkAddress; + private ParticipantNodeState participantNodeState; + + public ParticipantStateUpdateOpTemplate(BlockchainIdentity stateUpdateIdentity, NetworkAddress networkAddress, ParticipantNodeState participantNodeState) { + + this.stateUpdateIdentity = stateUpdateIdentity; + this.networkAddress = networkAddress; + this.participantNodeState = participantNodeState; + } + + + @Override + public BlockchainIdentity getStateUpdateIdentity() { + return stateUpdateIdentity; + } + + @Override + public NetworkAddress getNetworkAddress() { + return networkAddress; + } + + @Override + public ParticipantNodeState getState() { + return participantNodeState; + } +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantStateUpdateOperationBuilder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantStateUpdateOperationBuilder.java new file mode 100644 index 00000000..d6c69dc3 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantStateUpdateOperationBuilder.java @@ -0,0 +1,21 @@ +package com.jd.blockchain.transaction; + +import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.ParticipantNodeState; +import com.jd.blockchain.ledger.ParticipantStateUpdateInfo; +import com.jd.blockchain.ledger.ParticipantStateUpdateOperation; +import com.jd.blockchain.utils.net.NetworkAddress; + +public interface ParticipantStateUpdateOperationBuilder { + + /** + * 更新参与方状态,已注册->参与共识; + * + * @param + * + * @param + * + * @return + */ + ParticipantStateUpdateOperation update(BlockchainIdentity blockchainIdentity, NetworkAddress networkAddress, ParticipantNodeState participantNodeState); +} \ No newline at end of file diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantStateUpdateOperationBuilderImpl.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantStateUpdateOperationBuilderImpl.java new file mode 100644 index 00000000..9c84e181 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantStateUpdateOperationBuilderImpl.java @@ -0,0 +1,15 @@ +package com.jd.blockchain.transaction; + +import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.ParticipantNodeState; +import com.jd.blockchain.ledger.ParticipantStateUpdateInfo; +import com.jd.blockchain.ledger.ParticipantStateUpdateOperation; +import com.jd.blockchain.utils.net.NetworkAddress; + +public class ParticipantStateUpdateOperationBuilderImpl implements ParticipantStateUpdateOperationBuilder { + + @Override + public ParticipantStateUpdateOperation update(BlockchainIdentity blockchainIdentity, NetworkAddress networkAddress, ParticipantNodeState participantNodeState) { + return new ParticipantStateUpdateOpTemplate(blockchainIdentity, networkAddress, participantNodeState); + } +} 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 cb39f6b6..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; 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..ba5fc4e5 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/RolesConfigureOpTemplate.java @@ -0,0 +1,139 @@ +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); + DataContractRegistry.register(RolesConfigureOperation.class); + DataContractRegistry.register(RolePrivilegeEntry.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/TxBuilder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxBuilder.java index 1ff23a2f..0421b265 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 @@ -75,6 +75,11 @@ public class TxBuilder implements TransactionBuilder { public Collection getReturnValuehandlers() { return opFactory.getReturnValuetHandlers(); } + + @Override + public SecurityOperationBuilder security() { + return opFactory.security(); + } @Override public LedgerInitOperationBuilder ledgers() { @@ -110,6 +115,12 @@ public class TxBuilder implements TransactionBuilder { return opFactory.contractEvents(); } + @Override + public ParticipantRegisterOperationBuilder participants() {return opFactory.participants(); } + + @Override + public ParticipantStateUpdateOperationBuilder states() {return opFactory.states(); } + @Override public T contract(Bytes address, Class contractIntf) { return opFactory.contract(address, contractIntf); 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 ef4df764..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; @@ -55,13 +52,21 @@ public class TxRequestBuilder implements TransactionRequestBuilder { } @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) { 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..5f006111 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(); @@ -65,6 +71,18 @@ public class TxTemplate implements TransactionTemplate { return txBuilder.contracts(); } + @Override + public ParticipantRegisterOperationBuilder participants() { + stateManager.operate(); + return txBuilder.participants(); + } + + @Override + public ParticipantStateUpdateOperationBuilder states() { + stateManager.operate(); + return txBuilder.states(); + } + @Override public T contract(Bytes address, Class contractIntf) { stateManager.operate(); @@ -80,9 +98,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..ca66a6d9 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserAuthorizeOpTemplate.java @@ -0,0 +1,130 @@ +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); + DataContractRegistry.register(UserAuthorizeOperation.class); + DataContractRegistry.register(UserRolesEntry.class); + } + + private Set userAuthMap = Collections + .synchronizedSet(new LinkedHashSet()); + + public UserAuthorizeOpTemplate() { + } + + public UserAuthorizeOpTemplate(BlockchainIdentity userID) { + } + + @Override + public AuthorizationDataEntry[] getUserRolesAuthorizations() { + return ArrayUtils.toArray(userAuthMap, AuthorizationDataEntry.class); + } + + @Override + public UserAuthorizeOperation getOperation() { + return this; + } + + @Override + public UserRolesAuthorizer forUser(Bytes... userAddresses) { + AuthorizationDataEntry userRolesAuth = new AuthorizationDataEntry(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 AuthorizationDataEntry implements UserRolesAuthorizer, UserRolesEntry { + + private Bytes[] userAddress; + + private RolesPolicy policy = RolesPolicy.UNION; + + private Set authRoles = new LinkedHashSet(); + private Set unauthRoles = new LinkedHashSet(); + + private AuthorizationDataEntry(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/src/main/java/com/jd/blockchain/web/converters/BinaryMessageConverter.java b/source/ledger/ledger-rpc/src/main/java/com/jd/blockchain/web/converters/BinaryMessageConverter.java index 124b85cd..0814de76 100644 --- a/source/ledger/ledger-rpc/src/main/java/com/jd/blockchain/web/converters/BinaryMessageConverter.java +++ b/source/ledger/ledger-rpc/src/main/java/com/jd/blockchain/web/converters/BinaryMessageConverter.java @@ -46,6 +46,8 @@ public class BinaryMessageConverter extends AbstractHttpMessageConverter DataContractRegistry.register(ContractEventSendOperation.class); DataContractRegistry.register(DataAccountRegisterOperation.class); DataContractRegistry.register(UserRegisterOperation.class); + DataContractRegistry.register(ParticipantRegisterOperation.class); + DataContractRegistry.register(ParticipantStateUpdateOperation.class); DataContractRegistry.register(ActionRequest.class); DataContractRegistry.register(ActionResponse.class); 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 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> readStates(String ledgerKey) { + + String ledgerAllNodeKey = ledgerAllNodeKey(ledgerKey); + + String ledgerAllNodeValues = dbConnection.get(ledgerAllNodeKey); + + String[] ledgerAndNodeKeys = ledgerAllNodeValues.split(";"); + + Map> allInstallSchedules = new HashMap<>(); + + // 不存在就返回空值 + if (ledgerAndNodeKeys.length > 0) { + + for (String ledgerAndNodeKey : ledgerAndNodeKeys) { + // 获取每个LedgerAndNodeKey数据 + List installSchedules = readInstallSchedules(ledgerAndNodeKey); + + if (installSchedules != null) { + + allInstallSchedules.put(ledgerAndNodeKey, installSchedules); + } + } + } + + return allInstallSchedules; + } + + @Override + public LedgerIdentification readIdentification(String ledgerAndNodeKey) { + + String idKey = String.format(PEER_IDENTIFICATION_FORMAT, ledgerAndNodeKey); + + String identificationJson = dbConnection.get(idKey); + + if (identificationJson != null && identificationJson.length() > 0) { + + return JSON.parseObject(identificationJson, LedgerIdentification.class); + } + + return null; + } + + @Override + public List readLedgerPeerInstalls() { + + List peerInstallList = new ArrayList<>(); + + String maxIndexChars = dbConnection.get(PEER_INSTALL_MAX_KEY); + + if (maxIndexChars != null && maxIndexChars.length() > 0) { + + int maxIndex = Integer.parseInt(maxIndexChars); + + for (int i = 1; i <= maxIndex; i++) { + try { + String json = dbConnection.get(peerInstallKey(i)); + + if (json != null && json.length() > 0) { + peerInstallList.add(JSON.parseObject(json, LedgerPeerInstall.class)); + } + } catch (Exception e) { + LOGGER.error(e.toString()); + } + } + } + + return peerInstallList; + } + + @Override + public List readLedgerMasterInstalls() { + + List masterInstalls = new ArrayList<>(); + + String maxIndexChars = dbConnection.get(PEER_INSTALL_MAX_KEY); + + if (maxIndexChars != null && maxIndexChars.length() > 0) { + + int maxIndex = Integer.parseInt(maxIndexChars); + + for (int i = 1; i <= maxIndex; i++) { + try { + String json = dbConnection.get(masterInstallKey(i)); + + if (json != null && json.length() > 0) { + masterInstalls.add(JSON.parseObject(json, LedgerMasterInstall.class)); + } + } catch (Exception e) { + LOGGER.error(e.toString()); + } + } + } + + return masterInstalls; + } + + @Override + public List readLedgerPeerIniteds() { + + List peerIniteds = new ArrayList<>(); + + List peerInstalls = readLedgerPeerInstalls(); + + if (!peerInstalls.isEmpty()) { + + LOGGER.info("Read LedgerPeerInstalls, Size = {}", peerInstalls.size()); + for (LedgerPeerInstall peerInstall : peerInstalls) { + + String ledgerAndNodeKey = peerInstall.getLedgerAndNodeKey(); + + // 数据库中读取存放的LedgerHash + String ledgerHash = readLedgerHash(ledgerAndNodeKey); + + if (ledgerHash == null || ledgerHash.length() == 0) { + continue; + } + + LedgerPeerInited peerInited = new LedgerPeerInited(ledgerHash, peerInstall); + + // 检测账本中的Hash是否真正存在 + StartupState startupState = StartupState.UNKNOWN; + try { + startupState = startupState(ledgerHash, peerInstall); + } catch (Exception e) { + LOGGER.error("Check Ledger Hash Exist !!!", e); + } + + // 设置账本状态 + peerInited.setStartupState(startupState); + + // 添加到集合 + peerIniteds.add(peerInited); + } + } else { + LOGGER.error("Read LedgerPeerInstalls is Empty !!!"); + } + return peerIniteds; + } + + @Override + public List readLedgerPeerIniteds(String search) { + + List initedList = readLedgerPeerIniteds(); + + if (search != null && search.length() > 0 && !initedList.isEmpty()) { + + List filterInitedList = new ArrayList<>(); + + for (LedgerPeerInited peerInited : initedList) { + if (isMatch(peerInited, search)) { + filterInitedList.add(peerInited); + } + } + + return filterInitedList; + } + + return initedList; + } + + @Override + public List readLedgerIniteds(String search) { + + List ledgerInitedsFromConf = loadAllLedgerIniteds(UmpConstant.PROJECT_PATH); + + if (!ledgerInitedsFromConf.isEmpty()) { + + List ledgerIniteds = new ArrayList<>(); + + for (LedgerInited ledgerInited : ledgerInitedsFromConf) { + + if (isMatch(ledgerInited, search)) { + ledgerIniteds.add(ledgerInited); + } + } + + return ledgerIniteds; + } + + return ledgerInitedsFromConf; + } + + @Override + public String readLedgerHash(String ledgerAndNodeKey) { + + String ledgerHashKey = ledgerAndNodeHashKey(ledgerAndNodeKey); + + return dbConnection.get(ledgerHashKey); + } + + @Override + public void close() throws IOException { +// writeRunner.close(); + } + + private boolean isMatch(LedgerInited ledgerInited, String search) { + + if (search == null || search.length() == 0) { + return true; + } + + String ledgerHash = ledgerInited.getLedgerHash(); + String ledgerName = ledgerInited.getLedgerName(); + String partiName = ledgerInited.getPartiName(); + String partiAddress = ledgerInited.getPartiAddress(); + String dbUri = ledgerInited.getDbUri(); + StartupState startupState = ledgerInited.getStartupState(); + + if ( + ledgerHash.contains(search) || + startupState.toString().equals(search) || + ledgerName.contains(search) || + partiName.contains(search) || + partiAddress.contains(search) || + dbUri.contains(search) + ) { + return true; + } + return false; + } + + private boolean isMatch(LedgerPeerInited peerInited, String search) { + + if (search == null || search.length() == 0) { + return true; + } + + String ledgerHash = peerInited.getLedgerHash(); + StartupState startupState = peerInited.getStartupState(); + LedgerPeerInstall peerInstall = peerInited.getPeerInstall(); + + if (ledgerHash.contains(search) || + startupState.toString().equals(search) || + peerInstall.getNodeName().contains(search) || + peerInstall.getCreateTime().contains(search) + ) { + return true; + } + return false; + } + + private void loadInstallSchedules(PeerInstallSchedules installSchedules, String ledgerAndNodeKey) { + List schedules = readInstallSchedules(ledgerAndNodeKey); + + for (InstallSchedule installSchedule : schedules) { + installSchedules.addInstallSchedule( + new PeerInstallSchedule(installSchedule.getProcess(), installSchedule.getState())); + } + } + + private List readInstallSchedules(String ledgerAndNodeKey) { + String maxKey = ledgerAndNodeMaxKey(ledgerAndNodeKey); + String maxIdChars = dbConnection.get(maxKey); + if (maxIdChars == null || maxIdChars.length() == 0) { + return null; + } + int maxId = Integer.parseInt(maxIdChars); + + List schedules = new ArrayList<>(); + + for (int i = 0; i <= maxId; i++) { + + try { + String currentKey = ledgerAndNodeCurrentNewKey(ledgerAndNodeKey, i); + + String jsonChars = dbConnection.get(currentKey); + + if (jsonChars != null && jsonChars.length() > 0) { + schedules.add(JSON.parseObject(jsonChars, InstallSchedule.class)); + } + } catch (Exception e) { + // 打印错误,暂不处理其他 + LOGGER.error(e.toString()); + } + } + + return schedules; + } + + private List loadAllLedgerIniteds(String peerPath) { + + List ledgerInitedsFromConf = ledgerService.allLedgerIniteds(peerPath); + + if (!ledgerInitedsFromConf.isEmpty()) { + + // 逐个检查其状态 + for (LedgerInited ledgerInited : ledgerInitedsFromConf) { + // 判断该账本对应的数据库是否存在 + if (!dbConnection.exist(ledgerInited.getDbUri())) { + ledgerInited.setStartupState(StartupState.DB_UNEXIST); + continue; + } + + String peerVerify = ledgerService.peerVerifyKey(peerPath); + + try { + if (!CommandUtils.isActive(peerVerify)) { + // 进程不存在 + LOGGER.info("Can not find Peer Process {} !!!", peerVerify); + ledgerInited.setStartupState(StartupState.UNLOAD); + continue; + } + } catch (Exception e) { + // 进程处理错误打印日志即可 + LOGGER.error(String.format("Command Check %s !!!", peerVerify), e); + } + // 查看该进程对应的监听端口 + try { + int listenPort = listenPort(peerVerify); + + LOGGER.info("Find Listen Port = {} !", listenPort); + + if (listenPort > 0) { + + int maxSize = 5, checkIndex = 1; + + boolean isRead = false; + + while (maxSize > 0) { + + try { + // 发送请求到对应地址 + JSONArray ledgerHashs = HttpJsonClientUtils.httpGet(ledgersUrl(listenPort), JSONArray.class, true); + + if (ledgerHashs != null && !ledgerHashs.isEmpty()) { + for(Object hashObj : ledgerHashs) { + if (hashObj instanceof JSONObject) { + if (ledgerInited.getLedgerHash().equals(((JSONObject) hashObj).getString("value"))) { + // 说明该账本已经被加载 + ledgerInited.setStartupState(StartupState.LOADED); + isRead = true; + break; + } + } + } + if (isRead) { + break; + } + } + + // 6秒休眠 + Thread.sleep(6000); + } catch (Exception e) { + LOGGER.error(String.format("Request LedgerHashs from PeerNode [%s]", checkIndex++), e); + } + + maxSize --; + } + + if (!isRead) { + // 表明等待加载,无须再启动 + ledgerInited.setStartupState(StartupState.LOADING); + } + } + } catch (Exception e) { + LOGGER.error(String.format("Command [%s] 'Listen Port Check !!!", peerVerify), e); + } + } + } + + return ledgerInitedsFromConf; + } + + private StartupState startupState(String ledgerHash, LedgerPeerInstall peerInstall) { + + String peerPath = peerInstall.getPeerPath(); + + // 首先检查文件中是否存在该Hash值 + LedgerBindingConf ledgerBindingConf = ledgerService.allLedgerHashs(peerPath); + + Set allLedgerHashs = ledgerBindingConf.getLedgerHashs(); + + if (!allLedgerHashs.contains(ledgerHash)) { + + // 文件中不存在 + return StartupState.UNEXIST; + } + + // 判断该账本对应的数据库是否存在 + if (!ledgerService.dbExist(peerPath, ledgerHash)) { + + // 该账本对应数据库不存在 + return StartupState.DB_UNEXIST; + } + + // 文件中存在则检查进程是否存在 + // 进程存在标识为LOADED,否则标识为LOADING,暂时用不到LOADING + String peerVerify = ledgerService.peerVerifyKey(peerPath); + + try { + if (!CommandUtils.isActive(peerVerify)) { + // 进程不存在 + return StartupState.UNLOAD; + } + + } catch (Exception e) { + // 进程处理错误打印日志即可 + LOGGER.error(String.format("Command Check %s !!!", peerVerify), e); + } + + // 查看该进程对应的监听端口 + try { + int listenPort = listenPort(peerVerify); + + LOGGER.info("Find Listen Port = {} !", listenPort); + + if (listenPort > 0) { + // 发送请求到对应地址 + JSONArray ledgerHashs = HttpJsonClientUtils.httpGet(ledgersUrl(listenPort), JSONArray.class, true); + + if (ledgerHashs != null && !ledgerHashs.isEmpty()) { + for(Object hashObj : ledgerHashs) { + if (hashObj instanceof JSONObject) { + if (ledgerHash.equals(((JSONObject) hashObj).getString("value"))) { + // 说明该账本已经被加载 + return StartupState.LOADED; + } + } + } + // 表明等待加载,无须再启动 + return StartupState.LOADING; + } + } + } catch (Exception e) { + LOGGER.error(String.format("Command [%s] 'Listen Port Check !!!", peerVerify), e); + } + + return StartupState.UNKNOWN; + } + + private String ledgersUrl(int listenPort) { + return "http://" + LOCALHOST + ":" + listenPort + "/ledgers"; + } + + private int listenPort(String peerVerify) throws Exception { + + String portArg = mainArg(peerVerify, PORT_ARG); + + if (portArg != null && portArg.length() > 0) { + return Integer.parseInt(portArg); + } + + return 0; + } + + private String mainArg(String processName, String argKey) throws Exception { + + String[] cmdLineArray = mainArgs(processName); + + if (cmdLineArray != null && cmdLineArray.length > 0) { + for (int i = 0; i < cmdLineArray.length; i++) { + String currArg = cmdLineArray[i].trim(); + if (currArg.equals(argKey) && (i + 1) < cmdLineArray.length) { + return cmdLineArray[i+1].trim(); + } + } + } + return null; + } + + private String[] mainArgs(String processName) throws Exception { + + String mainArgs = CommandUtils.mainArgs(processName); + + if (mainArgs != null && mainArgs.length() > 0) { + ///Users/shaozhuguang/Documents/newenv/peer4/system/deployment-peer-1.1.0-SNAPSHOT.jar -home=/Users/shaozhuguang/Documents/newenv/peer4 -c /Users/shaozhuguang/Documents/newenv/peer4/config/ledger-binding.conf -p 7080 + return mainArgs.split(" "); + } + + return null; + } + + private synchronized int maxIndex(String key) { + int maxIndex = 1; + String maxIndexChars = dbConnection.get(key); + if (maxIndexChars != null && maxIndexChars.length() > 0) { + maxIndex = Integer.parseInt(maxIndexChars) + 1; + } + return maxIndex; + } + + private String usersKey(int userId) { + return String.format(USERS_KEY_FORMAT, userId); + } + + private String peerInstallKey(int index) { + return String.format(PEER_INSTALL_KEY_FORMAT, index); + } + + private String masterInstallKey(int index) { + return String.format(MASTER_INSTALL_KEY_FORMAT, index); + } + + private String ledgerAndNodeConfigKey(String ledgerAndNodeKey) { + + return ledgerAndNodeKey + LEDGER_NODE_KEY_CONFIG_SUFFIX; + } + + private String ledgerAllNodeKey(String ledgerKey) { + + return ledgerKey + LEDGER_NODE_KEY_SUFFIX; + } + + private String ledgerAndNodeMaxKey(String ledgerAndNodeKey) { + + return ledgerAndNodeKey + MAX_SIZE_KEY_SUFFIX; + } + + private String ledgerAndNodeHashKey(String ledgerAndNodeKey) { + + return ledgerAndNodeKey + LEDGER_HASH_KEY_SUFFIX; + } + + private String ledgerAndNodeCurrentNewKey(String ledgerAndNodeKey, int currentId) { + + return String.format( + ledgerAndNodeKey + CURRENT_INDEX_KEY_SUFFIX_FORMAT, + currentId); + } + + private void saveKeys2Files(String keysDirPath, UserKeys userKeys) throws IOException { + + // 写入私钥 + write(keysDirPath, userKeys.getName(), UmpConstant.PRIVATE_KEY_SUFFIX, userKeys.getPrivKey()); + // 写入公钥 + write(keysDirPath, userKeys.getName(), UmpConstant.PUBLIC_KEY_SUFFIX, userKeys.getPubKey()); + // 写入密钥 + write(keysDirPath, userKeys.getName(), UmpConstant.PWD_SUFFIX, userKeys.getEncodePwd()); + } + + private void write(String keysDirPath, String name, String suffix, String writeContent) throws IOException { + + String keyeFilePath = keysDirPath + File.separator + name + suffix; + + File keysFile = new File(keyeFilePath); + + if (keysFile.exists()) { + // 文件存在,备份文件 + FileUtils.copyFile(keysFile, new File(keyeFilePath + "_bak_" + currentTime())); + } + + // 将Priv文件内容写入 + FileUtils.writeStringToFile(keysFile, writeContent, StandardCharsets.UTF_8); + } + + private String currentTime() { + return SDF.format(new Date()); + } +} diff --git a/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UtilService.java b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UtilService.java new file mode 100644 index 00000000..a2083d88 --- /dev/null +++ b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UtilService.java @@ -0,0 +1,15 @@ +package com.jd.blockchain.ump.service; + +import com.jd.blockchain.ump.model.user.UserKeyBuilder; +import com.jd.blockchain.ump.model.user.UserKeys; + +public interface UtilService { + + UserKeys create(UserKeyBuilder builder); + + UserKeys create(String name, String seed, String pwd); + + UserKeys read(int id); + + boolean verify(UserKeys userKeys, String pwd); +} diff --git a/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UtilServiceHandler.java b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UtilServiceHandler.java new file mode 100644 index 00000000..3abf5bb4 --- /dev/null +++ b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/UtilServiceHandler.java @@ -0,0 +1,80 @@ +package com.jd.blockchain.ump.service; + +import com.jd.blockchain.crypto.PrivKey; +import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm; +import com.jd.blockchain.crypto.utils.classic.ED25519Utils; +import com.jd.blockchain.ump.model.user.UserKeyBuilder; +import com.jd.blockchain.ump.model.user.UserKeys; +import com.jd.blockchain.utils.codec.Base58Utils; +import com.jd.blockchain.utils.security.ShaUtils; +import org.bouncycastle.crypto.AsymmetricCipherKeyPair; +import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters; +import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters; +import org.bouncycastle.crypto.prng.FixedSecureRandom; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; + +import static com.jd.blockchain.tools.keygen.KeyGenCommand.encodePrivKey; +import static com.jd.blockchain.tools.keygen.KeyGenCommand.encodePubKey; + +@Service +public class UtilServiceHandler implements UtilService { + + private static final String UTF_8 = "UTF-8"; + + @Autowired + private UmpStateService umpStateService; + + @Override + public UserKeys create(UserKeyBuilder builder) { + + return create(builder.getName(), builder.getSeed(), builder.getPwd()); + } + + @Override + public UserKeys create(String name, String seed, String pwd) { + + AsymmetricCipherKeyPair keyPair = ED25519Utils.generateKeyPair( + new FixedSecureRandom(seed.getBytes(Charset.forName(UTF_8)))); + + PubKey pubKey = new PubKey(ClassicAlgorithm.ED25519, + ((Ed25519PublicKeyParameters) keyPair.getPublic()).getEncoded()); + + PrivKey privKey = new PrivKey(ClassicAlgorithm.ED25519, + ((Ed25519PrivateKeyParameters) keyPair.getPrivate()).getEncoded()); + + return create(name, pubKey, privKey, pwd); + } + + @Override + public UserKeys read(int userId) { + + return umpStateService.readUserKeys(userId); + } + + @Override + public boolean verify(UserKeys userKeys, String pwd) { + + String encodePwd = Base58Utils.encode((ShaUtils.hash_256(pwd.getBytes(Charset.forName(UTF_8))))); + + if (encodePwd.equals(userKeys.getEncodePwd())) { + return true; + } + return false; + } + + private UserKeys create(String name, PubKey pubKey, PrivKey privKey, String pwd) { + + byte[] pwdBytes = ShaUtils.hash_256(pwd.getBytes(Charset.forName(UTF_8))); + + return new UserKeys( + name, + encodePrivKey(privKey, pwdBytes), + encodePubKey(pubKey), +// pwd, // 密码不保存到数据库,防止泄露 + Base58Utils.encode(pwdBytes)); + } +} diff --git a/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/ConsensusProvider.java b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/ConsensusProvider.java new file mode 100644 index 00000000..124b6d10 --- /dev/null +++ b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/ConsensusProvider.java @@ -0,0 +1,21 @@ +package com.jd.blockchain.ump.service.consensus; + +import com.jd.blockchain.ump.model.config.PeerLocalConfig; + +import java.util.List; +import java.util.Properties; + +public interface ConsensusProvider { + + String NEXT_LINE = "\r\n"; + + String provider(); + + String configFilePath(); + + void setConfig(Properties properties); + + Properties getConfig(); + + byte[] handleSharedConfigs(List sharedConfigs); +} diff --git a/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/ConsensusService.java b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/ConsensusService.java new file mode 100644 index 00000000..aeb5fcba --- /dev/null +++ b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/ConsensusService.java @@ -0,0 +1,10 @@ +package com.jd.blockchain.ump.service.consensus; + +import com.jd.blockchain.ump.model.config.PeerLocalConfig; + +import java.util.List; + +public interface ConsensusService { + + String initConsensusConf(String consensusProvider, List sharedConfigs); +} diff --git a/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/ConsensusServiceHandler.java b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/ConsensusServiceHandler.java new file mode 100644 index 00000000..50cdb00f --- /dev/null +++ b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/ConsensusServiceHandler.java @@ -0,0 +1,79 @@ +package com.jd.blockchain.ump.service.consensus; + +import com.jd.blockchain.ump.model.config.PeerLocalConfig; +import com.jd.blockchain.ump.util.Base58Utils; +import org.reflections.Reflections; +import org.springframework.stereotype.Service; + +import java.io.File; +import java.io.InputStream; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +@Service +public class ConsensusServiceHandler implements ConsensusService { + + private static final Map CONSENSUS_PROVIDERS = new ConcurrentHashMap<>(); + + static { + try { + initProviders(); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + + @Override + public String initConsensusConf(String consensusProvider, List sharedConfigs) { + // 首先根据provider获取对应的配置信息 + ConsensusProvider provider = CONSENSUS_PROVIDERS.get(consensusProvider); + + if (provider == null) { + throw new IllegalStateException( + String.format("ConsensusProvider[%s] can not find Manage-Class !!!", consensusProvider)); + } + + byte[] result = provider.handleSharedConfigs(sharedConfigs); + + return Base58Utils.encode(result); + } + + private static void initProviders() { + // 初始化所有实现类 + Reflections reflections = new Reflections("com.jd.blockchain.ump.service.consensus"); + + Set> providerSet = + reflections.getSubTypesOf(ConsensusProvider.class); + + for (Class clazz : providerSet) { + + if (!clazz.isInterface()) { + try { + // 根据class生成对象 + ConsensusProvider provider = clazz.newInstance(); + String providerKey = provider.provider(); + if (providerKey != null && providerKey.length() > 0 && + !CONSENSUS_PROVIDERS.containsKey(providerKey)) { + + // 根据value读取配置文件中的内容 + InputStream currentFileInputStream = ConsensusServiceHandler.class.getResourceAsStream( + File.separator + provider.configFilePath()); + + Properties currentProps = new Properties(); + + currentProps.load(currentFileInputStream); + + provider.setConfig(currentProps); + + CONSENSUS_PROVIDERS.put(providerKey, provider); + } + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + } + } +} diff --git a/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/providers/BftsmartConsensusProvider.java b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/providers/BftsmartConsensusProvider.java new file mode 100644 index 00000000..acb89a84 --- /dev/null +++ b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/providers/BftsmartConsensusProvider.java @@ -0,0 +1,162 @@ +package com.jd.blockchain.ump.service.consensus.providers; + + +import com.jd.blockchain.ump.model.config.PeerLocalConfig; +import com.jd.blockchain.ump.model.config.PeerSharedConfig; +import com.jd.blockchain.ump.service.consensus.ConsensusProvider; + +import java.nio.charset.StandardCharsets; +import java.util.*; + +public class BftsmartConsensusProvider implements ConsensusProvider { + + public static final String BFTSMART_PROVIDER = "com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider"; + + public static final String BFTSMART_CONFIG_FILE = "bftsmart.config"; + + private static final int MIN_PARTI_SIZE = 4; + + private Properties bftsmartProps; + + @Override + public String provider() { + return BFTSMART_PROVIDER; + } + + @Override + public String configFilePath() { + return BFTSMART_CONFIG_FILE; + } + + @Override + public void setConfig(Properties properties) { + bftsmartProps = properties; + } + + @Override + public Properties getConfig() { + return bftsmartProps; + } + + @Override + public byte[] handleSharedConfigs(List sharedConfigs) { + + // 首先校验其中的ConsensusNode是否完全一致,若完全一致则不可以 + verify(sharedConfigs); + + StringBuilder sBuilder = new StringBuilder(); + + // 先加入当前节点信息 + List nodeConfigs = nodeConfigs(sharedConfigs); + + for (String nodeConfig : nodeConfigs) { + sBuilder.append(nodeConfig).append(NEXT_LINE); + } + + int nodeNum = sharedConfigs.size(); + + // 写入之前配置文件中的内容 + for (Map.Entry entry : bftsmartProps.entrySet()) { + + // 获取Key-Value + String key = (String) entry.getKey(), value = (String) entry.getValue(); + + // 对特殊的Key和Value单独处理 + /** + * system.servers.num = 4 + * + * system.servers.f = 1 + * + * system.initial.view = 0,1,2,3 + */ + if (key.startsWith(BftsmartConstant.SERVERS_NUM_PREFIX)) { + + sBuilder.append(BftsmartConstant.SERVERS_NUM_PREFIX + " = " + nodeNum).append(NEXT_LINE); + } else if (key.startsWith(BftsmartConstant.SERVERS_F_PREFIX)) { + + sBuilder.append(BftsmartConstant.SERVERS_F_PREFIX + " = " + nodeFNum(nodeNum)).append(NEXT_LINE); + } else if (key.startsWith(BftsmartConstant.INIT_VIEW_PREFIX)) { + + sBuilder.append(BftsmartConstant.INIT_VIEW_PREFIX + " = " + initView(nodeNum)).append(NEXT_LINE); + } else { + + sBuilder.append(key + " = " + value).append(NEXT_LINE); + } + } + + return sBuilder.toString().getBytes(StandardCharsets.UTF_8); + } + + private String initView(int nodeNum) { + + StringBuilder views = new StringBuilder(); + + for (int i = 0; i < nodeNum; i++) { + if (views.length() > 0) { + views.append(","); + } + views.append(i); + } + return views.toString(); + } + + private void verify(List sharedConfigs) { + + Set consensusInfos = new HashSet<>(); + + if (sharedConfigs == null) { + throw new IllegalStateException("Shared Configs is NULL !!!"); + } + + if (sharedConfigs.size() < MIN_PARTI_SIZE) { + throw new IllegalStateException( + String.format("Shared Configs's size = %s, can not meet minimum %s !!!", + sharedConfigs.size(), MIN_PARTI_SIZE)); + } + + for (PeerLocalConfig sharedConfig : sharedConfigs) { + String consensusInfo = sharedConfig.getConsensusNode(); + if (consensusInfos.contains(consensusInfo)) { + throw new IllegalStateException("Shared Configs's Consensus may be conflict !!!"); + } + consensusInfos.add(consensusInfo); + } + } + + private List nodeConfigs(List sharedConfigs) { + + List nodeConfigs = new ArrayList<>(); + + if (sharedConfigs != null && !sharedConfigs.isEmpty()) { + for (int i = 0; i < sharedConfigs.size(); i++) { + + PeerSharedConfig sharedConfig = sharedConfigs.get(i); + + String consensusNode = sharedConfig.getConsensusNode(); + + String[] hostAndPort = consensusNode.split(":"); + + nodeConfigs.add(String.format(BftsmartConstant.HOST_FORMAT, i, hostAndPort[0])); + + nodeConfigs.add(String.format(BftsmartConstant.PORT_FORMAT, i, hostAndPort[1])); + + nodeConfigs.add(String.format(BftsmartConstant.SECURE_FORMAT, i, false)); + + } + } + + return nodeConfigs; + } + + private int nodeFNum(int nodeNum) { + /** + * 3F+1 + * + * 假设有4个节点,则可有一个,若有N个,则N-1/3 + */ + if (nodeNum < 4) { + return 0; + } + return (nodeNum - 1) / 3; + } +} diff --git a/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/providers/BftsmartConstant.java b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/providers/BftsmartConstant.java new file mode 100644 index 00000000..78afdbe4 --- /dev/null +++ b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/providers/BftsmartConstant.java @@ -0,0 +1,17 @@ +package com.jd.blockchain.ump.service.consensus.providers; + +public class BftsmartConstant { + + public static final String HOST_FORMAT = "system.server.%s.network.host=%s"; + + public static final String PORT_FORMAT = "system.server.%s.network.port=%s"; + + public static final String SECURE_FORMAT = "system.server.%s.network.secure=%s"; + + public static final String SERVERS_NUM_PREFIX = "system.servers.num"; + + public static final String SERVERS_F_PREFIX = "system.servers.f"; + + public static final String INIT_VIEW_PREFIX = "system.initial.view"; + +} diff --git a/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/providers/MsgQueueConsensusProvider.java b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/providers/MsgQueueConsensusProvider.java new file mode 100644 index 00000000..d4b197e7 --- /dev/null +++ b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/service/consensus/providers/MsgQueueConsensusProvider.java @@ -0,0 +1,41 @@ +package com.jd.blockchain.ump.service.consensus.providers; + +import com.jd.blockchain.ump.model.config.PeerLocalConfig; +import com.jd.blockchain.ump.service.consensus.ConsensusProvider; + +import java.util.List; +import java.util.Properties; + +public class MsgQueueConsensusProvider implements ConsensusProvider { + + private static final String MSGQUEUE_PROVIDER = "com.jd.blockchain.consensus.mq.MsgQueueConsensusProvider"; + + private static final String MSGQUEUE_CONFIG_FILE = "mq.config"; + + private Properties msgQueueProps; + + @Override + public String provider() { + return MSGQUEUE_PROVIDER; + } + + @Override + public String configFilePath() { + return MSGQUEUE_CONFIG_FILE; + } + + @Override + public void setConfig(Properties properties) { + this.msgQueueProps = properties; + } + + @Override + public Properties getConfig() { + return msgQueueProps; + } + + @Override + public byte[] handleSharedConfigs(List sharedConfigs) { + return new byte[0]; + } +} diff --git a/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/util/Base58Utils.java b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/util/Base58Utils.java new file mode 100644 index 00000000..ff74ba9b --- /dev/null +++ b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/util/Base58Utils.java @@ -0,0 +1,153 @@ +package com.jd.blockchain.ump.util; + +import java.io.UnsupportedEncodingException; +import java.math.BigInteger; + +public class Base58Utils { + + public static final char[] ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".toCharArray(); + + private static final int[] INDEXES = new int[128]; + + static { + for (int i = 0; i < INDEXES.length; i++) { + INDEXES[i] = -1; + } + for (int i = 0; i < ALPHABET.length; i++) { + INDEXES[ALPHABET[i]] = i; + } + } + + /** + * Encodes the given bytes in base58. No checksum is appended. + */ + public static String encode(byte[] input) { + if (input.length == 0) { + return ""; + } + input = copyOfRange(input, 0, input.length); + // Count leading zeroes. + int zeroCount = 0; + while (zeroCount < input.length && input[zeroCount] == 0) { + ++zeroCount; + } + // The actual encoding. + byte[] temp = new byte[input.length * 2]; + int j = temp.length; + + int startAt = zeroCount; + while (startAt < input.length) { + byte mod = divmod58(input, startAt); + if (input[startAt] == 0) { + ++startAt; + } + temp[--j] = (byte) ALPHABET[mod]; + } + + // Strip extra '1' if there are some after decoding. + while (j < temp.length && temp[j] == ALPHABET[0]) { + ++j; + } + // Add as many leading '1' as there were leading zeros. + while (--zeroCount >= 0) { + temp[--j] = (byte) ALPHABET[0]; + } + + byte[] output = copyOfRange(temp, j, temp.length); + try { + return new String(output, "US-ASCII"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); // Cannot happen. + } + } + + public static byte[] decode(String input) throws IllegalArgumentException { + if (input.length() == 0) { + return new byte[0]; + } + byte[] input58 = new byte[input.length()]; + // Transform the String to a base58 byte sequence + for (int i = 0; i < input.length(); ++i) { + char c = input.charAt(i); + + int digit58 = -1; + if (c >= 0 && c < 128) { + digit58 = INDEXES[c]; + } + if (digit58 < 0) { + throw new IllegalArgumentException("Illegal character " + c + " at " + i); + } + + input58[i] = (byte) digit58; + } + // Count leading zeroes + int zeroCount = 0; + while (zeroCount < input58.length && input58[zeroCount] == 0) { + ++zeroCount; + } + // The encoding + byte[] temp = new byte[input.length()]; + int j = temp.length; + + int startAt = zeroCount; + while (startAt < input58.length) { + byte mod = divmod256(input58, startAt); + if (input58[startAt] == 0) { + ++startAt; + } + + temp[--j] = mod; + } + // Do no add extra leading zeroes, move j to first non null byte. + while (j < temp.length && temp[j] == 0) { + ++j; + } + + return copyOfRange(temp, j - zeroCount, temp.length); + } + + public static BigInteger decodeToBigInteger(String input) throws IllegalArgumentException { + return new BigInteger(1, decode(input)); + } + + // + // number -> number / 58, returns number % 58 + // + private static byte divmod58(byte[] number, int startAt) { + int remainder = 0; + for (int i = startAt; i < number.length; i++) { + int digit256 = (int) number[i] & 0xFF; + int temp = remainder * 256 + digit256; + + number[i] = (byte) (temp / 58); + + remainder = temp % 58; + } + + return (byte) remainder; + } + + // + // number -> number / 256, returns number % 256 + // + private static byte divmod256(byte[] number58, int startAt) { + int remainder = 0; + for (int i = startAt; i < number58.length; i++) { + int digit58 = (int) number58[i] & 0xFF; + int temp = remainder * 58 + digit58; + + number58[i] = (byte) (temp / 256); + + remainder = temp % 256; + } + + return (byte) remainder; + } + + private static byte[] copyOfRange(byte[] source, int from, int to) { + byte[] range = new byte[to - from]; + System.arraycopy(source, from, range, 0, range.length); + + return range; + } +} diff --git a/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/util/CommandUtils.java b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/util/CommandUtils.java new file mode 100644 index 00000000..3290d2ce --- /dev/null +++ b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/util/CommandUtils.java @@ -0,0 +1,133 @@ +package com.jd.blockchain.ump.util; + +import sun.jvmstat.monitor.MonitoredHost; +import sun.jvmstat.monitor.MonitoredVm; +import sun.jvmstat.monitor.MonitoredVmUtil; +import sun.jvmstat.monitor.VmIdentifier; + +import java.util.*; + +public class CommandUtils { + + public static void killVm(String processName) throws Exception { + + MonitoredVm activeVm = activeVm(processName); + + if (activeVm != null) { + killVm(activeVm); + } + } + + public static void killVm(MonitoredVm vm) throws Exception { + if (vm != null) { + int vmId = vm.getVmIdentifier().getLocalVmId(); + List killCmd = killCommand(vmId); + execute(killCmd); + } + } + + public static List toCommandList(String cmd) { + // 要求使用空格 + String[] cmdArray = cmd.split(" "); + + if (cmdArray.length > 0) { + return Arrays.asList(cmdArray); + } + + return null; + + } + + public static Process execute(List cmds) throws Exception { + + if (cmds == null || cmds.isEmpty()) { + throw new IllegalStateException("Command's List is NULL !!!"); + } + + ProcessBuilder pBuilder = new ProcessBuilder(cmds); + + Process process = pBuilder.start(); + + return process; + + } + + public static boolean executeAndVerify(List cmds, String verify) throws Exception { + + if (cmds == null || cmds.isEmpty()) { + throw new IllegalStateException("Command's List is NULL !!!"); + } + + ProcessBuilder pBuilder = new ProcessBuilder(cmds); + + pBuilder.start(); + + // 时延5s,再进行判断 + Thread.sleep(5000); + + return isActive(verify); + + } + + public static MonitoredVm activeVm(String processName) throws Exception { + + MonitoredHost localMonitored = MonitoredHost.getMonitoredHost("localhost"); + + Set activeVms = new HashSet<>(localMonitored.activeVms()); + + for (Integer vmId : activeVms) { + + try { + MonitoredVm vm = localMonitored.getMonitoredVm(new VmIdentifier("//" + vmId)); + + String vmProcessName = MonitoredVmUtil.mainClass(vm, true); + + if (vmProcessName.contains(processName)) { + return vm; + } + } catch (Exception e) { + // 此处异常打印即可,不需要处理 + System.err.println(e); + } + } + + return null; + } + + public static boolean isActive(String processName) throws Exception { + + MonitoredVm activeVm = activeVm(processName); + + return activeVm != null; + } + + public static String mainArgs(MonitoredVm vm) { + if (vm != null) { + try { + return MonitoredVmUtil.mainArgs(vm); + } catch (Exception e) { + // 打印日志即可 + System.err.println(e); + } + } + return null; + } + + public static String mainArgs(String processName) throws Exception { + + return mainArgs(activeVm(processName)); + } + + public static List killCommand(int vmId) { + if (vmId > 1) { + List killCmd = new ArrayList<>(); + killCmd.add("kill"); + killCmd.add("-9"); + killCmd.add(String.valueOf(vmId)); + + return killCmd; + } + + throw new IllegalStateException(String.format("Can not kill Process ID = [%s]", vmId)); + } +} diff --git a/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/util/HttpClientPool.java b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/util/HttpClientPool.java new file mode 100644 index 00000000..dd575d0d --- /dev/null +++ b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/util/HttpClientPool.java @@ -0,0 +1,289 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.utils.http.agent.HttpClientPool + * Author: shaozhuguang + * Department: 区块链研发部 + * Date: 2019/1/14 下午3:20 + * Description: + */ +package com.jd.blockchain.ump.util; + +import org.apache.http.*; +import org.apache.http.client.HttpRequestRetryHandler; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.config.Registry; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.ConnectTimeoutException; +import org.apache.http.conn.routing.HttpRoute; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.LayeredConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; + +import javax.net.ssl.SSLException; +import javax.net.ssl.SSLHandshakeException; +import java.io.IOException; +import java.io.InterruptedIOException; +import java.io.UnsupportedEncodingException; +import java.net.UnknownHostException; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * + * @author shaozhuguang + * @create 2019/1/14 + * @since 1.0.0 + */ + +public class HttpClientPool { + + private static final int TEN_MINUTE = 600 * 1000; + + private static final int TIME_OUT = TEN_MINUTE; + + private static final int CONNECT_TIME_OUT = TEN_MINUTE; + + private static final int SOCKET_TIME_OUT = TEN_MINUTE; + + private static final int MAX_TOTAL = 200; + + private static final int MAX_PER_ROUTE = 40; + + private static final int MAX_ROUTE = 100; + + private static final int RETRY_COUNT = 5; + + private static final String DEFAULT_CHARSET = "UTF-8"; + + private static final Map httpClients = new ConcurrentHashMap<>(); + + private final static Lock lock = new ReentrantLock(); + + private static void config(HttpRequestBase httpRequestBase) { + // 配置请求的超时设置 + RequestConfig requestConfig = RequestConfig.custom() + .setConnectionRequestTimeout(TIME_OUT) + .setConnectTimeout(CONNECT_TIME_OUT) + .setSocketTimeout(SOCKET_TIME_OUT) + .build(); + httpRequestBase.setConfig(requestConfig); + } + + /** + * 获取HttpClient对象 + * + * @param url + * @return + */ + public static CloseableHttpClient getHttpClient(String url) { + String hostName = url.split("/")[2]; + int port = 80; + if (hostName.contains(":")) { + String[] arr = hostName.split(":"); + hostName = arr[0]; + port = Integer.parseInt(arr[1]); + } + return getHttpClient(hostName, port); + } + + /** + * 获取HttpClient对象 + * + * @param hostName + * @param port + * @return + */ + public static CloseableHttpClient getHttpClient(String hostName, int port) { + String key = hostName + ":" + port; + CloseableHttpClient httpClient = httpClients.get(key); + if (httpClient == null) { + try { + lock.lock(); + if (httpClient == null) { + httpClient = createHttpClient(MAX_TOTAL, MAX_PER_ROUTE, MAX_ROUTE, hostName, port); + httpClients.put(key, httpClient); + } + } finally { + lock.unlock(); + } + } + return httpClient; + } + + /** + * 创建HttpClient + * + * @param maxTotal + * @param maxPerRoute + * @param maxRoute + * @param hostname + * @param port + * @return + */ + public static CloseableHttpClient createHttpClient(int maxTotal, + int maxPerRoute, int maxRoute, String hostname, int port) { + ConnectionSocketFactory plainsf = PlainConnectionSocketFactory + .getSocketFactory(); + LayeredConnectionSocketFactory sslsf = SSLConnectionSocketFactory + .getSocketFactory(); + Registry registry = RegistryBuilder + . create().register("http", plainsf) + .register("https", sslsf).build(); + PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager( + registry); + cm.setMaxTotal(maxTotal); + cm.setDefaultMaxPerRoute(maxPerRoute); + HttpHost httpHost = new HttpHost(hostname, port); + cm.setMaxPerRoute(new HttpRoute(httpHost), maxRoute); + HttpRequestRetryHandler httpRequestRetryHandler = (exception, executionCount, context) -> { + if (executionCount >= RETRY_COUNT) {// 最多重试5次 + return false; + }else if (exception instanceof NoHttpResponseException) { + return true; + }else if (exception instanceof SSLException) { + return false; + }else if (exception instanceof InterruptedIOException) { + return false; + }else if (exception instanceof SSLHandshakeException) { + return false; + }else if (exception instanceof UnknownHostException) { + return false; + }else if (exception instanceof ConnectTimeoutException) { + return false; + } + + HttpClientContext clientContext = HttpClientContext + .adapt(context); + HttpRequest request = clientContext.getRequest(); + if (!(request instanceof HttpEntityEnclosingRequest)) { + return true; + } + return false; + }; + + CloseableHttpClient httpClient = HttpClients.custom() + .setConnectionManager(cm) + .setRetryHandler(httpRequestRetryHandler).build(); + + return httpClient; + } + + private static void setPostParams(HttpPost httpPost, + Map params) { + List nameValuePairs = new ArrayList<>(); + Set keySet = params.keySet(); + for (String key : keySet) { + nameValuePairs.add(new BasicNameValuePair(key, params.get(key).toString())); + } + try { + httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, DEFAULT_CHARSET)); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + + private static void setJsonPostParams(HttpPost httpPost, String json) { + httpPost.addHeader("Content-type","application/json; charset=utf-8"); + httpPost.setHeader("Accept", "application/json"); + httpPost.setEntity(new StringEntity(json, Charset.forName("UTF-8"))); + } + + /** + * POST请求 + * + * @param url + * @param params + * @return String + * @throws IOException + */ + public static String post(String url, Map params) throws IOException { + HttpPost httpPost = new HttpPost(url); + config(httpPost); + setPostParams(httpPost, params); + try (CloseableHttpResponse response = httpPost(url, httpPost)) { + return parseResponse(response); + } + } + + public static String jsonPost(String url, String json) throws IOException { + HttpPost httpPost = new HttpPost(url); + config(httpPost); + setJsonPostParams(httpPost, json); + try (CloseableHttpResponse response = httpPost(url, httpPost)) { + return parseResponse(response); + } + } + + /** + * GET请求 + * + * @param url + * @return String + */ + public static String get(String url) throws IOException { + HttpGet httpGet = new HttpGet(url); + config(httpGet); + try (CloseableHttpResponse response = httpGet(url, httpGet)) { + return parseResponse(response); + } + } + + /** + * Get请求的真实执行 + * + * @param url + * @param httpGet + * @return + * @throws IOException + */ + private static CloseableHttpResponse httpGet(String url, HttpGet httpGet) throws IOException { + return getHttpClient(url) + .execute(httpGet, HttpClientContext.create()); + } + + /** + * POST请求的真实执行 + * + * @param url + * @param httpPost + * @return + * @throws IOException + */ + private static CloseableHttpResponse httpPost(String url, HttpPost httpPost) throws IOException { + return getHttpClient(url) + .execute(httpPost, HttpClientContext.create()); + } + + /** + * 解析response + * + * @param response + * @return + * @throws IOException + */ + private static String parseResponse(CloseableHttpResponse response) throws IOException { + HttpEntity entity = response.getEntity(); + String result = EntityUtils.toString(entity, DEFAULT_CHARSET); + EntityUtils.consume(entity); + return result; + } +} \ No newline at end of file diff --git a/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/util/HttpJsonClientUtils.java b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/util/HttpJsonClientUtils.java new file mode 100644 index 00000000..04c8c927 --- /dev/null +++ b/source/manager/ump-service/src/main/java/com/jd/blockchain/ump/util/HttpJsonClientUtils.java @@ -0,0 +1,61 @@ +package com.jd.blockchain.ump.util; + +import com.alibaba.fastjson.JSON; +import com.jd.blockchain.ump.model.MasterAddr; +import com.jd.blockchain.ump.model.web.WebResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class HttpJsonClientUtils { + + private static final Logger LOGGER = LoggerFactory.getLogger(HttpJsonClientUtils.class); + + public static T httpPost(MasterAddr masterAddr, String url, Object body, Class returnType, boolean isWrapper) { + + try { + String responseJson = HttpClientPool.jsonPost(masterAddr.toHttpUrl() + url, JSON.toJSONString(body)); + + LOGGER.info("Http Post Receive info =[ {} ] from {} ", responseJson, masterAddr.toHttpUrl() + url); + + return response(responseJson, returnType, isWrapper); + } catch (Exception e) { + + LOGGER.error("HttpPostRequestException {}", e.getMessage()); + + throw new IllegalStateException(e); + } + } + + public static T httpGet(String url, Class returnType, boolean isWrapper) { + try { + String responseJson = HttpClientPool.get(url); + + LOGGER.info("Http Get Receive info =[ {} ] from {} ", responseJson, url); + + return response(responseJson, returnType, isWrapper); + + } catch (Exception e) { + + LOGGER.error("HttpGetRequestException {}", e.toString()); + + throw new IllegalStateException(e); + } + } + + private static T response(String responseJson, Class returnType, boolean isWrapper) { + if (isWrapper) { + // 封装类型的情况下使用的是WebResponse + WebResponse webResponse = JSON.parseObject(responseJson, WebResponse.class); + LOGGER.info("Wrapper JSON Data = {}", JSON.toJSONString(webResponse)); + return webResponse.getData(); + } + + if (!JSON.isValid(responseJson)) { + return (T)responseJson; + } + // 对responseJson进行转换 + T data = JSON.parseObject(responseJson, returnType); + LOGGER.info("UnWrapper JSON Data = {}", JSON.toJSONString(data)); + return data; + } +} diff --git a/source/manager/ump-service/src/main/resources/bftsmart.config b/source/manager/ump-service/src/main/resources/bftsmart.config new file mode 100644 index 00000000..5ec6e530 --- /dev/null +++ b/source/manager/ump-service/src/main/resources/bftsmart.config @@ -0,0 +1,122 @@ + +# 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 +#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 ### +############################################ + +#Number of servers in the group +system.servers.num = 4 + +#Maximum number of faulty replicas +system.servers.f = 1 + +#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 ###### +############################################ + +#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 + +#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 \ No newline at end of file diff --git a/source/manager/ump-service/src/main/resources/mq.config b/source/manager/ump-service/src/main/resources/mq.config new file mode 100644 index 00000000..e69de29b diff --git a/source/manager/ump-web/pom.xml b/source/manager/ump-web/pom.xml new file mode 100644 index 00000000..658f3205 --- /dev/null +++ b/source/manager/ump-web/pom.xml @@ -0,0 +1,83 @@ + + + + + manager + com.jd.blockchain + 1.1.0-SNAPSHOT + + 4.0.0 + + ump-web + + ump-web + + + 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.jd.blockchain + ump-service + ${project.version} + + + + com.jd.blockchain + ump-model + ${project.version} + + + + com.jd.blockchain + utils-common + ${project.version} + + + + com.jd.blockchain + ump-explorer + + + + junit + junit + test + + + diff --git a/source/manager/ump-web/src/main/java/com/jd/blockchain/ump/controller/UmpDBController.java b/source/manager/ump-web/src/main/java/com/jd/blockchain/ump/controller/UmpDBController.java new file mode 100644 index 00000000..be55fa34 --- /dev/null +++ b/source/manager/ump-web/src/main/java/com/jd/blockchain/ump/controller/UmpDBController.java @@ -0,0 +1,22 @@ +package com.jd.blockchain.ump.controller; + +import com.jd.blockchain.ump.dao.DBConnection; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping(path = "/db/") +public class UmpDBController { + + @Autowired + private DBConnection dbConnection; + + @RequestMapping(method = RequestMethod.GET, path = "read/{key}") + public String read(@PathVariable(name = "key") String key) { + + return dbConnection.get(key); + } +} diff --git a/source/manager/ump-web/src/main/java/com/jd/blockchain/ump/controller/UmpKeyController.java b/source/manager/ump-web/src/main/java/com/jd/blockchain/ump/controller/UmpKeyController.java new file mode 100644 index 00000000..a7d2aed3 --- /dev/null +++ b/source/manager/ump-web/src/main/java/com/jd/blockchain/ump/controller/UmpKeyController.java @@ -0,0 +1,85 @@ +package com.jd.blockchain.ump.controller; + +import com.jd.blockchain.ump.model.user.UserKeyBuilder; +import com.jd.blockchain.ump.model.user.UserKeys; +import com.jd.blockchain.ump.model.user.UserKeysVv; +import com.jd.blockchain.ump.service.UmpStateService; +import com.jd.blockchain.ump.service.UtilService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping(path = "/keys/") +public class UmpKeyController { + + @Autowired + private UtilService utilService; + + @Autowired + private UmpStateService umpStateService; + + + /** + * 创建用户 + * + * @param builder + * @return + */ + @RequestMapping(method = RequestMethod.POST, path = "create") + public UserKeysVv create(@RequestBody final UserKeyBuilder builder) { + + // 使用种子生成公私钥 + UserKeys userKeys = utilService.create(builder); + + // 将userKeys保存至数据库 + umpStateService.save(userKeys); + + return userKeys.toUserKeysVv(); + } + + @RequestMapping(method = RequestMethod.GET, path = "list") + public List list() { + + // 从数据库中读取,返回 + return umpStateService.readUserKeysVvList(); + } + + @RequestMapping(method = RequestMethod.GET, path = "read/{user}/{pubKey}") + public UserKeysVv read(@PathVariable(name = "user") int userId, + @PathVariable(name = "pubKey") String pubKey) { + + UserKeys userKeys = utilService.read(userId); + + if (userKeys != null) { + if (userKeys.getPubKey().equals(pubKey)) { + + return userKeys.toUserKeysVv(); + } + } + throw new IllegalStateException(String.format("Can not find UserKeys by %s", pubKey)); + } + + /** + * 解析UserKeys + * + * @param userId + * 用户ID + * @param pwd + * 密码(非编码后密码) + * @return + */ + @RequestMapping(method = RequestMethod.GET, path = "resolve/{user}/{pwd}") + public UserKeys resolve(@PathVariable(name = "user") int userId, + @PathVariable(name = "pwd") String pwd) { + + UserKeys userKeys = utilService.read(userId); + + if (utilService.verify(userKeys, pwd)) { + + return userKeys; + } + throw new IllegalStateException(String.format("Can not resolve UserKeys by %s", pwd)); + } +} diff --git a/source/manager/ump-web/src/main/java/com/jd/blockchain/ump/controller/UmpMasterController.java b/source/manager/ump-web/src/main/java/com/jd/blockchain/ump/controller/UmpMasterController.java new file mode 100644 index 00000000..7caa0584 --- /dev/null +++ b/source/manager/ump-web/src/main/java/com/jd/blockchain/ump/controller/UmpMasterController.java @@ -0,0 +1,76 @@ +package com.jd.blockchain.ump.controller; + +import com.jd.blockchain.ump.model.PeerSharedConfigs; +import com.jd.blockchain.ump.model.config.LedgerConfig; +import com.jd.blockchain.ump.model.config.PeerLocalConfig; +import com.jd.blockchain.ump.model.state.InstallSchedule; +import com.jd.blockchain.ump.model.state.LedgerMasterInstall; +import com.jd.blockchain.ump.service.UmpService; +import com.jd.blockchain.ump.service.UmpStateService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + +@RestController +@RequestMapping(path = "/master/") +public class UmpMasterController { + + @Autowired + private UmpService umpService; + + @Autowired + private UmpStateService umpStateService; + + /** + * 需要支持的接口 + * 1、接收节点Share的信息 + * 2、接收节点发送来的状态信息 + * 3、接收前端查看某些节点状态的请求 + */ + @RequestMapping(method = RequestMethod.POST, path = "share") + public LedgerConfig share(@RequestBody final PeerLocalConfig sharedConfig) { + + PeerSharedConfigs sharedConfigs = umpService.loadPeerSharedConfigs(sharedConfig); + + if (sharedConfigs == null) { + throw new IllegalStateException("PeerSharedConfig may be exits Conflict !!!"); + } + + return umpService.response(sharedConfigs, sharedConfig); + } + + /** + * 接收其他Peer节点发送的安装信息 + * + * @param installSchedule + * 安装信息 + * + * @return + */ + @RequestMapping(method = RequestMethod.POST, path = "receive") + public String receive(@RequestBody final InstallSchedule installSchedule) { + + try { + umpStateService.save(installSchedule, null); + } catch (Exception e) { + return "FAIL"; + } + + return "SUCCESS"; + } + + @RequestMapping(method = RequestMethod.GET, path = "read/{ledgerKey}") + public Map> readState(@PathVariable(name = "ledgerKey") String ledgerKey) { + + return umpStateService.readStates(ledgerKey); + } + + @RequestMapping(method = RequestMethod.GET, path = "list") + public List ledgerInstallList() { + + // 返回当前Master收到的所有节点所有的安装信息 + return umpStateService.readLedgerMasterInstalls(); + } +} diff --git a/source/manager/ump-web/src/main/java/com/jd/blockchain/ump/controller/UmpPeerController.java b/source/manager/ump-web/src/main/java/com/jd/blockchain/ump/controller/UmpPeerController.java new file mode 100644 index 00000000..9222b14c --- /dev/null +++ b/source/manager/ump-web/src/main/java/com/jd/blockchain/ump/controller/UmpPeerController.java @@ -0,0 +1,147 @@ +package com.jd.blockchain.ump.controller; + +import com.jd.blockchain.ump.model.MasterAddr; +import com.jd.blockchain.ump.model.UmpConstant; +import com.jd.blockchain.ump.model.config.LedgerConfig; +import com.jd.blockchain.ump.model.config.LedgerIdentification; +import com.jd.blockchain.ump.model.config.PeerLocalConfig; +import com.jd.blockchain.ump.model.config.PeerSharedConfigVv; +import com.jd.blockchain.ump.model.state.*; +import com.jd.blockchain.ump.model.user.UserKeys; +import com.jd.blockchain.ump.service.UmpService; +import com.jd.blockchain.ump.service.UmpStateService; +import com.jd.blockchain.ump.service.UtilService; +import com.jd.blockchain.ump.util.HttpJsonClientUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping(path = "/peer/") +public class UmpPeerController { + + @Autowired + private UmpService umpService; + + @Autowired + private UmpStateService umpStateService; + + @Autowired + private UmpMasterController masterController; + + @Autowired + private UtilService utilService; + +// @RequestMapping(method = RequestMethod.POST, path = "share") + public LedgerIdentification share(@RequestBody PeerLocalConfig localConfig) { + + //首先校验配置信息 + localConfig.verify(); + + MasterAddr masterAddr = localConfig.masterAddr(); + + LedgerConfig ledgerConfig; + + if (localConfig.master()) { + // 当前节点本身是master,直接调用Controller方法 + ledgerConfig = masterController.share(localConfig); + } else { + ledgerConfig = HttpJsonClientUtils.httpPost(masterAddr, UmpConstant.REQUEST_SHARED_URL, localConfig, LedgerConfig.class, false); + } + + if (ledgerConfig == null) { + // 未加载成功 + throw new IllegalStateException("Can not load Ledger-Config's Data from Master Node !!!"); + } + + String ledgerAndNodeKey = umpService.save(masterAddr, ledgerConfig, localConfig); + + int nodeId = ledgerConfig.getInitConfig().nodeId(localConfig.getPubKey()); + + LedgerIdentification identification = new LedgerIdentification(nodeId, localConfig, + masterAddr, ledgerAndNodeKey, ledgerConfig.getInitConfig()); + + // 将数据写入数据库 + umpStateService.save(identification); + + return identification; + } + + @RequestMapping(method = RequestMethod.POST, path = "share") + public LedgerIdentification share(@RequestBody PeerSharedConfigVv sharedConfigVv) { + + String pubKey = sharedConfigVv.getPubKey(); + + if (pubKey == null || pubKey.length() == 0) { + throw new IllegalStateException("Public Key can not be empty !!!"); + } + + // 获取对应的UsersKey,转换为LocalConfig + UserKeys userKeys = utilService.read(sharedConfigVv.getUserId()); + + if (userKeys == null || !pubKey.equals(userKeys.getPubKey())) { + throw new IllegalStateException(String.format("Can not find UserKeys by %s", pubKey)); + } + + PeerLocalConfig localConfig = sharedConfigVv.toPeerLocalConfig(userKeys); + + return share(localConfig); + } + + @RequestMapping(method = RequestMethod.POST, path = "install/{ledgerAndNodeKey}") + public PeerInstallSchedules install(@PathVariable(name = "ledgerAndNodeKey") String ledgerAndNodeKey) { + + return umpService.install(ledgerAndNodeKey); + } + + @RequestMapping(method = RequestMethod.POST, path = "init/{ledgerAndNodeKey}") + public PeerInstallSchedules init(@PathVariable(name = "ledgerAndNodeKey") String ledgerAndNodeKey) { + + return umpService.init(ledgerAndNodeKey); + } + + @RequestMapping(method = RequestMethod.POST, path = "startup") + public PeerStartupSchedules startup() { + + return umpService.startup(); + } + +// @RequestMapping(method = RequestMethod.POST, path = "stop/{ledgerAndNodeKey}") + public boolean stop(@PathVariable(name = "ledgerAndNodeKey") String ledgerAndNodeKey) { + + return umpService.stop(ledgerAndNodeKey); + } + + @RequestMapping(method = RequestMethod.POST, path = "stop") + public boolean stop() { + + return umpService.stop(); + } + + @RequestMapping(method = RequestMethod.GET, path = "init/read/{ledgerAndNodeKey}") + public PeerInstallSchedules readInitState(@PathVariable(name = "ledgerAndNodeKey") String ledgerAndNodeKey) { + + return umpStateService.readInitState(ledgerAndNodeKey); + } + + @RequestMapping(method = RequestMethod.GET, path = "list") + public List ledgerInstallList() { + + // 返回当前Peer节点所有的安装信息 + return umpStateService.readLedgerPeerInstalls(); + } + + public List ledgerInitedList(@RequestParam(name = "search", required = false) String search) { + + // 返回当前Peer节点所有的初始化后信息 + return umpStateService.readLedgerPeerIniteds(search); + } + + @RequestMapping(method = RequestMethod.GET, path = "initeds") + public List ledgerIniteds(@RequestParam(name = "search", required = false) String search) { + + // 返回当前Peer节点所有的初始化后信息 + return umpStateService.readLedgerIniteds(search); + } +} diff --git a/source/manager/ump-web/src/main/java/com/jd/blockchain/ump/controller/UmpPeerSimulateController.java b/source/manager/ump-web/src/main/java/com/jd/blockchain/ump/controller/UmpPeerSimulateController.java new file mode 100644 index 00000000..35f0e8af --- /dev/null +++ b/source/manager/ump-web/src/main/java/com/jd/blockchain/ump/controller/UmpPeerSimulateController.java @@ -0,0 +1,64 @@ +package com.jd.blockchain.ump.controller; + +import com.jd.blockchain.ump.model.config.LedgerIdentification; +import com.jd.blockchain.ump.model.config.PeerLocalConfig; +import com.jd.blockchain.ump.model.state.PeerInstallSchedules; +import com.jd.blockchain.ump.service.UmpService; +import com.jd.blockchain.ump.service.UmpSimulateService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@RestController +@RequestMapping(path = "/peer/") +public class UmpPeerSimulateController { + + private final Map ledgerAndNodeKeys = new ConcurrentHashMap<>(); + + @Autowired + private UmpService umpService; + + @Autowired + private UmpSimulateService simulateService; + + @Autowired + private UmpPeerController peerController; + + @RequestMapping(method = RequestMethod.GET, path = "share/simulate/{node}") + public LedgerIdentification share(@PathVariable(name = "node") int nodeId) { + + boolean isMaster = false; + if (nodeId == 0) { + isMaster = true; + } + + PeerLocalConfig localConfig = simulateService.nodePeerLocalConfig(nodeId, isMaster); + + LedgerIdentification identification = peerController.share(localConfig); + + // 作为缓存使用 + ledgerAndNodeKeys.put(nodeId, identification.getLedgerAndNodeKey()); + + return identification; + } + + + @RequestMapping(method = RequestMethod.GET, path = "install/simulate/{node}") + public PeerInstallSchedules install(@PathVariable(name = "node") int nodeId) { + + String ledgerAndNodeKey = ledgerAndNodeKeys.get(nodeId); + + return umpService.install(ledgerAndNodeKey); + } + + @RequestMapping(method = RequestMethod.GET, path = "init/simulate/{node}") + public PeerInstallSchedules init(@PathVariable(name = "node") int nodeId) { + + return umpService.init(ledgerAndNodeKeys.get(nodeId)); + } +} diff --git a/source/manager/ump-web/src/main/java/com/jd/blockchain/ump/web/ControllerConfigurer.java b/source/manager/ump-web/src/main/java/com/jd/blockchain/ump/web/ControllerConfigurer.java new file mode 100644 index 00000000..6c5be2f3 --- /dev/null +++ b/source/manager/ump-web/src/main/java/com/jd/blockchain/ump/web/ControllerConfigurer.java @@ -0,0 +1,29 @@ +package com.jd.blockchain.ump.web; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class ControllerConfigurer implements WebMvcConfigurer { + + @Override + public void addInterceptors(InterceptorRegistry registry) { + + // 添加打印日志的拦截器 + registry.addInterceptor(new LogPrintInterceptor()).addPathPatterns("/**"); + } + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/webjars/**") + .addResourceLocations("classpath:/META-INF/resources"); + } + + @Override + public void addViewControllers(ViewControllerRegistry registry) { + registry.addViewController("/").setViewName("web/index.html"); + } +} diff --git a/source/manager/ump-web/src/main/java/com/jd/blockchain/ump/web/ExceptionResponseAdvice.java b/source/manager/ump-web/src/main/java/com/jd/blockchain/ump/web/ExceptionResponseAdvice.java new file mode 100644 index 00000000..c079fccc --- /dev/null +++ b/source/manager/ump-web/src/main/java/com/jd/blockchain/ump/web/ExceptionResponseAdvice.java @@ -0,0 +1,38 @@ +package com.jd.blockchain.ump.web; + +import com.jd.blockchain.ump.model.web.ErrorCode; +import com.jd.blockchain.ump.model.web.WebResponse; +import com.jd.blockchain.utils.BusinessException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import javax.servlet.http.HttpServletRequest; + +@RestControllerAdvice +public class ExceptionResponseAdvice { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + @ExceptionHandler(value = Exception.class) + @ResponseBody + public WebResponse json(HttpServletRequest req, Exception ex) { + + WebResponse.ErrorMessage message; + + String reqURL = "[" + req.getMethod() + "] " + req.getRequestURL().toString(); + + if (ex instanceof BusinessException) { + BusinessException businessException = (BusinessException) ex; + message = new WebResponse.ErrorMessage(businessException.getErrorCode(), businessException.getMessage()); + } else { + logger.error("Exception occurred! --[RequestURL=" + reqURL + "][" + ex.getClass().toString() + + "]" + ex.getMessage(), ex); + + message = new WebResponse.ErrorMessage(ErrorCode.UNEXPECTED.getValue(), ex.toString()); + } + return WebResponse.createFailureResult(message); + } +} diff --git a/source/manager/ump-web/src/main/java/com/jd/blockchain/ump/web/JsonResponseAdvice.java b/source/manager/ump-web/src/main/java/com/jd/blockchain/ump/web/JsonResponseAdvice.java new file mode 100644 index 00000000..822aee64 --- /dev/null +++ b/source/manager/ump-web/src/main/java/com/jd/blockchain/ump/web/JsonResponseAdvice.java @@ -0,0 +1,51 @@ +package com.jd.blockchain.ump.web; + +import com.jd.blockchain.ump.model.config.LedgerConfig; +import com.jd.blockchain.ump.model.web.WebResponse; +import org.springframework.core.MethodParameter; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; + +@RestControllerAdvice +public class JsonResponseAdvice implements ResponseBodyAdvice { + + @Override + public boolean supports(MethodParameter returnType, Class> converterType) { + if (MappingJackson2HttpMessageConverter.class == converterType + && (returnType.getContainingClass().getName().startsWith("com.jd.blockchain.ump") + || returnType.getDeclaringClass().getName().startsWith("com.jd.blockchain.ump"))) { + return true; + } + return false; + } + + @Override + public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, + Class> selectedConverterType, ServerHttpRequest request, + ServerHttpResponse response) { + if (body == null) { + return WebResponse.createSuccessResult(null); + } + + if (body instanceof ResponseEntity) { + return body; + } + + // LedgerConfig单独处理 + if (body instanceof LedgerConfig) { + return body; + } + + // 把返回结果自动转换为 WebResponse; + if (body instanceof WebResponse) { + return body; + } + return WebResponse.createSuccessResult(body); + } +} diff --git a/source/manager/ump-web/src/main/java/com/jd/blockchain/ump/web/LogPrintInterceptor.java b/source/manager/ump-web/src/main/java/com/jd/blockchain/ump/web/LogPrintInterceptor.java new file mode 100644 index 00000000..c68ef5e8 --- /dev/null +++ b/source/manager/ump-web/src/main/java/com/jd/blockchain/ump/web/LogPrintInterceptor.java @@ -0,0 +1,32 @@ +package com.jd.blockchain.ump.web; + +import com.alibaba.fastjson.JSON; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Map; + +public class LogPrintInterceptor implements HandlerInterceptor { + + private final Logger LOGGER = LoggerFactory.getLogger(getClass()); + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + // 记录日志 + // 请求的参数: + String parameters = ""; + Map requestParameters = request.getParameterMap(); + if (requestParameters != null && !requestParameters.isEmpty()) { + parameters = JSON.toJSONString(requestParameters); + } + LOGGER.info("Request[{}][{}], parameters=[{}]", + request.getRequestURL().toString(), // 请求URL + request.getMethod(), // 请求的方法 + parameters); // 请求的参数 + + return true; + } +} diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/PeerServerBooter.java b/source/peer/src/main/java/com/jd/blockchain/peer/PeerServerBooter.java index 8e7811a0..056753fe 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/PeerServerBooter.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/PeerServerBooter.java @@ -1,5 +1,6 @@ package com.jd.blockchain.peer; +import com.jd.blockchain.consts.Global; import com.jd.blockchain.storage.service.DbConnectionFactory; import com.jd.blockchain.tools.initializer.LedgerBindingConfig; import com.jd.blockchain.utils.ArgumentSet; @@ -41,6 +42,11 @@ public class PeerServerBooter { private static final String DEBUG_OPT = "-debug"; public static String ledgerBindConfigFile; + + static { + // 加载 Global ,初始化全局设置; + Global.initialize(); + } public static void main(String[] args) { PeerServerBooter peerServerBooter = new PeerServerBooter(); @@ -58,8 +64,12 @@ public class PeerServerBooter { if (ledgerBindConfigFile == null) { ConsoleUtils.info("Load build-in default configuration ..."); ClassPathResource configResource = new ClassPathResource("ledger-binding.conf"); - InputStream in = configResource.getInputStream(); - ledgerBindingConfig = LedgerBindingConfig.resolve(in); + + try (InputStream in = configResource.getInputStream()) { + ledgerBindingConfig = LedgerBindingConfig.resolve(in); + } catch (Exception e) { + throw e; + } } else { ConsoleUtils.info("Load configuration,ledgerBindConfigFile position="+ledgerBindConfigFile); File file = new File(ledgerBindConfigFile); diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/consensus/ConsensusRealmImpl.java b/source/peer/src/main/java/com/jd/blockchain/peer/consensus/ConsensusRealmImpl.java index 108365a6..d5d5fca9 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/consensus/ConsensusRealmImpl.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/consensus/ConsensusRealmImpl.java @@ -16,7 +16,7 @@ public class ConsensusRealmImpl implements ConsensusRealm { public ConsensusRealmImpl(ParticipantNode[] nodeList) { this.nodes = nodeList; - String[] addrs = new String[nodes.length]; + Bytes[] addrs = new Bytes[nodes.length]; int i = 0; for (ParticipantNode n : nodes) { addrs[i++] = n.getAddress(); diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/ledger/LedgerConfigurer.java b/source/peer/src/main/java/com/jd/blockchain/peer/ledger/LedgerConfigurer.java index 5a2bc247..f6c8bcb9 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/ledger/LedgerConfigurer.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/ledger/LedgerConfigurer.java @@ -3,10 +3,10 @@ package com.jd.blockchain.peer.ledger; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import com.jd.blockchain.ledger.core.impl.DefaultOperationHandleRegisteration; -import com.jd.blockchain.ledger.core.impl.LedgerManager; -import com.jd.blockchain.ledger.core.impl.OperationHandleRegisteration; -import com.jd.blockchain.ledger.core.impl.TransactionEngineImpl; +import com.jd.blockchain.ledger.core.DefaultOperationHandleRegisteration; +import com.jd.blockchain.ledger.core.LedgerManager; +import com.jd.blockchain.ledger.core.OperationHandleRegisteration; +import com.jd.blockchain.ledger.core.TransactionEngineImpl; import com.jd.blockchain.service.TransactionEngine; @Configuration diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java b/source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java index 341136b0..ad5f3aeb 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java @@ -14,15 +14,14 @@ import org.springframework.web.bind.annotation.RestController; import com.jd.blockchain.contract.ContractException; import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.ledger.core.ContractAccountSet; +import com.jd.blockchain.ledger.core.ContractAccountQuery; 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.DataAccountQuery; +import com.jd.blockchain.ledger.core.LedgerQuery; import com.jd.blockchain.ledger.core.LedgerService; import com.jd.blockchain.ledger.core.ParticipantCertData; -import com.jd.blockchain.ledger.core.TransactionSet; -import com.jd.blockchain.ledger.core.UserAccountSet; +import com.jd.blockchain.ledger.core.TransactionQuery; +import com.jd.blockchain.ledger.core.UserAccountQuery; import com.jd.blockchain.transaction.BlockchainQueryService; import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.QueryUtil; @@ -43,7 +42,7 @@ public class LedgerQueryController implements BlockchainQueryService { @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}") @Override public LedgerInfo getLedger(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); // TODO: 需要配置返回值的 spring MsgQueueMessageDispatcher // ,对返回对象仅仅序列化声明的返回值类型的属性,而不是整个对象本身; LedgerInfo ledgerInfo = new LedgerInfo(); @@ -56,8 +55,8 @@ public class LedgerQueryController implements BlockchainQueryService { @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/participants") @Override public ParticipantNode[] getConsensusParticipants(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); - LedgerAdministration ledgerAdministration = ledger.getAdminInfo(); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); + LedgerAdminInfo ledgerAdministration = ledger.getAdminInfo(); long participantCount = ledgerAdministration.getParticipantCount(); if (participantCount <= 0) { return null; @@ -73,12 +72,20 @@ public class LedgerQueryController implements BlockchainQueryService { } return null; } + + @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/admininfo") + @Override + public LedgerAdminInfo getLedgerAdminInfo(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) { + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); + LedgerAdminInfo ledgerAdministration = ledger.getAdminInfo(); + return ledgerAdministration; + } @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/metadata") @Override public LedgerMetadata getLedgerMetadata(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); - LedgerAdministration ledgerAdministration = ledger.getAdminInfo(); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); + LedgerAdminInfo ledgerAdministration = ledger.getAdminInfo(); LedgerMetadata ledgerMetadata = ledgerAdministration.getMetadata(); return ledgerMetadata; } @@ -87,7 +94,7 @@ public class LedgerQueryController implements BlockchainQueryService { @Override public LedgerBlock getBlock(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, @PathVariable(name = "blockHeight") long blockHeight) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); // TODO: 需要配置返回值的 spring MsgQueueMessageDispatcher // ,对返回对象仅仅序列化声明的返回值类型的属性,而不是整个对象本身; return ledger.getBlock(blockHeight); @@ -97,7 +104,7 @@ public class LedgerQueryController implements BlockchainQueryService { @Override public LedgerBlock getBlock(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, @PathVariable(name = "blockHash") HashDigest blockHash) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); // TODO: 需要配置返回值的 spring MsgQueueMessageDispatcher // ,对返回对象仅仅序列化声明的返回值类型的属性,而不是整个对象本身; return ledger.getBlock(blockHash); @@ -107,9 +114,9 @@ public class LedgerQueryController implements BlockchainQueryService { @Override public long getTransactionCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, @PathVariable(name = "blockHeight") long blockHeight) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock block = ledger.getBlock(blockHeight); - TransactionSet txSet = ledger.getTransactionSet(block); + TransactionQuery txSet = ledger.getTransactionSet(block); return txSet.getTotalCount(); } @@ -117,18 +124,18 @@ public class LedgerQueryController implements BlockchainQueryService { @Override public long getTransactionCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, @PathVariable(name = "blockHash") HashDigest blockHash) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock block = ledger.getBlock(blockHash); - TransactionSet txSet = ledger.getTransactionSet(block); + TransactionQuery txSet = ledger.getTransactionSet(block); return txSet.getTotalCount(); } @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/txs/count") @Override public long getTransactionTotalCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - TransactionSet txSet = ledger.getTransactionSet(block); + TransactionQuery txSet = ledger.getTransactionSet(block); return txSet.getTotalCount(); } @@ -136,87 +143,87 @@ public class LedgerQueryController implements BlockchainQueryService { @Override public long getDataAccountCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, @PathVariable(name = "blockHeight") long height) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock block = ledger.getBlock(height); - DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); - return dataAccountSet.getTotalCount(); + DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); + return dataAccountSet.getTotal(); } @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) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock block = ledger.getBlock(blockHash); - DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); - return dataAccountSet.getTotalCount(); + DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); + return dataAccountSet.getTotal(); } @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts/count") @Override public long getDataAccountTotalCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); - return dataAccountSet.getTotalCount(); + DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); + return dataAccountSet.getTotal(); } @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 height) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock block = ledger.getBlock(height); - UserAccountSet userAccountSet = ledger.getUserAccountSet(block); - return userAccountSet.getTotalCount(); + UserAccountQuery userAccountSet = ledger.getUserAccountSet(block); + return userAccountSet.getTotal(); } @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) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock block = ledger.getBlock(blockHash); - UserAccountSet userAccountSet = ledger.getUserAccountSet(block); - return userAccountSet.getTotalCount(); + UserAccountQuery userAccountSet = ledger.getUserAccountSet(block); + return userAccountSet.getTotal(); } @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/users/count") @Override public long getUserTotalCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - UserAccountSet userAccountSet = ledger.getUserAccountSet(block); - return userAccountSet.getTotalCount(); + UserAccountQuery userAccountSet = ledger.getUserAccountSet(block); + return userAccountSet.getTotal(); } @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 height) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock block = ledger.getBlock(height); - ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); - return contractAccountSet.getTotalCount(); + ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block); + return contractAccountSet.getTotal(); } @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) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock block = ledger.getBlock(blockHash); - ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); - return contractAccountSet.getTotalCount(); + ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block); + return contractAccountSet.getTotal(); } @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts/count") @Override public long getContractTotalCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); - return contractAccountSet.getTotalCount(); + ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block); + return contractAccountSet.getTotal(); } @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/txs") @@ -226,9 +233,9 @@ public class LedgerQueryController implements BlockchainQueryService { @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, @RequestParam(name = "count", required = false, defaultValue = "-1") int count) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock ledgerBlock = ledger.getBlock(blockHeight); - TransactionSet transactionSet = ledger.getTransactionSet(ledgerBlock); + TransactionQuery transactionSet = ledger.getTransactionSet(ledgerBlock); int lastHeightTxTotalNums = 0; if (blockHeight > 0) { @@ -259,10 +266,10 @@ public class LedgerQueryController implements BlockchainQueryService { @PathVariable(name = "blockHash") HashDigest blockHash, @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, @RequestParam(name = "count", required = false, defaultValue = "-1") int count) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock ledgerBlock = ledger.getBlock(blockHash); long height = ledgerBlock.getHeight(); - TransactionSet transactionSet = ledger.getTransactionSet(ledgerBlock); + TransactionQuery transactionSet = ledger.getTransactionSet(ledgerBlock); int lastHeightTxTotalNums = 0; if (height > 0) { @@ -291,9 +298,9 @@ public class LedgerQueryController implements BlockchainQueryService { @Override public LedgerTransaction getTransactionByContentHash(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, @PathVariable(name = "contentHash") HashDigest contentHash) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - TransactionSet txset = ledger.getTransactionSet(block); + TransactionQuery txset = ledger.getTransactionSet(block); return txset.get(contentHash); } @@ -301,30 +308,30 @@ public class LedgerQueryController implements BlockchainQueryService { @Override public TransactionState getTransactionStateByContentHash(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, @PathVariable(name = "contentHash") HashDigest contentHash) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - TransactionSet txset = ledger.getTransactionSet(block); - return txset.getTxState(contentHash); + TransactionQuery txset = ledger.getTransactionSet(block); + return txset.getState(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) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - UserAccountSet userAccountSet = ledger.getUserAccountSet(block); - return userAccountSet.getUser(address); + UserAccountQuery userAccountSet = ledger.getUserAccountSet(block); + return userAccountSet.getAccount(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) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); - return dataAccountSet.getDataAccount(Bytes.fromBase58(address)); + DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); + return dataAccountSet.getAccount(Bytes.fromBase58(address)); } @RequestMapping(method = { RequestMethod.GET, @@ -335,10 +342,10 @@ public class LedgerQueryController implements BlockchainQueryService { if (keys == null || keys.length == 0) { return null; } - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); - DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address)); + DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); + DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address)); KVDataEntry[] entries = new KVDataEntry[keys.length]; long ver; @@ -384,10 +391,10 @@ public class LedgerQueryController implements BlockchainQueryService { throw new ContractException("keys.length!=versions.length!"); } - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); - DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address)); + DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); + DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address)); KVDataEntry[] entries = new KVDataEntry[keys.length]; long ver = -1; @@ -419,10 +426,10 @@ public class LedgerQueryController implements BlockchainQueryService { @RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex, @RequestParam(name = "count", required = false, defaultValue = "-1") int count) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); - DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address)); + DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); + DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address)); int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccount.getDataEntriesTotalCount()); return dataAccount.getDataEntries(pages[0], pages[1]); @@ -433,10 +440,10 @@ public class LedgerQueryController implements BlockchainQueryService { public long getDataEntriesTotalCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, @PathVariable(name = "address") String address) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); - DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address)); + DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); + DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address)); return dataAccount.getDataEntriesTotalCount(); } @@ -445,10 +452,10 @@ public class LedgerQueryController implements BlockchainQueryService { @Override public ContractInfo getContract(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, @PathVariable(name = "address") String address) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); - return contractAccountSet.getContract(Bytes.fromBase58(address)); + ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block); + return contractAccountSet.getAccount(Bytes.fromBase58(address)); } /** @@ -464,11 +471,11 @@ public class LedgerQueryController implements BlockchainQueryService { 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) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - UserAccountSet userAccountSet = ledger.getUserAccountSet(block); - int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) userAccountSet.getTotalCount()); - return userAccountSet.getAccounts(pages[0], pages[1]); + UserAccountQuery userAccountSet = ledger.getUserAccountSet(block); + int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) userAccountSet.getTotal()); + return userAccountSet.getHeaders(pages[0], pages[1]); } /** @@ -484,11 +491,11 @@ public class LedgerQueryController implements BlockchainQueryService { 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) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); - int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccountSet.getTotalCount()); - return dataAccountSet.getAccounts(pages[0], pages[1]); + DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); + int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccountSet.getTotal()); + return dataAccountSet.getHeaders(pages[0], pages[1]); } @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts") @@ -496,11 +503,11 @@ public class LedgerQueryController implements BlockchainQueryService { 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) { - LedgerRepository ledger = ledgerService.getLedger(ledgerHash); + LedgerQuery ledger = ledgerService.getLedger(ledgerHash); LedgerBlock block = ledger.getLatestBlock(); - ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); - int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) contractAccountSet.getTotalCount()); - return contractAccountSet.getAccounts(pages[0], pages[1]); + ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block); + int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) contractAccountSet.getTotal()); + return contractAccountSet.getHeaders(pages[0], pages[1]); } } diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/web/ManagementController.java b/source/peer/src/main/java/com/jd/blockchain/peer/web/ManagementController.java index ac95d361..b21ba8da 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/web/ManagementController.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/web/ManagementController.java @@ -1,278 +1,281 @@ -package com.jd.blockchain.peer.web; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.authentication.AuthenticationServiceException; -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.RestController; - -import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.consensus.ClientIdentification; -import com.jd.blockchain.consensus.ClientIdentifications; -import com.jd.blockchain.consensus.ClientIncomingSettings; -import com.jd.blockchain.consensus.ConsensusProvider; -import com.jd.blockchain.consensus.ConsensusProviders; -import com.jd.blockchain.consensus.ConsensusSettings; -import com.jd.blockchain.consensus.NodeSettings; -import com.jd.blockchain.consensus.action.ActionResponse; -import com.jd.blockchain.consensus.bftsmart.BftsmartConsensusSettings; -import com.jd.blockchain.consensus.bftsmart.BftsmartNodeSettings; -import com.jd.blockchain.consensus.mq.server.MsgQueueMessageDispatcher; -import com.jd.blockchain.consensus.service.MessageHandle; -import com.jd.blockchain.consensus.service.NodeServer; -import com.jd.blockchain.consensus.service.ServerSettings; -import com.jd.blockchain.consensus.service.StateMachineReplicate; -import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.ledger.ContractCodeDeployOperation; -import com.jd.blockchain.ledger.ContractEventSendOperation; -import com.jd.blockchain.ledger.CryptoSetting; -import com.jd.blockchain.ledger.DataAccountKVSetOperation; -import com.jd.blockchain.ledger.DataAccountRegisterOperation; -import com.jd.blockchain.ledger.EndpointRequest; -import com.jd.blockchain.ledger.LedgerBlock; -import com.jd.blockchain.ledger.LedgerInitOperation; -import com.jd.blockchain.ledger.NodeRequest; -import com.jd.blockchain.ledger.Operation; -import com.jd.blockchain.ledger.TransactionContent; -import com.jd.blockchain.ledger.TransactionContentBody; -import com.jd.blockchain.ledger.TransactionRequest; -import com.jd.blockchain.ledger.TransactionResponse; -import com.jd.blockchain.ledger.UserRegisterOperation; -import com.jd.blockchain.ledger.core.LedgerAdminAccount; -import com.jd.blockchain.ledger.core.LedgerManage; -import com.jd.blockchain.ledger.core.LedgerRepository; -import com.jd.blockchain.peer.ConsensusRealm; -import com.jd.blockchain.peer.LedgerBindingConfigAware; -import com.jd.blockchain.peer.PeerManage; -import com.jd.blockchain.setting.GatewayIncomingSetting; -import com.jd.blockchain.setting.LedgerIncomingSetting; -import com.jd.blockchain.storage.service.DbConnection; -import com.jd.blockchain.storage.service.DbConnectionFactory; -import com.jd.blockchain.tools.initializer.LedgerBindingConfig; -import com.jd.blockchain.utils.Bytes; -import com.jd.blockchain.utils.io.ByteArray; -import com.jd.blockchain.web.converters.BinaryMessageConverter; - -/** - * 网关管理服务; - * - * 提供 - * - * @author huanghaiquan - * - */ -@RestController -@RequestMapping(path = "/management") -public class ManagementController implements LedgerBindingConfigAware, PeerManage { - - private static Logger LOGGER = LoggerFactory.getLogger(ManagementController.class); - - public static final String GATEWAY_PUB_EXT_NAME = ".gw.pub"; - - public static final int MIN_GATEWAY_ID = 10000; - - @Autowired - private LedgerManage ledgerManager; - - @Autowired - private DbConnectionFactory connFactory; - - private Map ledgerTxConverters = new ConcurrentHashMap<>(); - - private Map ledgerPeers = new ConcurrentHashMap<>(); - private Map ledgerCryptoSettings = new ConcurrentHashMap<>(); - - - private LedgerBindingConfig config; - - @Autowired - private MessageHandle consensusMessageHandler; - - @Autowired - private StateMachineReplicate consensusStateManager; - - static { - DataContractRegistry.register(LedgerInitOperation.class); - DataContractRegistry.register(LedgerBlock.class); - 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(DataAccountKVSetOperation.class); - DataContractRegistry.register(DataAccountKVSetOperation.KVWriteEntry.class); - - DataContractRegistry.register(Operation.class); - DataContractRegistry.register(ContractCodeDeployOperation.class); - DataContractRegistry.register(ContractEventSendOperation.class); - DataContractRegistry.register(DataAccountRegisterOperation.class); - DataContractRegistry.register(UserRegisterOperation.class); - - DataContractRegistry.register(ActionResponse.class); - - DataContractRegistry.register(BftsmartConsensusSettings.class); - DataContractRegistry.register(BftsmartNodeSettings.class); - - } - - /** - * 接入认证; - * - * @param clientIdentifications - * @return - */ - @RequestMapping(path = "/gateway/auth", method = RequestMethod.POST, consumes = BinaryMessageConverter.CONTENT_TYPE_VALUE) - public GatewayIncomingSetting authenticateGateway(@RequestBody ClientIdentifications clientIdentifications) { - // 去掉不严谨的网关注册和认证逻辑;暂时先放开,不做认证,后续应该在链上注册网关信息,并基于链上的网关信息进行认证; - // by: huanghaiquan; at 2018-09-11 18:34; - // TODO: 实现网关的链上注册与认证机制; - // TODO: 暂时先返回全部账本对应的共识网络配置信息;以账本哈希为 key 标识每一个账本对应的共识域、以及共识配置参数; - if (ledgerPeers.size() == 0 || clientIdentifications == null) { - return null; - } - - ClientIdentification[] identificationArray = clientIdentifications.getClientIdentifications(); - if (identificationArray == null || identificationArray.length <= 0) { - return null; - } - - GatewayIncomingSetting setting = new GatewayIncomingSetting(); - List ledgerIncomingList = new ArrayList(); - - for (HashDigest ledgerHash : ledgerPeers.keySet()) { - - NodeServer peer = ledgerPeers.get(ledgerHash); - - String peerProviderName = peer.getProviderName(); - - ConsensusProvider provider = ConsensusProviders.getProvider(peer.getProviderName()); - - ClientIncomingSettings clientIncomingSettings = null; - for (ClientIdentification authId : identificationArray) { - if (authId.getProviderName() == null || - authId.getProviderName().length() <= 0 || - !authId.getProviderName().equalsIgnoreCase(peerProviderName)) { - continue; - } - try { - clientIncomingSettings = peer.getManageService().authClientIncoming(authId); - break; - } catch (Exception e) { - throw new AuthenticationServiceException(e.getMessage(), e); - } - } - if (clientIncomingSettings == null) { - continue; - } - - byte[] clientIncomingBytes = provider.getSettingsFactory().getIncomingSettingsEncoder() - .encode(clientIncomingSettings); - String base64ClientIncomingSettings = ByteArray.toBase64(clientIncomingBytes); - - LedgerIncomingSetting ledgerIncomingSetting = new LedgerIncomingSetting(); - ledgerIncomingSetting.setLedgerHash(ledgerHash); - ledgerIncomingSetting.setCryptoSetting(ledgerCryptoSettings.get(ledgerHash)); - ledgerIncomingSetting.setClientSetting(base64ClientIncomingSettings); - ledgerIncomingSetting.setProviderName(peerProviderName); - - ledgerIncomingList.add(ledgerIncomingSetting); - - } - setting.setLedgers(ledgerIncomingList.toArray(new LedgerIncomingSetting[ledgerIncomingList.size()])); - return setting; - } - - @Override - public void setConfig(LedgerBindingConfig config) { - // TODO 更新配置;暂时不考虑变化过程的平滑切换问题,后续完善该流程; - // 1、检查账本的数据库配置;a、配置发生变化的账本,建立新的账本库(LedgerRepository)替换旧的实例;b、加入新增加的账本库实例;c、移除已经废弃的账本库; - // 2、完成账本库更改后,读取最新的共识配置信息,更新共识域; - // 3、基于当前共识地址检查共识域;a、启动新增加的共识地址,以及更新相应的共识域关系;c、已经废弃的共识域直接停止; - try { - // remove all existing ledger repositories; - HashDigest[] existingLedgerHashs = ledgerManager.getLedgerHashs(); - for (HashDigest lh : existingLedgerHashs) { - ledgerManager.unregister(lh); - } - HashDigest[] ledgerHashs = config.getLedgerHashs(); - for (HashDigest ledgerHash : ledgerHashs) { - setConfig(config,ledgerHash); - } - - this.config = config; - - } catch (Exception e) { - LOGGER.error("Error occurred on configing LedgerBindingConfig! --" + e.getMessage(), e); - throw new IllegalStateException(e); - } - } - - @Override - public NodeServer setConfig(LedgerBindingConfig config, HashDigest ledgerHash) { - LedgerBindingConfig.BindingConfig bindingConfig = config.getLedger(ledgerHash); - DbConnection dbConnNew = connFactory.connect(bindingConfig.getDbConnection().getUri(), - bindingConfig.getDbConnection().getPassword()); - LedgerRepository ledgerRepository = ledgerManager.register(ledgerHash, dbConnNew.getStorageService()); - - // load provider; - LedgerAdminAccount ledgerAdminAccount = ledgerRepository.getAdminAccount(); - String consensusProvider = ledgerAdminAccount.getSetting().getConsensusProvider(); - ConsensusProvider provider = ConsensusProviders.getProvider(consensusProvider); - // find current node; - Bytes csSettingBytes = ledgerAdminAccount.getSetting().getConsensusSetting(); - ConsensusSettings csSettings = provider.getSettingsFactory().getConsensusSettingsEncoder() - .decode(csSettingBytes.toBytes()); - NodeSettings currentNode = null; - for (NodeSettings nodeSettings : csSettings.getNodes()) { - if (nodeSettings.getAddress().equals(bindingConfig.getParticipant().getAddress())) { - currentNode = nodeSettings; - } - } - if (currentNode == null) { - throw new IllegalArgumentException( - "Current node is not found from the consensus settings of ledger[" + ledgerHash.toBase58() - + "]!"); - } - ServerSettings serverSettings = provider.getServerFactory().buildServerSettings(ledgerHash.toBase58(), csSettings, currentNode.getAddress()); - - NodeServer server = provider.getServerFactory().setupServer(serverSettings, consensusMessageHandler, - consensusStateManager); - ledgerPeers.put(ledgerHash, server); - ledgerCryptoSettings.put(ledgerHash, ledgerAdminAccount.getSetting().getCryptoSetting()); - - return server; - } - - @Override - public ConsensusRealm[] getRealms() { - throw new IllegalStateException("Not implemented!"); - } - - @Override - public void runAllRealms() { - for (NodeServer peer : ledgerPeers.values()) { - runRealm(peer); - } - } - - @Override - public void runRealm(NodeServer nodeServer) { - nodeServer.start(); - } - - @Override - public void closeAllRealms() { - for (NodeServer peer : ledgerPeers.values()) { - peer.stop(); - } - } -} +package com.jd.blockchain.peer.web; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import com.jd.blockchain.ledger.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.AuthenticationServiceException; +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.RestController; + +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.consensus.ClientIdentification; +import com.jd.blockchain.consensus.ClientIdentifications; +import com.jd.blockchain.consensus.ClientIncomingSettings; +import com.jd.blockchain.consensus.ConsensusProvider; +import com.jd.blockchain.consensus.ConsensusProviders; +import com.jd.blockchain.consensus.ConsensusSettings; +import com.jd.blockchain.consensus.NodeSettings; +import com.jd.blockchain.consensus.action.ActionResponse; +import com.jd.blockchain.consensus.bftsmart.BftsmartConsensusSettings; +import com.jd.blockchain.consensus.bftsmart.BftsmartNodeSettings; +import com.jd.blockchain.consensus.mq.server.MsgQueueMessageDispatcher; +import com.jd.blockchain.consensus.service.MessageHandle; +import com.jd.blockchain.consensus.service.NodeServer; +import com.jd.blockchain.consensus.service.ServerSettings; +import com.jd.blockchain.consensus.service.StateMachineReplicate; +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.ledger.LedgerAdminInfo; +import com.jd.blockchain.ledger.core.LedgerAdminDataQuery; +import com.jd.blockchain.ledger.core.LedgerManage; +import com.jd.blockchain.ledger.core.LedgerQuery; +import com.jd.blockchain.peer.ConsensusRealm; +import com.jd.blockchain.peer.LedgerBindingConfigAware; +import com.jd.blockchain.peer.PeerManage; +import com.jd.blockchain.setting.GatewayIncomingSetting; +import com.jd.blockchain.setting.LedgerIncomingSetting; +import com.jd.blockchain.storage.service.DbConnection; +import com.jd.blockchain.storage.service.DbConnectionFactory; +import com.jd.blockchain.tools.initializer.LedgerBindingConfig; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.io.ByteArray; +import com.jd.blockchain.web.converters.BinaryMessageConverter; + +/** + * 网关管理服务; + * + * 提供 + * + * @author huanghaiquan + * + */ +@RestController +@RequestMapping(path = "/management") +public class ManagementController implements LedgerBindingConfigAware, PeerManage { + + private static Logger LOGGER = LoggerFactory.getLogger(ManagementController.class); + + public static final String GATEWAY_PUB_EXT_NAME = ".gw.pub"; + + public static final int MIN_GATEWAY_ID = 10000; + + @Autowired + private LedgerManage ledgerManager; + + @Autowired + private DbConnectionFactory connFactory; + + private Map ledgerTxConverters = new ConcurrentHashMap<>(); + + private Map ledgerPeers = new ConcurrentHashMap<>(); + private Map ledgerCryptoSettings = new ConcurrentHashMap<>(); + + + private LedgerBindingConfig config; + + @Autowired + private MessageHandle consensusMessageHandler; + + @Autowired + private StateMachineReplicate consensusStateManager; + + static { + DataContractRegistry.register(LedgerInitOperation.class); + DataContractRegistry.register(LedgerBlock.class); + 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(DataAccountKVSetOperation.class); + DataContractRegistry.register(DataAccountKVSetOperation.KVWriteEntry.class); + + DataContractRegistry.register(Operation.class); + DataContractRegistry.register(ContractCodeDeployOperation.class); + DataContractRegistry.register(ContractEventSendOperation.class); + DataContractRegistry.register(DataAccountRegisterOperation.class); + DataContractRegistry.register(UserRegisterOperation.class); + DataContractRegistry.register(ParticipantRegisterOperation.class); + DataContractRegistry.register(ParticipantStateUpdateOperation.class); + + DataContractRegistry.register(ActionResponse.class); + + DataContractRegistry.register(BftsmartConsensusSettings.class); + DataContractRegistry.register(BftsmartNodeSettings.class); + + DataContractRegistry.register(LedgerAdminInfo.class); + DataContractRegistry.register(LedgerSettings.class); + + // 注册角色/权限相关接口 + DataContractRegistry.register(RolesConfigureOperation.class); + DataContractRegistry.register(RolesConfigureOperation.RolePrivilegeEntry.class); + DataContractRegistry.register(UserAuthorizeOperation.class); + DataContractRegistry.register(UserAuthorizeOperation.UserRolesEntry.class); + DataContractRegistry.register(PrivilegeSet.class); + DataContractRegistry.register(RoleSet.class); + DataContractRegistry.register(SecurityInitSettings.class); + DataContractRegistry.register(RoleInitSettings.class); + DataContractRegistry.register(UserAuthInitSettings.class); + DataContractRegistry.register(LedgerMetadata_V2.class); + } + + /** + * 接入认证; + * + * @param clientIdentifications + * @return + */ + @RequestMapping(path = "/gateway/auth", method = RequestMethod.POST, consumes = BinaryMessageConverter.CONTENT_TYPE_VALUE) + public GatewayIncomingSetting authenticateGateway(@RequestBody ClientIdentifications clientIdentifications) { + // 去掉不严谨的网关注册和认证逻辑;暂时先放开,不做认证,后续应该在链上注册网关信息,并基于链上的网关信息进行认证; + // by: huanghaiquan; at 2018-09-11 18:34; + // TODO: 实现网关的链上注册与认证机制; + // TODO: 暂时先返回全部账本对应的共识网络配置信息;以账本哈希为 key 标识每一个账本对应的共识域、以及共识配置参数; + if (ledgerPeers.size() == 0 || clientIdentifications == null) { + return null; + } + + ClientIdentification[] identificationArray = clientIdentifications.getClientIdentifications(); + if (identificationArray == null || identificationArray.length <= 0) { + return null; + } + + GatewayIncomingSetting setting = new GatewayIncomingSetting(); + List ledgerIncomingList = new ArrayList(); + + for (HashDigest ledgerHash : ledgerPeers.keySet()) { + + NodeServer peer = ledgerPeers.get(ledgerHash); + + String peerProviderName = peer.getProviderName(); + + ConsensusProvider provider = ConsensusProviders.getProvider(peer.getProviderName()); + + ClientIncomingSettings clientIncomingSettings = null; + for (ClientIdentification authId : identificationArray) { + if (authId.getProviderName() == null || + authId.getProviderName().length() <= 0 || + !authId.getProviderName().equalsIgnoreCase(peerProviderName)) { + continue; + } + try { + clientIncomingSettings = peer.getManageService().authClientIncoming(authId); + break; + } catch (Exception e) { + throw new AuthenticationServiceException(e.getMessage(), e); + } + } + if (clientIncomingSettings == null) { + continue; + } + + byte[] clientIncomingBytes = provider.getSettingsFactory().getIncomingSettingsEncoder() + .encode(clientIncomingSettings); + String base64ClientIncomingSettings = ByteArray.toBase64(clientIncomingBytes); + + LedgerIncomingSetting ledgerIncomingSetting = new LedgerIncomingSetting(); + ledgerIncomingSetting.setLedgerHash(ledgerHash); + ledgerIncomingSetting.setCryptoSetting(ledgerCryptoSettings.get(ledgerHash)); + ledgerIncomingSetting.setClientSetting(base64ClientIncomingSettings); + ledgerIncomingSetting.setProviderName(peerProviderName); + + ledgerIncomingList.add(ledgerIncomingSetting); + + } + setting.setLedgers(ledgerIncomingList.toArray(new LedgerIncomingSetting[ledgerIncomingList.size()])); + return setting; + } + + @Override + public void setConfig(LedgerBindingConfig config) { + // TODO 更新配置;暂时不考虑变化过程的平滑切换问题,后续完善该流程; + // 1、检查账本的数据库配置;a、配置发生变化的账本,建立新的账本库(LedgerRepository)替换旧的实例;b、加入新增加的账本库实例;c、移除已经废弃的账本库; + // 2、完成账本库更改后,读取最新的共识配置信息,更新共识域; + // 3、基于当前共识地址检查共识域;a、启动新增加的共识地址,以及更新相应的共识域关系;c、已经废弃的共识域直接停止; + try { + // remove all existing ledger repositories; + HashDigest[] existingLedgerHashs = ledgerManager.getLedgerHashs(); + for (HashDigest lh : existingLedgerHashs) { + ledgerManager.unregister(lh); + } + HashDigest[] ledgerHashs = config.getLedgerHashs(); + for (HashDigest ledgerHash : ledgerHashs) { + setConfig(config,ledgerHash); + } + + this.config = config; + + } catch (Exception e) { + LOGGER.error("Error occurred on configing LedgerBindingConfig! --" + e.getMessage(), e); + throw new IllegalStateException(e); + } + } + + @Override + public NodeServer setConfig(LedgerBindingConfig config, HashDigest ledgerHash) { + LedgerBindingConfig.BindingConfig bindingConfig = config.getLedger(ledgerHash); + DbConnection dbConnNew = connFactory.connect(bindingConfig.getDbConnection().getUri(), + bindingConfig.getDbConnection().getPassword()); + LedgerQuery ledgerRepository = ledgerManager.register(ledgerHash, dbConnNew.getStorageService()); + + // load provider; + LedgerAdminInfo ledgerAdminAccount = ledgerRepository.getAdminInfo(); + String consensusProvider = ledgerAdminAccount.getSettings().getConsensusProvider(); + ConsensusProvider provider = ConsensusProviders.getProvider(consensusProvider); + // find current node; + Bytes csSettingBytes = ledgerAdminAccount.getSettings().getConsensusSetting(); + ConsensusSettings csSettings = provider.getSettingsFactory().getConsensusSettingsEncoder() + .decode(csSettingBytes.toBytes()); + NodeSettings currentNode = null; + for (NodeSettings nodeSettings : csSettings.getNodes()) { + if (nodeSettings.getAddress().equals(bindingConfig.getParticipant().getAddress())) { + currentNode = nodeSettings; + } + } + if (currentNode == null) { + throw new IllegalArgumentException( + "Current node is not found from the consensus settings of ledger[" + ledgerHash.toBase58() + + "]!"); + } + ServerSettings serverSettings = provider.getServerFactory().buildServerSettings(ledgerHash.toBase58(), csSettings, currentNode.getAddress()); + + NodeServer server = provider.getServerFactory().setupServer(serverSettings, consensusMessageHandler, + consensusStateManager); + ledgerPeers.put(ledgerHash, server); + ledgerCryptoSettings.put(ledgerHash, ledgerAdminAccount.getSettings().getCryptoSetting()); + + return server; + } + + @Override + public ConsensusRealm[] getRealms() { + throw new IllegalStateException("Not implemented!"); + } + + @Override + public void runAllRealms() { + for (NodeServer peer : ledgerPeers.values()) { + runRealm(peer); + } + } + + @Override + public void runRealm(NodeServer nodeServer) { + nodeServer.start(); + } + + @Override + public void closeAllRealms() { + for (NodeServer peer : ledgerPeers.values()) { + peer.stop(); + } + } +} diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/web/PeerTimeTasks.java b/source/peer/src/main/java/com/jd/blockchain/peer/web/PeerTimeTasks.java index 698fb584..dc5c77ec 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/web/PeerTimeTasks.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/web/PeerTimeTasks.java @@ -107,14 +107,17 @@ public class PeerTimeTasks implements ApplicationContextAware { } private LedgerBindingConfig loadLedgerBindingConfig() throws Exception { - LedgerBindingConfig ledgerBindingConfig; + LedgerBindingConfig ledgerBindingConfig = null; ledgerBindConfigFile = PeerServerBooter.ledgerBindConfigFile; LOGGER.debug("Load LedgerBindConfigFile path = {}", ledgerBindConfigFile == null ? "Default" : ledgerBindConfigFile); if (ledgerBindConfigFile == null) { ClassPathResource configResource = new ClassPathResource("ledger-binding.conf"); - InputStream in = configResource.getInputStream(); - ledgerBindingConfig = LedgerBindingConfig.resolve(in); + try (InputStream in = configResource.getInputStream()) { + ledgerBindingConfig = LedgerBindingConfig.resolve(in); + } catch (Exception e) { + throw e; + } } else { File file = new File(ledgerBindConfigFile); ledgerBindingConfig = LedgerBindingConfig.resolve(file); diff --git a/source/peer/src/main/resources/log4j2.xml b/source/peer/src/main/resources/log4j2.xml index b3630520..3f7b9d7a 100644 --- a/source/peer/src/main/resources/log4j2.xml +++ b/source/peer/src/main/resources/log4j2.xml @@ -13,12 +13,12 @@ - + - + @@ -27,8 +27,8 @@ - + @@ -38,8 +38,8 @@ - + @@ -51,7 +51,7 @@ - + diff --git a/source/pom.xml b/source/pom.xml index eab86e33..77e8149b 100644 --- a/source/pom.xml +++ b/source/pom.xml @@ -8,11 +8,7 @@ spring-boot-starter-parent 2.0.6.RELEASE - - - - - + com.jd.blockchain jdchain-root 1.1.0-SNAPSHOT @@ -31,23 +27,23 @@ storage gateway peer + manager sdk tools test deployment - 0.8.1-SNAPSHOT - 0.1.1-SNAPSHOT + 0.0.8.RELEASE 0.7.0.RELEASE - - + 1.0.0-SNAPSHOT + 2.4 3.3.0 1.2.2 1.8.8 + 1.2.60 0.5.35 1.0.18 @@ -82,6 +78,10 @@ + junit junit @@ -115,6 +115,18 @@ ${explorer.version} + + com.jd.blockchain + ump-explorer + ${ump-explorer.version} + + + + commons-io + commons-io + ${commons-io.version} + + junit @@ -125,7 +137,6 @@ org.mockito mockito-core ${mockito.version} - test @@ -170,7 +181,7 @@ com.alibaba fastjson - 1.2.58 + ${fastjson.version} @@ -508,4 +519,4 @@ - \ No newline at end of file + diff --git a/source/runtime/runtime-context/src/main/java/com/jd/blockchain/runtime/RuntimeContext.java b/source/runtime/runtime-context/src/main/java/com/jd/blockchain/runtime/RuntimeContext.java index 569a95a5..ce45fabb 100644 --- a/source/runtime/runtime-context/src/main/java/com/jd/blockchain/runtime/RuntimeContext.java +++ b/source/runtime/runtime-context/src/main/java/com/jd/blockchain/runtime/RuntimeContext.java @@ -2,11 +2,10 @@ package com.jd.blockchain.runtime; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.net.URL; import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.jar.Attributes; import java.util.jar.JarFile; @@ -16,7 +15,7 @@ import com.jd.blockchain.utils.io.RuntimeIOException; public abstract class RuntimeContext { - public static interface Environment{ + public static interface Environment { boolean isProductMode(); @@ -24,6 +23,7 @@ public abstract class RuntimeContext { private static final Object mutex = new Object(); + private static volatile RuntimeContext runtimeContext; public static RuntimeContext get() { @@ -81,7 +81,7 @@ public abstract class RuntimeContext { if (jarFile.isFile()) { FileUtils.deleteFile(jarFile); } else { - throw new IllegalStateException("Code storage confliction! --" + jarFile.getAbsolutePath()); + throw new IllegalStateException("Code storage conflict! --" + jarFile.getAbsolutePath()); } } FileUtils.writeBytes(jarBytes, jarFile); @@ -202,8 +202,78 @@ public abstract class RuntimeContext { @Override protected URLClassLoader createDynamicModuleClassLoader(URL jarURL) { - return new URLClassLoader(new URL[] { jarURL }, RuntimeContext.class.getClassLoader()); + return new ContractURLClassLoader(jarURL, RuntimeContext.class.getClassLoader()); + } + + } + + static class ContractURLClassLoader extends URLClassLoader { + + private static final String BLACK_CONFIG = "black.config"; + + private static final Set BLACK_CLASSES = new HashSet<>(); + + private static final Set BLACK_PACKAGES = new HashSet<>(); + + static { + initBlacks(); + } + + public ContractURLClassLoader(URL contractJarURL, ClassLoader parent) { + super(new URL[] { contractJarURL }, parent); + } + + @Override + public Class loadClass(String name) throws ClassNotFoundException { + if (BLACK_CLASSES.contains(name)) { + throw new IllegalStateException(String.format("Contract cannot use Class [%s]", name)); + } else { + // 判断该包是否是黑名单 + String trimName = name.trim(); + String packageName = trimName.substring(0, trimName.length() - 2); + if (BLACK_PACKAGES.contains(packageName)) { + throw new IllegalStateException(String.format("Contract cannot use Class [%s]", name)); + } + } + return super.loadClass(name); } + private static void initBlacks() { + try { + InputStream inputStream = ContractURLClassLoader.class.getResourceAsStream(File.separator + BLACK_CONFIG); + String text = FileUtils.readText(inputStream); + String[] textArray = text.split("\n"); + for (String setting : textArray) { + // 支持按照逗号分隔 + if (setting == null || setting.length() == 0) { + continue; + } + String[] settingArray = setting.split(","); + for (String set : settingArray) { + String totalClass = set.trim(); + if (totalClass.endsWith("*")) { + // 说明是包,获取具体包名 + String packageName = totalClass.substring(0, totalClass.length() - 2); + BLACK_PACKAGES.add(packageName); + } else { + // 具体的类名,直接放入集合 + BLACK_CLASSES.add(totalClass); + } + } + } + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + + public static void main(String[] args) { + for (String s : BLACK_CLASSES) { + System.out.println(s); + } + + for (String s : BLACK_PACKAGES) { + System.out.println(s); + } + } } } diff --git a/source/runtime/runtime-context/src/main/resources/black.config b/source/runtime/runtime-context/src/main/resources/black.config new file mode 100644 index 00000000..d3353498 --- /dev/null +++ b/source/runtime/runtime-context/src/main/resources/black.config @@ -0,0 +1,2 @@ +java.util.Random, com.jd.blockchain.ledger.BlockchainKeyGenerator +java.io.*, java.nio.*, java.net.*, org.apache.commons.io.* \ No newline at end of file diff --git a/source/runtime/runtime-modular-booter/src/main/java/com/jd/blockchain/runtime/boot/HomeBooter.java b/source/runtime/runtime-modular-booter/src/main/java/com/jd/blockchain/runtime/boot/HomeBooter.java index 6000f04c..1e8329b2 100644 --- a/source/runtime/runtime-modular-booter/src/main/java/com/jd/blockchain/runtime/boot/HomeBooter.java +++ b/source/runtime/runtime-modular-booter/src/main/java/com/jd/blockchain/runtime/boot/HomeBooter.java @@ -91,7 +91,7 @@ public class HomeBooter { runtimeDir.mkdirs(); } - // 以 ExtClassLoader 作为所有创建的ClassLoader的 Parrent; + // 以 ExtClassLoader 作为所有创建的ClassLoader的 Parent; ClassLoader extClassLoader = HomeBooter.class.getClassLoader().getParent(); URL[] libJars = loadClassPaths(libDir); diff --git a/source/runtime/runtime-modular/src/main/java/com/jd/blockchain/runtime/modular/ModularFactory.java b/source/runtime/runtime-modular/src/main/java/com/jd/blockchain/runtime/modular/ModularFactory.java index b9615482..b23dbfe8 100644 --- a/source/runtime/runtime-modular/src/main/java/com/jd/blockchain/runtime/modular/ModularFactory.java +++ b/source/runtime/runtime-modular/src/main/java/com/jd/blockchain/runtime/modular/ModularFactory.java @@ -6,7 +6,7 @@ public class ModularFactory { * 启动系统; */ public static void startSystem(String runtimeDir, boolean productMode, - ClassLoader libClassLoader,String mainClassName, ClassLoader systemClassLoader, String[] args) { + ClassLoader libClassLoader, String mainClassName, ClassLoader systemClassLoader, String[] args) { JarsModule libModule = new JarsModule("LibModule", libClassLoader); diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/LedgerInitSettings.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/LedgerBaseSettings.java similarity index 98% rename from source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/LedgerInitSettings.java rename to source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/LedgerBaseSettings.java index d4f287ab..7cc58594 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/LedgerInitSettings.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/LedgerBaseSettings.java @@ -14,7 +14,7 @@ import com.jd.blockchain.ledger.ParticipantNode; * @since 1.0.0 * */ -public class LedgerInitSettings { +public class LedgerBaseSettings { /** * 账本初始化种子 diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/converters/ClientResolveUtil.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/converters/ClientResolveUtil.java index cbdf723a..e4aea5a0 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/converters/ClientResolveUtil.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/converters/ClientResolveUtil.java @@ -8,19 +8,27 @@ */ package com.jd.blockchain.sdk.converters; +import java.lang.reflect.Field; + +import com.jd.blockchain.ledger.*; +import org.apache.commons.codec.binary.Base64; + import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.jd.blockchain.crypto.CryptoProvider; import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.ledger.*; -import com.jd.blockchain.transaction.*; +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.KVData; +import com.jd.blockchain.transaction.LedgerInitData; +import com.jd.blockchain.transaction.LedgerInitOpTemplate; +import com.jd.blockchain.transaction.UserRegisterOpTemplate; import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.codec.Base58Utils; import com.jd.blockchain.utils.codec.HexUtils; import com.jd.blockchain.utils.io.BytesUtils; -import org.apache.commons.codec.binary.Base64; - -import java.lang.reflect.Field; /** * @@ -31,348 +39,354 @@ import java.lang.reflect.Field; public class ClientResolveUtil { - public static KVDataEntry[] read(KVDataEntry[] kvDataEntries) { - if (kvDataEntries == null || kvDataEntries.length == 0) { - return kvDataEntries; - } - KVDataEntry[] resolveKvDataEntries = new KVDataEntry[kvDataEntries.length]; - // kvDataEntries是代理对象,需要处理 - for (int i = 0; i < kvDataEntries.length; i++) { - KVDataEntry kvDataEntry = kvDataEntries[i]; - String key = kvDataEntry.getKey(); - long version = kvDataEntry.getVersion(); - DataType dataType = kvDataEntry.getType(); - KvData innerKvData = new KvData(key, version, dataType); - Object valueObj = kvDataEntry.getValue(); - switch (dataType) { - case NIL: - break; - case BYTES: - case TEXT: - case JSON: - innerKvData.setValue(valueObj.toString()); - break; - case INT32: - innerKvData.setValue(Integer.parseInt(valueObj.toString())); - break; - case INT64: - innerKvData.setValue(Long.parseLong(valueObj.toString())); - break; - default: - throw new IllegalStateException("Unsupported value type[" + dataType + "] to resolve!"); - } - resolveKvDataEntries[i] = innerKvData; - } - return resolveKvDataEntries; - } - - public static Operation read(Operation operation) { - - try { - // Class - Class clazz = operation.getClass(); - Field field = clazz.getSuperclass().getDeclaredField("h"); - field.setAccessible(true); - Object object = field.get(operation); - if (object instanceof JSONObject) { - JSONObject jsonObject = (JSONObject) object; - if (jsonObject.containsKey("accountID")) { - return convertDataAccountRegisterOperation(jsonObject); - } else if (jsonObject.containsKey("userID")) { - return convertUserRegisterOperation(jsonObject); - } else if (jsonObject.containsKey("contractID")) { - return convertContractCodeDeployOperation(jsonObject); - } else if (jsonObject.containsKey("writeSet")) { - return convertDataAccountKVSetOperation(jsonObject); - } else if (jsonObject.containsKey("initSetting")) { - return convertLedgerInitOperation(jsonObject); - } else if (jsonObject.containsKey("contractAddress")) { - return convertContractEventSendOperation(jsonObject); - } - } - } catch (Exception e) { - throw new RuntimeException(e); - } - - return null; - } - - public static Object readValueByBytesValue(BytesValue bytesValue) { - DataType dataType = bytesValue.getType(); - Bytes saveVal = bytesValue.getValue(); - Object showVal; - switch (dataType) { - case BYTES: - // return hex - showVal = HexUtils.encode(saveVal.toBytes()); - break; - case TEXT: - case JSON: - showVal = saveVal.toUTF8String(); - break; - case INT64: - showVal = BytesUtils.toLong(saveVal.toBytes()); - break; - default: - showVal = HexUtils.encode(saveVal.toBytes()); - break; - } - return showVal; - } - - public static DataAccountRegisterOperation convertDataAccountRegisterOperation(JSONObject jsonObject) { - JSONObject account = jsonObject.getJSONObject("accountID"); - return new DataAccountRegisterOpTemplate(blockchainIdentity(account)); - } - - public static DataAccountKVSetOperation convertDataAccountKVSetOperation(JSONObject jsonObject) { - // 写入集合处理 - JSONArray writeSetObj = jsonObject.getJSONArray("writeSet"); - JSONObject accountAddrObj = jsonObject.getJSONObject("accountAddress"); - String addressBase58 = accountAddrObj.getString("value"); - Bytes address = Bytes.fromBase58(addressBase58); - - DataAccountKVSetOpTemplate kvOperation = new DataAccountKVSetOpTemplate(address); - for (int i = 0; i clazz = operation.getClass(); + Field field = clazz.getSuperclass().getDeclaredField("h"); + field.setAccessible(true); + Object object = field.get(operation); + if (object instanceof JSONObject) { + JSONObject jsonObject = (JSONObject) object; + if (jsonObject.containsKey("accountID")) { + return convertDataAccountRegisterOperation(jsonObject); + } else if (jsonObject.containsKey("userID")) { + return convertUserRegisterOperation(jsonObject); + } else if (jsonObject.containsKey("contractID")) { + return convertContractCodeDeployOperation(jsonObject); + } else if (jsonObject.containsKey("writeSet")) { + return convertDataAccountKVSetOperation(jsonObject); + } else if (jsonObject.containsKey("initSetting")) { + return convertLedgerInitOperation(jsonObject); + } else if (jsonObject.containsKey("contractAddress")) { + return convertContractEventSendOperation(jsonObject); + } + } + } catch (Exception e) { + throw new RuntimeException(e); + } + + return null; + } + + public static Object readValueByBytesValue(BytesValue bytesValue) { + DataType dataType = bytesValue.getType(); + Bytes saveVal = bytesValue.getValue(); + Object showVal; + switch (dataType) { + case BYTES: + // return hex + showVal = HexUtils.encode(saveVal.toBytes()); + break; + case TEXT: + case JSON: + showVal = saveVal.toUTF8String(); + break; + case INT64: + showVal = BytesUtils.toLong(saveVal.toBytes()); + break; + default: + showVal = HexUtils.encode(saveVal.toBytes()); + break; + } + return showVal; + } + + public static DataAccountRegisterOperation convertDataAccountRegisterOperation(JSONObject jsonObject) { + JSONObject account = jsonObject.getJSONObject("accountID"); + return new DataAccountRegisterOpTemplate(blockchainIdentity(account)); + } + + public static DataAccountKVSetOperation convertDataAccountKVSetOperation(JSONObject jsonObject) { + // 写入集合处理 + JSONArray writeSetObj = jsonObject.getJSONArray("writeSet"); + JSONObject accountAddrObj = jsonObject.getJSONObject("accountAddress"); + String addressBase58 = accountAddrObj.getString("value"); + Bytes address = Bytes.fromBase58(addressBase58); + + DataAccountKVSetOpTemplate kvOperation = new DataAccountKVSetOpTemplate(address); + for (int i = 0; i < writeSetObj.size(); i++) { + JSONObject currWriteSetObj = writeSetObj.getJSONObject(i); + long expectedVersion = currWriteSetObj.getLong("expectedVersion"); + JSONObject valueObj = currWriteSetObj.getJSONObject("value"); + String typeStr = valueObj.getString("type"); + // Base58Utils.decode(valueObj.getJSONObject("value").getString("value")) + String realValBase58 = valueObj.getJSONObject("value").getString("value"); + String key = currWriteSetObj.getString("key"); + DataType dataType = DataType.valueOf(typeStr); + BytesValue bytesValue = BytesData.fromType(dataType, Base58Utils.decode(realValBase58)); + KVData kvData = new KVData(key, bytesValue, expectedVersion); + kvOperation.set(kvData); + } + + return kvOperation; + } + + public static LedgerInitOperation convertLedgerInitOperation(JSONObject jsonObject) { + JSONObject legerInitObj = jsonObject.getJSONObject("initSetting"); + LedgerInitData ledgerInitSettingData = new LedgerInitData(); + String ledgerSeedStr = legerInitObj.getString("ledgerSeed"); + + // 种子需要做Base64转换 + ledgerInitSettingData.setLedgerSeed(Base64.decodeBase64(BytesUtils.toBytes(ledgerSeedStr))); + + String consensusProvider = legerInitObj.getString("consensusProvider"); + + ledgerInitSettingData.setConsensusProvider(consensusProvider); + + JSONObject cryptoSettingObj = legerInitObj.getJSONObject("cryptoSetting"); + boolean autoVerifyHash = cryptoSettingObj.getBoolean("autoVerifyHash"); + short hashAlgorithm = cryptoSettingObj.getShort("hashAlgorithm"); + + CryptoConfig cryptoConfig = new CryptoConfig(); + + cryptoConfig.setAutoVerifyHash(autoVerifyHash); + + cryptoConfig.setHashAlgorithm(hashAlgorithm); + + ledgerInitSettingData.setCryptoSetting(cryptoConfig); + + JSONObject consensusSettingsObj = legerInitObj.getJSONObject("consensusSettings"); + Bytes consensusSettings = Bytes.fromBase58(consensusSettingsObj.getString("value")); + + ledgerInitSettingData.setConsensusSettings(consensusSettings); + + JSONArray consensusParticipantsArray = legerInitObj.getJSONArray("consensusParticipants"); + + if (!consensusParticipantsArray.isEmpty()) { + ParticipantNode[] participantNodes = new ParticipantNode[consensusParticipantsArray.size()]; + for (int i = 0; i < consensusParticipantsArray.size(); i++) { + JSONObject currConsensusParticipant = consensusParticipantsArray.getJSONObject(i); + Bytes address = Bytes.fromBase58(currConsensusParticipant.getString("address")); + String name = currConsensusParticipant.getString("name"); + int id = currConsensusParticipant.getInteger("id"); + JSONObject pubKeyObj = currConsensusParticipant.getJSONObject("pubKey"); + String pubKeyBase58 = pubKeyObj.getString("value"); + // 生成ParticipantNode对象 + ParticipantCertData participantCertData = new ParticipantCertData(id, address, name, new PubKey(Bytes.fromBase58(pubKeyBase58).toBytes())); + participantNodes[i] = participantCertData; + } + ledgerInitSettingData.setConsensusParticipants(participantNodes); + } + + return new LedgerInitOpTemplate(ledgerInitSettingData); + } + + public static UserRegisterOperation convertUserRegisterOperation(JSONObject jsonObject) { + JSONObject user = jsonObject.getJSONObject("userID"); + return new UserRegisterOpTemplate(blockchainIdentity(user)); + } + + public static ContractCodeDeployOperation convertContractCodeDeployOperation(JSONObject jsonObject) { + JSONObject contract = jsonObject.getJSONObject("contractID"); + BlockchainIdentityData blockchainIdentity = blockchainIdentity(contract); + + String chainCodeStr = jsonObject.getString("chainCode"); + ContractCodeDeployOpTemplate contractCodeDeployOpTemplate = new ContractCodeDeployOpTemplate(blockchainIdentity, + BytesUtils.toBytes(chainCodeStr)); + return contractCodeDeployOpTemplate; + } + + public static ContractEventSendOperation convertContractEventSendOperation(JSONObject jsonObject) { + JSONObject contractAddressObj = jsonObject.getJSONObject("contractAddress"); + String contractAddress = contractAddressObj.getString("value"); + String argsStr = jsonObject.getString("args"); + String event = jsonObject.getString("event"); + return new ContractEventSendOpTemplate(Bytes.fromBase58(contractAddress), event, + BytesValueEncoding.encodeArray(new Object[] { argsStr }, null)); + } + + private static BlockchainIdentityData blockchainIdentity(JSONObject jsonObject) { + JSONObject addressObj = jsonObject.getJSONObject("address"); + // base58值 + String addressBase58 = addressObj.getString("value"); + Bytes address = Bytes.fromBase58(addressBase58); + + JSONObject pubKeyObj = jsonObject.getJSONObject("pubKey"); + // base58值 + String pubKeyBase58 = pubKeyObj.getString("value"); + PubKey pubKey = new PubKey(Bytes.fromBase58(pubKeyBase58).toBytes()); + + // 生成对应的对象 + return new BlockchainIdentityData(address, pubKey); + } + + public static class CryptoConfig implements CryptoSetting { + + private short hashAlgorithm; + + private boolean autoVerifyHash; + + @Override + public CryptoProvider[] getSupportedProviders() { + return new CryptoProvider[0]; + } + + @Override + public short getHashAlgorithm() { + return hashAlgorithm; + } + + @Override + public boolean getAutoVerifyHash() { + return autoVerifyHash; + } + + public void setHashAlgorithm(short hashAlgorithm) { + this.hashAlgorithm = hashAlgorithm; + } + + public void setAutoVerifyHash(boolean autoVerifyHash) { + this.autoVerifyHash = autoVerifyHash; + } + } + + public static class ParticipantCertData implements ParticipantNode { + private int id; + private Bytes address; + private String name; + private PubKey pubKey; + private ParticipantNodeState participantNodeState; + + public ParticipantCertData() { + } + + public ParticipantCertData(ParticipantNode participantNode) { + this.address = participantNode.getAddress(); + this.name = participantNode.getName(); + this.pubKey = participantNode.getPubKey(); + } + + public ParticipantCertData(int id, Bytes address, String name, PubKey pubKey) { + this.id = id; + this.address = address; + this.name = name; + this.pubKey = pubKey; + this.participantNodeState = participantNodeState; + } + + @Override + public Bytes getAddress() { + return address; + } + + @Override + public String getName() { + return name; + } + + @Override + public PubKey getPubKey() { + return pubKey; + } + + @Override + public int getId() { + return id; + } @Override - public short getHashAlgorithm() { - return hashAlgorithm; + public ParticipantNodeState getParticipantNodeState() { + return participantNodeState; } - @Override - public boolean getAutoVerifyHash() { - return autoVerifyHash; - } + } - public void setHashAlgorithm(short hashAlgorithm) { - this.hashAlgorithm = hashAlgorithm; - } + public static class KvData implements KVDataEntry { - public void setAutoVerifyHash(boolean autoVerifyHash) { - this.autoVerifyHash = autoVerifyHash; - } - } - - public static class ParticipantCertData implements ParticipantNode{ - private int id; - private String address; - private String name; - private PubKey pubKey; - - public ParticipantCertData() { - } - - public ParticipantCertData(ParticipantNode participantNode) { - this.address = participantNode.getAddress(); - this.name = participantNode.getName(); - this.pubKey = participantNode.getPubKey(); - } + private String key; - public ParticipantCertData(int id, String address, String name, PubKey pubKey) { - this.id = id; - this.address = address; - this.name = name; - this.pubKey = pubKey; - } + private long version; - @Override - public String getAddress() { - return address; - } + private DataType dataType; - @Override - public String getName() { - return name; - } + private Object value; - @Override - public PubKey getPubKey() { - return pubKey; - } + public KvData() { + } - public int getId() { - return id; - } + public KvData(String key, long version, DataType dataType) { + this(key, version, dataType, null); + } - public void setId(int id) { - this.id = id; - } - } + public KvData(String key, long version, DataType dataType, Object value) { + this.key = key; + this.version = version; + this.dataType = dataType; + this.value = value; + } - public static class KvData implements KVDataEntry { + public void setKey(String key) { + this.key = key; + } - private String key; + public void setVersion(long version) { + this.version = version; + } - private long version; + public void setDataType(DataType dataType) { + this.dataType = dataType; + } - private DataType dataType; + public void setValue(Object value) { + this.value = value; + } - private Object value; + @Override + public String getKey() { + return key; + } - public KvData() { - } + @Override + public long getVersion() { + return version; + } - public KvData(String key, long version, DataType dataType) { - this(key, version, dataType, null); - } + @Override + public DataType getType() { + return dataType; + } - public KvData(String key, long version, DataType dataType, Object value) { - this.key = key; - this.version = version; - this.dataType = dataType; - this.value = value; - } - - public void setKey(String key) { - this.key = key; - } - - public void setVersion(long version) { - this.version = version; - } - - public void setDataType(DataType dataType) { - this.dataType = dataType; - } - - public void setValue(Object value) { - this.value = value; - } - - @Override - public String getKey() { - return key; - } - - @Override - public long getVersion() { - return version; - } - - @Override - public DataType getType() { - return dataType; - } - - @Override - public Object getValue() { - return value; - } - } + @Override + public Object getValue() { + return value; + } + } } \ No newline at end of file diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java index c850b57a..ff1c9176 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java @@ -1,7 +1,19 @@ package com.jd.blockchain.sdk.proxy; 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.TransactionState; +import com.jd.blockchain.ledger.TransactionTemplate; +import com.jd.blockchain.ledger.UserInfo; import com.jd.blockchain.sdk.BlockchainEventHandle; import com.jd.blockchain.sdk.BlockchainEventListener; import com.jd.blockchain.sdk.BlockchainService; @@ -32,6 +44,11 @@ public abstract class BlockchainServiceProxy implements BlockchainService { public LedgerInfo getLedger(HashDigest ledgerHash) { return getQueryService(ledgerHash).getLedger(ledgerHash); } + + @Override + public LedgerAdminInfo getLedgerAdminInfo(HashDigest ledgerHash) { + return getQueryService(ledgerHash).getLedgerAdminInfo(ledgerHash); + } @Override public ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash) { diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java index 838ad829..ccd5ceec 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java @@ -8,6 +8,8 @@ import com.jd.blockchain.transaction.BlockchainQueryService; import com.jd.blockchain.utils.http.*; import com.jd.blockchain.utils.web.client.WebResponseConverterFactory; import com.jd.blockchain.sdk.converters.HashDigestToStringConverter; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; /** * 作为内部使用的适配接口,用于声明 HTTP 协议的服务请求; @@ -194,6 +196,17 @@ public interface HttpBlockchainQueryService extends BlockchainExtendQueryService @Override long getAdditionalContractCount(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash); + + /** + * 获取账本信息; + * + * @param ledgerHash + * @return 账本对象;如果不存在,则返回 null; + */ + @HttpAction(method=HttpMethod.GET, path="ledgers/{ledgerHash}/admininfo") + @Override + LedgerAdminInfo getLedgerAdminInfo(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash); + /** * 返回指定账本的参与列表 * @@ -204,7 +217,6 @@ public interface HttpBlockchainQueryService extends BlockchainExtendQueryService @Override ParticipantNode[] getConsensusParticipants(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash); - /** * 返回指定账本的元数据 * diff --git a/source/sdk/sdk-client/src/main/java/com/jd/blockchain/sdk/client/GatewayServiceFactory.java b/source/sdk/sdk-client/src/main/java/com/jd/blockchain/sdk/client/GatewayServiceFactory.java index 1fb01269..79a329af 100644 --- a/source/sdk/sdk-client/src/main/java/com/jd/blockchain/sdk/client/GatewayServiceFactory.java +++ b/source/sdk/sdk-client/src/main/java/com/jd/blockchain/sdk/client/GatewayServiceFactory.java @@ -47,6 +47,8 @@ public class GatewayServiceFactory implements BlockchainServiceFactory, Closeabl DataContractRegistry.register(ContractEventSendOperation.class); DataContractRegistry.register(DataAccountRegisterOperation.class); DataContractRegistry.register(UserRegisterOperation.class); + DataContractRegistry.register(ParticipantRegisterOperation.class); + DataContractRegistry.register(ParticipantStateUpdateOperation.class); DataContractRegistry.register(ActionRequest.class); DataContractRegistry.register(ActionResponse.class); @@ -54,6 +56,18 @@ public class GatewayServiceFactory implements BlockchainServiceFactory, Closeabl DataContractRegistry.register(ClientIdentification.class); DataContractRegistry.register(BytesValueList.class); + // 注册角色/权限相关接口 + DataContractRegistry.register(RolesConfigureOperation.class); + DataContractRegistry.register(RolesConfigureOperation.RolePrivilegeEntry.class); + DataContractRegistry.register(UserAuthorizeOperation.class); + DataContractRegistry.register(UserAuthorizeOperation.UserRolesEntry.class); + DataContractRegistry.register(PrivilegeSet.class); + DataContractRegistry.register(RoleSet.class); + DataContractRegistry.register(SecurityInitSettings.class); + DataContractRegistry.register(RoleInitSettings.class); + DataContractRegistry.register(UserAuthInitSettings.class); + DataContractRegistry.register(LedgerMetadata_V2.class); + ByteArrayObjectUtil.init(); } diff --git a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/contract/samples/AssetContract.java b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/contract/samples/AssetContract.java index a6b91415..065e86d2 100644 --- a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/contract/samples/AssetContract.java +++ b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/contract/samples/AssetContract.java @@ -4,7 +4,7 @@ import com.jd.blockchain.contract.Contract; import com.jd.blockchain.contract.ContractEvent; /** - * 示例:一个“资产管理”智能合约; + * 示例:一个“资产管理”智能合约; * * @author huanghaiquan * @@ -15,10 +15,8 @@ public interface AssetContract { /** * 发行资产; * - * @param amount - * 新发行的资产数量; - * @param assetHolderAddress - * 新发行的资产的持有账户; + * @param amount 新发行的资产数量; + * @param assetHolderAddress 新发行的资产的持有账户; */ @ContractEvent(name = "issue-asset") void issue(long amount, String assetHolderAddress); @@ -26,14 +24,12 @@ public interface AssetContract { /** * 转移资产 * - * @param fromAddress - * 转出账户; - * @param toAddress - * 转入账户; - * @param amount - * 转移的资产数额; + * @param fromAddress 转出账户; + * @param toAddress 转入账户; + * @param amount 转移的资产数额; + * @return 返回转出账户的余额; */ @ContractEvent(name = "transfer-asset") - void transfer(String fromAddress, String toAddress, long amount); + long transfer(String fromAddress, String toAddress, long amount); } \ No newline at end of file diff --git a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/contract/samples/AssetContractImpl.java b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/contract/samples/AssetContractImpl.java index 02258ed2..d662378d 100644 --- a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/contract/samples/AssetContractImpl.java +++ b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/contract/samples/AssetContractImpl.java @@ -11,6 +11,7 @@ import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.ledger.BlockchainIdentity; import com.jd.blockchain.ledger.KVDataEntry; import com.jd.blockchain.ledger.KVDataObject; +import com.jd.blockchain.utils.Bytes; /** * 示例:一个“资产管理”智能合约的实现; @@ -48,59 +49,54 @@ public class AssetContractImpl implements EventProcessingAware, AssetContract { // 查询当前值; KVDataEntry[] kvEntries = eventContext.getLedger().getDataEntries(currentLedgerHash(), ASSET_ADDRESS, KEY_TOTAL, assetHolderAddress); - + // 计算资产的发行总数; KVDataObject currTotal = (KVDataObject) kvEntries[0]; long newTotal = currTotal.longValue() + amount; - eventContext.getLedger().dataAccount(ASSET_ADDRESS).setInt64(KEY_TOTAL, newTotal, - currTotal.getVersion()); - + eventContext.getLedger().dataAccount(ASSET_ADDRESS).setInt64(KEY_TOTAL, newTotal, currTotal.getVersion()); + // 分配到持有者账户; KVDataObject holderAmount = (KVDataObject) kvEntries[1]; long newHodlerAmount = holderAmount.longValue() + amount; - eventContext.getLedger().dataAccount(ASSET_ADDRESS).setInt64(assetHolderAddress, newHodlerAmount, - holderAmount.getVersion()).setText("K2", "info2", -1).setText("k3", "info3", 3); - + eventContext.getLedger().dataAccount(ASSET_ADDRESS) + .setInt64(assetHolderAddress, newHodlerAmount, holderAmount.getVersion()).setText("K2", "info2", -1) + .setText("k3", "info3", 3); + } @Override - public void transfer(String fromAddress, String toAddress, long amount) { - // if (amount < 0) { - // throw new ContractError("The amount is negative!"); - // } - // if (amount == 0) { - // return; - // } - // - // //校验“转出账户”是否已签名; - // checkSignerPermission(fromAddress); - // - // // 查询现有的余额; - // Set keys = new HashSet<>(); - // keys.add(fromAddress); - // keys.add(toAddress); - // StateMap origBalances = - // eventContext.getLedger().getStates(currentLedgerHash(), ASSET_ADDRESS, keys); - // KVDataObject fromBalance = origBalances.get(fromAddress); - // KVDataObject toBalance = origBalances.get(toAddress); - // - // //检查是否余额不足; - // if ((fromBalance.longValue() - amount) < 0) { - // throw new ContractError("Insufficient balance!"); - // } - // - // // 把数据的更改写入到账本; - // SimpleStateMap newBalances = new SimpleStateMap(origBalances.getAccount(), - // origBalances.getAccountVersion(), - // origBalances.getStateVersion()); - // KVDataObject newFromBalance = fromBalance.newLong(fromBalance.longValue() - - // amount); - // KVDataObject newToBalance = toBalance.newLong(toBalance.longValue() + - // amount); - // newBalances.setValue(newFromBalance); - // newBalances.setValue(newToBalance); - // - // eventContext.getLedger().updateState(ASSET_ADDRESS).setStates(newBalances); + public long transfer(String fromAddress, String toAddress, long amount) { + if (amount < 0) { + throw new ContractException("The amount is negative!"); + } + if (amount > 20000) { + throw new ContractException("The amount exceeds the limit of 20000!"); + } + + // 校验“转出账户”是否已签名; + checkSignerPermission(fromAddress); + + // 查询现有的余额; + KVDataEntry[] origBalances = eventContext.getLedger().getDataEntries(currentLedgerHash(), ASSET_ADDRESS, + fromAddress, toAddress); + KVDataEntry fromBalanceKV = origBalances[0]; + KVDataEntry toBalanceKV = origBalances[1]; + long fromBalance = fromBalanceKV.getVersion() == -1 ? 0 : (long) fromBalanceKV.getValue(); + long toBalance = toBalanceKV.getVersion() == -1 ? 0 : (long) toBalanceKV.getValue(); + + // 检查是否余额不足; + + if ((fromBalance - amount) < 0) { + throw new ContractException("The balance is insufficient and the transfer failed!"); + } + fromBalance = fromBalance + amount; + toBalance = toBalance + amount; + + // 把数据的更改写入到账本; + eventContext.getLedger().dataAccount(fromAddress).setInt64(ASSET_ADDRESS, fromBalance, fromBalanceKV.getVersion()); + eventContext.getLedger().dataAccount(toAddress).setInt64(ASSET_ADDRESS, toBalance, toBalanceKV.getVersion()); + + return -1; } // ------------------------------------------------------------- @@ -117,9 +113,9 @@ public class AssetContractImpl implements EventProcessingAware, AssetContract { throw new ContractException("Permission Error! -- The requestors is not exactlly being owners!"); } - Map ownerMap = new HashMap<>(); + Map ownerMap = new HashMap<>(); for (BlockchainIdentity o : owners) { - ownerMap.put(o.getAddress().toBase58(), o); + ownerMap.put(o.getAddress(), o); } for (BlockchainIdentity r : requestors) { if (!ownerMap.containsKey(r.getAddress())) { diff --git a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_ConfigureSecurity.java b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_ConfigureSecurity.java new file mode 100644 index 00000000..d7d2170b --- /dev/null +++ b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_ConfigureSecurity.java @@ -0,0 +1,97 @@ +/** + * Copyright: Copyright 2016-2020 JD.COM All Right Reserved + * FileName: com.jd.blockchain.sdk.samples.SDKDemo_RegisterUser + * Author: shaozhuguang + * Department: 区块链研发部 + * Date: 2018/10/18 下午2:00 + * Description: 注册用户 + */ +package com.jd.blockchain.sdk.samples; + +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.crypto.AsymmetricKeypair; +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.PrivKey; +import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.ledger.*; +import com.jd.blockchain.sdk.BlockchainService; +import com.jd.blockchain.sdk.client.GatewayServiceFactory; +import com.jd.blockchain.utils.ConsoleUtils; + +/** + * 注册用户 + * + * @author shaozhuguang + * @create 2018/10/18 + * @since 1.0.0 + */ + +public class SDKDemo_ConfigureSecurity { + public static void main(String[] args) { + + String GATEWAY_IPADDR = "127.0.0.1"; + int GATEWAY_PORT = 8081; + if (args != null && args.length == 2) { + GATEWAY_IPADDR = args[0]; + GATEWAY_PORT = Integer.parseInt(args[1]); + } + + // 注册相关class + DataContractRegistry.register(TransactionContent.class); + DataContractRegistry.register(TransactionContentBody.class); + DataContractRegistry.register(TransactionRequest.class); + DataContractRegistry.register(NodeRequest.class); + DataContractRegistry.register(EndpointRequest.class); + DataContractRegistry.register(TransactionResponse.class); + + PrivKey privKey = SDKDemo_Params.privkey1; + PubKey pubKey = SDKDemo_Params.pubKey1; + + BlockchainKeypair CLIENT_CERT = new BlockchainKeypair(SDKDemo_Params.pubKey0, SDKDemo_Params.privkey0); + + boolean SECURE = false; + GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IPADDR, GATEWAY_PORT, SECURE, + CLIENT_CERT); + BlockchainService service = serviceFactory.getBlockchainService(); + + HashDigest[] ledgerHashs = service.getLedgerHashs(); + // 在本地定义注册账号的 TX; + TransactionTemplate txTemp = service.newTransaction(ledgerHashs[0]); + + // existed signer + AsymmetricKeypair signer = getSigner(); + + BlockchainKeypair user = BlockchainKeyGenerator.getInstance().generate(); + + // 注册 + txTemp.users().register(user.getIdentity()); + + txTemp.security().roles() + .configure("ADMIN") + .enable(LedgerPermission.REGISTER_USER, LedgerPermission.REGISTER_DATA_ACCOUNT) + .enable(TransactionPermission.DIRECT_OPERATION) + .configure("GUEST") + .enable(TransactionPermission.CONTRACT_OPERATION); + + txTemp.security().authorziations() + .forUser(user.getIdentity()) + .authorize("ADMIN", "MANAGER") + .forUser(CLIENT_CERT.getAddress()) + .authorize("GUEST"); + + // TX 准备就绪; + PreparedTransaction prepTx = txTemp.prepare(); + + // 使用私钥进行签名; + prepTx.sign(signer); + + // 提交交易; + TransactionResponse transactionResponse = prepTx.commit(); + + ConsoleUtils.info("register user complete, result is [%s]", transactionResponse.isSuccess()); + } + + private static AsymmetricKeypair getSigner() { + return new BlockchainKeypair(SDKDemo_Params.pubKey1, SDKDemo_Params.privkey1); + } +} \ No newline at end of file diff --git a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_Contract.java b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_Contract.java index 3059aaac..06ec1801 100644 --- a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_Contract.java +++ b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_Contract.java @@ -11,6 +11,8 @@ import com.jd.blockchain.ledger.PreparedTransaction; import com.jd.blockchain.ledger.TransactionTemplate; import com.jd.blockchain.sdk.BlockchainService; import com.jd.blockchain.sdk.client.GatewayServiceFactory; +import com.jd.blockchain.transaction.ContractReturnValue; +import com.jd.blockchain.transaction.LongValueHolder; import com.jd.blockchain.utils.io.ByteArray; import com.jd.blockchain.utils.net.NetworkAddress; import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils; @@ -49,8 +51,6 @@ public class SDKDemo_Contract { BlockchainService service = serviceFactory.getBlockchainService(); HashDigest ledgerHash = getLedgerHash(); - // 发起交易; - TransactionTemplate txTemp = service.newTransaction(ledgerHash); // -------------------------------------- // 一个贸易账户,贸易结算后的利润将通过一个合约账户来执行利润分配; @@ -71,25 +71,26 @@ public class SDKDemo_Contract { // 备注信息; Remark remark = new Remark(); String remarkJSON = JSONSerializeUtils.serializeToJSON(remark); - + + // 发起交易; + TransactionTemplate txTemp = service.newTransaction(ledgerHash); + AssetContract assetContract = txTemp.contract(profitDistributionContract, AssetContract.class); assetContract.issue(1000, receiptorAccount1); - assetContract.transfer(receiptorAccount1, receiptorAccount2, 600); - -// assetContract. - - // -------------------------------------- + LongValueHolder balance = ContractReturnValue.decode(assetContract.transfer(receiptorAccount1, receiptorAccount2, 600)); // TX 准备就绪; PreparedTransaction prepTx = txTemp.prepare(); - String txHash = ByteArray.toBase64(prepTx.getHash().toBytes()); // 使用私钥进行签名; - AsymmetricKeypair keyPair = getSponsorKey(); + AsymmetricKeypair keyPair = getSponsorKey();//示例方法,取发起人的私钥; prepTx.sign(keyPair); // 提交交易; prepTx.commit(); + + //获取返回值; + System.out.println("balance = " + balance.get()); } private static HashDigest getLedgerHash() { diff --git a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_Params.java b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_Params.java index 491abef8..cc2c5bb2 100644 --- a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_Params.java +++ b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_Params.java @@ -8,9 +8,9 @@ */ package com.jd.blockchain.sdk.samples; +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; /** * @@ -33,13 +33,13 @@ public class SDKDemo_Params { "177gk2FpjufgEon92mf2oRRFXDBZkRy8SkFci7Jxc5pApZEJz3oeCoxieWatDD3Xg7i1QEN", "177gjvv7qvfCAXroFezSn23UFXLVLFofKS3y6DXkJ2DwVWS4LcRNtxRgiqWmQEeWNz4KQ3J" }; - public static PrivKey privkey0 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[0], PASSWORD); - public static PrivKey privkey1 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[1], PASSWORD); - public static PrivKey privkey2 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[2], PASSWORD); - public static PrivKey privkey3 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[3], PASSWORD); + public static PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[0], PASSWORD); + public static PrivKey privkey1 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[1], PASSWORD); + public static PrivKey privkey2 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[2], PASSWORD); + public static PrivKey privkey3 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[3], PASSWORD); - public static PubKey pubKey0 = KeyGenCommand.decodePubKey(PUB_KEYS[0]); - public static PubKey pubKey1 = KeyGenCommand.decodePubKey(PUB_KEYS[1]); - public static PubKey pubKey2 = KeyGenCommand.decodePubKey(PUB_KEYS[2]); - public static PubKey pubKey3 = KeyGenCommand.decodePubKey(PUB_KEYS[3]); + public static PubKey pubKey0 = KeyGenUtils.decodePubKey(PUB_KEYS[0]); + public static PubKey pubKey1 = KeyGenUtils.decodePubKey(PUB_KEYS[1]); + public static PubKey pubKey2 = KeyGenUtils.decodePubKey(PUB_KEYS[2]); + public static PubKey pubKey3 = KeyGenUtils.decodePubKey(PUB_KEYS[3]); } \ No newline at end of file diff --git a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_RegisterUser.java b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_RegisterUser.java index a1362a39..778e5851 100644 --- a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_RegisterUser.java +++ b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_RegisterUser.java @@ -20,60 +20,67 @@ import com.jd.blockchain.utils.ConsoleUtils; /** * 注册用户 + * * @author shaozhuguang * @create 2018/10/18 * @since 1.0.0 */ public class SDKDemo_RegisterUser { - public static void main(String[] args) { + public static void main(String[] args) { - String GATEWAY_IPADDR = "127.0.0.1"; - int GATEWAY_PORT = 8081; - if (args != null && args.length == 2) { - GATEWAY_IPADDR = args[0]; - GATEWAY_PORT = Integer.parseInt(args[1]); - } + String GATEWAY_IPADDR = "127.0.0.1"; + int GATEWAY_PORT = 8081; + if (args != null && args.length == 2) { + GATEWAY_IPADDR = args[0]; + GATEWAY_PORT = Integer.parseInt(args[1]); + } - // 注册相关class - DataContractRegistry.register(TransactionContent.class); - DataContractRegistry.register(TransactionContentBody.class); - DataContractRegistry.register(TransactionRequest.class); - DataContractRegistry.register(NodeRequest.class); - DataContractRegistry.register(EndpointRequest.class); - DataContractRegistry.register(TransactionResponse.class); + // 注册相关class + DataContractRegistry.register(TransactionContent.class); + DataContractRegistry.register(TransactionContentBody.class); + DataContractRegistry.register(TransactionRequest.class); + DataContractRegistry.register(NodeRequest.class); + DataContractRegistry.register(EndpointRequest.class); + DataContractRegistry.register(TransactionResponse.class); - PrivKey privKey = SDKDemo_Params.privkey1; - PubKey pubKey = SDKDemo_Params.pubKey1; + PrivKey privKey = SDKDemo_Params.privkey1; + PubKey pubKey = SDKDemo_Params.pubKey1; - BlockchainKeypair CLIENT_CERT = new BlockchainKeypair(SDKDemo_Params.pubKey0, SDKDemo_Params.privkey0); + BlockchainKeypair CLIENT_CERT = new BlockchainKeypair(SDKDemo_Params.pubKey0, SDKDemo_Params.privkey0); - boolean SECURE = false; - GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IPADDR, GATEWAY_PORT, SECURE, - CLIENT_CERT); - BlockchainService service = serviceFactory.getBlockchainService(); + boolean SECURE = false; + GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IPADDR, GATEWAY_PORT, SECURE, + CLIENT_CERT); + BlockchainService service = serviceFactory.getBlockchainService(); - HashDigest[] ledgerHashs = service.getLedgerHashs(); - // 在本地定义注册账号的 TX; - TransactionTemplate txTemp = service.newTransaction(ledgerHashs[0]); + HashDigest[] ledgerHashs = service.getLedgerHashs(); + // 在本地定义注册账号的 TX; + TransactionTemplate txTemp = service.newTransaction(ledgerHashs[0]); - //existed signer - AsymmetricKeypair keyPair = new BlockchainKeypair(pubKey, privKey); + // existed signer + AsymmetricKeypair keyPair = new BlockchainKeypair(pubKey, privKey); - BlockchainKeypair user = BlockchainKeyGenerator.getInstance().generate(); + BlockchainKeypair user = BlockchainKeyGenerator.getInstance().generate(); - // 注册 - txTemp.users().register(user.getIdentity()); + // 注册 + txTemp.users().register(user.getIdentity()); - // TX 准备就绪; - PreparedTransaction prepTx = txTemp.prepare(); + // 定义角色权限; + txTemp.security().roles().configure("MANAGER") + .enable(LedgerPermission.REGISTER_USER, LedgerPermission.REGISTER_DATA_ACCOUNT) + .enable(TransactionPermission.CONTRACT_OPERATION); + txTemp.security().authorziations().forUser(user.getIdentity()).authorize("MANAGER"); - // 使用私钥进行签名; - prepTx.sign(keyPair); + // TX 准备就绪; + PreparedTransaction prepTx = txTemp.prepare(); - // 提交交易; - TransactionResponse transactionResponse = prepTx.commit(); + // 使用私钥进行签名; + prepTx.sign(keyPair); - ConsoleUtils.info("register user complete, result is [%s]", transactionResponse.isSuccess()); - } + // 提交交易; + TransactionResponse transactionResponse = prepTx.commit(); + + ConsoleUtils.info("register user complete, result is [%s]", transactionResponse.isSuccess()); + } } \ No newline at end of file diff --git a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Base_Demo.java b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Base_Demo.java index bbd4ed71..c2a7ce73 100644 --- a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Base_Demo.java +++ b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Base_Demo.java @@ -1,6 +1,7 @@ package com.jd.blockchain.sdk.samples; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.ledger.BlockchainKeypair; @@ -9,7 +10,6 @@ import com.jd.blockchain.ledger.TransactionResponse; import com.jd.blockchain.ledger.TransactionTemplate; import com.jd.blockchain.sdk.BlockchainService; import com.jd.blockchain.sdk.client.GatewayServiceFactory; -import com.jd.blockchain.tools.keygen.KeyGenCommand; public abstract class SDK_Base_Demo { @@ -25,9 +25,9 @@ public abstract class SDK_Base_Demo { public void init() { // 生成连接网关的账号 - PrivKey privKey = KeyGenCommand.decodePrivKeyWithRawPassword(SDKDemo_Constant.PRIV_KEYS[0], SDKDemo_Constant.PASSWORD); + PrivKey privKey = KeyGenUtils.decodePrivKeyWithRawPassword(SDKDemo_Constant.PRIV_KEYS[0], SDKDemo_Constant.PASSWORD); - PubKey pubKey = KeyGenCommand.decodePubKey(SDKDemo_Constant.PUB_KEYS[0]); + PubKey pubKey = KeyGenUtils.decodePubKey(SDKDemo_Constant.PUB_KEYS[0]); adminKey = new BlockchainKeypair(pubKey, privKey); diff --git a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Contract_Check_Demo.java b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Contract_Check_Demo.java new file mode 100644 index 00000000..7d521776 --- /dev/null +++ b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Contract_Check_Demo.java @@ -0,0 +1,67 @@ +package com.jd.blockchain.sdk.samples; + +import com.jd.blockchain.contract.TransferContract; +import com.jd.blockchain.ledger.*; +import com.jd.blockchain.transaction.GenericValueHolder; +import com.jd.blockchain.utils.Bytes; +import com.jd.chain.contracts.ContractTestInf; + +import static com.jd.blockchain.sdk.samples.SDKDemo_Constant.readChainCodes; +import static com.jd.blockchain.transaction.ContractReturnValue.decode; + +public class SDK_Contract_Check_Demo extends SDK_Base_Demo { + + public static void main(String[] args) { + new SDK_Contract_Check_Demo().executeContract(); + } + + public void executeContract() { + + // 发布jar包 + // 定义交易模板 + TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); + + // 将jar包转换为二进制数据 + byte[] contractCode = readChainCodes("contract-jdchain.jar"); + + // 生成一个合约账号 + BlockchainKeypair contractDeployKey = BlockchainKeyGenerator.getInstance().generate(); + + // 生成发布合约操作 + txTpl.contracts().deploy(contractDeployKey.getIdentity(), contractCode); + + // 生成预发布交易; + PreparedTransaction ptx = txTpl.prepare(); + + // 对交易进行签名 + ptx.sign(adminKey); + + // 提交并等待共识返回; + TransactionResponse txResp = ptx.commit(); + + // 获取合约地址 + Bytes contractAddress = contractDeployKey.getAddress(); + + // 打印交易返回信息 + System.out.printf("Tx[%s] -> BlockHeight = %s, BlockHash = %s, isSuccess = %s, ExecutionState = %s \r\n", + txResp.getContentHash().toBase58(), txResp.getBlockHeight(), txResp.getBlockHash().toBase58(), + txResp.isSuccess(), txResp.getExecutionState()); + + // 打印合约地址 + System.out.printf("ContractAddress = %s \r\n", contractAddress.toBase58()); + + // 执行合约 + exeContract(contractAddress); + } + + private void exeContract(Bytes contractAddress) { + TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); + ContractTestInf contract = txTpl.contract(contractAddress, ContractTestInf.class); + GenericValueHolder result = decode(contract.randomChars(1024)); + commit(txTpl); + String random = result.get(); + System.out.println(random); + } + + +} diff --git a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_RoleConfig_Demo.java b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_RoleConfig_Demo.java new file mode 100644 index 00000000..6b768a82 --- /dev/null +++ b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_RoleConfig_Demo.java @@ -0,0 +1,26 @@ +package com.jd.blockchain.sdk.samples; + +import com.jd.blockchain.ledger.*; + +public class SDK_RoleConfig_Demo extends SDK_Base_Demo { + + public static void main(String[] args) { + new SDK_RoleConfig_Demo().executeRoleConfig(); + } + + public void executeRoleConfig() { + + // 定义交易模板 + TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); + + // 新增加一个角色 + + txTpl.security().roles().configure("MyRole") + .enable(LedgerPermission.APPROVE_TX, LedgerPermission.CONSENSUS_TX) + .disable(TransactionPermission.CONTRACT_OPERATION); + TransactionResponse txResp = commit(txTpl); + + System.out.println(txResp.isSuccess()); + + } +} diff --git a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Threads_KvInsert_Demo.java b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Threads_KvInsert_Demo.java new file mode 100644 index 00000000..c4924af3 --- /dev/null +++ b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Threads_KvInsert_Demo.java @@ -0,0 +1,56 @@ +package com.jd.blockchain.sdk.samples; + +import com.jd.blockchain.ledger.*; +import com.jd.blockchain.utils.codec.Base58Utils; + +import java.util.Random; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class SDK_Threads_KvInsert_Demo extends SDK_Base_Demo { + + public static void main(String[] args) throws Exception { + new SDK_Threads_KvInsert_Demo().executeThreadsInsert(); + } + + public void executeThreadsInsert() throws Exception { + + final int MAX = 30; + + final String dataAddress = "LdeNqP4S88t1YjkGQaCGbX95ygD6hA2B6yjp6"; + + ExecutorService threadPool = Executors.newFixedThreadPool(50); + + final CountDownLatch latch = new CountDownLatch(MAX); + + for (int i = 0; i < MAX; i++) { + + threadPool.execute(() -> { + TransactionTemplate txTemp = blockchainService.newTransaction(ledgerHash); + + String key = System.currentTimeMillis() + "-" + + System.nanoTime() + "-" + + new Random(Thread.currentThread().getId()).nextInt(1024); + + txTemp.dataAccount(dataAddress).setText(key,"value1",-1); + + // TX 准备就绪 + PreparedTransaction prepTx = txTemp.prepare(); + prepTx.sign(adminKey); + + // 提交交易; + TransactionResponse response = prepTx.commit(); + + System.out.printf("Key = %s, Result = %s \r\n", key, response.isSuccess()); + + latch.countDown(); + + }); + } + + latch.await(); + System.out.println("It is Over !!!"); + System.exit(0); + } +} diff --git a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_User2Role_Demo.java b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_User2Role_Demo.java new file mode 100644 index 00000000..5f18f6aa --- /dev/null +++ b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_User2Role_Demo.java @@ -0,0 +1,44 @@ +package com.jd.blockchain.sdk.samples; + +import com.jd.blockchain.ledger.*; +import com.jd.blockchain.utils.Bytes; + +public class SDK_User2Role_Demo extends SDK_Base_Demo { + + public static void main(String[] args) { + new SDK_User2Role_Demo().executeUser2Role(); + } + + public void executeUser2Role() { + + // 定义交易模板 + TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); + + // 注册一个用户 + BlockchainKeypair user = createUser(); + + Bytes userAddress = user.getAddress(); + // 获取数据账户地址 + System.out.printf("UserAddress = %s \r\n", userAddress.toBase58()); + + + txTpl.security().authorziations().forUser(user.getIdentity()) + .authorize("MYROLE") + .setPolicy(RolesPolicy.UNION) + .unauthorize("MYROLE"); + TransactionResponse txResp = commit(txTpl); + + System.out.println(txResp.isSuccess()); + + } + + private BlockchainKeypair createUser() { + // 首先注册一个数据账户 + BlockchainKeypair newUser = BlockchainKeyGenerator.getInstance().generate(); + + TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); + txTpl.users().register(newUser.getIdentity()); + commit(txTpl); + return newUser; + } +} diff --git a/source/sdk/sdk-samples/src/main/java/com/jd/chain/contracts/ContractTestInf.java b/source/sdk/sdk-samples/src/main/java/com/jd/chain/contracts/ContractTestInf.java new file mode 100644 index 00000000..7e5d362a --- /dev/null +++ b/source/sdk/sdk-samples/src/main/java/com/jd/chain/contracts/ContractTestInf.java @@ -0,0 +1,14 @@ +package com.jd.chain.contracts; + +import com.jd.blockchain.contract.Contract; +import com.jd.blockchain.contract.ContractEvent; + +@Contract +public interface ContractTestInf { + + @ContractEvent(name = "print") + void print(String name, int age); + + @ContractEvent(name = "random") + String randomChars(int max); +} \ No newline at end of file diff --git a/source/sdk/sdk-samples/src/main/resources/contract-jdchain.jar b/source/sdk/sdk-samples/src/main/resources/contract-jdchain.jar new file mode 100644 index 00000000..b9e41e1d Binary files /dev/null and b/source/sdk/sdk-samples/src/main/resources/contract-jdchain.jar differ diff --git a/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDKDemo_Contract_Test_.java b/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDKDemo_Contract_Test_.java index 2f7755da..4390c48c 100644 --- a/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDKDemo_Contract_Test_.java +++ b/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDKDemo_Contract_Test_.java @@ -8,6 +8,7 @@ import org.junit.Test; import com.jd.blockchain.contract.TransferContract; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.ledger.BlockchainKeyGenerator; @@ -18,9 +19,8 @@ import com.jd.blockchain.ledger.TransactionTemplate; import com.jd.blockchain.sdk.BlockchainService; import com.jd.blockchain.sdk.client.GatewayServiceFactory; import com.jd.blockchain.sdk.samples.SDKDemo_Constant; -import com.jd.blockchain.tools.keygen.KeyGenCommand; -import com.jd.blockchain.transaction.LongValueHolder; import com.jd.blockchain.transaction.GenericValueHolder; +import com.jd.blockchain.transaction.LongValueHolder; import com.jd.blockchain.utils.Bytes; public class SDKDemo_Contract_Test_ { @@ -34,10 +34,10 @@ public class SDKDemo_Contract_Test_ { @Before public void init() { // 生成连接网关的账号 - PrivKey privKey = KeyGenCommand.decodePrivKeyWithRawPassword(SDKDemo_Constant.PRIV_KEYS[0], + PrivKey privKey = KeyGenUtils.decodePrivKeyWithRawPassword(SDKDemo_Constant.PRIV_KEYS[0], SDKDemo_Constant.PASSWORD); - PubKey pubKey = KeyGenCommand.decodePubKey(SDKDemo_Constant.PUB_KEYS[0]); + PubKey pubKey = KeyGenUtils.decodePubKey(SDKDemo_Constant.PUB_KEYS[0]); adminKey = new BlockchainKeypair(pubKey, privKey); diff --git a/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_KeyPair_Para.java b/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_KeyPair_Para.java index 450e5ff4..706cd370 100644 --- a/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_KeyPair_Para.java +++ b/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_KeyPair_Para.java @@ -1,8 +1,8 @@ package test.com.jd.blockchain.sdk.test; +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; /** * Created by zhangshuang3 on 2018/10/17. @@ -21,14 +21,14 @@ public class SDK_GateWay_KeyPair_Para { "177gjtwLgmSx5v1hFb46ijh7L9kdbKUpJYqdKVf9afiEmAuLgo8Rck9yu5UuUcHknWJuWaF", "177gk1pudweTq5zgJTh8y3ENCTwtSFsKyX7YnpuKPo7rKgCkCBXVXh5z2syaTCPEMbuWRns" }; - public static PrivKey privkey0 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[0], PASSWORD); - public static PrivKey privkey1 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[1], PASSWORD); - public static PrivKey privkey2 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[2], PASSWORD); - public static PrivKey privkey3 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[3], PASSWORD); + public static PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[0], PASSWORD); + public static PrivKey privkey1 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[1], PASSWORD); + public static PrivKey privkey2 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[2], PASSWORD); + public static PrivKey privkey3 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[3], PASSWORD); - public static PubKey pubKey0 = KeyGenCommand.decodePubKey(PUB_KEYS[0]); - public static PubKey pubKey1 = KeyGenCommand.decodePubKey(PUB_KEYS[1]); - public static PubKey pubKey2 = KeyGenCommand.decodePubKey(PUB_KEYS[2]); - public static PubKey pubKey3 = KeyGenCommand.decodePubKey(PUB_KEYS[3]); + public static PubKey pubKey0 = KeyGenUtils.decodePubKey(PUB_KEYS[0]); + public static PubKey pubKey1 = KeyGenUtils.decodePubKey(PUB_KEYS[1]); + public static PubKey pubKey2 = KeyGenUtils.decodePubKey(PUB_KEYS[2]); + public static PubKey pubKey3 = KeyGenUtils.decodePubKey(PUB_KEYS[3]); } diff --git a/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Participant_Regist_Test_.java b/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Participant_Regist_Test_.java new file mode 100644 index 00000000..77157f0d --- /dev/null +++ b/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Participant_Regist_Test_.java @@ -0,0 +1,99 @@ +package test.com.jd.blockchain.sdk.test; + +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.crypto.*; +import com.jd.blockchain.ledger.*; +import com.jd.blockchain.sdk.BlockchainService; +import com.jd.blockchain.sdk.client.GatewayServiceFactory; +import com.jd.blockchain.sdk.samples.SDKDemo_Constant; +import com.jd.blockchain.tools.keygen.KeyGenCommand; +import com.jd.blockchain.utils.net.NetworkAddress; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +/** + * 注册参与方测试 + * @author zhangshuang + * @create 2019/7/4 + * @since 1.0.0 + */ + +public class SDK_GateWay_Participant_Regist_Test_ { + + private PrivKey privKey; + private PubKey pubKey; + + private BlockchainKeypair CLIENT_CERT = null; + + private String GATEWAY_IPADDR = null; + + private int GATEWAY_PORT; + + private boolean SECURE; + + private BlockchainService service; + + //根据密码工具产生的公私钥 + static String PUB = "3snPdw7i7PkdgqiGX7GbZuFSi1cwZn7vtjw4vifb1YoXgr9k6Kfmis"; + String PRIV = "177gjtZu8w1phqHFVNiFhA35cfimXmP6VuqrBFhfbXBWK8s4TRwro2tnpffwP1Emwr6SMN6"; + + @Before + public void init() { + + privKey = SDK_GateWay_KeyPair_Para.privkey1; + pubKey = SDK_GateWay_KeyPair_Para.pubKey1; + + CLIENT_CERT = new BlockchainKeypair(SDK_GateWay_KeyPair_Para.pubKey0, SDK_GateWay_KeyPair_Para.privkey0); + GATEWAY_IPADDR = "127.0.0.1"; + GATEWAY_PORT = 11000; + SECURE = false; + GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IPADDR, GATEWAY_PORT, SECURE, + CLIENT_CERT); + service = serviceFactory.getBlockchainService(); + + 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(ParticipantRegisterOperation.class); + DataContractRegistry.register(ParticipantStateUpdateOperation.class); + } + + @Test + public void registerParticipant_Test() { + HashDigest[] ledgerHashs = service.getLedgerHashs(); + // 在本地定义注册账号的 TX; + TransactionTemplate txTemp = service.newTransaction(ledgerHashs[0]); + + //existed signer + AsymmetricKeypair keyPair = new BlockchainKeypair(pubKey, privKey); + + PrivKey privKey = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV, SDKDemo_Constant.PASSWORD); + + PubKey pubKey = KeyGenUtils.decodePubKey(PUB); + + System.out.println("Address = "+AddressEncoding.generateAddress(pubKey)); + + BlockchainKeypair user = new BlockchainKeypair(pubKey, privKey); + + NetworkAddress networkAddress = new NetworkAddress("127.0.0.1", 20000); + + // 注册参与方 + txTemp.participants().register("Peer4", user.getIdentity(), networkAddress); + + // TX 准备就绪; + PreparedTransaction prepTx = txTemp.prepare(); + + // 使用私钥进行签名; + prepTx.sign(keyPair); + + // 提交交易; + TransactionResponse transactionResponse = prepTx.commit(); + assertTrue(transactionResponse.isSuccess()); + + } +} diff --git a/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Participant_State_Update_Test_.java b/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Participant_State_Update_Test_.java new file mode 100644 index 00000000..4fb229ce --- /dev/null +++ b/source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Participant_State_Update_Test_.java @@ -0,0 +1,97 @@ +package test.com.jd.blockchain.sdk.test; + +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.crypto.*; +import com.jd.blockchain.ledger.*; +import com.jd.blockchain.sdk.BlockchainService; +import com.jd.blockchain.sdk.client.GatewayServiceFactory; +import com.jd.blockchain.sdk.samples.SDKDemo_Constant; +import com.jd.blockchain.tools.keygen.KeyGenCommand; +import com.jd.blockchain.utils.net.NetworkAddress; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +/** + * 参与方状态更新测试 + * @author zhangshuang + * @create 2019/7/18 + * @since 1.0.0 + */ +public class SDK_GateWay_Participant_State_Update_Test_ { + private PrivKey privKey; + private PubKey pubKey; + + private BlockchainKeypair CLIENT_CERT = null; + + private String GATEWAY_IPADDR = null; + + private int GATEWAY_PORT; + + private boolean SECURE; + + private BlockchainService service; + + //根据密码工具产生的公私钥 + static String PUB = "3snPdw7i7PkdgqiGX7GbZuFSi1cwZn7vtjw4vifb1YoXgr9k6Kfmis"; + String PRIV = "177gjtZu8w1phqHFVNiFhA35cfimXmP6VuqrBFhfbXBWK8s4TRwro2tnpffwP1Emwr6SMN6"; + + @Before + public void init() { + + privKey = SDK_GateWay_KeyPair_Para.privkey1; + pubKey = SDK_GateWay_KeyPair_Para.pubKey1; + + CLIENT_CERT = new BlockchainKeypair(SDK_GateWay_KeyPair_Para.pubKey0, SDK_GateWay_KeyPair_Para.privkey0); + GATEWAY_IPADDR = "127.0.0.1"; + GATEWAY_PORT = 11000; + SECURE = false; + GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IPADDR, GATEWAY_PORT, SECURE, + CLIENT_CERT); + service = serviceFactory.getBlockchainService(); + + 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(ParticipantRegisterOperation.class); + DataContractRegistry.register(ParticipantStateUpdateOperation.class); + DataContractRegistry.register(ParticipantStateUpdateOperation.class); + } + + @Test + public void updateParticipantState_Test() { + HashDigest[] ledgerHashs = service.getLedgerHashs(); + // 在本地定义注册账号的 TX; + TransactionTemplate txTemp = service.newTransaction(ledgerHashs[0]); + + //existed signer + AsymmetricKeypair keyPair = new BlockchainKeypair(pubKey, privKey); + + PrivKey privKey = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV, SDKDemo_Constant.PASSWORD); + + PubKey pubKey = KeyGenUtils.decodePubKey(PUB); + + System.out.println("Address = "+AddressEncoding.generateAddress(pubKey)); + + BlockchainKeypair user = new BlockchainKeypair(pubKey, privKey); + + NetworkAddress networkAddress = new NetworkAddress("127.0.0.1", 20000); + + txTemp.states().update(user.getIdentity(),networkAddress, ParticipantNodeState.ACTIVED); + + // TX 准备就绪; + PreparedTransaction prepTx = txTemp.prepare(); + + // 使用私钥进行签名; + prepTx.sign(keyPair); + + // 提交交易; + TransactionResponse transactionResponse = prepTx.commit(); + assertTrue(transactionResponse.isSuccess()); + + } +} diff --git a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/MemoryKVStorage.java b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/MemoryKVStorage.java index 65920967..0c2192a3 100644 --- a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/MemoryKVStorage.java +++ b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/MemoryKVStorage.java @@ -12,11 +12,6 @@ import com.jd.blockchain.utils.io.BytesMap; public class MemoryKVStorage implements ExPolicyKVStorage, VersioningKVStorage, KVStorageService, BytesMap { -// private Set keys = new HashSet<>(); - -// private Set keys = Collections.synchronizedSet(new HashSet<>()); - -// private Map storageMap = new ConcurrentHashMap<>(); private ExistancePolicyKVStorageMap exStorage = new ExistancePolicyKVStorageMap(); private VersioningKVStorageMap verStorage = new VersioningKVStorageMap(); @@ -38,10 +33,6 @@ public class MemoryKVStorage implements ExPolicyKVStorage, VersioningKVStorage, @Override public long set(Bytes key, byte[] value, long version) { return verStorage.set(key, value, version); -// if (v > -1) { -// keys.add(key); -// } -// return v; } @Override @@ -57,10 +48,6 @@ public class MemoryKVStorage implements ExPolicyKVStorage, VersioningKVStorage, @Override public boolean set(Bytes key, byte[] value, ExPolicy ex) { return exStorage.set(key, value, ex); -// if (ok) { -// keys.add(key); -// } -// return ok; } @Override @@ -81,12 +68,10 @@ public class MemoryKVStorage implements ExPolicyKVStorage, VersioningKVStorage, HashSet keySet = new HashSet<>(exStorage.keySet()); keySet.addAll(verStorage.keySet()); return keySet; -// return storageMap.keySet(); } public int getStorageCount() { return exStorage.getCount() + verStorage.getCount(); -// return storageMap.size(); } // public void printStoragedKeys() { diff --git a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVData.java b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVData.java new file mode 100644 index 00000000..684c75fe --- /dev/null +++ b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVData.java @@ -0,0 +1,35 @@ +package com.jd.blockchain.storage.service.utils; + +import com.jd.blockchain.storage.service.VersioningKVEntry; +import com.jd.blockchain.utils.Bytes; + +public class VersioningKVData implements VersioningKVEntry { + + private Bytes key; + + private long version; + + private byte[] value; + + public VersioningKVData(Bytes key, long version, byte[] value) { + this.key = key; + this.version = version; + this.value = value; + } + + @Override + public Bytes getKey() { + return key; + } + + @Override + public long getVersion() { + return version; + } + + @Override + public byte[] getValue() { + return value; + } + + } \ No newline at end of file diff --git a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVStorageMap.java b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVStorageMap.java index 2569007f..3c4855e3 100644 --- a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVStorageMap.java +++ b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/utils/VersioningKVStorageMap.java @@ -215,38 +215,6 @@ public class VersioningKVStorageMap implements VersioningKVStorage, BytesMap test-consensus-client test-consensus-node - test-ledger-core + test-ledger test-integration - + diff --git a/source/test/test-consensus-client/pom.xml b/source/test/test-consensus-client/pom.xml index f3cab64c..1fbfa8aa 100644 --- a/source/test/test-consensus-client/pom.xml +++ b/source/test/test-consensus-client/pom.xml @@ -13,7 +13,19 @@ org.springframework.boot spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-log4j2 + + com.jd.blockchain consensus-bftsmart diff --git a/source/test/test-consensus-node/pom.xml b/source/test/test-consensus-node/pom.xml index 28a5776b..671ecd50 100644 --- a/source/test/test-consensus-node/pom.xml +++ b/source/test/test-consensus-node/pom.xml @@ -12,7 +12,19 @@ org.springframework.boot spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-log4j2 + + com.jd.blockchain peer diff --git a/source/test/test-ledger-core/pom.xml b/source/test/test-contract/pom.xml similarity index 73% rename from source/test/test-ledger-core/pom.xml rename to source/test/test-contract/pom.xml index c7350156..a9c59ddf 100644 --- a/source/test/test-ledger-core/pom.xml +++ b/source/test/test-contract/pom.xml @@ -5,11 +5,16 @@ com.jd.blockchain test - 1.1.0-SNAPSHOT + 1.0.1.RELEASE - test-ledger-core + test-contract + + com.jd.blockchain + contract-jvm + ${project.version} + com.jd.blockchain ledger-core @@ -17,7 +22,7 @@ com.jd.blockchain - storage-redis + storage-rocksdb ${project.version} diff --git a/source/test/test-contract/src/test/java/test/com/jd/blockchain/contract/ContractTransactionRollbackTest.java b/source/test/test-contract/src/test/java/test/com/jd/blockchain/contract/ContractTransactionRollbackTest.java new file mode 100644 index 00000000..bda44aed --- /dev/null +++ b/source/test/test-contract/src/test/java/test/com/jd/blockchain/contract/ContractTransactionRollbackTest.java @@ -0,0 +1,14 @@ +package test.com.jd.blockchain.contract; + +import static org.junit.Assert.*; + +import org.junit.Test; + +public class ContractTransactionRollbackTest { + + @Test + public void test() { + + } + +} diff --git a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/IntegratedContext.java b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/IntegratedContext.java index ef543c42..7a3bed53 100644 --- a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/IntegratedContext.java +++ b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/IntegratedContext.java @@ -6,7 +6,7 @@ import java.util.Map; import com.jd.blockchain.consensus.ConsensusSettings; import com.jd.blockchain.crypto.AsymmetricKeypair; -import com.jd.blockchain.ledger.core.impl.LedgerManager; +import com.jd.blockchain.ledger.core.LedgerManager; import com.jd.blockchain.storage.service.impl.composite.CompositeConnectionFactory; import com.jd.blockchain.tools.initializer.LedgerBindingConfig; diff --git a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/IntegrationTest.java b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/IntegrationTest.java index a7051431..70ca67b7 100644 --- a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/IntegrationTest.java +++ b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/IntegrationTest.java @@ -17,6 +17,7 @@ import com.jd.blockchain.crypto.AddressEncoding; import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.Crypto; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig; @@ -28,23 +29,22 @@ import com.jd.blockchain.ledger.DataAccountKVSetOperation; import com.jd.blockchain.ledger.KVDataEntry; import com.jd.blockchain.ledger.LedgerBlock; import com.jd.blockchain.ledger.LedgerInfo; +import com.jd.blockchain.ledger.LedgerInitProperties; import com.jd.blockchain.ledger.ParticipantNode; import com.jd.blockchain.ledger.PreparedTransaction; import com.jd.blockchain.ledger.TransactionResponse; import com.jd.blockchain.ledger.TransactionTemplate; import com.jd.blockchain.ledger.UserInfo; -import com.jd.blockchain.ledger.core.DataAccountSet; +import com.jd.blockchain.ledger.core.DataAccountQuery; import com.jd.blockchain.ledger.core.LedgerManage; -import com.jd.blockchain.ledger.core.LedgerRepository; -import com.jd.blockchain.ledger.core.impl.LedgerManager; +import com.jd.blockchain.ledger.core.LedgerManager; +import com.jd.blockchain.ledger.core.LedgerQuery; import com.jd.blockchain.sdk.BlockchainService; import com.jd.blockchain.sdk.client.GatewayServiceFactory; import com.jd.blockchain.storage.service.KVStorageService; import com.jd.blockchain.tools.initializer.DBConnectionConfig; import com.jd.blockchain.tools.initializer.LedgerBindingConfig; -import com.jd.blockchain.tools.initializer.LedgerInitProperties; import com.jd.blockchain.tools.initializer.Prompter; -import com.jd.blockchain.tools.keygen.KeyGenCommand; import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.codec.HexUtils; import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback; @@ -110,7 +110,7 @@ public class IntegrationTest { peerStarting2.waitReturn(); peerStarting3.waitReturn(); - String encodedBase58Pwd = KeyGenCommand.encodePasswordAsBase58(LedgerInitializeWebTest.PASSWORD); + String encodedBase58Pwd = KeyGenUtils.encodePasswordAsBase58(LedgerInitializeWebTest.PASSWORD); KeyPairConfig gwkey0 = new KeyPairConfig(); gwkey0.setPubKeyValue(LedgerInitializeWebTest.PUB_KEYS[0]); @@ -150,16 +150,16 @@ public class IntegrationTest { private void testConsistencyAmongNodes(IntegratedContext context) { int[] ids = context.getNodeIds(); Node[] nodes = new Node[ids.length]; - LedgerRepository[] ledgers = new LedgerRepository[ids.length]; + LedgerQuery[] ledgers = new LedgerQuery[ids.length]; for (int i = 0; i < nodes.length; i++) { nodes[i] = context.getNode(ids[i]); HashDigest ledgerHash = nodes[i].getLedgerManager().getLedgerHashs()[0]; ledgers[i] = nodes[i].getLedgerManager().getLedger(ledgerHash); } - LedgerRepository ledger0 = ledgers[0]; + LedgerQuery ledger0 = ledgers[0]; LedgerBlock latestBlock0 = ledger0.retrieveLatestBlock(); for (int i = 1; i < ledgers.length; i++) { - LedgerRepository otherLedger = ledgers[i]; + LedgerQuery otherLedger = ledgers[i]; LedgerBlock otherLatestBlock = otherLedger.retrieveLatestBlock(); } } @@ -212,7 +212,7 @@ public class IntegrationTest { TransactionResponse txResp = prepTx.commit(); Node node0 = context.getNode(0); - LedgerRepository ledgerOfNode0 = node0.getLedgerManager().getLedger(ledgerHash); + LedgerQuery ledgerOfNode0 = node0.getLedgerManager().getLedger(ledgerHash); ledgerOfNode0.retrieveLatestBlock(); // 更新内存 // 先验证应答 @@ -250,7 +250,7 @@ public class IntegrationTest { KVStorageService storageService = node0.getStorageDB().connect(memDbConnString).getStorageService(); - LedgerRepository ledgerOfNode0 = ledgerManager.register(ledgerHash, storageService); + LedgerQuery ledgerOfNode0 = ledgerManager.register(ledgerHash, storageService); return user; } @@ -282,7 +282,7 @@ public class IntegrationTest { KVStorageService storageService = node0.getStorageDB().connect(memDbConnString).getStorageService(); - LedgerRepository ledgerOfNode0 = ledgerManager.register(ledgerHash, storageService); + LedgerQuery ledgerOfNode0 = ledgerManager.register(ledgerHash, storageService); long latestBlockHeight = ledgerOfNode0.retrieveLatestBlockHeight(); return dataAccount; @@ -301,7 +301,7 @@ public class IntegrationTest { KVStorageService storageService = node0.getStorageDB().connect(memDbConnString).getStorageService(); - LedgerRepository ledgerOfNode0 = ledgerManager.register(ledgerHash, storageService); + LedgerQuery ledgerOfNode0 = ledgerManager.register(ledgerHash, storageService); // getLedgerHashs HashDigest[] ledgerHashs = blockchainService.getLedgerHashs(); @@ -336,21 +336,21 @@ public class IntegrationTest { // getDataAccountCount according to blockhash for (int i = 0; i < ledgerHeight + 1; i++) { LedgerBlock expectBlock = ledgerOfNode0.getBlock(i); - long expectDataCount = ledgerOfNode0.getDataAccountSet(expectBlock).getTotalCount(); + long expectDataCount = ledgerOfNode0.getDataAccountSet(expectBlock).getTotal(); long actualDataCount = blockchainService.getDataAccountCount(ledgerHash, expectBlock.getHash()); } // getUserCount according to blockhash for (int i = 0; i < ledgerHeight + 1; i++) { LedgerBlock expectBlock = ledgerOfNode0.getBlock(i); - long expectUserCount = ledgerOfNode0.getUserAccountSet(expectBlock).getTotalCount(); + long expectUserCount = ledgerOfNode0.getUserAccountSet(expectBlock).getTotal(); long actualUserCount = blockchainService.getUserCount(ledgerHash, expectBlock.getHash()); } // getContractCount according to blockhash for (int i = 0; i < ledgerHeight + 1; i++) { LedgerBlock expectBlock = ledgerOfNode0.getBlock(i); - long expectContractCount = ledgerOfNode0.getContractAccountSet(expectBlock).getTotalCount(); + long expectContractCount = ledgerOfNode0.getContractAccountSet(expectBlock).getTotal(); long actualContractCount = blockchainService.getContractCount(ledgerHash, expectBlock.getHash()); } @@ -372,9 +372,9 @@ public class IntegrationTest { // expect block acount total LedgerBlock ledgerBlock = ledgerOfNode0.getBlock(i); expectTransactionTotal = ledgerOfNode0.getTransactionSet(ledgerBlock).getTotalCount(); - expectUserTotal = ledgerOfNode0.getUserAccountSet(ledgerBlock).getTotalCount(); - expectDataTotal = ledgerOfNode0.getDataAccountSet(ledgerBlock).getTotalCount(); - expectContractTotal = ledgerOfNode0.getContractAccountSet(ledgerBlock).getTotalCount(); + expectUserTotal = ledgerOfNode0.getUserAccountSet(ledgerBlock).getTotal(); + expectDataTotal = ledgerOfNode0.getDataAccountSet(ledgerBlock).getTotal(); + expectContractTotal = ledgerOfNode0.getContractAccountSet(ledgerBlock).getTotal(); } // getTransactionTotalCount @@ -452,16 +452,16 @@ public class IntegrationTest { NetworkAddress initAddr3 = initSetting.getConsensusParticipant(3).getInitializerAddress(); LedgerInitializeWebTest.NodeWebContext nodeCtx3 = new LedgerInitializeWebTest.NodeWebContext(3, initAddr3); - PrivKey privkey0 = KeyGenCommand.decodePrivKeyWithRawPassword(LedgerInitializeWebTest.PRIV_KEYS[0], + PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(LedgerInitializeWebTest.PRIV_KEYS[0], LedgerInitializeWebTest.PASSWORD); - PrivKey privkey1 = KeyGenCommand.decodePrivKeyWithRawPassword(LedgerInitializeWebTest.PRIV_KEYS[1], + PrivKey privkey1 = KeyGenUtils.decodePrivKeyWithRawPassword(LedgerInitializeWebTest.PRIV_KEYS[1], LedgerInitializeWebTest.PASSWORD); - PrivKey privkey2 = KeyGenCommand.decodePrivKeyWithRawPassword(LedgerInitializeWebTest.PRIV_KEYS[2], + PrivKey privkey2 = KeyGenUtils.decodePrivKeyWithRawPassword(LedgerInitializeWebTest.PRIV_KEYS[2], LedgerInitializeWebTest.PASSWORD); - PrivKey privkey3 = KeyGenCommand.decodePrivKeyWithRawPassword(LedgerInitializeWebTest.PRIV_KEYS[3], + PrivKey privkey3 = KeyGenUtils.decodePrivKeyWithRawPassword(LedgerInitializeWebTest.PRIV_KEYS[3], LedgerInitializeWebTest.PASSWORD); - String encodedPassword = KeyGenCommand.encodePasswordAsBase58(LedgerInitializeWebTest.PASSWORD); + String encodedPassword = KeyGenUtils.encodePasswordAsBase58(LedgerInitializeWebTest.PASSWORD); CountDownLatch quitLatch = new CountDownLatch(4); @@ -494,10 +494,10 @@ public class IntegrationTest { HashDigest ledgerHash2 = callback2.waitReturn(); HashDigest ledgerHash3 = callback3.waitReturn(); - LedgerRepository ledger0 = nodeCtx0.registLedger(ledgerHash0); - LedgerRepository ledger1 = nodeCtx1.registLedger(ledgerHash1); - LedgerRepository ledger2 = nodeCtx2.registLedger(ledgerHash2); - LedgerRepository ledger3 = nodeCtx3.registLedger(ledgerHash3); + LedgerQuery ledger0 = nodeCtx0.registLedger(ledgerHash0); + LedgerQuery ledger1 = nodeCtx1.registLedger(ledgerHash1); + LedgerQuery ledger2 = nodeCtx2.registLedger(ledgerHash2); + LedgerQuery ledger3 = nodeCtx3.registLedger(ledgerHash3); IntegratedContext context = new IntegratedContext(); @@ -577,9 +577,9 @@ public class IntegrationTest { txResp.getContentHash(); Node node0 = context.getNode(0); - LedgerRepository ledgerOfNode0 = node0.getLedgerManager().getLedger(ledgerHash); + LedgerQuery ledgerOfNode0 = node0.getLedgerManager().getLedger(ledgerHash); LedgerBlock block = ledgerOfNode0.getBlock(txResp.getBlockHeight()); - byte[] contractCodeInDb = ledgerOfNode0.getContractAccountSet(block).getContract(contractDeployKey.getAddress()) + byte[] contractCodeInDb = ledgerOfNode0.getContractAccountSet(block).getAccount(contractDeployKey.getAddress()) .getChainCode(); txContentHash = ptx.getHash(); @@ -615,11 +615,11 @@ public class IntegrationTest { LedgerInfo latestLedgerInfo = blockchainService.getLedger(ledgerHash); Node node0 = context.getNode(0); - LedgerRepository ledgerOfNode0 = node0.getLedgerManager().getLedger(ledgerHash); + LedgerQuery ledgerOfNode0 = node0.getLedgerManager().getLedger(ledgerHash); LedgerBlock backgroundLedgerBlock = ledgerOfNode0.retrieveLatestBlock(); // 验证合约中的赋值,外部可以获得; - DataAccountSet dataAccountSet = ledgerOfNode0.getDataAccountSet(backgroundLedgerBlock); + DataAccountQuery dataAccountSet = ledgerOfNode0.getDataAccountSet(backgroundLedgerBlock); AsymmetricKeypair key = Crypto.getSignatureFunction("ED25519").generateKeypair(); PubKey pubKey = key.getPubKey(); Bytes dataAddress = AddressEncoding.generateAddress(pubKey); @@ -657,11 +657,11 @@ public class IntegrationTest { // 验证结果; Node node0 = context.getNode(0); - LedgerRepository ledgerOfNode0 = node0.getLedgerManager().getLedger(ledgerHash); + LedgerQuery ledgerOfNode0 = node0.getLedgerManager().getLedger(ledgerHash); LedgerBlock block = ledgerOfNode0.getBlock(txResp.getBlockHeight()); - BytesValue val1InDb = ledgerOfNode0.getDataAccountSet(block).getDataAccount(contractDataKey.getAddress()) + BytesValue val1InDb = ledgerOfNode0.getDataAccountSet(block).getAccount(contractDataKey.getAddress()) .getBytes("A"); - BytesValue val2InDb = ledgerOfNode0.getDataAccountSet(block).getDataAccount(contractDataKey.getAddress()) + BytesValue val2InDb = ledgerOfNode0.getDataAccountSet(block).getAccount(contractDataKey.getAddress()) .getBytes(KEY_TOTAL); } diff --git a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/consensus/ConsensusTest.java b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/consensus/ConsensusTest.java index 9eb45aee..7c959bc3 100644 --- a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/consensus/ConsensusTest.java +++ b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/consensus/ConsensusTest.java @@ -16,19 +16,21 @@ import com.jd.blockchain.consensus.ConsensusProviders; import com.jd.blockchain.consensus.ConsensusSettings; import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.SignatureDigest; import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig; import com.jd.blockchain.ledger.BlockchainKeyGenerator; import com.jd.blockchain.ledger.BlockchainKeypair; import com.jd.blockchain.ledger.LedgerBlock; +import com.jd.blockchain.ledger.LedgerInitProperties; import com.jd.blockchain.ledger.PreparedTransaction; import com.jd.blockchain.ledger.TransactionContent; import com.jd.blockchain.ledger.TransactionTemplate; import com.jd.blockchain.ledger.core.LedgerInitDecision; -import com.jd.blockchain.ledger.core.LedgerInitPermission; -import com.jd.blockchain.ledger.core.LedgerRepository; -import com.jd.blockchain.ledger.core.impl.LedgerManager; +import com.jd.blockchain.ledger.core.LedgerInitProposal; +import com.jd.blockchain.ledger.core.LedgerManager; +import com.jd.blockchain.ledger.core.LedgerQuery; import com.jd.blockchain.sdk.BlockchainService; import com.jd.blockchain.sdk.client.GatewayServiceFactory; import com.jd.blockchain.storage.service.DbConnection; @@ -37,10 +39,8 @@ import com.jd.blockchain.tools.initializer.DBConnectionConfig; import com.jd.blockchain.tools.initializer.LedgerBindingConfig; import com.jd.blockchain.tools.initializer.LedgerInitCommand; import com.jd.blockchain.tools.initializer.LedgerInitProcess; -import com.jd.blockchain.tools.initializer.LedgerInitProperties; import com.jd.blockchain.tools.initializer.Prompter; import com.jd.blockchain.tools.initializer.web.LedgerInitializeWebController; -import com.jd.blockchain.tools.keygen.KeyGenCommand; import com.jd.blockchain.utils.ConsoleUtils; import com.jd.blockchain.utils.concurrent.ThreadInvoker; import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback; @@ -90,7 +90,7 @@ public class ConsensusTest { peerStarting2.waitReturn(); peerStarting3.waitReturn(); - String encodedBase58Pwd = KeyGenCommand.encodePasswordAsBase58(Utils.PASSWORD); + String encodedBase58Pwd = KeyGenUtils.encodePasswordAsBase58(Utils.PASSWORD); KeyPairConfig gwkey0 = new KeyPairConfig(); gwkey0.setPubKeyValue(Utils.PUB_KEYS[0]); @@ -118,7 +118,7 @@ public class ConsensusTest { BlockchainKeypair[] keys = generateKeys(batchSize); HashDigest ledgerHash = node0.getLedgerManager().getLedgerHashs()[0]; - LedgerRepository ledger = node0.getLedgerManager().getLedger(ledgerHash); + LedgerQuery ledger = node0.getLedgerManager().getLedger(ledgerHash); PreparedTransaction[] ptxs = prepareTransactions_RegisterDataAcount(keys, node0.getPartiKeyPair(), ledgerHash, blockchainService); @@ -205,12 +205,12 @@ public class ConsensusTest { NetworkAddress initAddr3 = initSetting.getConsensusParticipant(3).getInitializerAddress(); NodeInitContext nodeCtx3 = new NodeInitContext(3, initAddr3); - PrivKey privkey0 = KeyGenCommand.decodePrivKeyWithRawPassword(Utils.PRIV_KEYS[0], Utils.PASSWORD); - PrivKey privkey1 = KeyGenCommand.decodePrivKeyWithRawPassword(Utils.PRIV_KEYS[1], Utils.PASSWORD); - PrivKey privkey2 = KeyGenCommand.decodePrivKeyWithRawPassword(Utils.PRIV_KEYS[2], Utils.PASSWORD); - PrivKey privkey3 = KeyGenCommand.decodePrivKeyWithRawPassword(Utils.PRIV_KEYS[3], Utils.PASSWORD); + PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(Utils.PRIV_KEYS[0], Utils.PASSWORD); + PrivKey privkey1 = KeyGenUtils.decodePrivKeyWithRawPassword(Utils.PRIV_KEYS[1], Utils.PASSWORD); + PrivKey privkey2 = KeyGenUtils.decodePrivKeyWithRawPassword(Utils.PRIV_KEYS[2], Utils.PASSWORD); + PrivKey privkey3 = KeyGenUtils.decodePrivKeyWithRawPassword(Utils.PRIV_KEYS[3], Utils.PASSWORD); - String encodedPassword = KeyGenCommand.encodePasswordAsBase58(Utils.PASSWORD); + String encodedPassword = KeyGenUtils.encodePasswordAsBase58(Utils.PASSWORD); CountDownLatch quitLatch = new CountDownLatch(4); @@ -326,7 +326,7 @@ public class ConsensusTest { return controller.getInitTxContent(); } - public LedgerInitPermission getLocalPermission() { + public LedgerInitProposal getLocalPermission() { return controller.getLocalPermission(); } @@ -339,7 +339,7 @@ public class ConsensusTest { this.serverAddress = serverAddress; } - public LedgerRepository registLedger(HashDigest ledgerHash) { + public LedgerQuery registLedger(HashDigest ledgerHash) { // LedgerManage ledgerManager = ctx.getBean(LedgerManage.class); // // DbConnectionFactory dbConnFactory = ctx.getBean(DbConnectionFactory.class); @@ -347,7 +347,7 @@ public class ConsensusTest { // dbConnConfig.getPassword()); DbConnection conn = db.connect(dbConnConfig.getUri(), dbConnConfig.getPassword()); - LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, conn.getStorageService()); + LedgerQuery ledgerRepo = ledgerManager.register(ledgerHash, conn.getStorageService()); return ledgerRepo; } @@ -398,9 +398,8 @@ public class ConsensusTest { return invoker.start(); } - public LedgerInitPermission preparePermision(PrivKey privKey, LedgerInitProperties setting, - ConsensusSettings csProps) { - return controller.prepareLocalPermission(id, privKey, setting, csProps); + public LedgerInitProposal preparePermision(PrivKey privKey, LedgerInitProperties initProps) { + return controller.prepareLocalPermission(id, privKey, initProps); } public boolean consensusPermission(PrivKey privKey) { diff --git a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/GlobalPerformanceTest.java b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/GlobalPerformanceTest.java index f4c21fe7..7f23a276 100644 --- a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/GlobalPerformanceTest.java +++ b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/GlobalPerformanceTest.java @@ -18,19 +18,21 @@ import com.jd.blockchain.consensus.ConsensusProviders; import com.jd.blockchain.consensus.ConsensusSettings; import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.SignatureDigest; import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig; import com.jd.blockchain.ledger.BlockchainKeyGenerator; import com.jd.blockchain.ledger.BlockchainKeypair; import com.jd.blockchain.ledger.LedgerBlock; +import com.jd.blockchain.ledger.LedgerInitProperties; import com.jd.blockchain.ledger.PreparedTransaction; import com.jd.blockchain.ledger.TransactionContent; import com.jd.blockchain.ledger.TransactionTemplate; import com.jd.blockchain.ledger.core.LedgerInitDecision; -import com.jd.blockchain.ledger.core.LedgerInitPermission; -import com.jd.blockchain.ledger.core.LedgerRepository; -import com.jd.blockchain.ledger.core.impl.LedgerManager; +import com.jd.blockchain.ledger.core.LedgerInitProposal; +import com.jd.blockchain.ledger.core.LedgerManager; +import com.jd.blockchain.ledger.core.LedgerQuery; import com.jd.blockchain.sdk.BlockchainService; import com.jd.blockchain.sdk.client.GatewayServiceFactory; import com.jd.blockchain.storage.service.DbConnection; @@ -38,10 +40,8 @@ import com.jd.blockchain.tools.initializer.DBConnectionConfig; import com.jd.blockchain.tools.initializer.LedgerBindingConfig; import com.jd.blockchain.tools.initializer.LedgerInitCommand; import com.jd.blockchain.tools.initializer.LedgerInitProcess; -import com.jd.blockchain.tools.initializer.LedgerInitProperties; import com.jd.blockchain.tools.initializer.Prompter; import com.jd.blockchain.tools.initializer.web.LedgerInitializeWebController; -import com.jd.blockchain.tools.keygen.KeyGenCommand; import com.jd.blockchain.utils.ConsoleUtils; import com.jd.blockchain.utils.concurrent.ThreadInvoker; import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback; @@ -88,7 +88,7 @@ public class GlobalPerformanceTest { peerStarting2.waitReturn(); peerStarting3.waitReturn(); - String encodedBase58Pwd = KeyGenCommand.encodePasswordAsBase58(Utils.PASSWORD); + String encodedBase58Pwd = KeyGenUtils.encodePasswordAsBase58(Utils.PASSWORD); KeyPairConfig gwkey0 = new KeyPairConfig(); gwkey0.setPubKeyValue(Utils.PUB_KEYS[0]); @@ -116,7 +116,7 @@ public class GlobalPerformanceTest { BlockchainKeypair[] keys = generateKeys(batchSize); HashDigest ledgerHash = node0.getLedgerManager().getLedgerHashs()[0]; - LedgerRepository ledger = node0.getLedgerManager().getLedger(ledgerHash); + LedgerQuery ledger = node0.getLedgerManager().getLedger(ledgerHash); PreparedTransaction[] ptxs = prepareTransactions_RegisterDataAcount(keys, node0.getPartiKeyPair(), ledgerHash, blockchainService); @@ -186,9 +186,8 @@ public class GlobalPerformanceTest { LedgerInitProperties initSetting = loadInitSetting_integration(); Properties props = Utils.loadConsensusSetting(); ConsensusProvider csProvider = getConsensusProvider(); - ConsensusSettings csProps = csProvider.getSettingsFactory() - .getConsensusSettingsBuilder() - .createSettings(props, Utils.loadParticipantNodes()); + ConsensusSettings csProps = csProvider.getSettingsFactory().getConsensusSettingsBuilder().createSettings(props, + Utils.loadParticipantNodes()); // 启动服务器; NetworkAddress initAddr0 = initSetting.getConsensusParticipant(0).getInitializerAddress(); @@ -203,12 +202,12 @@ public class GlobalPerformanceTest { NetworkAddress initAddr3 = initSetting.getConsensusParticipant(3).getInitializerAddress(); NodeInitContext nodeCtx3 = new NodeInitContext(3, initAddr3); - PrivKey privkey0 = KeyGenCommand.decodePrivKeyWithRawPassword(Utils.PRIV_KEYS[0], Utils.PASSWORD); - PrivKey privkey1 = KeyGenCommand.decodePrivKeyWithRawPassword(Utils.PRIV_KEYS[1], Utils.PASSWORD); - PrivKey privkey2 = KeyGenCommand.decodePrivKeyWithRawPassword(Utils.PRIV_KEYS[2], Utils.PASSWORD); - PrivKey privkey3 = KeyGenCommand.decodePrivKeyWithRawPassword(Utils.PRIV_KEYS[3], Utils.PASSWORD); + PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(Utils.PRIV_KEYS[0], Utils.PASSWORD); + PrivKey privkey1 = KeyGenUtils.decodePrivKeyWithRawPassword(Utils.PRIV_KEYS[1], Utils.PASSWORD); + PrivKey privkey2 = KeyGenUtils.decodePrivKeyWithRawPassword(Utils.PRIV_KEYS[2], Utils.PASSWORD); + PrivKey privkey3 = KeyGenUtils.decodePrivKeyWithRawPassword(Utils.PRIV_KEYS[3], Utils.PASSWORD); - String encodedPassword = KeyGenCommand.encodePasswordAsBase58(Utils.PASSWORD); + String encodedPassword = KeyGenUtils.encodePasswordAsBase58(Utils.PASSWORD); CountDownLatch quitLatch = new CountDownLatch(4); @@ -326,7 +325,7 @@ public class GlobalPerformanceTest { return controller.getInitTxContent(); } - public LedgerInitPermission getLocalPermission() { + public LedgerInitProposal getLocalPermission() { return controller.getLocalPermission(); } @@ -339,7 +338,7 @@ public class GlobalPerformanceTest { this.serverAddress = serverAddress; } - public LedgerRepository registLedger(HashDigest ledgerHash) { + public LedgerQuery registLedger(HashDigest ledgerHash) { // LedgerManage ledgerManager = ctx.getBean(LedgerManage.class); // // DbConnectionFactory dbConnFactory = ctx.getBean(DbConnectionFactory.class); @@ -348,7 +347,7 @@ public class GlobalPerformanceTest { DbConnection conn = db.connect(dbConnConfig.getUri(), dbConnConfig.getPassword()); conns.add(conn); - LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, conn.getStorageService()); + LedgerQuery ledgerRepo = ledgerManager.register(ledgerHash, conn.getStorageService()); return ledgerRepo; } @@ -400,9 +399,8 @@ public class GlobalPerformanceTest { return invoker.start(); } - public LedgerInitPermission preparePermision(PrivKey privKey, LedgerInitProperties setting, - ConsensusSettings csProps) { - return controller.prepareLocalPermission(id, privKey, setting, csProps); + public LedgerInitProposal preparePermision(PrivKey privKey, LedgerInitProperties initProps) { + return controller.prepareLocalPermission(id, privKey, initProps); } public boolean consensusPermission(PrivKey privKey) { diff --git a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerInitializeTest.java b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerInitializeTest.java index dbd8b21b..36ef321f 100644 --- a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerInitializeTest.java +++ b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerInitializeTest.java @@ -15,27 +15,27 @@ import com.jd.blockchain.crypto.AddressEncoding; import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.Crypto; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.crypto.SignatureDigest; import com.jd.blockchain.ledger.LedgerBlock; +import com.jd.blockchain.ledger.LedgerInitProperties; import com.jd.blockchain.ledger.core.CryptoConfig; import com.jd.blockchain.ledger.core.LedgerInitDecision; -import com.jd.blockchain.ledger.core.LedgerInitPermission; -import com.jd.blockchain.ledger.core.LedgerRepository; +import com.jd.blockchain.ledger.core.LedgerInitProposal; +import com.jd.blockchain.ledger.core.LedgerManager; +import com.jd.blockchain.ledger.core.LedgerQuery; 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.MemoryDBConnFactory; //import com.jd.blockchain.storage.service.utils.MemoryBasedDb; import com.jd.blockchain.tools.initializer.DBConnectionConfig; import com.jd.blockchain.tools.initializer.LedgerInitProcess; -import com.jd.blockchain.tools.initializer.LedgerInitProperties; import com.jd.blockchain.tools.initializer.Prompter; import com.jd.blockchain.tools.initializer.web.InitConsensusServiceFactory; import com.jd.blockchain.tools.initializer.web.LedgerInitConsensusService; import com.jd.blockchain.tools.initializer.web.LedgerInitializeWebController; -import com.jd.blockchain.tools.keygen.KeyGenCommand; import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.concurrent.ThreadInvoker; import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback; @@ -81,22 +81,22 @@ public class LedgerInitializeTest { String[] memoryConnString = new String[] { "memory://local/0", "memory://local/1", "memory://local/2", "memory://local/3" }; - PrivKey privkey0 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[0], PASSWORD); + PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[0], PASSWORD); DBConnectionConfig testDb0 = new DBConnectionConfig(); testDb0.setConnectionUri(memoryConnString[0]); AsyncCallback callback0 = node0.startInit(0, privkey0, initSetting, testDb0, consolePrompter); - PrivKey privkey1 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[1], PASSWORD); + PrivKey privkey1 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[1], PASSWORD); DBConnectionConfig testDb1 = new DBConnectionConfig(); testDb1.setConnectionUri(memoryConnString[1]); AsyncCallback callback1 = node1.startInit(1, privkey1, initSetting, testDb1, consolePrompter); - PrivKey privkey2 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[2], PASSWORD); + PrivKey privkey2 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[2], PASSWORD); DBConnectionConfig testDb2 = new DBConnectionConfig(); testDb2.setConnectionUri(memoryConnString[2]); AsyncCallback callback2 = node2.startInit(2, privkey2, initSetting, testDb2, consolePrompter); - PrivKey privkey3 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[3], PASSWORD); + PrivKey privkey3 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[3], PASSWORD); DBConnectionConfig testDb03 = new DBConnectionConfig(); testDb03.setConnectionUri(memoryConnString[3]); AsyncCallback callback3 = node3.startInit(3, privkey3, initSetting, testDb03, consolePrompter); @@ -106,30 +106,30 @@ public class LedgerInitializeTest { HashDigest ledgerHash2 = callback2.waitReturn(); HashDigest ledgerHash3 = callback3.waitReturn(); - LedgerRepository ledger0 = node0.registLedger(ledgerHash0, memoryConnString[0]); - LedgerRepository ledger1 = node1.registLedger(ledgerHash1, memoryConnString[1]); - LedgerRepository ledger2 = node2.registLedger(ledgerHash2, memoryConnString[2]); - LedgerRepository ledger3 = node3.registLedger(ledgerHash3, memoryConnString[3]); + LedgerQuery ledger0 = node0.registLedger(ledgerHash0, memoryConnString[0]); + LedgerQuery ledger1 = node1.registLedger(ledgerHash1, memoryConnString[1]); + LedgerQuery ledger2 = node2.registLedger(ledgerHash2, memoryConnString[2]); + LedgerQuery ledger3 = node3.registLedger(ledgerHash3, memoryConnString[3]); LedgerBlock genesisBlock = ledger0.getLatestBlock(); - UserAccountSet userset0 = ledger0.getUserAccountSet(genesisBlock); + UserAccountQuery userset0 = ledger0.getUserAccountSet(genesisBlock); - PubKey pubKey0 = KeyGenCommand.decodePubKey(PUB_KEYS[0]); + PubKey pubKey0 = KeyGenUtils.decodePubKey(PUB_KEYS[0]); Bytes address0 = AddressEncoding.generateAddress(pubKey0); - UserAccount user0_0 = userset0.getUser(address0); + UserAccount user0_0 = userset0.getAccount(address0); - PubKey pubKey1 = KeyGenCommand.decodePubKey(PUB_KEYS[1]); + PubKey pubKey1 = KeyGenUtils.decodePubKey(PUB_KEYS[1]); Bytes address1 = AddressEncoding.generateAddress(pubKey1); - UserAccount user1_0 = userset0.getUser(address1); + UserAccount user1_0 = userset0.getAccount(address1); - PubKey pubKey2 = KeyGenCommand.decodePubKey(PUB_KEYS[2]); + PubKey pubKey2 = KeyGenUtils.decodePubKey(PUB_KEYS[2]); Bytes address2 = AddressEncoding.generateAddress(pubKey2); - UserAccount user2_0 = userset0.getUser(address2); + UserAccount user2_0 = userset0.getAccount(address2); - PubKey pubKey3 = KeyGenCommand.decodePubKey(PUB_KEYS[3]); + PubKey pubKey3 = KeyGenUtils.decodePubKey(PUB_KEYS[3]); Bytes address3 = AddressEncoding.generateAddress(pubKey3); - UserAccount user3_0 = userset0.getUser(address3); + UserAccount user3_0 = userset0.getAccount(address3); } public static LedgerInitProperties loadInitSetting() { @@ -182,8 +182,8 @@ public class LedgerInitializeTest { public NodeContext(NetworkAddress address, Map serviceRegisterMap) { this.initCsServiceFactory = new MultiThreadInterInvokerFactory(serviceRegisterMap); - LedgerInitializeWebController initController = new LedgerInitializeWebController(ledgerManager, - memoryDBConnFactory, initCsServiceFactory); + LedgerInitializeWebController initController = new LedgerInitializeWebController(memoryDBConnFactory, + initCsServiceFactory); serviceRegisterMap.put(address, initController); this.initProcess = initController; } @@ -203,26 +203,25 @@ public class LedgerInitializeTest { return invoker.start(); } - public AsyncCallback startInit(int currentId, PrivKey privKey, LedgerInitProperties setting, + public AsyncCallback startInit(int currentId, PrivKey privKey, LedgerInitProperties initProps, DBConnectionConfig dbConnConfig, Prompter prompter, boolean autoVerifyHash) { - CryptoConfig cryptoSetting = new CryptoConfig(); - cryptoSetting.setAutoVerifyHash(autoVerifyHash); - cryptoSetting.setHashAlgorithm(Crypto.getAlgorithm("SHA256")); + initProps.getCryptoProperties().setVerifyHash(autoVerifyHash); + initProps.getCryptoProperties().setHashAlgorithm("SHA256"); - partiKey = new AsymmetricKeypair(setting.getConsensusParticipant(0).getPubKey(), privKey); + partiKey = new AsymmetricKeypair(initProps.getConsensusParticipant(0).getPubKey(), privKey); ThreadInvoker invoker = new ThreadInvoker() { @Override protected HashDigest invoke() throws Exception { - return initProcess.initialize(currentId, privKey, setting, dbConnConfig, prompter, cryptoSetting); + return initProcess.initialize(currentId, privKey, initProps, dbConnConfig, prompter); } }; return invoker.start(); } - public LedgerRepository registLedger(HashDigest ledgerHash, String connString) { + public LedgerQuery registLedger(HashDigest ledgerHash, String connString) { return ledgerManager.register(ledgerHash, memoryDBConnFactory.connect(connString).getStorageService()); } } @@ -251,10 +250,10 @@ public class LedgerInitializeTest { } @Override - public LedgerInitPermission requestPermission(int requesterId, SignatureDigest signature) { - ThreadInvoker invoker = new ThreadInvoker() { + public LedgerInitProposal requestPermission(int requesterId, SignatureDigest signature) { + ThreadInvoker invoker = new ThreadInvoker() { @Override - protected LedgerInitPermission invoke() { + protected LedgerInitProposal invoke() { return initCsService.requestPermission(requesterId, signature); } }; diff --git a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerInitializeWebTest.java b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerInitializeWebTest.java index 569472d9..8ee650cc 100644 --- a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerInitializeWebTest.java +++ b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerInitializeWebTest.java @@ -16,21 +16,23 @@ import com.jd.blockchain.consensus.ConsensusSettings; import com.jd.blockchain.crypto.AddressEncoding; import com.jd.blockchain.crypto.Crypto; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.crypto.SignatureDigest; import com.jd.blockchain.crypto.SignatureFunction; import com.jd.blockchain.ledger.LedgerBlock; import com.jd.blockchain.ledger.LedgerInitOperation; +import com.jd.blockchain.ledger.LedgerInitProperties; import com.jd.blockchain.ledger.Operation; import com.jd.blockchain.ledger.TransactionContent; import com.jd.blockchain.ledger.UserRegisterOperation; import com.jd.blockchain.ledger.core.LedgerInitDecision; -import com.jd.blockchain.ledger.core.LedgerInitPermission; -import com.jd.blockchain.ledger.core.LedgerRepository; +import com.jd.blockchain.ledger.core.LedgerInitProposal; +import com.jd.blockchain.ledger.core.LedgerManager; +import com.jd.blockchain.ledger.core.LedgerQuery; 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.DbConnection; import com.jd.blockchain.storage.service.impl.composite.CompositeConnectionFactory; //import com.jd.blockchain.storage.service.utils.MemoryBasedDb; @@ -38,12 +40,11 @@ import com.jd.blockchain.tools.initializer.DBConnectionConfig; import com.jd.blockchain.tools.initializer.LedgerBindingConfig; import com.jd.blockchain.tools.initializer.LedgerInitCommand; import com.jd.blockchain.tools.initializer.LedgerInitProcess; -import com.jd.blockchain.tools.initializer.LedgerInitProperties; import com.jd.blockchain.tools.initializer.Prompter; import com.jd.blockchain.tools.initializer.web.HttpInitConsensServiceFactory; +import com.jd.blockchain.tools.initializer.web.LedgerInitConfiguration; import com.jd.blockchain.tools.initializer.web.LedgerInitConsensusService; import com.jd.blockchain.tools.initializer.web.LedgerInitializeWebController; -import com.jd.blockchain.tools.keygen.KeyGenCommand; import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.concurrent.ThreadInvoker; import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback; @@ -101,21 +102,23 @@ public class LedgerInitializeWebTest { node2.setPrompter(prompter); node3.setPrompter(prompter); - PrivKey privkey0 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[0], PASSWORD); - PrivKey privkey1 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[1], PASSWORD); - PrivKey privkey2 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[2], PASSWORD); - PrivKey privkey3 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[3], PASSWORD); + PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[0], PASSWORD); + PrivKey privkey1 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[1], PASSWORD); + PrivKey privkey2 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[2], PASSWORD); + PrivKey privkey3 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[3], PASSWORD); - PubKey pubKey0 = KeyGenCommand.decodePubKey(PUB_KEYS[0]); - PubKey pubKey1 = KeyGenCommand.decodePubKey(PUB_KEYS[1]); - PubKey pubKey2 = KeyGenCommand.decodePubKey(PUB_KEYS[2]); - PubKey pubKey3 = KeyGenCommand.decodePubKey(PUB_KEYS[3]); + PubKey pubKey0 = KeyGenUtils.decodePubKey(PUB_KEYS[0]); + PubKey pubKey1 = KeyGenUtils.decodePubKey(PUB_KEYS[1]); + PubKey pubKey2 = KeyGenUtils.decodePubKey(PUB_KEYS[2]); + PubKey pubKey3 = KeyGenUtils.decodePubKey(PUB_KEYS[3]); // 测试生成“账本初始化许可”; - LedgerInitPermission permission0 = testPreparePermisssion(node0, privkey0, initSetting, csProps); - LedgerInitPermission permission1 = testPreparePermisssion(node1, privkey1, initSetting, csProps); - LedgerInitPermission permission2 = testPreparePermisssion(node2, privkey2, initSetting, csProps); - LedgerInitPermission permission3 = testPreparePermisssion(node3, privkey3, initSetting, csProps); + LedgerInitConfiguration initConfig = LedgerInitConfiguration.create(initSetting); + initConfig.setConsensusSettings(csProvider, csProps); + LedgerInitProposal permission0 = testPreparePermisssion(node0, privkey0, initConfig); + LedgerInitProposal permission1 = testPreparePermisssion(node1, privkey1, initConfig); + LedgerInitProposal permission2 = testPreparePermisssion(node2, privkey2, initConfig); + LedgerInitProposal permission3 = testPreparePermisssion(node3, privkey3, initConfig); TransactionContent initTxContent0 = node0.getInitTxContent(); TransactionContent initTxContent1 = node1.getInitTxContent(); @@ -205,9 +208,9 @@ public class LedgerInitializeWebTest { testRequestDecision(node3, node2, initCsService2); } - private LedgerInitPermission testPreparePermisssion(NodeWebContext node, PrivKey privKey, - LedgerInitProperties setting, ConsensusSettings csProps) { - LedgerInitPermission permission = node.preparePermision(privKey, setting, csProps); + private LedgerInitProposal testPreparePermisssion(NodeWebContext node, PrivKey privKey, + LedgerInitConfiguration setting) { + LedgerInitProposal permission = node.preparePermision(privKey, setting); return permission; } @@ -215,7 +218,7 @@ public class LedgerInitializeWebTest { private void testRequestPermission(NodeWebContext fromNode, PrivKey fromPrivkey, NodeWebContext targetNode, LedgerInitConsensusService targetNodeService) { SignatureDigest reqSignature = fromNode.createPermissionRequestSignature(fromNode.getId(), fromPrivkey); - LedgerInitPermission targetPermission = targetNodeService.requestPermission(fromNode.getId(), reqSignature); + LedgerInitProposal targetPermission = targetNodeService.requestPermission(fromNode.getId(), reqSignature); } private void testRequestDecision(NodeWebContext fromNode, NodeWebContext targetNode, @@ -259,10 +262,10 @@ public class LedgerInitializeWebTest { NetworkAddress initAddr3 = initSetting.getConsensusParticipant(3).getInitializerAddress(); NodeWebContext node3 = new NodeWebContext(3, initAddr3); - PrivKey privkey0 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[0], PASSWORD); - PrivKey privkey1 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[1], PASSWORD); - PrivKey privkey2 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[2], PASSWORD); - PrivKey privkey3 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[3], PASSWORD); + PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[0], PASSWORD); + PrivKey privkey1 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[1], PASSWORD); + PrivKey privkey2 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[2], PASSWORD); + PrivKey privkey3 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[3], PASSWORD); CountDownLatch quitLatch = new CountDownLatch(4); @@ -291,30 +294,30 @@ public class LedgerInitializeWebTest { HashDigest ledgerHash2 = callback2.waitReturn(); HashDigest ledgerHash3 = callback3.waitReturn(); - LedgerRepository ledger0 = node0.registLedger(ledgerHash0); - LedgerRepository ledger1 = node1.registLedger(ledgerHash1); - LedgerRepository ledger2 = node2.registLedger(ledgerHash2); - LedgerRepository ledger3 = node3.registLedger(ledgerHash3); + LedgerQuery ledger0 = node0.registLedger(ledgerHash0); + LedgerQuery ledger1 = node1.registLedger(ledgerHash1); + LedgerQuery ledger2 = node2.registLedger(ledgerHash2); + LedgerQuery ledger3 = node3.registLedger(ledgerHash3); LedgerBlock genesisBlock = ledger0.getLatestBlock(); - UserAccountSet userset0 = ledger0.getUserAccountSet(genesisBlock); + UserAccountQuery userset0 = ledger0.getUserAccountSet(genesisBlock); - PubKey pubKey0 = KeyGenCommand.decodePubKey(PUB_KEYS[0]); + PubKey pubKey0 = KeyGenUtils.decodePubKey(PUB_KEYS[0]); Bytes address0 = AddressEncoding.generateAddress(pubKey0); - UserAccount user0_0 = userset0.getUser(address0); + UserAccount user0_0 = userset0.getAccount(address0); - PubKey pubKey1 = KeyGenCommand.decodePubKey(PUB_KEYS[1]); + PubKey pubKey1 = KeyGenUtils.decodePubKey(PUB_KEYS[1]); Bytes address1 = AddressEncoding.generateAddress(pubKey1); - UserAccount user1_0 = userset0.getUser(address1); + UserAccount user1_0 = userset0.getAccount(address1); - PubKey pubKey2 = KeyGenCommand.decodePubKey(PUB_KEYS[2]); + PubKey pubKey2 = KeyGenUtils.decodePubKey(PUB_KEYS[2]); Bytes address2 = AddressEncoding.generateAddress(pubKey2); - UserAccount user2_0 = userset0.getUser(address2); + UserAccount user2_0 = userset0.getAccount(address2); - PubKey pubKey3 = KeyGenCommand.decodePubKey(PUB_KEYS[3]); + PubKey pubKey3 = KeyGenUtils.decodePubKey(PUB_KEYS[3]); Bytes address3 = AddressEncoding.generateAddress(pubKey3); - UserAccount user3_0 = userset0.getUser(address3); + UserAccount user3_0 = userset0.getAccount(address3); } public static LedgerInitProperties loadInitSetting_1() { @@ -374,7 +377,7 @@ public class LedgerInitializeWebTest { return controller.getInitTxContent(); } - public LedgerInitPermission getLocalPermission() { + public LedgerInitProposal getLocalPermission() { return controller.getLocalPermission(); } @@ -387,7 +390,7 @@ public class LedgerInitializeWebTest { this.serverAddress = serverAddress; } - public LedgerRepository registLedger(HashDigest ledgerHash) { + public LedgerQuery registLedger(HashDigest ledgerHash) { // LedgerManage ledgerManager = ctx.getBean(LedgerManage.class); // // DbConnectionFactory dbConnFactory = ctx.getBean(DbConnectionFactory.class); @@ -397,7 +400,7 @@ public class LedgerInitializeWebTest { // DbConnection conn = db.connect(dbConnConfig.getUri(), // dbConnConfig.getPassword()); DbConnection conn = db.connect(dbConnConfig.getUri()); - LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, conn.getStorageService()); + LedgerQuery ledgerRepo = ledgerManager.register(ledgerHash, conn.getStorageService()); return ledgerRepo; } @@ -457,9 +460,8 @@ public class LedgerInitializeWebTest { return invoker.start(); } - public LedgerInitPermission preparePermision(PrivKey privKey, LedgerInitProperties setting, - ConsensusSettings csProps) { - return controller.prepareLocalPermission(id, privKey, setting, csProps); + public LedgerInitProposal preparePermision(PrivKey privKey, LedgerInitConfiguration initConfig) { + return controller.prepareLocalPermission(id, privKey, initConfig); } public boolean consensusPermission(PrivKey privKey) { diff --git a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerPerformanceTest.java b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerPerformanceTest.java index 76f3a1e7..c9d74a1d 100644 --- a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerPerformanceTest.java +++ b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerPerformanceTest.java @@ -7,35 +7,36 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.DoubleStream; -import com.jd.blockchain.crypto.*; -import com.jd.blockchain.ledger.core.CryptoConfig; +import com.jd.blockchain.ledger.*; import org.springframework.core.io.ClassPathResource; import com.jd.blockchain.binaryproto.DataContractRegistry; import com.jd.blockchain.consensus.ConsensusProvider; import com.jd.blockchain.consensus.ConsensusProviders; import com.jd.blockchain.consensus.ConsensusSettings; -import com.jd.blockchain.ledger.BlockchainIdentity; -import com.jd.blockchain.ledger.BlockchainKeyGenerator; -import com.jd.blockchain.ledger.BlockchainKeypair; -import com.jd.blockchain.ledger.BytesDataList; -import com.jd.blockchain.ledger.DataAccountKVSetOperation; -import com.jd.blockchain.ledger.DataAccountRegisterOperation; -import com.jd.blockchain.ledger.LedgerBlock; -import com.jd.blockchain.ledger.LedgerInitOperation; -import com.jd.blockchain.ledger.TransactionRequest; -import com.jd.blockchain.ledger.TransactionRequestBuilder; -import com.jd.blockchain.ledger.TransactionResponse; -import com.jd.blockchain.ledger.UserRegisterOperation; -import com.jd.blockchain.ledger.core.LedgerDataSet; +import com.jd.blockchain.crypto.AsymmetricKeypair; +import com.jd.blockchain.crypto.Crypto; +import com.jd.blockchain.crypto.CryptoAlgorithm; +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.KeyGenUtils; +import com.jd.blockchain.crypto.PrivKey; +import com.jd.blockchain.ledger.LedgerInitProperties; +import com.jd.blockchain.ledger.LedgerPermission; +import com.jd.blockchain.ledger.LedgerSecurityException; +import com.jd.blockchain.ledger.TransactionPermission; +import com.jd.blockchain.ledger.core.DefaultOperationHandleRegisteration; +import com.jd.blockchain.ledger.core.LedgerDataQuery; 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.impl.DefaultOperationHandleRegisteration; -import com.jd.blockchain.ledger.core.impl.LedgerManager; -import com.jd.blockchain.ledger.core.impl.TransactionBatchProcessor; +import com.jd.blockchain.ledger.core.LedgerSecurityManager; +import com.jd.blockchain.ledger.core.MultiIDsPolicy; +import com.jd.blockchain.ledger.core.SecurityPolicy; +import com.jd.blockchain.ledger.core.TransactionBatchProcessor; import com.jd.blockchain.service.TransactionBatchResultHandle; import com.jd.blockchain.storage.service.DbConnectionFactory; import com.jd.blockchain.storage.service.impl.redis.JedisConnection; @@ -44,12 +45,11 @@ import com.jd.blockchain.storage.service.impl.redis.RedisStorageService; import com.jd.blockchain.storage.service.impl.rocksdb.RocksDBConnectionFactory; import com.jd.blockchain.storage.service.utils.MemoryDBConnFactory; import com.jd.blockchain.tools.initializer.DBConnectionConfig; -import com.jd.blockchain.tools.initializer.LedgerInitProperties; import com.jd.blockchain.tools.initializer.Prompter; import com.jd.blockchain.tools.initializer.web.LedgerInitConsensusService; -import com.jd.blockchain.tools.keygen.KeyGenCommand; import com.jd.blockchain.transaction.TxBuilder; import com.jd.blockchain.utils.ArgumentSet; +import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.ConsoleUtils; import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback; import com.jd.blockchain.utils.io.FileUtils; @@ -87,8 +87,12 @@ public class LedgerPerformanceTest { DataContractRegistry.register(UserRegisterOperation.class); DataContractRegistry.register(DataAccountRegisterOperation.class); DataContractRegistry.register(DataAccountKVSetOperation.class); + DataContractRegistry.register(ParticipantRegisterOperation.class); + DataContractRegistry.register(ParticipantStateUpdateOperation.class); } + public static final LedgerSecurityManager DEFAULT_SECURITY_MANAGER = new FreedomLedgerSecurityManager(); + public static void test(String[] args) { NodeContext[] nodes = null; try { @@ -278,10 +282,10 @@ public class LedgerPerformanceTest { ConsoleUtils.info("\r\n\r\n================= 准备测试交易 [执行合约] ================="); LedgerBlock latestBlock = ledger.getLatestBlock(); - LedgerDataSet previousDataSet = ledger.getDataSet(latestBlock); + LedgerDataQuery previousDataSet = ledger.getLedgerData(latestBlock); LedgerEditor newEditor = ledger.createNextBlock(); - TransactionBatchProcessor txProc = new TransactionBatchProcessor(newEditor, previousDataSet, opHandler, - ledgerManager); + TransactionBatchProcessor txProc = new TransactionBatchProcessor(DEFAULT_SECURITY_MANAGER, newEditor, + ledger, opHandler); // 准备请求 int totalCount = batchSize * batchCount; @@ -311,15 +315,15 @@ public class LedgerPerformanceTest { long batchStartTs = System.currentTimeMillis(); for (int i = 0; i < batchCount; i++) { LedgerBlock latestBlock = ledger.getLatestBlock(); - LedgerDataSet previousDataSet = ledger.getDataSet(latestBlock); + LedgerDataQuery previousDataSet = ledger.getLedgerData(latestBlock); if (statistic) { ConsoleUtils.info("------ 开始执行交易, 即将生成区块[高度:%s] ------", (latestBlock.getHeight() + 1)); } long startTs = System.currentTimeMillis(); LedgerEditor newEditor = ledger.createNextBlock(); - TransactionBatchProcessor txProc = new TransactionBatchProcessor(newEditor, previousDataSet, opHandler, - ledgerManager); + TransactionBatchProcessor txProc = new TransactionBatchProcessor(DEFAULT_SECURITY_MANAGER, newEditor, + ledger, opHandler); testTxExec(txList, i * batchSize, batchSize, txProc); @@ -495,9 +499,8 @@ public class LedgerPerformanceTest { LedgerInitProperties initSetting = loadInitSetting(); Properties props = loadConsensusSetting(config); ConsensusProvider csProvider = getConsensusProvider(provider); - ConsensusSettings csProps = csProvider.getSettingsFactory() - .getConsensusSettingsBuilder() - .createSettings(props, Utils.loadParticipantNodes()); + ConsensusSettings csProps = csProvider.getSettingsFactory().getConsensusSettingsBuilder().createSettings(props, + Utils.loadParticipantNodes()); DBSetting dbsetting0; DBSetting dbsetting1; @@ -547,19 +550,19 @@ public class LedgerPerformanceTest { NodeContext node3 = new NodeContext(initSetting.getConsensusParticipant(3).getInitializerAddress(), serviceRegisterMap, dbsetting3.connectionFactory); - PrivKey privkey0 = KeyGenCommand.decodePrivKeyWithRawPassword(Utils.PRIV_KEYS[0], Utils.PASSWORD); + PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(Utils.PRIV_KEYS[0], Utils.PASSWORD); AsyncCallback callback0 = node0.startInit(0, privkey0, initSetting, csProps, csProvider, dbsetting0.connectionConfig, consolePrompter, !optimized, hashAlg); - PrivKey privkey1 = KeyGenCommand.decodePrivKeyWithRawPassword(Utils.PRIV_KEYS[1], Utils.PASSWORD); + PrivKey privkey1 = KeyGenUtils.decodePrivKeyWithRawPassword(Utils.PRIV_KEYS[1], Utils.PASSWORD); AsyncCallback callback1 = node1.startInit(1, privkey1, initSetting, csProps, csProvider, dbsetting1.connectionConfig, consolePrompter, !optimized, hashAlg); - PrivKey privkey2 = KeyGenCommand.decodePrivKeyWithRawPassword(Utils.PRIV_KEYS[2], Utils.PASSWORD); + PrivKey privkey2 = KeyGenUtils.decodePrivKeyWithRawPassword(Utils.PRIV_KEYS[2], Utils.PASSWORD); AsyncCallback callback2 = node2.startInit(2, privkey2, initSetting, csProps, csProvider, dbsetting2.connectionConfig, consolePrompter, !optimized, hashAlg); - PrivKey privkey3 = KeyGenCommand.decodePrivKeyWithRawPassword(Utils.PRIV_KEYS[3], Utils.PASSWORD); + PrivKey privkey3 = KeyGenUtils.decodePrivKeyWithRawPassword(Utils.PRIV_KEYS[3], Utils.PASSWORD); AsyncCallback callback3 = node3.startInit(3, privkey3, initSetting, csProps, csProvider, dbsetting3.connectionConfig, consolePrompter, !optimized, hashAlg); @@ -631,4 +634,94 @@ public class LedgerPerformanceTest { } } + + private static class FreedomLedgerSecurityManager implements LedgerSecurityManager { + + public static final FreedomLedgerSecurityManager INSTANCE = new FreedomLedgerSecurityManager(); + + @Override + public SecurityPolicy createSecurityPolicy(Set endpoints, Set nodes) { + return new FreedomSecurityPolicy(endpoints, nodes); + } + + } + + private static class FreedomSecurityPolicy implements SecurityPolicy { + + private Set endpoints; + private Set nodes; + + public FreedomSecurityPolicy(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 { + } + + } } diff --git a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/Utils.java b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/Utils.java index 80b133ad..d1e9409c 100644 --- a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/Utils.java +++ b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/Utils.java @@ -6,29 +6,41 @@ import java.util.Map; import java.util.Properties; import java.util.concurrent.ConcurrentHashMap; -import com.jd.blockchain.crypto.*; -import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; -import com.jd.blockchain.crypto.service.sm.SMCryptoService; -import com.jd.blockchain.ledger.ParticipantNode; -import com.jd.blockchain.tools.keygen.KeyGenCommand; +import com.jd.blockchain.ledger.ParticipantNodeState; import org.springframework.core.io.ClassPathResource; import com.jd.blockchain.consensus.ConsensusProvider; import com.jd.blockchain.consensus.ConsensusSettings; +import com.jd.blockchain.crypto.AddressEncoding; +import com.jd.blockchain.crypto.AsymmetricKeypair; +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.KeyGenUtils; +import com.jd.blockchain.crypto.PrivKey; +import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.crypto.SignatureDigest; +import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; +import com.jd.blockchain.crypto.service.sm.SMCryptoService; import com.jd.blockchain.ledger.CryptoSetting; +import com.jd.blockchain.ledger.LedgerInitProperties; +import com.jd.blockchain.ledger.ParticipantNode; import com.jd.blockchain.ledger.core.CryptoConfig; +import com.jd.blockchain.ledger.core.LedgerConfiguration; import com.jd.blockchain.ledger.core.LedgerInitDecision; -import com.jd.blockchain.ledger.core.LedgerInitPermission; -import com.jd.blockchain.ledger.core.LedgerRepository; -import com.jd.blockchain.ledger.core.impl.LedgerManager; +import com.jd.blockchain.ledger.core.LedgerInitProposal; +import com.jd.blockchain.ledger.core.LedgerManager; +import com.jd.blockchain.ledger.core.LedgerQuery; import com.jd.blockchain.storage.service.DbConnectionFactory; import com.jd.blockchain.tools.initializer.DBConnectionConfig; import com.jd.blockchain.tools.initializer.LedgerInitProcess; -import com.jd.blockchain.tools.initializer.LedgerInitProperties; import com.jd.blockchain.tools.initializer.Prompter; import com.jd.blockchain.tools.initializer.web.InitConsensusServiceFactory; +import com.jd.blockchain.tools.initializer.web.LedgerInitConfiguration; import com.jd.blockchain.tools.initializer.web.LedgerInitConsensusService; import com.jd.blockchain.tools.initializer.web.LedgerInitializeWebController; +import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.concurrent.ThreadInvoker; import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback; import com.jd.blockchain.utils.io.FileUtils; @@ -38,8 +50,7 @@ public class Utils { public static final String PASSWORD = "abc"; - public static final String[] PUB_KEYS = { - "3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9", + public static final String[] PUB_KEYS = { "3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9", "3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX", "3snPdw7i7PZi6TStiyc6mzjprnNhgs2atSGNS8wPYzhbKaUWGFJt7x", "3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk" }; @@ -77,7 +88,7 @@ public class Utils { public static ParticipantNode[] loadParticipantNodes() { ParticipantNode[] participantNodes = new ParticipantNode[PUB_KEYS.length]; for (int i = 0; i < PUB_KEYS.length; i++) { - participantNodes[i] = new PartNode(i, KeyGenCommand.decodePubKey(PUB_KEYS[i])); + participantNodes[i] = new PartNode(i, KeyGenUtils.decodePubKey(PUB_KEYS[i]), ParticipantNodeState.ACTIVED); } return participantNodes; } @@ -110,8 +121,8 @@ public class Utils { DbConnectionFactory dbConnFactory) { this.dbConnFactory = dbConnFactory; this.initCsServiceFactory = new MultiThreadInterInvokerFactory(serviceRegisterMap); - LedgerInitializeWebController initController = new LedgerInitializeWebController(ledgerManager, - dbConnFactory, initCsServiceFactory); + LedgerInitializeWebController initController = new LedgerInitializeWebController(dbConnFactory, + initCsServiceFactory); serviceRegisterMap.put(address, initController); this.initProcess = initController; } @@ -161,19 +172,23 @@ public class Utils { ConsensusSettings csProps, ConsensusProvider consensusProvider, DBConnectionConfig dbConnConfig, Prompter prompter, CryptoSetting cryptoSetting) { + LedgerInitConfiguration ledgerInitConfig = LedgerInitConfiguration.create(setting); + ledgerInitConfig.getLedgerSettings().setCryptoSetting(cryptoSetting); + partiKey = new AsymmetricKeypair(setting.getConsensusParticipant(0).getPubKey(), privKey); ThreadInvoker invoker = new ThreadInvoker() { @Override protected HashDigest invoke() throws Exception { - return initProcess.initialize(currentId, privKey, setting, dbConnConfig, prompter, cryptoSetting); + + return initProcess.initialize(currentId, privKey, setting, dbConnConfig, prompter); } }; return invoker.start(); } - public LedgerRepository registLedger(HashDigest ledgerHash, DBConnectionConfig dbConnConf) { + public LedgerQuery registLedger(HashDigest ledgerHash, DBConnectionConfig dbConnConf) { return ledgerManager.register(ledgerHash, dbConnFactory.connect(dbConnConf.getUri()).getStorageService()); } } @@ -202,10 +217,10 @@ public class Utils { } @Override - public LedgerInitPermission requestPermission(int requesterId, SignatureDigest signature) { - ThreadInvoker invoker = new ThreadInvoker() { + public LedgerInitProposal requestPermission(int requesterId, SignatureDigest signature) { + ThreadInvoker invoker = new ThreadInvoker() { @Override - protected LedgerInitPermission invoke() { + protected LedgerInitProposal invoke() { return initCsService.requestPermission(requesterId, signature); } }; @@ -229,21 +244,24 @@ public class Utils { private int id; - private String address; + private Bytes address; private String name; private PubKey pubKey; - public PartNode(int id, PubKey pubKey) { - this(id, id + "", pubKey); + private ParticipantNodeState participantNodeState; + + public PartNode(int id, PubKey pubKey, ParticipantNodeState participantNodeState) { + this(id, id + "", pubKey, participantNodeState); } - public PartNode(int id, String name, PubKey pubKey) { + public PartNode(int id, String name, PubKey pubKey, ParticipantNodeState participantNodeState) { this.id = id; this.name = name; this.pubKey = pubKey; - this.address = pubKey.toBase58(); + this.address = AddressEncoding.generateAddress(pubKey); + this.participantNodeState = participantNodeState; } @Override @@ -252,7 +270,7 @@ public class Utils { } @Override - public String getAddress() { + public Bytes getAddress() { return address; } @@ -265,6 +283,12 @@ public class Utils { public PubKey getPubKey() { return pubKey; } + + @Override + public ParticipantNodeState getParticipantNodeState() { + return participantNodeState; + } + } } diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java index a13445a5..9c3b3320 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java @@ -25,6 +25,7 @@ import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicLong; +import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.ledger.*; import org.apache.commons.io.FileUtils; import org.springframework.core.io.ClassPathResource; @@ -34,8 +35,8 @@ import com.jd.blockchain.contract.ReadContract; import com.jd.blockchain.crypto.AddressEncoding; import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.ledger.core.LedgerRepository; -import com.jd.blockchain.ledger.core.impl.LedgerManager; +import com.jd.blockchain.ledger.core.LedgerManager; +import com.jd.blockchain.ledger.core.LedgerQuery; import com.jd.blockchain.sdk.BlockchainService; import com.jd.blockchain.storage.service.DbConnection; import com.jd.blockchain.storage.service.DbConnectionFactory; @@ -166,7 +167,60 @@ public class IntegrationBase { return kvResponse; } - public static void validKeyPair(IntegrationBase.KeyPairResponse keyPairResponse, LedgerRepository ledgerRepository, + public static KeyPairResponse testSDK_RegisterParticipant(AsymmetricKeypair adminKey, HashDigest ledgerHash, + BlockchainService blockchainService) { + // 注册参与方,并验证最终写入; + BlockchainKeypair participant = BlockchainKeyGenerator.getInstance().generate(); + + // 定义交易; + TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); + + txTpl.participants().register("peer4", new BlockchainIdentityData(participant.getPubKey()), new NetworkAddress("127.0.0.1", 20000)); + + // 签名; + PreparedTransaction ptx = txTpl.prepare(); + + HashDigest transactionHash = ptx.getHash(); + + ptx.sign(adminKey); + + // 提交并等待共识返回; + TransactionResponse txResp = ptx.commit(); + + KeyPairResponse keyPairResponse = new KeyPairResponse(); + keyPairResponse.keyPair = participant; + keyPairResponse.txResp = txResp; + keyPairResponse.txHash = transactionHash; + return keyPairResponse; + } + + public static KeyPairResponse testSDK_UpdateParticipantState(AsymmetricKeypair adminKey, BlockchainKeypair participantKeyPair, HashDigest ledgerHash, + BlockchainService blockchainService) { + // 定义交易; + TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); + + ParticipantInfoData participantInfoData = new ParticipantInfoData("peer4", participantKeyPair.getPubKey(), new NetworkAddress("127.0.0.1", 20000)); + + txTpl.states().update(new BlockchainIdentityData(participantInfoData.getPubKey()), participantInfoData.getNetworkAddress(), ParticipantNodeState.ACTIVED); + + // 签名; + PreparedTransaction ptx = txTpl.prepare(); + + HashDigest transactionHash = ptx.getHash(); + + ptx.sign(adminKey); + + // 提交并等待共识返回; + TransactionResponse txResp = ptx.commit(); + + KeyPairResponse keyPairResponse = new KeyPairResponse(); + keyPairResponse.keyPair = participantKeyPair; + keyPairResponse.txResp = txResp; + keyPairResponse.txHash = transactionHash; + return keyPairResponse; + } + + public static void validKeyPair(IntegrationBase.KeyPairResponse keyPairResponse, LedgerQuery ledgerRepository, KeyPairType keyPairType) { TransactionResponse txResp = keyPairResponse.txResp; HashDigest transactionHash = keyPairResponse.txHash; @@ -186,12 +240,12 @@ public class IntegrationBase { if (keyPairType == KeyPairType.DATAACCOUNT) { assertNotNull(ledgerRepository.getDataAccountSet(ledgerRepository.getLatestBlock()) - .getDataAccount(keyPair.getAddress())); + .getAccount(keyPair.getAddress())); } System.out.printf("validKeyPair end %s \r\n", index); } - public static void validKeyPair(IntegrationBase.KeyPairResponse keyPairResponse, LedgerRepository ledgerRepository, + public static void validKeyPair(IntegrationBase.KeyPairResponse keyPairResponse, LedgerQuery ledgerRepository, KeyPairType keyPairType, CountDownLatch countDownLatch) { TransactionResponse txResp = keyPairResponse.txResp; @@ -210,12 +264,12 @@ public class IntegrationBase { if (keyPairType == KeyPairType.DATAACCOUNT) { assertNotNull(ledgerRepository.getDataAccountSet(ledgerRepository.getLatestBlock()) - .getDataAccount(keyPair.getAddress())); + .getAccount(keyPair.getAddress())); } countDownLatch.countDown(); } - public static void validKvWrite(IntegrationBase.KvResponse kvResponse, LedgerRepository ledgerRepository, + public static void validKvWrite(IntegrationBase.KvResponse kvResponse, LedgerQuery ledgerRepository, BlockchainService blockchainService) { // 先验证应答 TransactionResponse txResp = kvResponse.getTxResp(); @@ -240,10 +294,10 @@ public class IntegrationBase { } } - public static LedgerRepository[] buildLedgers(LedgerBindingConfig[] bindingConfigs, + public static LedgerQuery[] buildLedgers(LedgerBindingConfig[] bindingConfigs, DbConnectionFactory[] dbConnectionFactories) { int[] ids = { 0, 1, 2, 3 }; - LedgerRepository[] ledgers = new LedgerRepository[ids.length]; + LedgerQuery[] ledgers = new LedgerQuery[ids.length]; LedgerManager[] ledgerManagers = new LedgerManager[ids.length]; for (int i = 0; i < ids.length; i++) { ledgerManagers[i] = new LedgerManager(); @@ -255,11 +309,11 @@ public class IntegrationBase { return ledgers; } - public static void testConsistencyAmongNodes(LedgerRepository[] ledgers) { - LedgerRepository ledger0 = ledgers[0]; + public static void testConsistencyAmongNodes(LedgerQuery[] ledgers) { + LedgerQuery ledger0 = ledgers[0]; LedgerBlock latestBlock0 = ledger0.retrieveLatestBlock(); for (int i = 1; i < ledgers.length; i++) { - LedgerRepository otherLedger = ledgers[i]; + LedgerQuery otherLedger = ledgers[i]; LedgerBlock otherLatestBlock = otherLedger.retrieveLatestBlock(); assertEquals(ledger0.getHash(), otherLedger.getHash()); assertEquals(ledger0.getLatestBlockHeight(), otherLedger.getLatestBlockHeight()); @@ -447,7 +501,7 @@ public class IntegrationBase { static HashDigest txContentHash; public static LedgerBlock testSDK_Contract(AsymmetricKeypair adminKey, HashDigest ledgerHash, - BlockchainService blockchainService, LedgerRepository ledgerRepository) { + BlockchainService blockchainService, LedgerQuery ledgerRepository) { KeyPairResponse keyPairResponse = testSDK_RegisterDataAccount(adminKey,ledgerHash,blockchainService); System.out.println("adminKey=" + AddressEncoding.generateAddress(adminKey.getPubKey())); @@ -473,7 +527,7 @@ public class IntegrationBase { LedgerBlock block = ledgerRepository.getBlock(txResp.getBlockHeight()); byte[] contractCodeInDb = ledgerRepository.getContractAccountSet(block) - .getContract(contractDeployKey.getAddress()).getChainCode(); + .getAccount(contractDeployKey.getAddress()).getChainCode(); assertArrayEquals(contractCode, contractCodeInDb); // execute the contract; diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBaseTest.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBaseTest.java index 0fb2d461..d28a2b45 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBaseTest.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBaseTest.java @@ -14,15 +14,15 @@ import com.jd.blockchain.consensus.ConsensusProvider; import com.jd.blockchain.consensus.ConsensusSettings; import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig; import com.jd.blockchain.ledger.LedgerBlock; -import com.jd.blockchain.ledger.core.LedgerRepository; +import com.jd.blockchain.ledger.LedgerInitProperties; +import com.jd.blockchain.ledger.core.LedgerQuery; import com.jd.blockchain.tools.initializer.DBConnectionConfig; import com.jd.blockchain.tools.initializer.LedgerBindingConfig; -import com.jd.blockchain.tools.initializer.LedgerInitProperties; import com.jd.blockchain.tools.initializer.Prompter; -import com.jd.blockchain.tools.keygen.KeyGenCommand; import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback; import com.jd.blockchain.utils.net.NetworkAddress; @@ -68,7 +68,7 @@ public class IntegrationBaseTest { peerStarting2.waitReturn(); peerStarting3.waitReturn(); - String encodedBase58Pwd = KeyGenCommand.encodePasswordAsBase58(LedgerInitializeWeb4SingleStepsTest.PASSWORD); + String encodedBase58Pwd = KeyGenUtils.encodePasswordAsBase58(LedgerInitializeWeb4SingleStepsTest.PASSWORD); KeyPairConfig gwkey0 = new KeyPairConfig(); gwkey0.setPubKeyValue(LedgerInitializeWeb4SingleStepsTest.PUB_KEYS[0]); @@ -92,16 +92,16 @@ public class IntegrationBaseTest { public void testConsistencyAmongNodes(IntegratedContext context) { int[] ids = context.getNodeIds(); Node[] nodes = new Node[ids.length]; - LedgerRepository[] ledgers = new LedgerRepository[ids.length]; + LedgerQuery[] ledgers = new LedgerQuery[ids.length]; for (int i = 0; i < nodes.length; i++) { nodes[i] = context.getNode(ids[i]); HashDigest ledgerHash = nodes[i].getLedgerManager().getLedgerHashs()[0]; ledgers[i] = nodes[i].getLedgerManager().getLedger(ledgerHash); } - LedgerRepository ledger0 = ledgers[0]; + LedgerQuery ledger0 = ledgers[0]; LedgerBlock latestBlock0 = ledger0.retrieveLatestBlock(); for (int i = 1; i < ledgers.length; i++) { - LedgerRepository otherLedger = ledgers[i]; + LedgerQuery otherLedger = ledgers[i]; LedgerBlock otherLatestBlock = otherLedger.retrieveLatestBlock(); assertEquals(ledger0.getHash(), otherLedger.getHash()); assertEquals(ledger0.getLatestBlockHeight(), otherLedger.getLatestBlockHeight()); @@ -140,16 +140,16 @@ public class IntegrationBaseTest { NetworkAddress initAddr3 = initSetting.getConsensusParticipant(3).getInitializerAddress(); NodeWebContext nodeCtx3 = new NodeWebContext(3, initAddr3); - PrivKey privkey0 = KeyGenCommand.decodePrivKeyWithRawPassword(LedgerInitializeWeb4SingleStepsTest.PRIV_KEYS[0], + PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(LedgerInitializeWeb4SingleStepsTest.PRIV_KEYS[0], LedgerInitializeWeb4SingleStepsTest.PASSWORD); - PrivKey privkey1 = KeyGenCommand.decodePrivKeyWithRawPassword(LedgerInitializeWeb4SingleStepsTest.PRIV_KEYS[1], + PrivKey privkey1 = KeyGenUtils.decodePrivKeyWithRawPassword(LedgerInitializeWeb4SingleStepsTest.PRIV_KEYS[1], LedgerInitializeWeb4SingleStepsTest.PASSWORD); - PrivKey privkey2 = KeyGenCommand.decodePrivKeyWithRawPassword(LedgerInitializeWeb4SingleStepsTest.PRIV_KEYS[2], + PrivKey privkey2 = KeyGenUtils.decodePrivKeyWithRawPassword(LedgerInitializeWeb4SingleStepsTest.PRIV_KEYS[2], LedgerInitializeWeb4SingleStepsTest.PASSWORD); - PrivKey privkey3 = KeyGenCommand.decodePrivKeyWithRawPassword(LedgerInitializeWeb4SingleStepsTest.PRIV_KEYS[3], + PrivKey privkey3 = KeyGenUtils.decodePrivKeyWithRawPassword(LedgerInitializeWeb4SingleStepsTest.PRIV_KEYS[3], LedgerInitializeWeb4SingleStepsTest.PASSWORD); - String encodedPassword = KeyGenCommand.encodePasswordAsBase58(LedgerInitializeWeb4SingleStepsTest.PASSWORD); + String encodedPassword = KeyGenUtils.encodePasswordAsBase58(LedgerInitializeWeb4SingleStepsTest.PASSWORD); CountDownLatch quitLatch = new CountDownLatch(4); @@ -187,10 +187,10 @@ public class IntegrationBaseTest { assertEquals(ledgerHash0, ledgerHash2); assertEquals(ledgerHash0, ledgerHash3); - LedgerRepository ledger0 = nodeCtx0.registLedger(ledgerHash0); - LedgerRepository ledger1 = nodeCtx1.registLedger(ledgerHash1); - LedgerRepository ledger2 = nodeCtx2.registLedger(ledgerHash2); - LedgerRepository ledger3 = nodeCtx3.registLedger(ledgerHash3); + LedgerQuery ledger0 = nodeCtx0.registLedger(ledgerHash0); + LedgerQuery ledger1 = nodeCtx1.registLedger(ledgerHash1); + LedgerQuery ledger2 = nodeCtx2.registLedger(ledgerHash2); + LedgerQuery ledger3 = nodeCtx3.registLedger(ledgerHash3); assertNotNull(ledger0); assertNotNull(ledger1); diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest2.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest2.java index 3e5a1e85..683ed91f 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest2.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest2.java @@ -18,23 +18,23 @@ import com.jd.blockchain.consensus.ConsensusProvider; import com.jd.blockchain.consensus.ConsensusSettings; import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig; import com.jd.blockchain.ledger.BlockchainKeyGenerator; import com.jd.blockchain.ledger.BlockchainKeypair; import com.jd.blockchain.ledger.LedgerBlock; import com.jd.blockchain.ledger.LedgerInfo; +import com.jd.blockchain.ledger.LedgerInitProperties; import com.jd.blockchain.ledger.PreparedTransaction; import com.jd.blockchain.ledger.TransactionResponse; import com.jd.blockchain.ledger.TransactionTemplate; -import com.jd.blockchain.ledger.core.LedgerRepository; +import com.jd.blockchain.ledger.core.LedgerQuery; import com.jd.blockchain.sdk.BlockchainService; import com.jd.blockchain.sdk.client.GatewayServiceFactory; import com.jd.blockchain.tools.initializer.DBConnectionConfig; import com.jd.blockchain.tools.initializer.LedgerBindingConfig; -import com.jd.blockchain.tools.initializer.LedgerInitProperties; import com.jd.blockchain.tools.initializer.Prompter; -import com.jd.blockchain.tools.keygen.KeyGenCommand; import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback; import com.jd.blockchain.utils.net.NetworkAddress; @@ -85,7 +85,7 @@ public class IntegrationTest2 { peerStarting2.waitReturn(); peerStarting3.waitReturn(); - String encodedBase58Pwd = KeyGenCommand.encodePasswordAsBase58(LedgerInitializeWeb4SingleStepsTest.PASSWORD); + String encodedBase58Pwd = KeyGenUtils.encodePasswordAsBase58(LedgerInitializeWeb4SingleStepsTest.PASSWORD); KeyPairConfig gwkey0 = new KeyPairConfig(); gwkey0.setPubKeyValue(LedgerInitializeWeb4SingleStepsTest.PUB_KEYS[0]); @@ -117,16 +117,16 @@ public class IntegrationTest2 { private void testConsistencyAmongNodes(IntegratedContext context) { int[] ids = context.getNodeIds(); Node[] nodes = new Node[ids.length]; - LedgerRepository[] ledgers = new LedgerRepository[ids.length]; + LedgerQuery[] ledgers = new LedgerQuery[ids.length]; for (int i = 0; i < nodes.length; i++) { nodes[i] = context.getNode(ids[i]); HashDigest ledgerHash = nodes[i].getLedgerManager().getLedgerHashs()[0]; ledgers[i] = nodes[i].getLedgerManager().getLedger(ledgerHash); } - LedgerRepository ledger0 = ledgers[0]; + LedgerQuery ledger0 = ledgers[0]; LedgerBlock latestBlock0 = ledger0.retrieveLatestBlock(); for (int i = 1; i < ledgers.length; i++) { - LedgerRepository otherLedger = ledgers[i]; + LedgerQuery otherLedger = ledgers[i]; LedgerBlock otherLatestBlock = otherLedger.retrieveLatestBlock(); assertEquals(ledger0.getHash(), otherLedger.getHash()); assertEquals(ledger0.getLatestBlockHeight(), otherLedger.getLatestBlockHeight()); @@ -178,16 +178,16 @@ public class IntegrationTest2 { NetworkAddress initAddr3 = initSetting.getConsensusParticipant(3).getInitializerAddress(); NodeWebContext nodeCtx3 = new NodeWebContext(3, initAddr3); - PrivKey privkey0 = KeyGenCommand.decodePrivKeyWithRawPassword(LedgerInitializeWeb4SingleStepsTest.PRIV_KEYS[0], + PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(LedgerInitializeWeb4SingleStepsTest.PRIV_KEYS[0], LedgerInitializeWeb4SingleStepsTest.PASSWORD); - PrivKey privkey1 = KeyGenCommand.decodePrivKeyWithRawPassword(LedgerInitializeWeb4SingleStepsTest.PRIV_KEYS[1], + PrivKey privkey1 = KeyGenUtils.decodePrivKeyWithRawPassword(LedgerInitializeWeb4SingleStepsTest.PRIV_KEYS[1], LedgerInitializeWeb4SingleStepsTest.PASSWORD); - PrivKey privkey2 = KeyGenCommand.decodePrivKeyWithRawPassword(LedgerInitializeWeb4SingleStepsTest.PRIV_KEYS[2], + PrivKey privkey2 = KeyGenUtils.decodePrivKeyWithRawPassword(LedgerInitializeWeb4SingleStepsTest.PRIV_KEYS[2], LedgerInitializeWeb4SingleStepsTest.PASSWORD); - PrivKey privkey3 = KeyGenCommand.decodePrivKeyWithRawPassword(LedgerInitializeWeb4SingleStepsTest.PRIV_KEYS[3], + PrivKey privkey3 = KeyGenUtils.decodePrivKeyWithRawPassword(LedgerInitializeWeb4SingleStepsTest.PRIV_KEYS[3], LedgerInitializeWeb4SingleStepsTest.PASSWORD); - String encodedPassword = KeyGenCommand.encodePasswordAsBase58(LedgerInitializeWeb4SingleStepsTest.PASSWORD); + String encodedPassword = KeyGenUtils.encodePasswordAsBase58(LedgerInitializeWeb4SingleStepsTest.PASSWORD); CountDownLatch quitLatch = new CountDownLatch(4); @@ -225,10 +225,10 @@ public class IntegrationTest2 { assertEquals(ledgerHash0, ledgerHash2); assertEquals(ledgerHash0, ledgerHash3); - LedgerRepository ledger0 = nodeCtx0.registLedger(ledgerHash0); - LedgerRepository ledger1 = nodeCtx1.registLedger(ledgerHash1); - LedgerRepository ledger2 = nodeCtx2.registLedger(ledgerHash2); - LedgerRepository ledger3 = nodeCtx3.registLedger(ledgerHash3); + LedgerQuery ledger0 = nodeCtx0.registLedger(ledgerHash0); + LedgerQuery ledger1 = nodeCtx1.registLedger(ledgerHash1); + LedgerQuery ledger2 = nodeCtx2.registLedger(ledgerHash2); + LedgerQuery ledger3 = nodeCtx3.registLedger(ledgerHash3); assertNotNull(ledger0); assertNotNull(ledger1); diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4Bftsmart.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4Bftsmart.java index 9b7ae2ba..28efbdb2 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4Bftsmart.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4Bftsmart.java @@ -1,17 +1,22 @@ package test.com.jd.blockchain.intgr; +import com.jd.blockchain.consensus.ConsensusProviders; +import com.jd.blockchain.consensus.bftsmart.BftsmartConsensusSettings; import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.gateway.GatewayConfigProperties; import com.jd.blockchain.ledger.BlockchainKeypair; -import com.jd.blockchain.ledger.core.LedgerRepository; +import com.jd.blockchain.ledger.ParticipantNodeState; +import com.jd.blockchain.ledger.ParticipantStateUpdateInfo; +import com.jd.blockchain.ledger.ParticipantStateUpdateInfoData; +import com.jd.blockchain.ledger.core.LedgerQuery; import com.jd.blockchain.sdk.BlockchainService; import com.jd.blockchain.sdk.client.GatewayServiceFactory; import com.jd.blockchain.storage.service.DbConnectionFactory; import com.jd.blockchain.tools.initializer.LedgerBindingConfig; -import com.jd.blockchain.tools.keygen.KeyGenCommand; import com.jd.blockchain.utils.concurrent.ThreadInvoker; import org.junit.Test; @@ -30,6 +35,10 @@ public class IntegrationTest4Bftsmart { private static final boolean isRegisterDataAccount = true; + private static final boolean isRegisterParticipant = true; + + private static final boolean isParticipantStateUpdate = true; + private static final boolean isWriteKv = true; private static final String DB_TYPE_MEM = "mem"; @@ -38,6 +47,8 @@ public class IntegrationTest4Bftsmart { private static final String DB_TYPE_ROCKSDB = "rocksdb"; + public static final String BFTSMART_PROVIDER = "com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider"; + @Test public void test4Memory() { test(LedgerInitConsensusConfig.bftsmartProvider, DB_TYPE_MEM, LedgerInitConsensusConfig.memConnectionStrings); @@ -65,7 +76,7 @@ public class IntegrationTest4Bftsmart { DbConnectionFactory dbConnectionFactory2 = peerNodes[2].getDBConnectionFactory(); DbConnectionFactory dbConnectionFactory3 = peerNodes[3].getDBConnectionFactory(); - String encodedBase58Pwd = KeyGenCommand.encodePasswordAsBase58(LedgerInitializeTest.PASSWORD); + String encodedBase58Pwd = KeyGenUtils.encodePasswordAsBase58(LedgerInitializeTest.PASSWORD); GatewayConfigProperties.KeyPairConfig gwkey0 = new GatewayConfigProperties.KeyPairConfig(); gwkey0.setPubKeyValue(IntegrationBase.PUB_KEYS[0]); @@ -79,7 +90,7 @@ public class IntegrationTest4Bftsmart { gwStarting.waitReturn(); // 执行测试用例之前,校验每个节点的一致性; - LedgerRepository[] ledgers = buildLedgers(new LedgerBindingConfig[]{ + LedgerQuery[] ledgers = buildLedgers(new LedgerBindingConfig[]{ peerNodes[0].getLedgerBindingConfig(), peerNodes[1].getLedgerBindingConfig(), peerNodes[2].getLedgerBindingConfig(), @@ -93,13 +104,13 @@ public class IntegrationTest4Bftsmart { IntegrationBase.testConsistencyAmongNodes(ledgers); - LedgerRepository ledgerRepository = ledgers[0]; + LedgerQuery ledgerRepository = ledgers[0]; GatewayServiceFactory gwsrvFact = GatewayServiceFactory.connect(gateway.getServiceAddress()); - PrivKey privkey0 = KeyGenCommand.decodePrivKeyWithRawPassword(IntegrationBase.PRIV_KEYS[0], IntegrationBase.PASSWORD); + PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(IntegrationBase.PRIV_KEYS[0], IntegrationBase.PASSWORD); - PubKey pubKey0 = KeyGenCommand.decodePubKey(IntegrationBase.PUB_KEYS[0]); + PubKey pubKey0 = KeyGenUtils.decodePubKey(IntegrationBase.PUB_KEYS[0]); AsymmetricKeypair adminKey = new AsymmetricKeypair(pubKey0, privkey0); @@ -140,6 +151,41 @@ public class IntegrationTest4Bftsmart { } } + long participantCount = ledgerRepository.getAdminInfo(ledgerRepository.retrieveLatestBlock()).getParticipantCount(); + + long userCount = ledgerRepository.getUserAccountSet(ledgerRepository.retrieveLatestBlock()).getTotal(); + + System.out.printf("before add participant: participantCount = %d, userCount = %d\r\n", (int)participantCount, (int)userCount); + + IntegrationBase.KeyPairResponse participantResponse; + if (isRegisterParticipant) { + participantResponse = IntegrationBase.testSDK_RegisterParticipant(adminKey, ledgerHash, blockchainService); + } + + participantCount = ledgerRepository.getAdminInfo(ledgerRepository.retrieveLatestBlock()).getParticipantCount(); + + userCount = ledgerRepository.getUserAccountSet(ledgerRepository.retrieveLatestBlock()).getTotal(); + + System.out.printf("after add participant: participantCount = %d, userCount = %d\r\n", (int)participantCount, (int)userCount); + + BftsmartConsensusSettings consensusSettings = (BftsmartConsensusSettings) ConsensusProviders.getProvider(BFTSMART_PROVIDER).getSettingsFactory().getConsensusSettingsEncoder().decode(ledgerRepository.getAdminInfo().getSettings().getConsensusSetting().toBytes()); + System.out.printf("update participant state before ,old consensus env node num = %d\r\n", consensusSettings.getNodes().length); + + for (int i = 0; i < participantCount; i++) { + System.out.printf("part%d state = %d\r\n",i, ledgerRepository.getAdminInfo(ledgerRepository.retrieveLatestBlock()).getParticipants()[i].getParticipantNodeState().CODE); + } + + if (isParticipantStateUpdate) { + IntegrationBase.testSDK_UpdateParticipantState(adminKey, new BlockchainKeypair(participantResponse.getKeyPair().getPubKey(), participantResponse.getKeyPair().getPrivKey()), ledgerHash, blockchainService); + } + + BftsmartConsensusSettings consensusSettingsNew = (BftsmartConsensusSettings) ConsensusProviders.getProvider(BFTSMART_PROVIDER).getSettingsFactory().getConsensusSettingsEncoder().decode(ledgerRepository.getAdminInfo(ledgerRepository.retrieveLatestBlock()).getSettings().getConsensusSetting().toBytes()); + + System.out.printf("update participant state after ,new consensus env node num = %d\r\n", consensusSettingsNew.getNodes().length); + for (int i = 0; i < participantCount; i++) { + System.out.printf("part%d state = %d\r\n",i, ledgerRepository.getAdminInfo(ledgerRepository.retrieveLatestBlock()).getParticipants()[i].getParticipantNodeState().CODE); + } + try { System.out.println("----------------- Init Completed -----------------"); Thread.sleep(Integer.MAX_VALUE); diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4Contract.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4Contract.java index b2067f62..098b7385 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4Contract.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4Contract.java @@ -2,16 +2,16 @@ package test.com.jd.blockchain.intgr; import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.gateway.GatewayConfigProperties; import com.jd.blockchain.ledger.BlockchainKeypair; -import com.jd.blockchain.ledger.core.LedgerRepository; +import com.jd.blockchain.ledger.core.LedgerQuery; import com.jd.blockchain.sdk.BlockchainService; import com.jd.blockchain.sdk.client.GatewayServiceFactory; import com.jd.blockchain.storage.service.DbConnectionFactory; import com.jd.blockchain.tools.initializer.LedgerBindingConfig; -import com.jd.blockchain.tools.keygen.KeyGenCommand; import com.jd.blockchain.utils.concurrent.ThreadInvoker; import org.junit.Test; @@ -46,7 +46,7 @@ public class IntegrationTest4Contract { DbConnectionFactory dbConnectionFactory2 = peerNodes[2].getDBConnectionFactory(); DbConnectionFactory dbConnectionFactory3 = peerNodes[3].getDBConnectionFactory(); - String encodedBase58Pwd = KeyGenCommand.encodePasswordAsBase58(LedgerInitializeTest.PASSWORD); + String encodedBase58Pwd = KeyGenUtils.encodePasswordAsBase58(LedgerInitializeTest.PASSWORD); GatewayConfigProperties.KeyPairConfig gwkey0 = new GatewayConfigProperties.KeyPairConfig(); gwkey0.setPubKeyValue(IntegrationBase.PUB_KEYS[0]); @@ -60,7 +60,7 @@ public class IntegrationTest4Contract { gwStarting.waitReturn(); // 执行测试用例之前,校验每个节点的一致性; - LedgerRepository[] ledgers = buildLedgers(new LedgerBindingConfig[]{ + LedgerQuery[] ledgers = buildLedgers(new LedgerBindingConfig[]{ peerNodes[0].getLedgerBindingConfig(), peerNodes[1].getLedgerBindingConfig(), peerNodes[2].getLedgerBindingConfig(), @@ -74,13 +74,13 @@ public class IntegrationTest4Contract { IntegrationBase.testConsistencyAmongNodes(ledgers); - LedgerRepository ledgerRepository = ledgers[0]; + LedgerQuery ledgerRepository = ledgers[0]; GatewayServiceFactory gwsrvFact = GatewayServiceFactory.connect(gateway.getServiceAddress()); - PrivKey privkey0 = KeyGenCommand.decodePrivKeyWithRawPassword(IntegrationBase.PRIV_KEYS[0], IntegrationBase.PASSWORD); + PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(IntegrationBase.PRIV_KEYS[0], IntegrationBase.PASSWORD); - PubKey pubKey0 = KeyGenCommand.decodePubKey(IntegrationBase.PUB_KEYS[0]); + PubKey pubKey0 = KeyGenUtils.decodePubKey(IntegrationBase.PUB_KEYS[0]); AsymmetricKeypair adminKey = new AsymmetricKeypair(pubKey0, privkey0); diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4MQ.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4MQ.java index 6e8c7f1a..c8426253 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4MQ.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest4MQ.java @@ -1,7 +1,11 @@ package test.com.jd.blockchain.intgr; +import com.jd.blockchain.consensus.ConsensusProviders; +import com.jd.blockchain.consensus.bftsmart.BftsmartConsensusSettings; +import com.jd.blockchain.consensus.mq.settings.MsgQueueConsensusSettings; import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig; @@ -11,7 +15,6 @@ import com.jd.blockchain.sdk.BlockchainService; import com.jd.blockchain.sdk.client.GatewayServiceFactory; import com.jd.blockchain.storage.service.DbConnectionFactory; import com.jd.blockchain.tools.initializer.LedgerBindingConfig; -import com.jd.blockchain.tools.keygen.KeyGenCommand; import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback; import com.jd.blockchain.utils.io.FileUtils; @@ -30,6 +33,10 @@ public class IntegrationTest4MQ { private static final boolean isRegisterDataAccount = true; + private static final boolean isRegisterParticipant = true; + + private static final boolean isParticipantStateUpdate = true; + private static final boolean isWriteKv = true; private static final boolean isContract = false; @@ -44,6 +51,8 @@ public class IntegrationTest4MQ { private static final String DATA_RETRIEVAL_URL= "http://192.168.151.39:10001"; + public static final String MQ_PROVIDER = "com.jd.blockchain.consensus.mq.MsgQueueConsensusProvider"; + @Test public void test4Memory() { test(LedgerInitConsensusConfig.mqProvider, DB_TYPE_MEM, LedgerInitConsensusConfig.memConnectionStrings); @@ -72,7 +81,7 @@ public class IntegrationTest4MQ { DbConnectionFactory dbConnectionFactory2 = peerNodes[2].getDBConnectionFactory(); DbConnectionFactory dbConnectionFactory3 = peerNodes[3].getDBConnectionFactory(); - String encodedBase58Pwd = KeyGenCommand.encodePasswordAsBase58(LedgerInitializeTest.PASSWORD); + String encodedBase58Pwd = KeyGenUtils.encodePasswordAsBase58(LedgerInitializeTest.PASSWORD); KeyPairConfig gwkey0 = new KeyPairConfig(); gwkey0.setPubKeyValue(IntegrationBase.PUB_KEYS[0]); @@ -89,7 +98,7 @@ public class IntegrationTest4MQ { gwStarting.waitReturn(); // 执行测试用例之前,校验每个节点的一致性; - LedgerRepository[] ledgers = buildLedgers(new LedgerBindingConfig[]{ + LedgerQuery[] ledgers = buildLedgers(new LedgerBindingConfig[]{ peerNodes[0].getLedgerBindingConfig(), peerNodes[1].getLedgerBindingConfig(), peerNodes[2].getLedgerBindingConfig(), @@ -103,13 +112,13 @@ public class IntegrationTest4MQ { IntegrationBase.testConsistencyAmongNodes(ledgers); - LedgerRepository ledgerRepository = ledgers[0]; + LedgerQuery ledgerRepository = ledgers[0]; GatewayServiceFactory gwsrvFact = GatewayServiceFactory.connect(gateway.getServiceAddress()); - PrivKey privkey0 = KeyGenCommand.decodePrivKeyWithRawPassword(IntegrationBase.PRIV_KEYS[0], IntegrationBase.PASSWORD); + PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(IntegrationBase.PRIV_KEYS[0], IntegrationBase.PASSWORD); - PubKey pubKey0 = KeyGenCommand.decodePubKey(IntegrationBase.PUB_KEYS[0]); + PubKey pubKey0 = KeyGenUtils.decodePubKey(IntegrationBase.PUB_KEYS[0]); AsymmetricKeypair adminKey = new AsymmetricKeypair(pubKey0, privkey0); @@ -138,6 +147,43 @@ public class IntegrationTest4MQ { integrationBase.testSDK_Contract(adminKey, ledgerHash, blockchainService,ledgerRepository); } + long participantCount = ledgerRepository.getAdminInfo(ledgerRepository.retrieveLatestBlock()).getParticipantCount(); + + long userCount = ledgerRepository.getUserAccountSet(ledgerRepository.retrieveLatestBlock()).getTotal(); + + System.out.printf("before add participant: participantCount = %d, userCount = %d\r\n", (int)participantCount, (int)userCount); + + IntegrationBase.KeyPairResponse participantResponse; + if (isRegisterParticipant) { + participantResponse = IntegrationBase.testSDK_RegisterParticipant(adminKey, ledgerHash, blockchainService); + } + + participantCount = ledgerRepository.getAdminInfo(ledgerRepository.retrieveLatestBlock()).getParticipantCount(); + + userCount = ledgerRepository.getUserAccountSet(ledgerRepository.retrieveLatestBlock()).getTotal(); + + System.out.printf("after add participant: participantCount = %d, userCount = %d\r\n", (int)participantCount, (int)userCount); + + MsgQueueConsensusSettings consensusSettings = (MsgQueueConsensusSettings) ConsensusProviders.getProvider(MQ_PROVIDER).getSettingsFactory().getConsensusSettingsEncoder().decode(ledgerRepository.getAdminInfo().getSettings().getConsensusSetting().toBytes()); + + System.out.printf("update participant state before ,old consensus env node num = %d\r\n", consensusSettings.getNodes().length); + + for (int i = 0; i < participantCount; i++) { + System.out.printf("part%d state = %d\r\n",i, ledgerRepository.getAdminInfo(ledgerRepository.retrieveLatestBlock()).getParticipants()[i].getParticipantNodeState().CODE); + } + + if (isParticipantStateUpdate) { + IntegrationBase.testSDK_UpdateParticipantState(adminKey, new BlockchainKeypair(participantResponse.getKeyPair().getPubKey(), participantResponse.getKeyPair().getPrivKey()), ledgerHash, blockchainService); + } + + BftsmartConsensusSettings consensusSettingsNew = (BftsmartConsensusSettings) ConsensusProviders.getProvider(MQ_PROVIDER).getSettingsFactory().getConsensusSettingsEncoder().decode(ledgerRepository.getAdminInfo(ledgerRepository.retrieveLatestBlock()).getSettings().getConsensusSetting().toBytes()); + + System.out.printf("update participant state after ,new consensus env node num = %d\r\n", consensusSettingsNew.getNodes().length); + + for (int i = 0; i < participantCount; i++) { + System.out.printf("part%d state = %d\r\n",i, ledgerRepository.getAdminInfo(ledgerRepository.retrieveLatestBlock()).getParticipants()[i].getParticipantNodeState().CODE); + } + IntegrationBase.testConsistencyAmongNodes(ledgers); if(isOnline){ diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestAll4Redis.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestAll4Redis.java index 9dd3ea10..50ccb64c 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestAll4Redis.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestAll4Redis.java @@ -2,20 +2,17 @@ package test.com.jd.blockchain.intgr; import com.jd.blockchain.crypto.*; import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig; -import com.jd.blockchain.ledger.BytesValue; import com.jd.blockchain.ledger.*; import com.jd.blockchain.ledger.core.DataAccount; -import com.jd.blockchain.ledger.core.DataAccountSet; +import com.jd.blockchain.ledger.core.DataAccountQuery; import com.jd.blockchain.ledger.core.LedgerManage; -import com.jd.blockchain.ledger.core.LedgerRepository; -import com.jd.blockchain.ledger.core.impl.LedgerManager; +import com.jd.blockchain.ledger.core.LedgerManager; +import com.jd.blockchain.ledger.core.LedgerQuery; import com.jd.blockchain.sdk.BlockchainService; import com.jd.blockchain.sdk.client.GatewayServiceFactory; import com.jd.blockchain.storage.service.DbConnection; import com.jd.blockchain.storage.service.DbConnectionFactory; import com.jd.blockchain.tools.initializer.LedgerBindingConfig; -import com.jd.blockchain.tools.initializer.LedgerInitProperties; -import com.jd.blockchain.tools.keygen.KeyGenCommand; import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.codec.HexUtils; import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback; @@ -99,7 +96,7 @@ public class IntegrationTestAll4Redis { DbConnectionFactory dbConnectionFactory2 = peer2.getDBConnectionFactory(); DbConnectionFactory dbConnectionFactory3 = peer3.getDBConnectionFactory(); - String encodedBase58Pwd = KeyGenCommand.encodePasswordAsBase58(LedgerInitializeWeb4SingleStepsTest.PASSWORD); + String encodedBase58Pwd = KeyGenUtils.encodePasswordAsBase58(LedgerInitializeWeb4SingleStepsTest.PASSWORD); KeyPairConfig gwkey0 = new KeyPairConfig(); gwkey0.setPubKeyValue(PUB_KEYS[0]); @@ -112,21 +109,21 @@ public class IntegrationTestAll4Redis { gwStarting0.waitReturn(); // 执行测试用例之前,校验每个节点的一致性; - LedgerRepository[] ledgers = buildLedgers( + LedgerQuery[] ledgers = buildLedgers( new LedgerBindingConfig[] { bindingConfig0, bindingConfig1, bindingConfig2, bindingConfig3 }, new DbConnectionFactory[] { dbConnectionFactory0, dbConnectionFactory1, dbConnectionFactory2, dbConnectionFactory3 }); testConsistencyAmongNodes(ledgers); - PrivKey privkey0 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[0], PASSWORD); - PrivKey privkey1 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[1], PASSWORD); - PrivKey privkey2 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[2], PASSWORD); - PrivKey privkey3 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[3], PASSWORD); + PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[0], PASSWORD); + PrivKey privkey1 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[1], PASSWORD); + PrivKey privkey2 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[2], PASSWORD); + PrivKey privkey3 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[3], PASSWORD); - PubKey pubKey0 = KeyGenCommand.decodePubKey(PUB_KEYS[0]); - PubKey pubKey1 = KeyGenCommand.decodePubKey(PUB_KEYS[1]); - PubKey pubKey2 = KeyGenCommand.decodePubKey(PUB_KEYS[2]); - PubKey pubKey3 = KeyGenCommand.decodePubKey(PUB_KEYS[3]); + PubKey pubKey0 = KeyGenUtils.decodePubKey(PUB_KEYS[0]); + PubKey pubKey1 = KeyGenUtils.decodePubKey(PUB_KEYS[1]); + PubKey pubKey2 = KeyGenUtils.decodePubKey(PUB_KEYS[2]); + PubKey pubKey3 = KeyGenUtils.decodePubKey(PUB_KEYS[3]); AsymmetricKeypair adminKey = new AsymmetricKeypair(pubKey0, privkey0); @@ -147,10 +144,10 @@ public class IntegrationTestAll4Redis { } } - private LedgerRepository[] buildLedgers(LedgerBindingConfig[] bindingConfigs, + private LedgerQuery[] buildLedgers(LedgerBindingConfig[] bindingConfigs, DbConnectionFactory[] dbConnectionFactories) { int[] ids = { 0, 1, 2, 3 }; - LedgerRepository[] ledgers = new LedgerRepository[ids.length]; + LedgerQuery[] ledgers = new LedgerQuery[ids.length]; LedgerManager[] ledgerManagers = new LedgerManager[ids.length]; for (int i = 0; i < ids.length; i++) { ledgerManagers[i] = new LedgerManager(); @@ -163,11 +160,11 @@ public class IntegrationTestAll4Redis { return ledgers; } - private void testConsistencyAmongNodes(LedgerRepository[] ledgers) { - LedgerRepository ledger0 = ledgers[0]; + private void testConsistencyAmongNodes(LedgerQuery[] ledgers) { + LedgerQuery ledger0 = ledgers[0]; LedgerBlock latestBlock0 = ledger0.retrieveLatestBlock(); for (int i = 1; i < ledgers.length; i++) { - LedgerRepository otherLedger = ledgers[i]; + LedgerQuery otherLedger = ledgers[i]; LedgerBlock otherLatestBlock = otherLedger.retrieveLatestBlock(); assertEquals(ledger0.getHash(), otherLedger.getHash()); assertEquals(ledger0.getLatestBlockHeight(), otherLedger.getLatestBlockHeight()); @@ -186,7 +183,7 @@ public class IntegrationTestAll4Redis { // 测试一个区块包含多个交易的写入情况,并验证写入结果; private void testWriteBatchTransactions(GatewayTestRunner gateway, AsymmetricKeypair adminKey, - LedgerRepository ledgerRepository) { + LedgerQuery ledgerRepository) { // 连接网关; GatewayServiceFactory gwsrvFact = GatewayServiceFactory.connect(gateway.getServiceAddress()); BlockchainService blockchainService = gwsrvFact.getBlockchainService(); @@ -217,26 +214,26 @@ public class IntegrationTestAll4Redis { assertEquals(ledgerRepository.retrieveLatestBlockHeight(), txResp.getBlockHeight()); assertEquals("Value_A_0", ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock()) - .getDataAccount(dataKey.getAddress()).getBytes("A").getValue().toUTF8String()); + .getAccount(dataKey.getAddress()).getBytes("A").getValue().toUTF8String()); assertEquals("Value_B_0", ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock()) - .getDataAccount(dataKey.getAddress()).getBytes("B").getValue().toUTF8String()); + .getAccount(dataKey.getAddress()).getBytes("B").getValue().toUTF8String()); assertEquals("Value_C_0", ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock()) - .getDataAccount(dataKey.getAddress()).getBytes("C").getValue().toUTF8String()); + .getAccount(dataKey.getAddress()).getBytes("C").getValue().toUTF8String()); assertEquals("Value_D_0", ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock()) - .getDataAccount(dataKey.getAddress()).getBytes("D").getValue().toUTF8String()); + .getAccount(dataKey.getAddress()).getBytes("D").getValue().toUTF8String()); assertEquals(0, ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock()) - .getDataAccount(dataKey.getAddress()).getDataVersion("A")); + .getAccount(dataKey.getAddress()).getDataVersion("A")); assertEquals(0, ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock()) - .getDataAccount(dataKey.getAddress()).getDataVersion("B")); + .getAccount(dataKey.getAddress()).getDataVersion("B")); assertEquals(0, ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock()) - .getDataAccount(dataKey.getAddress()).getDataVersion("C")); + .getAccount(dataKey.getAddress()).getDataVersion("C")); assertEquals(0, ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock()) - .getDataAccount(dataKey.getAddress()).getDataVersion("D")); + .getAccount(dataKey.getAddress()).getDataVersion("D")); return; } - private void testSDK(GatewayTestRunner gateway, AsymmetricKeypair adminKey, LedgerRepository ledgerRepository) { + private void testSDK(GatewayTestRunner gateway, AsymmetricKeypair adminKey, LedgerQuery ledgerRepository) { // 连接网关; GatewayServiceFactory gwsrvFact = GatewayServiceFactory.connect(gateway.getServiceAddress()); BlockchainService bcsrv = gwsrvFact.getBlockchainService(); @@ -251,7 +248,7 @@ public class IntegrationTestAll4Redis { } private void testSDK_InsertData(AsymmetricKeypair adminKey, HashDigest ledgerHash, - BlockchainService blockchainService, Bytes dataAccountAddress, LedgerRepository ledgerRepository) { + BlockchainService blockchainService, Bytes dataAccountAddress, LedgerQuery ledgerRepository) { // 在本地定义注册账号的 TX; TransactionTemplate txTemp = blockchainService.newTransaction(ledgerHash); @@ -295,7 +292,7 @@ public class IntegrationTestAll4Redis { } private BlockchainKeypair testSDK_RegisterDataAccount(AsymmetricKeypair adminKey, HashDigest ledgerHash, - BlockchainService blockchainService, LedgerRepository ledgerRepository) { + BlockchainService blockchainService, LedgerQuery ledgerRepository) { // 注册数据账户,并验证最终写入; BlockchainKeypair dataAccount = BlockchainKeyGenerator.getInstance().generate(); @@ -324,13 +321,13 @@ public class IntegrationTestAll4Redis { assertEquals(txResp.getContentHash(), transactionHash); assertEquals(txResp.getBlockHash(), ledgerRepository.getLatestBlockHash()); assertNotNull(ledgerRepository.getDataAccountSet(ledgerRepository.getLatestBlock()) - .getDataAccount(dataAccount.getAddress())); + .getAccount(dataAccount.getAddress())); return dataAccount; } private BlockchainKeypair testSDK_RegisterUser(AsymmetricKeypair adminKey, HashDigest ledgerHash, - BlockchainService blockchainService, LedgerRepository ledgerRepository) { + BlockchainService blockchainService, LedgerQuery ledgerRepository) { // 注册用户,并验证最终写入; BlockchainKeypair user = BlockchainKeyGenerator.getInstance().generate(); @@ -370,7 +367,7 @@ public class IntegrationTestAll4Redis { } private LedgerBlock testSDK_Contract(AsymmetricKeypair adminKey, HashDigest ledgerHash, - BlockchainService blockchainService, LedgerRepository ledgerRepository) { + BlockchainService blockchainService, LedgerQuery ledgerRepository) { System.out.println("adminKey=" + AddressEncoding.generateAddress(adminKey.getPubKey())); BlockchainKeypair userKey = BlockchainKeyGenerator.getInstance().generate(); System.out.println("userKey=" + userKey.getAddress()); @@ -386,7 +383,7 @@ public class IntegrationTestAll4Redis { txTpl.dataAccounts().register(contractDataKey.getIdentity()); // dataAccountSet.getDataAccount(dataAddress) DataAccount dataAccount = ledgerRepository.getDataAccountSet(ledgerRepository.getLatestBlock()) - .getDataAccount(contractDataKey.getAddress()); + .getAccount(contractDataKey.getAddress()); DataAccountKVSetOperation kvsetOP = txTpl.dataAccount(contractDataKey.getAddress()) .setText("A", "Value_A_0", -1).setText("B", "Value_B_0", -1) @@ -410,7 +407,7 @@ public class IntegrationTestAll4Redis { LedgerBlock block = ledgerRepository.getBlock(txResp.getBlockHeight()); byte[] contractCodeInDb = ledgerRepository.getContractAccountSet(block) - .getContract(contractDeployKey.getAddress()).getChainCode(); + .getAccount(contractDeployKey.getAddress()).getChainCode(); assertArrayEquals(contractCode, contractCodeInDb); txContentHash = ptx.getHash(); @@ -421,7 +418,7 @@ public class IntegrationTestAll4Redis { } private void testContractExe(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainKeypair userKey, - BlockchainService blockchainService, LedgerRepository ledgerRepository) { + BlockchainService blockchainService, LedgerQuery ledgerRepository) { LedgerInfo ledgerInfo = blockchainService.getLedger(ledgerHash); LedgerBlock previousBlock = blockchainService.getBlock(ledgerHash, ledgerInfo.getLatestBlockHeight() - 1); @@ -448,13 +445,13 @@ public class IntegrationTestAll4Redis { assertEquals(txResp.getBlockHeight(), backgroundLedgerBlock.getHeight()); // 验证合约中的赋值,外部可以获得; - DataAccountSet dataAccountSet = ledgerRepository.getDataAccountSet(backgroundLedgerBlock); + DataAccountQuery dataAccountSet = ledgerRepository.getDataAccountSet(backgroundLedgerBlock); AsymmetricKeypair key = Crypto.getSignatureFunction("ED25519").generateKeypair(); PubKey pubKey = key.getPubKey(); Bytes dataAddress = AddressEncoding.generateAddress(pubKey); - assertEquals(dataAddress, dataAccountSet.getDataAccount(dataAddress).getAddress()); + assertEquals(dataAddress, dataAccountSet.getAccount(dataAddress).getAddress()); assertEquals("hello", - dataAccountSet.getDataAccount(dataAddress).getBytes(KEY_TOTAL, -1).getValue().toUTF8String()); + dataAccountSet.getAccount(dataAddress).getBytes(KEY_TOTAL, -1).getValue().toUTF8String()); // 验证userAccount,从合约内部赋值,然后外部验证;内部定义动态key,外部不便于得到,临时屏蔽; // UserAccountSet userAccountSet = @@ -466,7 +463,7 @@ public class IntegrationTestAll4Redis { } private void prepareContractData(AsymmetricKeypair adminKey, HashDigest ledgerHash, - BlockchainService blockchainService, LedgerRepository ledgerRepository) { + BlockchainService blockchainService, LedgerQuery ledgerRepository) { // 定义交易; TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); @@ -481,9 +478,9 @@ public class IntegrationTestAll4Redis { // 验证结果; LedgerBlock block = ledgerRepository.getBlock(txResp.getBlockHeight()); - BytesValue val1InDb = ledgerRepository.getDataAccountSet(block).getDataAccount(contractDataKey.getAddress()) + BytesValue val1InDb = ledgerRepository.getDataAccountSet(block).getAccount(contractDataKey.getAddress()) .getBytes("A"); - BytesValue val2InDb = ledgerRepository.getDataAccountSet(block).getDataAccount(contractDataKey.getAddress()) + BytesValue val2InDb = ledgerRepository.getDataAccountSet(block).getAccount(contractDataKey.getAddress()) .getBytes(KEY_TOTAL); assertEquals("Value_A_0", val1InDb.getValue().toUTF8String()); assertEquals("total value,dataAccount", val2InDb.getValue().toUTF8String()); diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestDataAccount.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestDataAccount.java index 41d8c800..c6361d89 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestDataAccount.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestDataAccount.java @@ -16,6 +16,7 @@ import com.jd.blockchain.consensus.ConsensusProvider; import com.jd.blockchain.consensus.ConsensusSettings; import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig; @@ -24,20 +25,19 @@ import com.jd.blockchain.ledger.BlockchainKeypair; import com.jd.blockchain.ledger.DataAccountKVSetOperation; import com.jd.blockchain.ledger.KVDataEntry; import com.jd.blockchain.ledger.LedgerBlock; +import com.jd.blockchain.ledger.LedgerInitProperties; import com.jd.blockchain.ledger.PreparedTransaction; import com.jd.blockchain.ledger.TransactionResponse; import com.jd.blockchain.ledger.TransactionTemplate; -import com.jd.blockchain.ledger.core.DataAccountSet; -import com.jd.blockchain.ledger.core.LedgerRepository; -import com.jd.blockchain.ledger.core.impl.LedgerManager; +import com.jd.blockchain.ledger.core.DataAccountQuery; +import com.jd.blockchain.ledger.core.LedgerManager; +import com.jd.blockchain.ledger.core.LedgerQuery; import com.jd.blockchain.sdk.BlockchainService; import com.jd.blockchain.sdk.client.GatewayServiceFactory; import com.jd.blockchain.storage.service.DbConnection; import com.jd.blockchain.tools.initializer.DBConnectionConfig; import com.jd.blockchain.tools.initializer.LedgerBindingConfig; -import com.jd.blockchain.tools.initializer.LedgerInitProperties; import com.jd.blockchain.tools.initializer.Prompter; -import com.jd.blockchain.tools.keygen.KeyGenCommand; import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback; import com.jd.blockchain.utils.io.BytesUtils; @@ -99,7 +99,7 @@ public class IntegrationTestDataAccount { peerStarting2.waitReturn(); peerStarting3.waitReturn(); - String encodedBase58Pwd = KeyGenCommand.encodePasswordAsBase58(LedgerInitializeWeb4SingleStepsTest.PASSWORD); + String encodedBase58Pwd = KeyGenUtils.encodePasswordAsBase58(LedgerInitializeWeb4SingleStepsTest.PASSWORD); KeyPairConfig gwkey0 = new KeyPairConfig(); gwkey0.setPubKeyValue(LedgerInitializeWeb4SingleStepsTest.PUB_KEYS[0]); @@ -123,9 +123,9 @@ public class IntegrationTestDataAccount { testConsistencyAmongNodes(context); // temp test add - PrivKey privkey0 = KeyGenCommand.decodePrivKeyWithRawPassword(LedgerInitializeWeb4SingleStepsTest.PRIV_KEYS[0], + PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(LedgerInitializeWeb4SingleStepsTest.PRIV_KEYS[0], LedgerInitializeWeb4SingleStepsTest.PASSWORD); - PubKey pubKey0 = KeyGenCommand.decodePubKey(LedgerInitializeWeb4SingleStepsTest.PUB_KEYS[0]); + PubKey pubKey0 = KeyGenUtils.decodePubKey(LedgerInitializeWeb4SingleStepsTest.PUB_KEYS[0]); AsymmetricKeypair adminKey = new AsymmetricKeypair(pubKey0, privkey0); // regist data account @@ -185,9 +185,9 @@ public class IntegrationTestDataAccount { DbConnection memoryBasedDb = context.getNode(0).getStorageDB() .connect(LedgerInitConsensusConfig.memConnectionStrings[0]); - LedgerRepository ledgerRepository = ledgerManager.register(ledgerHashs[0], memoryBasedDb.getStorageService()); + LedgerQuery ledgerRepository = ledgerManager.register(ledgerHashs[0], memoryBasedDb.getStorageService()); - DataAccountSet dataAccountSet = ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock()); + DataAccountQuery dataAccountSet = ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock()); TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHashs[0]); @@ -227,16 +227,16 @@ public class IntegrationTestDataAccount { public void testConsistencyAmongNodes(IntegratedContext context) { int[] ids = context.getNodeIds(); Node[] nodes = new Node[ids.length]; - LedgerRepository[] ledgers = new LedgerRepository[ids.length]; + LedgerQuery[] ledgers = new LedgerQuery[ids.length]; for (int i = 0; i < nodes.length; i++) { nodes[i] = context.getNode(ids[i]); HashDigest ledgerHash = nodes[i].getLedgerManager().getLedgerHashs()[0]; ledgers[i] = nodes[i].getLedgerManager().getLedger(ledgerHash); } - LedgerRepository ledger0 = ledgers[0]; + LedgerQuery ledger0 = ledgers[0]; LedgerBlock latestBlock0 = ledger0.retrieveLatestBlock(); for (int i = 1; i < ledgers.length; i++) { - LedgerRepository otherLedger = ledgers[i]; + LedgerQuery otherLedger = ledgers[i]; LedgerBlock otherLatestBlock = otherLedger.retrieveLatestBlock(); assertEquals(ledger0.getHash(), otherLedger.getHash()); assertEquals(ledger0.getLatestBlockHeight(), otherLedger.getLatestBlockHeight()); @@ -275,16 +275,16 @@ public class IntegrationTestDataAccount { NetworkAddress initAddr3 = initSetting.getConsensusParticipant(3).getInitializerAddress(); NodeWebContext nodeCtx3 = new NodeWebContext(3, initAddr3); - PrivKey privkey0 = KeyGenCommand.decodePrivKeyWithRawPassword(LedgerInitializeWeb4SingleStepsTest.PRIV_KEYS[0], + PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(LedgerInitializeWeb4SingleStepsTest.PRIV_KEYS[0], LedgerInitializeWeb4SingleStepsTest.PASSWORD); - PrivKey privkey1 = KeyGenCommand.decodePrivKeyWithRawPassword(LedgerInitializeWeb4SingleStepsTest.PRIV_KEYS[1], + PrivKey privkey1 = KeyGenUtils.decodePrivKeyWithRawPassword(LedgerInitializeWeb4SingleStepsTest.PRIV_KEYS[1], LedgerInitializeWeb4SingleStepsTest.PASSWORD); - PrivKey privkey2 = KeyGenCommand.decodePrivKeyWithRawPassword(LedgerInitializeWeb4SingleStepsTest.PRIV_KEYS[2], + PrivKey privkey2 = KeyGenUtils.decodePrivKeyWithRawPassword(LedgerInitializeWeb4SingleStepsTest.PRIV_KEYS[2], LedgerInitializeWeb4SingleStepsTest.PASSWORD); - PrivKey privkey3 = KeyGenCommand.decodePrivKeyWithRawPassword(LedgerInitializeWeb4SingleStepsTest.PRIV_KEYS[3], + PrivKey privkey3 = KeyGenUtils.decodePrivKeyWithRawPassword(LedgerInitializeWeb4SingleStepsTest.PRIV_KEYS[3], LedgerInitializeWeb4SingleStepsTest.PASSWORD); - String encodedPassword = KeyGenCommand.encodePasswordAsBase58(LedgerInitializeWeb4SingleStepsTest.PASSWORD); + String encodedPassword = KeyGenUtils.encodePasswordAsBase58(LedgerInitializeWeb4SingleStepsTest.PASSWORD); CountDownLatch quitLatch = new CountDownLatch(4); @@ -322,10 +322,10 @@ public class IntegrationTestDataAccount { assertEquals(ledgerHash0, ledgerHash2); assertEquals(ledgerHash0, ledgerHash3); - LedgerRepository ledger0 = nodeCtx0.registLedger(ledgerHash0); - LedgerRepository ledger1 = nodeCtx1.registLedger(ledgerHash1); - LedgerRepository ledger2 = nodeCtx2.registLedger(ledgerHash2); - LedgerRepository ledger3 = nodeCtx3.registLedger(ledgerHash3); + LedgerQuery ledger0 = nodeCtx0.registLedger(ledgerHash0); + LedgerQuery ledger1 = nodeCtx1.registLedger(ledgerHash1); + LedgerQuery ledger2 = nodeCtx2.registLedger(ledgerHash2); + LedgerQuery ledger3 = nodeCtx3.registLedger(ledgerHash3); assertNotNull(ledger0); assertNotNull(ledger1); diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/batch/bftsmart/BftsmartLedgerInit.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/batch/bftsmart/BftsmartLedgerInit.java index 11f7d8e6..f7ddad5c 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/batch/bftsmart/BftsmartLedgerInit.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/batch/bftsmart/BftsmartLedgerInit.java @@ -10,18 +10,18 @@ package test.com.jd.blockchain.intgr.batch.bftsmart; import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.gateway.GatewayConfigProperties; import com.jd.blockchain.ledger.BlockchainKeypair; -import com.jd.blockchain.ledger.core.LedgerRepository; +import com.jd.blockchain.ledger.core.LedgerQuery; import com.jd.blockchain.peer.PeerServerBooter; import com.jd.blockchain.sdk.BlockchainService; import com.jd.blockchain.sdk.client.GatewayServiceFactory; import com.jd.blockchain.storage.service.DbConnectionFactory; import com.jd.blockchain.tools.initializer.LedgerBindingConfig; import com.jd.blockchain.tools.initializer.LedgerInitCommand; -import com.jd.blockchain.tools.keygen.KeyGenCommand; import com.jd.blockchain.utils.concurrent.ThreadInvoker; import com.jd.blockchain.utils.io.FileUtils; import com.jd.blockchain.utils.net.NetworkAddress; @@ -93,7 +93,7 @@ public class BftsmartLedgerInit { localConf4NodesLoad(); PeerTestRunner[] peerNodes = startNodes(4); // 检查账本一致性 - LedgerRepository[] ledgers = checkNodes(peerNodes); + LedgerQuery[] ledgers = checkNodes(peerNodes); txRequestTest(peerNodes, ledgers); } @@ -110,7 +110,7 @@ public class BftsmartLedgerInit { localConf8NodesLoad(); PeerTestRunner[] peerNodes = startNodes(8); // 检查账本一致性 - LedgerRepository[] ledgers = checkNodes(peerNodes); + LedgerQuery[] ledgers = checkNodes(peerNodes); txRequestTest(peerNodes, ledgers); } @@ -127,7 +127,7 @@ public class BftsmartLedgerInit { localConf16NodesLoad(); PeerTestRunner[] peerNodes = startNodes(16); // 检查账本一致性 - LedgerRepository[] ledgers = checkNodes(peerNodes); + LedgerQuery[] ledgers = checkNodes(peerNodes); txRequestTest(peerNodes, ledgers); } @@ -145,7 +145,7 @@ public class BftsmartLedgerInit { // ledgerInitPools.shutdown(); PeerTestRunner[] peerNodes = startNodes(32); // 检查账本一致性 - LedgerRepository[] ledgers = checkNodes(peerNodes); + LedgerQuery[] ledgers = checkNodes(peerNodes); txRequestTest(peerNodes, ledgers); } @@ -162,24 +162,24 @@ public class BftsmartLedgerInit { localConf64NodesLoad(); PeerTestRunner[] peerNodes = startNodes(64); // 检查账本一致性 - LedgerRepository[] ledgers = checkNodes(peerNodes); + LedgerQuery[] ledgers = checkNodes(peerNodes); txRequestTest(peerNodes, ledgers); } - public void txRequestTest(PeerTestRunner[] peerNodes, LedgerRepository[] ledgers) { + public void txRequestTest(PeerTestRunner[] peerNodes, LedgerQuery[] ledgers) { // 测试K-V GatewayTestRunner gateway = initGateWay(peerNodes[0]); - LedgerRepository ledgerRepository = ledgers[0]; + LedgerQuery ledgerRepository = ledgers[0]; HashDigest ledgerHash = ledgerRepository.getHash(); GatewayServiceFactory gwsrvFact = GatewayServiceFactory.connect(gateway.getServiceAddress()); - PrivKey privkey0 = KeyGenCommand.decodePrivKeyWithRawPassword(BftsmartConfig.PRIV_KEY[0], IntegrationBase.PASSWORD); + PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(BftsmartConfig.PRIV_KEY[0], IntegrationBase.PASSWORD); - PubKey pubKey0 = KeyGenCommand.decodePubKey(BftsmartConfig.PUB_KEY[0]); + PubKey pubKey0 = KeyGenUtils.decodePubKey(BftsmartConfig.PUB_KEY[0]); AsymmetricKeypair adminKey = new AsymmetricKeypair(pubKey0, privkey0); @@ -233,7 +233,7 @@ public class BftsmartLedgerInit { } public GatewayTestRunner initGateWay(PeerTestRunner peerNode) { - String encodedBase58Pwd = KeyGenCommand.encodePasswordAsBase58(LedgerInitializeTest.PASSWORD); + String encodedBase58Pwd = KeyGenUtils.encodePasswordAsBase58(LedgerInitializeTest.PASSWORD); GatewayConfigProperties.KeyPairConfig gwkey0 = new GatewayConfigProperties.KeyPairConfig(); gwkey0.setPubKeyValue(BftsmartConfig.PUB_KEY[0]); @@ -249,7 +249,7 @@ public class BftsmartLedgerInit { return gateway; } - public LedgerRepository[] checkNodes(PeerTestRunner[] peerNodes) { + public LedgerQuery[] checkNodes(PeerTestRunner[] peerNodes) { int size = peerNodes.length; LedgerBindingConfig[] ledgerBindingConfigs = new LedgerBindingConfig[size]; DbConnectionFactory[] connectionFactories = new DbConnectionFactory[size]; @@ -259,7 +259,7 @@ public class BftsmartLedgerInit { } // 执行测试用例之前,校验每个节点的一致性; - LedgerRepository[] ledgers = buildLedgers(ledgerBindingConfigs, connectionFactories); + LedgerQuery[] ledgers = buildLedgers(ledgerBindingConfigs, connectionFactories); IntegrationBase.testConsistencyAmongNodes(ledgers); return ledgers; } diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/batch/bftsmart/BftsmartTestBase.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/batch/bftsmart/BftsmartTestBase.java index f94f9364..9a485a22 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/batch/bftsmart/BftsmartTestBase.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/batch/bftsmart/BftsmartTestBase.java @@ -8,8 +8,8 @@ */ package test.com.jd.blockchain.intgr.batch.bftsmart; -import static com.jd.blockchain.tools.keygen.KeyGenCommand.encodePrivKey; -import static com.jd.blockchain.tools.keygen.KeyGenCommand.encodePubKey; +import static com.jd.blockchain.crypto.KeyGenUtils.encodePrivKey; +import static com.jd.blockchain.crypto.KeyGenUtils.encodePubKey; import org.junit.Test; diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeTest.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeTest.java index 09ddf134..217c0491 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeTest.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeTest.java @@ -13,13 +13,12 @@ import org.junit.Test; import org.springframework.core.io.ClassPathResource; import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.consensus.ConsensusProvider; -import com.jd.blockchain.consensus.ConsensusSettings; import com.jd.blockchain.crypto.AddressEncoding; import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.Crypto; import com.jd.blockchain.crypto.CryptoProvider; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.crypto.SignatureDigest; @@ -27,23 +26,24 @@ import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; import com.jd.blockchain.crypto.service.sm.SMCryptoService; import com.jd.blockchain.ledger.LedgerBlock; import com.jd.blockchain.ledger.LedgerInitOperation; +import com.jd.blockchain.ledger.LedgerInitProperties; +import com.jd.blockchain.ledger.RolesConfigureOperation; +import com.jd.blockchain.ledger.UserAuthorizeOperation; import com.jd.blockchain.ledger.UserRegisterOperation; import com.jd.blockchain.ledger.core.CryptoConfig; import com.jd.blockchain.ledger.core.LedgerInitDecision; -import com.jd.blockchain.ledger.core.LedgerInitPermission; -import com.jd.blockchain.ledger.core.LedgerRepository; +import com.jd.blockchain.ledger.core.LedgerInitProposal; +import com.jd.blockchain.ledger.core.LedgerManager; +import com.jd.blockchain.ledger.core.LedgerQuery; 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.MemoryDBConnFactory; import com.jd.blockchain.tools.initializer.DBConnectionConfig; import com.jd.blockchain.tools.initializer.LedgerInitProcess; -import com.jd.blockchain.tools.initializer.LedgerInitProperties; import com.jd.blockchain.tools.initializer.Prompter; import com.jd.blockchain.tools.initializer.web.InitConsensusServiceFactory; import com.jd.blockchain.tools.initializer.web.LedgerInitConsensusService; import com.jd.blockchain.tools.initializer.web.LedgerInitializeWebController; -import com.jd.blockchain.tools.keygen.KeyGenCommand; import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.concurrent.ThreadInvoker; import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback; @@ -59,6 +59,8 @@ public class LedgerInitializeTest { static { DataContractRegistry.register(LedgerInitOperation.class); DataContractRegistry.register(UserRegisterOperation.class); + DataContractRegistry.register(RolesConfigureOperation.class); + DataContractRegistry.register(UserAuthorizeOperation.class); } private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(), @@ -101,22 +103,22 @@ public class LedgerInitializeTest { NodeContext node3 = new NodeContext(initSetting.getConsensusParticipant(3).getInitializerAddress(), serviceRegisterMap); - PrivKey privkey0 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[0], PASSWORD); + PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[0], PASSWORD); DBConnectionConfig testDb0 = new DBConnectionConfig(); testDb0.setConnectionUri(dbConnections[0]); AsyncCallback callback0 = node0.startInit(0, privkey0, initSetting, testDb0, consolePrompter); - PrivKey privkey1 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[1], PASSWORD); + PrivKey privkey1 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[1], PASSWORD); DBConnectionConfig testDb1 = new DBConnectionConfig(); testDb1.setConnectionUri(dbConnections[1]); AsyncCallback callback1 = node1.startInit(1, privkey1, initSetting, testDb1, consolePrompter); - PrivKey privkey2 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[2], PASSWORD); + PrivKey privkey2 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[2], PASSWORD); DBConnectionConfig testDb2 = new DBConnectionConfig(); testDb2.setConnectionUri(dbConnections[2]); AsyncCallback callback2 = node2.startInit(2, privkey2, initSetting, testDb2, consolePrompter); - PrivKey privkey3 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[3], PASSWORD); + PrivKey privkey3 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[3], PASSWORD); DBConnectionConfig testDb03 = new DBConnectionConfig(); testDb03.setConnectionUri(dbConnections[3]); AsyncCallback callback3 = node3.startInit(3, privkey3, initSetting, testDb03, consolePrompter); @@ -131,10 +133,10 @@ public class LedgerInitializeTest { assertEquals(ledgerHash0, ledgerHash2); assertEquals(ledgerHash0, ledgerHash3); - LedgerRepository ledger0 = node0.registLedger(ledgerHash0, dbConnections[0]); - LedgerRepository ledger1 = node1.registLedger(ledgerHash1, dbConnections[1]); - LedgerRepository ledger2 = node2.registLedger(ledgerHash2, dbConnections[2]); - LedgerRepository ledger3 = node3.registLedger(ledgerHash3, dbConnections[3]); + LedgerQuery ledger0 = node0.registLedger(ledgerHash0, dbConnections[0]); + LedgerQuery ledger1 = node1.registLedger(ledgerHash1, dbConnections[1]); + LedgerQuery ledger2 = node2.registLedger(ledgerHash2, dbConnections[2]); + LedgerQuery ledger3 = node3.registLedger(ledgerHash3, dbConnections[3]); assertNotNull(ledger0); assertNotNull(ledger1); @@ -145,26 +147,26 @@ public class LedgerInitializeTest { assertEquals(0, genesisBlock.getHeight()); assertEquals(ledgerHash0, genesisBlock.getHash()); - UserAccountSet userset0 = ledger0.getUserAccountSet(genesisBlock); + UserAccountQuery userset0 = ledger0.getUserAccountSet(genesisBlock); - PubKey pubKey0 = KeyGenCommand.decodePubKey(PUB_KEYS[0]); + PubKey pubKey0 = KeyGenUtils.decodePubKey(PUB_KEYS[0]); Bytes address0 = AddressEncoding.generateAddress(pubKey0); - UserAccount user0_0 = userset0.getUser(address0); + UserAccount user0_0 = userset0.getAccount(address0); assertNotNull(user0_0); - PubKey pubKey1 = KeyGenCommand.decodePubKey(PUB_KEYS[1]); + PubKey pubKey1 = KeyGenUtils.decodePubKey(PUB_KEYS[1]); Bytes address1 = AddressEncoding.generateAddress(pubKey1); - UserAccount user1_0 = userset0.getUser(address1); + UserAccount user1_0 = userset0.getAccount(address1); assertNotNull(user1_0); - PubKey pubKey2 = KeyGenCommand.decodePubKey(PUB_KEYS[2]); + PubKey pubKey2 = KeyGenUtils.decodePubKey(PUB_KEYS[2]); Bytes address2 = AddressEncoding.generateAddress(pubKey2); - UserAccount user2_0 = userset0.getUser(address2); + UserAccount user2_0 = userset0.getAccount(address2); assertNotNull(user2_0); - PubKey pubKey3 = KeyGenCommand.decodePubKey(PUB_KEYS[3]); + PubKey pubKey3 = KeyGenUtils.decodePubKey(PUB_KEYS[3]); Bytes address3 = AddressEncoding.generateAddress(pubKey3); - UserAccount user3_0 = userset0.getUser(address3); + UserAccount user3_0 = userset0.getAccount(address3); assertNotNull(user3_0); } @@ -227,7 +229,7 @@ public class LedgerInitializeTest { public NodeContext(NetworkAddress address, Map serviceRegisterMap) { this.initCsServiceFactory = new MultiThreadInterInvokerFactory(serviceRegisterMap); - LedgerInitializeWebController initController = new LedgerInitializeWebController(ledgerManager, storageDb, + LedgerInitializeWebController initController = new LedgerInitializeWebController(storageDb, initCsServiceFactory); serviceRegisterMap.put(address, initController); this.initProcess = initController; @@ -259,20 +261,23 @@ public class LedgerInitializeTest { cryptoSetting.setSupportedProviders(supportedProviders); cryptoSetting.setAutoVerifyHash(autoVerifyHash); cryptoSetting.setHashAlgorithm(Crypto.getAlgorithm("SHA256")); + + setting.getCryptoProperties().setHashAlgorithm("SHA256"); + setting.getCryptoProperties().setVerifyHash(autoVerifyHash); partiKey = new AsymmetricKeypair(setting.getConsensusParticipant(0).getPubKey(), privKey); ThreadInvoker invoker = new ThreadInvoker() { @Override protected HashDigest invoke() throws Exception { - return initProcess.initialize(currentId, privKey, setting, dbConnConfig, prompter, cryptoSetting); + return initProcess.initialize(currentId, privKey, setting, dbConnConfig, prompter); } }; return invoker.start(); } - public LedgerRepository registLedger(HashDigest ledgerHash, String memConn) { + public LedgerQuery registLedger(HashDigest ledgerHash, String memConn) { return ledgerManager.register(ledgerHash, storageDb.connect(memConn).getStorageService()); } } @@ -301,10 +306,10 @@ public class LedgerInitializeTest { } @Override - public LedgerInitPermission requestPermission(int requesterId, SignatureDigest signature) { - ThreadInvoker invoker = new ThreadInvoker() { + public LedgerInitProposal requestPermission(int requesterId, SignatureDigest signature) { + ThreadInvoker invoker = new ThreadInvoker() { @Override - protected LedgerInitPermission invoke() { + protected LedgerInitProposal invoke() { return initCsService.requestPermission(requesterId, signature); } }; diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeWeb4Nodes.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeWeb4Nodes.java index a37afc62..ec77fbee 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeWeb4Nodes.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeWeb4Nodes.java @@ -4,16 +4,15 @@ import com.jd.blockchain.consensus.ConsensusProvider; import com.jd.blockchain.consensus.ConsensusSettings; import com.jd.blockchain.crypto.AddressEncoding; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.ledger.*; import com.jd.blockchain.ledger.core.*; -import com.jd.blockchain.ledger.core.impl.LedgerManager; import com.jd.blockchain.storage.service.DbConnection; import com.jd.blockchain.storage.service.impl.composite.CompositeConnectionFactory; import com.jd.blockchain.tools.initializer.*; import com.jd.blockchain.tools.initializer.web.LedgerInitializeWebController; -import com.jd.blockchain.tools.keygen.KeyGenCommand; import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.concurrent.ThreadInvoker; import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback; @@ -44,6 +43,21 @@ public class LedgerInitializeWeb4Nodes { public static final String[] PRIV_KEYS = IntegrationBase.PRIV_KEYS; + static { + try { + // 首先获取当前Resource路径 + ClassPathResource ledgerInitSettingResource = new ClassPathResource(""); + String path = ledgerInitSettingResource.getURL().getPath(); + System.out.println("-----" + path + "-----"); + // 将参数注册进去 + System.setProperty("peer.log", path); + System.setProperty("init.log", path); + System.setProperty("gateway.log", path); + } catch (Exception e) { + e.printStackTrace(); + } + } + @Test public void testMQInitByMemWith4Nodes() { testInitWith4Nodes(LedgerInitConsensusConfig.mqConfig, LedgerInitConsensusConfig.memConnectionStrings); @@ -88,10 +102,10 @@ public class LedgerInitializeWeb4Nodes { NetworkAddress initAddr3 = initSetting.getConsensusParticipant(3).getInitializerAddress(); NodeWebContext node3 = new NodeWebContext(3, initAddr3); - PrivKey privkey0 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[0], PASSWORD); - PrivKey privkey1 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[1], PASSWORD); - PrivKey privkey2 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[2], PASSWORD); - PrivKey privkey3 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[3], PASSWORD); + PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[0], PASSWORD); + PrivKey privkey1 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[1], PASSWORD); + PrivKey privkey2 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[2], PASSWORD); + PrivKey privkey3 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[3], PASSWORD); CountDownLatch quitLatch = new CountDownLatch(4); @@ -125,10 +139,10 @@ public class LedgerInitializeWeb4Nodes { assertEquals(ledgerHash0, ledgerHash2); assertEquals(ledgerHash0, ledgerHash3); - LedgerRepository ledger0 = node0.registLedger(ledgerHash0); - LedgerRepository ledger1 = node1.registLedger(ledgerHash1); - LedgerRepository ledger2 = node2.registLedger(ledgerHash2); - LedgerRepository ledger3 = node3.registLedger(ledgerHash3); + LedgerQuery ledger0 = node0.registLedger(ledgerHash0); + LedgerQuery ledger1 = node1.registLedger(ledgerHash1); + LedgerQuery ledger2 = node2.registLedger(ledgerHash2); + LedgerQuery ledger3 = node3.registLedger(ledgerHash3); assertNotNull(ledger0); assertNotNull(ledger1); @@ -139,29 +153,29 @@ public class LedgerInitializeWeb4Nodes { assertEquals(0, genesisBlock.getHeight()); assertEquals(ledgerHash0, genesisBlock.getHash()); - UserAccountSet userset0 = ledger0.getUserAccountSet(genesisBlock); + UserAccountQuery userset0 = ledger0.getUserAccountSet(genesisBlock); - PubKey pubKey0 = KeyGenCommand.decodePubKey(PUB_KEYS[0]); + PubKey pubKey0 = KeyGenUtils.decodePubKey(PUB_KEYS[0]); Bytes address0 = AddressEncoding.generateAddress(pubKey0); System.out.printf("localNodeAddress0 = %s \r\n", address0.toBase58()); - UserAccount user0_0 = userset0.getUser(address0); + UserAccount user0_0 = userset0.getAccount(address0); assertNotNull(user0_0); - PubKey pubKey1 = KeyGenCommand.decodePubKey(PUB_KEYS[1]); + PubKey pubKey1 = KeyGenUtils.decodePubKey(PUB_KEYS[1]); Bytes address1 = AddressEncoding.generateAddress(pubKey1); - UserAccount user1_0 = userset0.getUser(address1); + UserAccount user1_0 = userset0.getAccount(address1); assertNotNull(user1_0); System.out.printf("localNodeAddress1 = %s \r\n", address1.toBase58()); - PubKey pubKey2 = KeyGenCommand.decodePubKey(PUB_KEYS[2]); + PubKey pubKey2 = KeyGenUtils.decodePubKey(PUB_KEYS[2]); Bytes address2 = AddressEncoding.generateAddress(pubKey2); - UserAccount user2_0 = userset0.getUser(address2); + UserAccount user2_0 = userset0.getAccount(address2); assertNotNull(user2_0); System.out.printf("localNodeAddress2 = %s \r\n", address2.toBase58()); - PubKey pubKey3 = KeyGenCommand.decodePubKey(PUB_KEYS[3]); + PubKey pubKey3 = KeyGenUtils.decodePubKey(PUB_KEYS[3]); Bytes address3 = AddressEncoding.generateAddress(pubKey3); - UserAccount user3_0 = userset0.getUser(address3); + UserAccount user3_0 = userset0.getAccount(address3); assertNotNull(user3_0); System.out.printf("localNodeAddress3 = %s \r\n", address3.toBase58()); @@ -213,7 +227,7 @@ public class LedgerInitializeWeb4Nodes { return controller.getInitTxContent(); } - public LedgerInitPermission getLocalPermission() { + public LedgerInitProposal getLocalPermission() { return controller.getLocalPermission(); } @@ -226,9 +240,9 @@ public class LedgerInitializeWeb4Nodes { this.serverAddress = serverAddress; } - public LedgerRepository registLedger(HashDigest ledgerHash) { + public LedgerQuery registLedger(HashDigest ledgerHash) { DbConnection conn = db.connect(dbConnConfig.getUri()); - LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, conn.getStorageService()); + LedgerQuery ledgerRepo = ledgerManager.register(ledgerHash, conn.getStorageService()); return ledgerRepo; } diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeWeb4SingleStepsTest.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeWeb4SingleStepsTest.java index 2cf5701d..e478c70f 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeWeb4SingleStepsTest.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeWeb4SingleStepsTest.java @@ -10,7 +10,6 @@ import java.io.InputStream; import java.util.Properties; import java.util.concurrent.CountDownLatch; -import com.jd.blockchain.transaction.SignatureUtils; import org.springframework.boot.SpringApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.io.ClassPathResource; @@ -19,30 +18,31 @@ import com.jd.blockchain.binaryproto.BinaryProtocol; import com.jd.blockchain.consensus.ConsensusProvider; import com.jd.blockchain.consensus.ConsensusSettings; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.crypto.SignatureDigest; import com.jd.blockchain.ledger.LedgerInitOperation; +import com.jd.blockchain.ledger.LedgerInitProperties; import com.jd.blockchain.ledger.Operation; import com.jd.blockchain.ledger.TransactionContent; import com.jd.blockchain.ledger.UserRegisterOperation; import com.jd.blockchain.ledger.core.LedgerInitDecision; -import com.jd.blockchain.ledger.core.LedgerInitPermission; -import com.jd.blockchain.ledger.core.LedgerRepository; -import com.jd.blockchain.ledger.core.impl.LedgerManager; +import com.jd.blockchain.ledger.core.LedgerInitProposal; +import com.jd.blockchain.ledger.core.LedgerManager; +import com.jd.blockchain.ledger.core.LedgerQuery; import com.jd.blockchain.storage.service.DbConnection; import com.jd.blockchain.storage.service.impl.composite.CompositeConnectionFactory; import com.jd.blockchain.tools.initializer.DBConnectionConfig; import com.jd.blockchain.tools.initializer.LedgerBindingConfig; import com.jd.blockchain.tools.initializer.LedgerInitCommand; import com.jd.blockchain.tools.initializer.LedgerInitProcess; -import com.jd.blockchain.tools.initializer.LedgerInitProperties; import com.jd.blockchain.tools.initializer.Prompter; import com.jd.blockchain.tools.initializer.web.HttpInitConsensServiceFactory; +import com.jd.blockchain.tools.initializer.web.LedgerInitConfiguration; import com.jd.blockchain.tools.initializer.web.LedgerInitConsensusService; import com.jd.blockchain.tools.initializer.web.LedgerInitializeWebController; -import com.jd.blockchain.tools.keygen.KeyGenCommand; -import com.jd.blockchain.transaction.TxRequestBuilder; +import com.jd.blockchain.transaction.SignatureUtils; import com.jd.blockchain.utils.concurrent.ThreadInvoker; import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback; import com.jd.blockchain.utils.io.BytesUtils; @@ -79,9 +79,8 @@ public class LedgerInitializeWeb4SingleStepsTest { // 加载共识配置; Properties props = loadConsensusSetting(consensusConfig.getConfigPath()); ConsensusProvider csProvider = LedgerInitConsensusConfig.getConsensusProvider(consensusConfig.getProvider()); - ConsensusSettings csProps = csProvider.getSettingsFactory() - .getConsensusSettingsBuilder() - .createSettings(props, Utils.loadParticipantNodes()); + ConsensusSettings csProps = csProvider.getSettingsFactory().getConsensusSettingsBuilder().createSettings(props, + Utils.loadParticipantNodes()); // 启动服务器; NetworkAddress initAddr0 = initSetting.getConsensusParticipant(0).getInitializerAddress(); @@ -105,21 +104,23 @@ public class LedgerInitializeWeb4SingleStepsTest { node2.setPrompter(prompter); node3.setPrompter(prompter); - PrivKey privkey0 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[0], PASSWORD); - PrivKey privkey1 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[1], PASSWORD); - PrivKey privkey2 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[2], PASSWORD); - PrivKey privkey3 = KeyGenCommand.decodePrivKeyWithRawPassword(PRIV_KEYS[3], PASSWORD); + PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[0], PASSWORD); + PrivKey privkey1 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[1], PASSWORD); + PrivKey privkey2 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[2], PASSWORD); + PrivKey privkey3 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[3], PASSWORD); - PubKey pubKey0 = KeyGenCommand.decodePubKey(PUB_KEYS[0]); - PubKey pubKey1 = KeyGenCommand.decodePubKey(PUB_KEYS[1]); - PubKey pubKey2 = KeyGenCommand.decodePubKey(PUB_KEYS[2]); - PubKey pubKey3 = KeyGenCommand.decodePubKey(PUB_KEYS[3]); + PubKey pubKey0 = KeyGenUtils.decodePubKey(PUB_KEYS[0]); + PubKey pubKey1 = KeyGenUtils.decodePubKey(PUB_KEYS[1]); + PubKey pubKey2 = KeyGenUtils.decodePubKey(PUB_KEYS[2]); + PubKey pubKey3 = KeyGenUtils.decodePubKey(PUB_KEYS[3]); // 测试生成“账本初始化许可”; - LedgerInitPermission permission0 = testPreparePermisssion(node0, privkey0, initSetting, csProps); - LedgerInitPermission permission1 = testPreparePermisssion(node1, privkey1, initSetting, csProps); - LedgerInitPermission permission2 = testPreparePermisssion(node2, privkey2, initSetting, csProps); - LedgerInitPermission permission3 = testPreparePermisssion(node3, privkey3, initSetting, csProps); + LedgerInitConfiguration initConfig = LedgerInitConfiguration.create(initSetting); + initConfig.setConsensusSettings(csProvider, csProps); + LedgerInitProposal permission0 = testPreparePermisssion(node0, privkey0, initConfig); + LedgerInitProposal permission1 = testPreparePermisssion(node1, privkey1, initConfig); + LedgerInitProposal permission2 = testPreparePermisssion(node2, privkey2, initConfig); + LedgerInitProposal permission3 = testPreparePermisssion(node3, privkey3, initConfig); TransactionContent initTxContent0 = node0.getInitTxContent(); TransactionContent initTxContent1 = node1.getInitTxContent(); @@ -240,9 +241,9 @@ public class LedgerInitializeWeb4SingleStepsTest { testRequestDecision(node3, node2, initCsService2); } - private LedgerInitPermission testPreparePermisssion(NodeWebContext node, PrivKey privKey, - LedgerInitProperties setting, ConsensusSettings csProps) { - LedgerInitPermission permission = node.preparePermision(privKey, setting, csProps); + private LedgerInitProposal testPreparePermisssion(NodeWebContext node, PrivKey privKey, + LedgerInitConfiguration setting) { + LedgerInitProposal permission = node.preparePermision(privKey, setting); assertEquals(node.getId(), permission.getParticipantId()); assertNotNull(permission.getTransactionSignature()); @@ -253,7 +254,7 @@ public class LedgerInitializeWeb4SingleStepsTest { private void testRequestPermission(NodeWebContext fromNode, PrivKey fromPrivkey, NodeWebContext targetNode, LedgerInitConsensusService targetNodeService) { SignatureDigest reqSignature = fromNode.createPermissionRequestSignature(fromNode.getId(), fromPrivkey); - LedgerInitPermission targetPermission = targetNodeService.requestPermission(fromNode.getId(), reqSignature); + LedgerInitProposal targetPermission = targetNodeService.requestPermission(fromNode.getId(), reqSignature); assertEquals(targetNode.getId(), targetPermission.getParticipantId()); assertEquals(targetNode.getLocalPermission().getTransactionSignature(), targetPermission.getTransactionSignature()); @@ -312,7 +313,7 @@ public class LedgerInitializeWeb4SingleStepsTest { return controller.getInitTxContent(); } - public LedgerInitPermission getLocalPermission() { + public LedgerInitProposal getLocalPermission() { return controller.getLocalPermission(); } @@ -325,7 +326,7 @@ public class LedgerInitializeWeb4SingleStepsTest { this.serverAddress = serverAddress; } - public LedgerRepository registLedger(HashDigest ledgerHash) { + public LedgerQuery registLedger(HashDigest ledgerHash) { // LedgerManage ledgerManager = ctx.getBean(LedgerManage.class); // // DbConnectionFactory dbConnFactory = ctx.getBean(DbConnectionFactory.class); @@ -335,7 +336,7 @@ public class LedgerInitializeWeb4SingleStepsTest { // DbConnection conn = db.connect(dbConnConfig.getUri(), // dbConnConfig.getPassword()); DbConnection conn = db.connect(dbConnConfig.getUri()); - LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, conn.getStorageService()); + LedgerQuery ledgerRepo = ledgerManager.register(ledgerHash, conn.getStorageService()); return ledgerRepo; } @@ -385,9 +386,8 @@ public class LedgerInitializeWeb4SingleStepsTest { return invoker.start(); } - public LedgerInitPermission preparePermision(PrivKey privKey, LedgerInitProperties setting, - ConsensusSettings csProps) { - return controller.prepareLocalPermission(id, privKey, setting, csProps); + public LedgerInitProposal preparePermision(PrivKey privKey, LedgerInitConfiguration setting) { + return controller.prepareLocalPermission(id, privKey, setting); } public boolean consensusPermission(PrivKey privKey) { diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/ledger/LedgerBlockGeneratingTest.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/ledger/LedgerBlockGeneratingTest.java index 306d065f..f9ca3833 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/ledger/LedgerBlockGeneratingTest.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/ledger/LedgerBlockGeneratingTest.java @@ -18,24 +18,24 @@ import com.jd.blockchain.consensus.ConsensusProviders; import com.jd.blockchain.consensus.ConsensusSettings; import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.ledger.BlockchainKeyGenerator; import com.jd.blockchain.ledger.BlockchainKeypair; import com.jd.blockchain.ledger.LedgerBlock; +import com.jd.blockchain.ledger.LedgerInitProperties; import com.jd.blockchain.ledger.TransactionRequest; import com.jd.blockchain.ledger.TransactionRequestBuilder; -import com.jd.blockchain.ledger.core.LedgerDataSet; +import com.jd.blockchain.ledger.core.DefaultOperationHandleRegisteration; +import com.jd.blockchain.ledger.core.LedgerDataQuery; 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.impl.DefaultOperationHandleRegisteration; -import com.jd.blockchain.ledger.core.impl.LedgerManager; -import com.jd.blockchain.ledger.core.impl.TransactionBatchProcessor; +import com.jd.blockchain.ledger.core.TransactionBatchProcessor; import com.jd.blockchain.service.TransactionBatchResultHandle; import com.jd.blockchain.tools.initializer.DBConnectionConfig; -import com.jd.blockchain.tools.initializer.LedgerInitProperties; import com.jd.blockchain.tools.initializer.Prompter; import com.jd.blockchain.tools.initializer.web.LedgerInitConsensusService; -import com.jd.blockchain.tools.keygen.KeyGenCommand; import com.jd.blockchain.transaction.TxBuilder; import com.jd.blockchain.utils.ConsoleUtils; import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback; @@ -45,6 +45,7 @@ import com.jd.blockchain.utils.net.NetworkAddress; import test.com.jd.blockchain.intgr.PresetAnswerPrompter; import test.com.jd.blockchain.intgr.initializer.LedgerInitializeTest; import test.com.jd.blockchain.intgr.initializer.LedgerInitializeTest.NodeContext; +import test.com.jd.blockchain.intgr.perf.LedgerPerformanceTest; import test.com.jd.blockchain.intgr.perf.Utils; public class LedgerBlockGeneratingTest { @@ -76,13 +77,13 @@ public class LedgerBlockGeneratingTest { LedgerBlock latestBlock = ledger.getLatestBlock(); assertEquals(height + i, latestBlock.getHeight()); - LedgerDataSet previousDataSet = ledger.getDataSet(latestBlock); + LedgerDataQuery previousDataSet = ledger.getLedgerData(latestBlock); ConsoleUtils.info("------ 开始执行交易, 即将生成区块[%s] ------", (latestBlock.getHeight() + 1)); long startTs = System.currentTimeMillis(); LedgerEditor newEditor = ledger.createNextBlock(); - TransactionBatchProcessor txProc = new TransactionBatchProcessor(newEditor, previousDataSet, opHandler, - ledgerManager); + TransactionBatchProcessor txProc = new TransactionBatchProcessor( + LedgerPerformanceTest.DEFAULT_SECURITY_MANAGER, newEditor, ledger, opHandler); testTxExec(txList, i * batchSize, batchSize, txProc); @@ -129,9 +130,8 @@ public class LedgerBlockGeneratingTest { LedgerInitProperties initSetting = loadInitSetting(); Properties props = loadConsensusSetting(); ConsensusProvider csProvider = getConsensusProvider(); - ConsensusSettings csProps = csProvider.getSettingsFactory() - .getConsensusSettingsBuilder() - .createSettings(props, Utils.loadParticipantNodes()); + ConsensusSettings csProps = csProvider.getSettingsFactory().getConsensusSettingsBuilder().createSettings(props, + Utils.loadParticipantNodes()); NodeContext node0 = new NodeContext(initSetting.getConsensusParticipant(0).getInitializerAddress(), serviceRegisterMap); @@ -145,28 +145,28 @@ public class LedgerBlockGeneratingTest { String[] memConns = new String[] { "memory://local/0", "memory://local/1", "memory://local/2", "memory://local/3" }; - PrivKey privkey0 = KeyGenCommand.decodePrivKeyWithRawPassword(LedgerInitializeTest.PRIV_KEYS[0], + PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(LedgerInitializeTest.PRIV_KEYS[0], LedgerInitializeTest.PASSWORD); DBConnectionConfig testDb0 = new DBConnectionConfig(); testDb0.setConnectionUri(memConns[0]); AsyncCallback callback0 = node0.startInit(0, privkey0, initSetting, testDb0, consolePrompter, !optimized); - PrivKey privkey1 = KeyGenCommand.decodePrivKeyWithRawPassword(LedgerInitializeTest.PRIV_KEYS[1], + PrivKey privkey1 = KeyGenUtils.decodePrivKeyWithRawPassword(LedgerInitializeTest.PRIV_KEYS[1], LedgerInitializeTest.PASSWORD); DBConnectionConfig testDb1 = new DBConnectionConfig(); testDb1.setConnectionUri(memConns[1]); AsyncCallback callback1 = node1.startInit(1, privkey1, initSetting, testDb1, consolePrompter, !optimized); - PrivKey privkey2 = KeyGenCommand.decodePrivKeyWithRawPassword(LedgerInitializeTest.PRIV_KEYS[2], + PrivKey privkey2 = KeyGenUtils.decodePrivKeyWithRawPassword(LedgerInitializeTest.PRIV_KEYS[2], LedgerInitializeTest.PASSWORD); DBConnectionConfig testDb2 = new DBConnectionConfig(); testDb2.setConnectionUri(memConns[2]); AsyncCallback callback2 = node2.startInit(2, privkey2, initSetting, testDb2, consolePrompter, !optimized); - PrivKey privkey3 = KeyGenCommand.decodePrivKeyWithRawPassword(LedgerInitializeTest.PRIV_KEYS[3], + PrivKey privkey3 = KeyGenUtils.decodePrivKeyWithRawPassword(LedgerInitializeTest.PRIV_KEYS[3], LedgerInitializeTest.PASSWORD); DBConnectionConfig testDb03 = new DBConnectionConfig(); testDb03.setConnectionUri(memConns[3]); diff --git a/source/test/test-integration/src/test/resources/ledger-binding-mem-0.conf b/source/test/test-integration/src/test/resources/ledger-binding-mem-0.conf index 1976cb9e..0c79d2ba 100644 --- a/source/test/test-integration/src/test/resources/ledger-binding-mem-0.conf +++ b/source/test/test-integration/src/test/resources/ledger-binding-mem-0.conf @@ -3,8 +3,12 @@ ledger.bindings=6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ #第 1 个账本[6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ]的配置; +#账本的名字; +binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.name=myledger #账本的当前共识参与方的ID; binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.id=0 +#账本的当前共识参与方的名字; +binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.name=a.com #账本的当前共识参与方的私钥文件的保存路径; binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.pk-path= #账本的当前共识参与方的私钥内容(Base58编码);如果指定了,优先选用此属性,其次是 pk-path 属性; diff --git a/source/test/test-integration/src/test/resources/ledger-binding-mem-1.conf b/source/test/test-integration/src/test/resources/ledger-binding-mem-1.conf index de4e8387..8c0b420f 100644 --- a/source/test/test-integration/src/test/resources/ledger-binding-mem-1.conf +++ b/source/test/test-integration/src/test/resources/ledger-binding-mem-1.conf @@ -3,8 +3,12 @@ ledger.bindings=6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ #第 1 个账本[6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ]的配置; +#账本的名字; +binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.name=myledger #账本的当前共识参与方的ID; binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.id=1 +#账本的当前共识参与方的名字; +binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.name=b.com #账本的当前共识参与方的私钥文件的保存路径; binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.pk-path= #账本的当前共识参与方的私钥内容(Base58编码);如果指定了,优先选用此属性,其次是 pk-path 属性; diff --git a/source/test/test-integration/src/test/resources/ledger-binding-mem-2.conf b/source/test/test-integration/src/test/resources/ledger-binding-mem-2.conf index 09d8c70a..8605cdb8 100644 --- a/source/test/test-integration/src/test/resources/ledger-binding-mem-2.conf +++ b/source/test/test-integration/src/test/resources/ledger-binding-mem-2.conf @@ -3,8 +3,12 @@ ledger.bindings=6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ #第 1 个账本[6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ]的配置; +#账本的名字; +binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.name=myledger #账本的当前共识参与方的ID; binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.id=2 +#账本的当前共识参与方的名字; +binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.name=c.com #账本的当前共识参与方的私钥文件的保存路径; binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.pk-path= #账本的当前共识参与方的私钥内容(Base58编码);如果指定了,优先选用此属性,其次是 pk-path 属性; diff --git a/source/test/test-integration/src/test/resources/ledger-binding-mem-3.conf b/source/test/test-integration/src/test/resources/ledger-binding-mem-3.conf index de8e48b3..bfc77145 100644 --- a/source/test/test-integration/src/test/resources/ledger-binding-mem-3.conf +++ b/source/test/test-integration/src/test/resources/ledger-binding-mem-3.conf @@ -3,8 +3,12 @@ ledger.bindings=6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ #第 1 个账本[6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ]的配置; +#账本的名字; +binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.name=myledger #账本的当前共识参与方的ID; binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.id=3 +#账本的当前共识参与方的名字; +binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.name=d.com #账本的当前共识参与方的私钥文件的保存路径; binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.pk-path= #账本的当前共识参与方的私钥内容(Base58编码);如果指定了,优先选用此属性,其次是 pk-path 属性; diff --git a/source/test/test-integration/src/test/resources/ledger-binding-redis-0.conf b/source/test/test-integration/src/test/resources/ledger-binding-redis-0.conf index 81ebfdfa..958d8846 100644 --- a/source/test/test-integration/src/test/resources/ledger-binding-redis-0.conf +++ b/source/test/test-integration/src/test/resources/ledger-binding-redis-0.conf @@ -3,8 +3,12 @@ ledger.bindings=6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ #第 1 个账本[6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ]的配置; +#账本的名字; +binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.name=myledger #账本的当前共识参与方的ID; binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.id=0 +#账本的当前共识参与方的名字; +binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.name=a.com #账本的当前共识参与方的私钥文件的保存路径; binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.pk-path= #账本的当前共识参与方的私钥内容(Base58编码);如果指定了,优先选用此属性,其次是 pk-path 属性; diff --git a/source/test/test-integration/src/test/resources/ledger-binding-redis-1.conf b/source/test/test-integration/src/test/resources/ledger-binding-redis-1.conf index 04a378c9..c311a690 100644 --- a/source/test/test-integration/src/test/resources/ledger-binding-redis-1.conf +++ b/source/test/test-integration/src/test/resources/ledger-binding-redis-1.conf @@ -3,8 +3,12 @@ ledger.bindings=6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ #第 1 个账本[6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ]的配置; +#账本的名字; +binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.name=myledger #账本的当前共识参与方的ID; binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.id=1 +#账本的当前共识参与方的名字; +binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.name=b.com #账本的当前共识参与方的私钥文件的保存路径; binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.pk-path= #账本的当前共识参与方的私钥内容(Base58编码);如果指定了,优先选用此属性,其次是 pk-path 属性; diff --git a/source/test/test-integration/src/test/resources/ledger-binding-redis-2.conf b/source/test/test-integration/src/test/resources/ledger-binding-redis-2.conf index 5054b7bc..d5a8ce58 100644 --- a/source/test/test-integration/src/test/resources/ledger-binding-redis-2.conf +++ b/source/test/test-integration/src/test/resources/ledger-binding-redis-2.conf @@ -3,8 +3,12 @@ ledger.bindings=6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ #第 1 个账本[6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ]的配置; +#账本的名字; +binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.name=myledger #账本的当前共识参与方的ID; binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.id=2 +#账本的当前共识参与方的名字; +binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.name=c.com #账本的当前共识参与方的私钥文件的保存路径; binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.pk-path= #账本的当前共识参与方的私钥内容(Base58编码);如果指定了,优先选用此属性,其次是 pk-path 属性; diff --git a/source/test/test-integration/src/test/resources/ledger-binding-redis-3.conf b/source/test/test-integration/src/test/resources/ledger-binding-redis-3.conf index 7b7bb525..68ef1bd3 100644 --- a/source/test/test-integration/src/test/resources/ledger-binding-redis-3.conf +++ b/source/test/test-integration/src/test/resources/ledger-binding-redis-3.conf @@ -3,8 +3,12 @@ ledger.bindings=6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ #第 1 个账本[6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ]的配置; +#账本的名字; +binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.name=myledger #账本的当前共识参与方的ID; binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.id=3 +#账本的当前共识参与方的名字; +binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.name=d.com #账本的当前共识参与方的私钥文件的保存路径; binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.pk-path= #账本的当前共识参与方的私钥内容(Base58编码);如果指定了,优先选用此属性,其次是 pk-path 属性; diff --git a/source/test/test-integration/src/test/resources/ledger-binding-rocksdb-0.conf b/source/test/test-integration/src/test/resources/ledger-binding-rocksdb-0.conf index a47d1ddd..73ac4731 100644 --- a/source/test/test-integration/src/test/resources/ledger-binding-rocksdb-0.conf +++ b/source/test/test-integration/src/test/resources/ledger-binding-rocksdb-0.conf @@ -3,8 +3,12 @@ ledger.bindings=6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ #第 1 个账本[6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ]的配置; +#账本的名字; +binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.name=myledger #账本的当前共识参与方的ID; binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.id=0 +#账本的当前共识参与方的名字; +binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.name=a.com #账本的当前共识参与方的私钥文件的保存路径; binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.pk-path= #账本的当前共识参与方的私钥内容(Base58编码);如果指定了,优先选用此属性,其次是 pk-path 属性; diff --git a/source/test/test-integration/src/test/resources/ledger-binding-rocksdb-1.conf b/source/test/test-integration/src/test/resources/ledger-binding-rocksdb-1.conf index ccd3679f..9af1f941 100644 --- a/source/test/test-integration/src/test/resources/ledger-binding-rocksdb-1.conf +++ b/source/test/test-integration/src/test/resources/ledger-binding-rocksdb-1.conf @@ -3,8 +3,12 @@ ledger.bindings=6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ #第 1 个账本[6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ]的配置; +#账本的名字; +binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.name=myledger #账本的当前共识参与方的ID; binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.id=1 +#账本的当前共识参与方的名字; +binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.name=b.com #账本的当前共识参与方的私钥文件的保存路径; binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.pk-path= #账本的当前共识参与方的私钥内容(Base58编码);如果指定了,优先选用此属性,其次是 pk-path 属性; diff --git a/source/test/test-integration/src/test/resources/ledger-binding-rocksdb-2.conf b/source/test/test-integration/src/test/resources/ledger-binding-rocksdb-2.conf index 0d440618..087955da 100644 --- a/source/test/test-integration/src/test/resources/ledger-binding-rocksdb-2.conf +++ b/source/test/test-integration/src/test/resources/ledger-binding-rocksdb-2.conf @@ -3,8 +3,12 @@ ledger.bindings=6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ #第 1 个账本[6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ]的配置; +#账本的名字; +binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.name=myledger #账本的当前共识参与方的ID; binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.id=2 +#账本的当前共识参与方的名字; +binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.name=c.com #账本的当前共识参与方的私钥文件的保存路径; binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.pk-path= #账本的当前共识参与方的私钥内容(Base58编码);如果指定了,优先选用此属性,其次是 pk-path 属性; diff --git a/source/test/test-integration/src/test/resources/ledger-binding-rocksdb-3.conf b/source/test/test-integration/src/test/resources/ledger-binding-rocksdb-3.conf index 6fd34834..2e27c865 100644 --- a/source/test/test-integration/src/test/resources/ledger-binding-rocksdb-3.conf +++ b/source/test/test-integration/src/test/resources/ledger-binding-rocksdb-3.conf @@ -3,8 +3,12 @@ ledger.bindings=6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ #第 1 个账本[6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ]的配置; +#账本的名字; +binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.name=myledger #账本的当前共识参与方的ID; binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.id=3 +#账本的当前共识参与方的名字; +binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.name=d.com #账本的当前共识参与方的私钥文件的保存路径; binding.6BCg5vgU57ykY6g2CpyUnt5ZMgdxfD1b3qXxQrRyfiXTQ.parti.pk-path= #账本的当前共识参与方的私钥内容(Base58编码);如果指定了,优先选用此属性,其次是 pk-path 属性; diff --git a/source/test/test-integration/src/test/resources/ledger_init_test.init b/source/test/test-integration/src/test/resources/ledger_init_test.init index a1dde11f..4253311e 100644 --- a/source/test/test-integration/src/test/resources/ledger_init_test.init +++ b/source/test/test-integration/src/test/resources/ledger_init_test.init @@ -3,11 +3,53 @@ ledger.seed=932dfe23-fe23232f-283f32fa-dd32aa76-8322ca2f-56236cda-7136b322-cb323ffe #账本的描述名称;此属性不参与共识,仅仅在当前参与方的本地节点用于描述用途; -ledger.name= +ledger.name=TEST-LEDGER #声明的账本创建时间;格式为 “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 @@ -18,6 +60,12 @@ 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 @@ -27,6 +75,10 @@ cons_parti.0.name=jd.com 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个参与方的共识服务的端口; @@ -46,6 +98,10 @@ cons_parti.1.name=at.com 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个参与方的共识服务的端口; @@ -65,6 +121,10 @@ cons_parti.2.name=bt.com cons_parti.2.pubkey-path=keys/bt-com.pub #第2个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数; cons_parti.2.pubkey=3snPdw7i7PZi6TStiyc6mzjprnNhgs2atSGNS8wPYzhbKaUWGFJt7x +#第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个参与方的共识服务的端口; @@ -84,6 +144,10 @@ cons_parti.3.name=xt.com 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个参与方的共识服务的端口; diff --git a/source/test/test-integration/src/test/resources/ledger_init_test_web2.init b/source/test/test-integration/src/test/resources/ledger_init_test_web2.init index 90dbedc1..5be0e69d 100644 --- a/source/test/test-integration/src/test/resources/ledger_init_test_web2.init +++ b/source/test/test-integration/src/test/resources/ledger_init_test_web2.init @@ -2,7 +2,7 @@ ledger.seed=932dfe23-fe23232f-283f32fa-dd32aa76-8322ca2f-56236cda-7136b322-cb323ffe #账本的描述名称;此属性不参与共识,仅仅在当前参与方的本地节点用于描述用途; -#ledger.name= +ledger.name==myledger #声明的账本创建时间;格式为 “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 diff --git a/source/test/test-integration/src/test/resources/mq.config b/source/test/test-integration/src/test/resources/mq.config index 33eefafe..9bd3238e 100644 --- a/source/test/test-integration/src/test/resources/mq.config +++ b/source/test/test-integration/src/test/resources/mq.config @@ -6,7 +6,7 @@ system.msg.queue.block.txsize=1000 system.msg.queue.block.maxdelay=2000 system.servers.num=4 -system.server.0.pubkey=endPsK36koyFr1D245Sa9j83vt6pZUdFBJoJRB3xAsWM6cwhRbna -system.server.1.pubkey=endPsK36sC5JdPCDPDAXUwZtS3sxEmqEhFcC4whayAsTTh8Z6eoZ -system.server.2.pubkey=endPsK36jEG281HMHeh6oSqzqLkT95DTnCM6REDURjdb2c67uR3R -system.server.3.pubkey=endPsK36nse1dck4uF19zPvAMijCV336Y3zWdgb4rQG8QoRj5ktR \ No newline at end of file +system.server.0.pubkey=3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9 +system.server.1.pubkey=3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX +system.server.2.pubkey=3snPdw7i7PZi6TStiyc6mzjprnNhgs2atSGNS8wPYzhbKaUWGFJt7x +system.server.3.pubkey=3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk diff --git a/source/test/test-ledger/pom.xml b/source/test/test-ledger/pom.xml new file mode 100644 index 00000000..3e32fb6d --- /dev/null +++ b/source/test/test-ledger/pom.xml @@ -0,0 +1,40 @@ + + 4.0.0 + + com.jd.blockchain + test + 1.1.0-SNAPSHOT + + test-ledger + + + + com.jd.blockchain + tools-initializer + ${project.version} + + + com.jd.blockchain + ledger-core + ${project.version} + + + com.jd.blockchain + storage-redis + ${project.version} + + + com.jd.blockchain + storage-rocksdb + ${project.version} + + + com.jd.blockchain + crypto-classic + ${project.version} + + + + \ No newline at end of file diff --git a/source/test/test-ledger-core/src/main/java/test/perf/com/jd/blockchain/ledger/core/MerkleDatasetPerformanceTester.java b/source/test/test-ledger/src/main/java/test/perf/com/jd/blockchain/ledger/MerkleDatasetPerformanceTester.java similarity index 93% rename from source/test/test-ledger-core/src/main/java/test/perf/com/jd/blockchain/ledger/core/MerkleDatasetPerformanceTester.java rename to source/test/test-ledger/src/main/java/test/perf/com/jd/blockchain/ledger/MerkleDatasetPerformanceTester.java index ef2f6064..7b5faffb 100644 --- a/source/test/test-ledger-core/src/main/java/test/perf/com/jd/blockchain/ledger/core/MerkleDatasetPerformanceTester.java +++ b/source/test/test-ledger/src/main/java/test/perf/com/jd/blockchain/ledger/MerkleDatasetPerformanceTester.java @@ -1,11 +1,12 @@ -package test.perf.com.jd.blockchain.ledger.core; +package test.perf.com.jd.blockchain.ledger; import java.io.IOException; import java.util.Random; -import com.jd.blockchain.crypto.CryptoAlgorithm; 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.ClassicCryptoService; import com.jd.blockchain.ledger.core.CryptoConfig; import com.jd.blockchain.ledger.core.MerkleDataSet; import com.jd.blockchain.storage.service.DbConnection; @@ -16,6 +17,8 @@ import com.jd.blockchain.storage.service.utils.MemoryKVStorage; public class MerkleDatasetPerformanceTester { + private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName() }; + private static final String MKL_KEY_PREFIX = ""; public static void main(String[] args) { @@ -131,7 +134,13 @@ public class MerkleDatasetPerformanceTester { VersioningKVStorage verStorage) { Random rand = new Random(); + CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length]; + for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) { + supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]); + } + CryptoConfig cryptoConfig = new CryptoConfig(); + cryptoConfig.setSupportedProviders(supportedProviders); cryptoConfig.setHashAlgorithm(Crypto.getAlgorithm("SHA256")); cryptoConfig.setAutoVerifyHash(true); diff --git a/source/test/test-ledger-core/src/main/resources/MerkleDataset_Performance_Result_20180922.txt b/source/test/test-ledger/src/main/resources/MerkleDataset_Performance_Result_20180922.txt similarity index 100% rename from source/test/test-ledger-core/src/main/resources/MerkleDataset_Performance_Result_20180922.txt rename to source/test/test-ledger/src/main/resources/MerkleDataset_Performance_Result_20180922.txt diff --git a/source/test/test-ledger/src/test/java/test/com/jd/blockchain/test/ledger/RolesAuthorizationTest.java b/source/test/test-ledger/src/test/java/test/com/jd/blockchain/test/ledger/RolesAuthorizationTest.java new file mode 100644 index 00000000..87b3acc6 --- /dev/null +++ b/source/test/test-ledger/src/test/java/test/com/jd/blockchain/test/ledger/RolesAuthorizationTest.java @@ -0,0 +1,374 @@ +package test.com.jd.blockchain.test.ledger; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.junit.Test; +import org.springframework.core.io.ClassPathResource; + +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.KeyGenUtils; +import com.jd.blockchain.crypto.PrivKey; +import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.BlockchainKeyGenerator; +import com.jd.blockchain.ledger.BlockchainKeypair; +import com.jd.blockchain.ledger.DataAccountRegisterOperation; +import com.jd.blockchain.ledger.DigitalSignature; +import com.jd.blockchain.ledger.LedgerBlock; +import com.jd.blockchain.ledger.LedgerInitOperation; +import com.jd.blockchain.ledger.LedgerInitProperties; +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.RolesPolicy; +import com.jd.blockchain.ledger.TransactionBuilder; +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.UserAuthorizeOperation; +import com.jd.blockchain.ledger.UserRegisterOperation; +import com.jd.blockchain.ledger.UserRoles; +import com.jd.blockchain.ledger.core.DataAccount; +import com.jd.blockchain.ledger.core.DefaultOperationHandleRegisteration; +import com.jd.blockchain.ledger.core.LedgerInitializer; +import com.jd.blockchain.ledger.core.LedgerManager; +import com.jd.blockchain.ledger.core.LedgerQuery; +import com.jd.blockchain.ledger.core.LedgerRepository; +import com.jd.blockchain.ledger.core.OperationHandleRegisteration; +import com.jd.blockchain.ledger.core.TransactionBatchProcessor; +import com.jd.blockchain.ledger.core.UserAccount; +import com.jd.blockchain.service.TransactionBatchResult; +import com.jd.blockchain.service.TransactionBatchResultHandle; +import com.jd.blockchain.storage.service.KVStorageService; +import com.jd.blockchain.storage.service.utils.MemoryKVStorage; +import com.jd.blockchain.tools.initializer.web.LedgerInitConfiguration; +import com.jd.blockchain.transaction.TxBuilder; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.io.RuntimeIOException; + +public class RolesAuthorizationTest { + + private static final OperationHandleRegisteration HANDLE_REG = new DefaultOperationHandleRegisteration(); + + 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" }; + + public static final BlockchainKeypair[] KEYS; + + private static final BlockchainKeypair ADMIN_USER; + private static final BlockchainKeypair MANAGER_USER; + private static final BlockchainKeypair DEFAULT_USER; + private static final BlockchainKeypair GUEST_USER; + + // 预置的新普通用户; + private static final BlockchainKeypair NEW_USER = BlockchainKeyGenerator.getInstance().generate(); + // 预置的数据账户; + private static final BlockchainIdentity DATA_ACCOUNT_ID = BlockchainKeyGenerator.getInstance().generate() + .getIdentity(); + + static { + KEYS = new BlockchainKeypair[PRIV_KEYS.length]; + for (int i = 0; i < PRIV_KEYS.length; i++) { + PrivKey privKey = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[i], PASSWORD); + PubKey pubKey = KeyGenUtils.decodePubKey(PUB_KEYS[i]); + KEYS[i] = new BlockchainKeypair(pubKey, privKey); + } + ADMIN_USER = KEYS[0]; + MANAGER_USER = KEYS[1]; + DEFAULT_USER = KEYS[2]; + GUEST_USER = KEYS[3]; + + // ---------- + DataContractRegistry.register(LedgerInitOperation.class); + DataContractRegistry.register(UserRegisterOperation.class); + DataContractRegistry.register(DataAccountRegisterOperation.class); + DataContractRegistry.register(RolesConfigureOperation.class); + DataContractRegistry.register(UserAuthorizeOperation.class); + } + + @Test + public void test() { + MemoryKVStorage storage = new MemoryKVStorage(); + LedgerBlock genesisBlock = initLedger(storage); + final HashDigest ledgerHash = genesisBlock.getHash(); + + LedgerManager ledgerManager = new LedgerManager(); + LedgerRepository ledger = ledgerManager.register(ledgerHash, storage); + + // 验证角色和用户的权限配置; + assertUserRolesPermissions(ledger); + + // 预置数据:准备一个新用户和数据账户; + TransactionRequest predefinedTx = buildRequest(ledger.getHash(), ADMIN_USER, ADMIN_USER, + new TransactionDefiner() { + @Override + public void define(TransactionBuilder txBuilder) { + txBuilder.security().roles().configure("NORMAL") + .enable(LedgerPermission.REGISTER_DATA_ACCOUNT) + .disable(LedgerPermission.REGISTER_USER) + .enable(TransactionPermission.CONTRACT_OPERATION); + + txBuilder.users().register(NEW_USER.getIdentity()); + + txBuilder.security().authorziations().forUser(NEW_USER.getAddress()).authorize("NORMAL"); + + txBuilder.dataAccounts().register(DATA_ACCOUNT_ID); + } + }); + + TransactionBatchResult procResult = executeTransactions(ledger, predefinedTx); + + //断言预定义数据的交易和区块成功; + assertBlock(1, procResult); + assertTransactionAllSuccess(procResult); + + //断言预定义的数据符合预期; + assertPredefineData(ledgerHash, storage); + + // 用不具备“注册用户”权限的用户,注册另一个新用户,预期交易失败; + BlockchainKeypair tempUser = BlockchainKeyGenerator.getInstance().generate(); + TransactionRequest tx = buildRequest(ledger.getHash(), NEW_USER, ADMIN_USER, new TransactionDefiner() { + @Override + public void define(TransactionBuilder txBuilder) { + txBuilder.users().register(tempUser.getIdentity()); + } + }); + + procResult = executeTransactions(ledger, tx); + assertBlock(2, procResult); + + assertTransactionAllFail(procResult, TransactionState.REJECTED_BY_SECURITY_POLICY); + } + + /** + * 断言区块高度; + * + * @param blockHeight + * @param procResult + */ + private void assertBlock(long blockHeight, TransactionBatchResult procResult) { + assertEquals(blockHeight, procResult.getBlock().getHeight()); + } + + /** + * 断言全部交易结果都是成功的; + * + * @param procResult + */ + private void assertTransactionAllSuccess(TransactionBatchResult procResult) { + + Iterator responses = procResult.getResponses(); + while (responses.hasNext()) { + TransactionResponse transactionResponse = (TransactionResponse) responses.next(); + + assertEquals(true, transactionResponse.isSuccess()); + assertEquals(TransactionState.SUCCESS, transactionResponse.getExecutionState()); + assertEquals(procResult.getBlock().getHash(), transactionResponse.getBlockHash()); + assertEquals(procResult.getBlock().getHeight(), transactionResponse.getBlockHeight()); + } + } + + /** + * 断言全部交易结果都是失败的; + * + * @param procResult + */ + private void assertTransactionAllFail(TransactionBatchResult procResult, TransactionState txState) { + Iterator responses = procResult.getResponses(); + while (responses.hasNext()) { + TransactionResponse transactionResponse = (TransactionResponse) responses.next(); + + assertEquals(false, transactionResponse.isSuccess()); + assertEquals(txState, transactionResponse.getExecutionState()); + } + } + + /** + * 断言预定义的数据符合预期; + * + * @param ledgerHash + * @param storage + */ + private void assertPredefineData(HashDigest ledgerHash, MemoryKVStorage storage) { + LedgerManager ledgerManager = new LedgerManager(); + LedgerRepository ledger = ledgerManager.register(ledgerHash, storage); + UserAccount newUser = ledger.getUserAccountSet().getAccount(NEW_USER.getAddress()); + assertNotNull(newUser); + DataAccount dataAccount = ledger.getDataAccountSet().getAccount(DATA_ACCOUNT_ID.getAddress()); + assertNotNull(dataAccount); + + UserRoles userRoles = ledger.getAdminSettings().getAuthorizations().getUserRoles(NEW_USER.getAddress()); + assertNotNull(userRoles); + assertEquals(1, userRoles.getRoleCount()); + assertEquals("NORMAL", userRoles.getRoles()[0]); + + RolePrivileges normalRole = ledger.getAdminSettings().getRolePrivileges().getRolePrivilege("NORMAL"); + assertNotNull(normalRole); + assertEquals(true, normalRole.getLedgerPrivilege().isEnable(LedgerPermission.REGISTER_DATA_ACCOUNT)); + assertEquals(false, normalRole.getLedgerPrivilege().isEnable(LedgerPermission.REGISTER_USER)); + assertEquals(true, normalRole.getTransactionPrivilege().isEnable(TransactionPermission.CONTRACT_OPERATION)); + assertEquals(false, normalRole.getTransactionPrivilege().isEnable(TransactionPermission.DIRECT_OPERATION)); + } + + private TransactionBatchResult executeTransactions(LedgerRepository ledger, TransactionRequest... transactions) { + TransactionBatchProcessor txProcessor = new TransactionBatchProcessor(ledger, HANDLE_REG); + + for (TransactionRequest request : transactions) { + txProcessor.schedule(request); + } + + TransactionBatchResultHandle procResult = txProcessor.prepare(); + procResult.commit(); + + return procResult; + } + + private TransactionRequest buildRequest(HashDigest ledgerHash, BlockchainKeypair endpoint, BlockchainKeypair node, + TransactionDefiner definer) { + TransactionBuilder txBuilder = new TxBuilder(ledgerHash); + definer.define(txBuilder); + TransactionRequestBuilder reqBuilder = txBuilder.prepareRequest(); + reqBuilder.signAsEndpoint(endpoint); + if (node != null) { + reqBuilder.signAsNode(node); + } + return reqBuilder.buildRequest(); + } + + private void assertUserRolesPermissions(LedgerQuery ledger) { + // 验证角色-权限; + assertRolePermissions(ledger, "DEFAULT", + new LedgerPermission[] { LedgerPermission.REGISTER_USER, LedgerPermission.REGISTER_DATA_ACCOUNT }, + new TransactionPermission[] { TransactionPermission.DIRECT_OPERATION, + TransactionPermission.CONTRACT_OPERATION }); + + assertRolePermissions(ledger, "ADMIN", + new LedgerPermission[] { LedgerPermission.CONFIGURE_ROLES, LedgerPermission.AUTHORIZE_USER_ROLES, + LedgerPermission.SET_CONSENSUS, LedgerPermission.SET_CRYPTO, + LedgerPermission.REGISTER_PARTICIPANT, LedgerPermission.REGISTER_USER }, + new TransactionPermission[] { TransactionPermission.DIRECT_OPERATION }); + + assertRolePermissions(ledger, "MANAGER", + 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, + LedgerPermission.APPROVE_TX }, + new TransactionPermission[] { TransactionPermission.DIRECT_OPERATION, + TransactionPermission.CONTRACT_OPERATION }); + + assertRolePermissions(ledger, "GUEST", new LedgerPermission[] {}, + new TransactionPermission[] { TransactionPermission.CONTRACT_OPERATION }); + + // 验证用户-角色; + assertUserRoles(ledger, ADMIN_USER, RolesPolicy.UNION, "ADMIN", "MANAGER"); + assertUserRoles(ledger, MANAGER_USER, RolesPolicy.UNION, "MANAGER"); + assertUserRoles(ledger, DEFAULT_USER, RolesPolicy.UNION); + assertUserRoles(ledger, DEFAULT_USER, RolesPolicy.UNION); + } + + private void assertUserRoles(LedgerQuery ledger, BlockchainKeypair userKey, RolesPolicy policy, String... roles) { + assertUserRoles(ledger, userKey.getAddress(), policy, roles); + } + + private void assertUserRoles(LedgerQuery ledger, Bytes address, RolesPolicy policy, String[] roles) { + if (roles == null) { + roles = new String[0]; + } + UserRoles userRoles = ledger.getAdminSettings().getAuthorizations().getUserRoles(address); + assertNotNull(userRoles); + assertEquals(policy, userRoles.getPolicy()); + + Set expectedRoles = new HashSet(Arrays.asList(roles)); + Set actualRoles = userRoles.getRoleSet(); + assertEquals(expectedRoles.size(), actualRoles.size()); + for (String r : actualRoles) { + assertTrue(expectedRoles.contains(r)); + } + } + + private void assertRolePermissions(LedgerQuery ledger, String roleName, LedgerPermission[] ledgerPermissions, + TransactionPermission[] txPermissions) { + RolePrivilegeSettings roles = ledger.getAdminSettings().getRolePrivileges(); + assertTrue(roles.contains(roleName)); + RolePrivileges privileges = roles.getRolePrivilege(roleName); + assertEquals(ledgerPermissions.length, privileges.getLedgerPrivilege().getPermissionCount()); + assertEquals(txPermissions.length, privileges.getTransactionPrivilege().getPermissionCount()); + + Set expectedLedgerPermissions = new HashSet( + Arrays.asList(ledgerPermissions)); + for (LedgerPermission p : LedgerPermission.values()) { + if (expectedLedgerPermissions.contains(p)) { + assertTrue(privileges.getLedgerPrivilege().isEnable(p)); + } else { + assertFalse(privileges.getLedgerPrivilege().isEnable(p)); + } + } + + Set expectedTxPermissions = new HashSet( + Arrays.asList(txPermissions)); + for (TransactionPermission p : TransactionPermission.values()) { + if (expectedTxPermissions.contains(p)) { + assertTrue(privileges.getTransactionPrivilege().isEnable(p)); + } else { + assertFalse(privileges.getTransactionPrivilege().isEnable(p)); + } + } + } + + private LedgerBlock initLedger(KVStorageService storage) { + LedgerInitProperties initProps = loadInitProperties(); + LedgerInitConfiguration initConfig = LedgerInitConfiguration.create(initProps); + LedgerInitializer initializer = LedgerInitializer.create(initConfig.getLedgerSettings(), + initConfig.getSecuritySettings()); + + DigitalSignature sign0 = initializer.signTransaction(KEYS[0]); + DigitalSignature sign1 = initializer.signTransaction(KEYS[1]); + DigitalSignature sign2 = initializer.signTransaction(KEYS[2]); + DigitalSignature sign3 = initializer.signTransaction(KEYS[3]); + + LedgerBlock genesisBlock = initializer.prepareLedger(storage, sign0, sign1, sign2, sign3); + initializer.commit(); + return genesisBlock; + } + + private LedgerInitProperties loadInitProperties() { + try { + ClassPathResource ledgerInitSettingResource = new ClassPathResource("ledger.init"); + InputStream in = ledgerInitSettingResource.getInputStream(); + return LedgerInitProperties.resolve(in); + } catch (IOException e) { + throw new RuntimeIOException(e.getMessage(), e); + } + } + + private static interface TransactionDefiner { + + void define(TransactionBuilder txBuilder); + + } +} diff --git a/source/test/test-ledger/src/test/resources/bftsmart.config b/source/test/test-ledger/src/test/resources/bftsmart.config new file mode 100644 index 00000000..df69caf5 --- /dev/null +++ b/source/test/test-ledger/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/test/test-ledger/src/test/resources/keys/parti2.pub b/source/test/test-ledger/src/test/resources/keys/parti2.pub new file mode 100644 index 00000000..dde44b8e --- /dev/null +++ b/source/test/test-ledger/src/test/resources/keys/parti2.pub @@ -0,0 +1 @@ +3snPdw7i7PZi6TStiyc6mzjprnNhgs2atSGNS8wPYzhbKaUWGFJt7x \ No newline at end of file diff --git a/source/test/test-ledger/src/test/resources/ledger.init b/source/test/test-ledger/src/test/resources/ledger.init new file mode 100644 index 00000000..a503c96a --- /dev/null +++ b/source/test/test-ledger/src/test/resources/ledger.init @@ -0,0 +1,165 @@ + +#账本的种子;一段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, APPROVE_TX +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= +#第2个参与方的角色权限策略,可选值有:UNION(并集),INTERSECT(交集);可选项; +cons_parti.2.roles-policy= +#第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/test/test-ledger/src/test/resources/logback-test.xml b/source/test/test-ledger/src/test/resources/logback-test.xml new file mode 100644 index 00000000..29013782 --- /dev/null +++ b/source/test/test-ledger/src/test/resources/logback-test.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/source/tools/pom.xml b/source/tools/pom.xml index d10fd85f..ce56cf0f 100644 --- a/source/tools/pom.xml +++ b/source/tools/pom.xml @@ -14,8 +14,8 @@ tools-keygen-booter tools-initializer tools-initializer-booter - tools-capability - tools-mocker + + \ No newline at end of file diff --git a/source/tools/tools-capability/src/main/java/com/jd/blockchain/capability/service/SettingsInit.java b/source/tools/tools-capability/src/main/java/com/jd/blockchain/capability/service/SettingsInit.java index 4723d615..0c0e6db9 100644 --- a/source/tools/tools-capability/src/main/java/com/jd/blockchain/capability/service/SettingsInit.java +++ b/source/tools/tools-capability/src/main/java/com/jd/blockchain/capability/service/SettingsInit.java @@ -15,22 +15,10 @@ import com.jd.blockchain.consensus.bftsmart.BftsmartConsensusSettings; import com.jd.blockchain.consensus.bftsmart.BftsmartNodeSettings; import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.ledger.ContractCodeDeployOperation; -import com.jd.blockchain.ledger.ContractEventSendOperation; -import com.jd.blockchain.ledger.DataAccountKVSetOperation; -import com.jd.blockchain.ledger.DataAccountRegisterOperation; -import com.jd.blockchain.ledger.EndpointRequest; -import com.jd.blockchain.ledger.LedgerBlock; -import com.jd.blockchain.ledger.NodeRequest; -import com.jd.blockchain.ledger.Operation; -import com.jd.blockchain.ledger.TransactionContent; -import com.jd.blockchain.ledger.TransactionContentBody; -import com.jd.blockchain.ledger.TransactionRequest; -import com.jd.blockchain.ledger.TransactionResponse; -import com.jd.blockchain.ledger.UserRegisterOperation; -import com.jd.blockchain.tools.keygen.KeyGenCommand; +import com.jd.blockchain.ledger.*; import com.jd.blockchain.utils.codec.Base58Utils; /** @@ -58,6 +46,8 @@ public class SettingsInit { DataContractRegistry.register(ContractEventSendOperation.class); DataContractRegistry.register(DataAccountRegisterOperation.class); DataContractRegistry.register(UserRegisterOperation.class); + DataContractRegistry.register(ParticipantRegisterOperation.class); + DataContractRegistry.register(ParticipantStateUpdateOperation.class); DataContractRegistry.register(ActionResponse.class); @@ -116,8 +106,8 @@ public class SettingsInit { CapabilitySettings.ledgerHash = hash; // 处理用户 - PrivKey privKey = KeyGenCommand.decodePrivKeyWithRawPassword(settings.getPrivKey(), settings.getPwd()); - PubKey pubKey = KeyGenCommand.decodePubKey(settings.getPubKey()); + PrivKey privKey = KeyGenUtils.decodePrivKeyWithRawPassword(settings.getPrivKey(), settings.getPwd()); + PubKey pubKey = KeyGenUtils.decodePubKey(settings.getPubKey()); CapabilitySettings.adminKey = new AsymmetricKeypair(pubKey, privKey); } diff --git a/source/tools/tools-initializer-booter/src/main/java/com/jd/blockchain/tools/initializer/boot/LedgerInitCommandBooter.java b/source/tools/tools-initializer-booter/src/main/java/com/jd/blockchain/tools/initializer/boot/LedgerInitCommandBooter.java index 0f333e1d..1a25ac34 100644 --- a/source/tools/tools-initializer-booter/src/main/java/com/jd/blockchain/tools/initializer/boot/LedgerInitCommandBooter.java +++ b/source/tools/tools-initializer-booter/src/main/java/com/jd/blockchain/tools/initializer/boot/LedgerInitCommandBooter.java @@ -11,6 +11,8 @@ import java.util.List; public class LedgerInitCommandBooter { + private static final String[] JAR_DIRS = new String[]{"libs", "system"}; + public static void main(String[] args) { // 加载当前包及../system包下的所有class load(); @@ -32,7 +34,7 @@ public class LedgerInitCommandBooter { Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); boolean accessible = method.isAccessible(); try { - if (accessible == false) { + if (!accessible) { method.setAccessible(true); } // 获取系统类加载器 @@ -64,9 +66,12 @@ public class LedgerInitCommandBooter { } File file = new File(currPath); loadJarFiles.addAll(dirJars(file)); - // 获取上级路径 - String systemPath = file.getParent() + File.separator + "system"; - loadJarFiles.addAll(dirJars(new File(systemPath))); + + for (String jarDir : JAR_DIRS) { + // 获取上级路径 + String jarPath = file.getParent() + File.separator + jarDir; + loadJarFiles.addAll(dirJars(new File(jarPath))); + } } catch (Exception e) { throw new RuntimeException(e); } diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/InitializerConfiguration.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/InitializerConfiguration.java index 3ad076d9..5129433f 100644 --- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/InitializerConfiguration.java +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/InitializerConfiguration.java @@ -2,8 +2,12 @@ package com.jd.blockchain.tools.initializer; import org.springframework.context.annotation.Configuration; +/** + * Spring Boot 项目的配置类; + * + * @author huanghaiquan + * + */ @Configuration public interface InitializerConfiguration { - - } diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerBindingConfig.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerBindingConfig.java index 33fa7674..25fc6519 100644 --- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerBindingConfig.java +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerBindingConfig.java @@ -35,6 +35,8 @@ public class LedgerBindingConfig { // Participant Attribute Key; public static final String PARTI_ADDRESS = PARTI_PREFIX + "address"; + // 参与方名称 + public static final String PARTI_NAME = PARTI_PREFIX + "name"; public static final String PARTI_PK_PATH = PARTI_PREFIX + "pk-path"; public static final String PARTI_PK = PARTI_PREFIX + "pk"; public static final String PARTI_PASSWORD = PARTI_PREFIX + "pwd"; @@ -47,6 +49,9 @@ public class LedgerBindingConfig { public static final String DB_CONN = DB_PREFIX + "uri"; public static final String DB_PASSWORD = DB_PREFIX + "pwd"; + // 账本名字 + public static final String LEDGER_NAME = "name"; + // ------------------------------ private Map bindings = new LinkedHashMap<>(); @@ -89,6 +94,7 @@ public class LedgerBindingConfig { for (int i = 0; i < hashs.length; i++) { writeLine(builder, "#第 %s 个账本[%s]的配置;", i + 1, hashs[i].toBase58()); BindingConfig binding = getLedger(hashs[i]); + writeLedger(builder, hashs[i], binding); writeParticipant(builder, hashs[i], binding); writeDB(builder, hashs[i], binding); writeLine(builder); @@ -113,11 +119,14 @@ public class LedgerBindingConfig { // 参与方配置; String partiAddressKey = String.join(ATTR_SEPERATOR, ledgerPrefix, PARTI_ADDRESS); String partiPkPathKey = String.join(ATTR_SEPERATOR, ledgerPrefix, PARTI_PK_PATH); + String partiNameKey = String.join(ATTR_SEPERATOR, ledgerPrefix, PARTI_NAME); String partiPKKey = String.join(ATTR_SEPERATOR, ledgerPrefix, PARTI_PK); String partiPwdKey = String.join(ATTR_SEPERATOR, ledgerPrefix, PARTI_PASSWORD); writeLine(builder, "#账本的当前共识参与方的节点地址 Address;"); writeLine(builder, "%s=%s", partiAddressKey, stringOf(binding.getParticipant().getAddress())); + writeLine(builder, "#账本的当前共识参与方的节点名称 NodeName;"); + writeLine(builder, "%s=%s", partiNameKey, stringOf(binding.getParticipant().getName())); writeLine(builder, "#账本的当前共识参与方的私钥文件的保存路径;"); writeLine(builder, "%s=%s", partiPkPathKey, stringOf(binding.getParticipant().getPkPath())); writeLine(builder, "#账本的当前共识参与方的私钥内容(Base58编码);如果指定了,优先选用此属性,其次是 pk-path 属性;"); @@ -140,6 +149,16 @@ public class LedgerBindingConfig { writeLine(builder); } + private void writeLedger(StringBuilder builder, HashDigest ledgerHash, BindingConfig binding) { + String ledgerPrefix = String.join(ATTR_SEPERATOR, BINDING_PREFIX, ledgerHash.toBase58()); + // 账本相关信息配置; + String ledgerNameKey = String.join(ATTR_SEPERATOR, ledgerPrefix, LEDGER_NAME); + + writeLine(builder, "#账本的名称;"); + writeLine(builder, "%s=%s", ledgerNameKey, stringOf(binding.getLedgerName())); + writeLine(builder); + } + private static String stringOf(Object obj) { if (obj == null) { return ""; @@ -219,11 +238,12 @@ public class LedgerBindingConfig { // 参与方配置; String partiAddrKey = String.join(ATTR_SEPERATOR, ledgerPrefix, PARTI_ADDRESS); String partiPkPathKey = String.join(ATTR_SEPERATOR, ledgerPrefix, PARTI_PK_PATH); + String partiNameKey = String.join(ATTR_SEPERATOR, ledgerPrefix, PARTI_NAME); String partiPKKey = String.join(ATTR_SEPERATOR, ledgerPrefix, PARTI_PK); String partiPwdKey = String.join(ATTR_SEPERATOR, ledgerPrefix, PARTI_PASSWORD); - String strPartiAddr = getProperty(props, partiAddrKey, true); - binding.participant.address = strPartiAddr; + binding.participant.address = getProperty(props, partiAddrKey, true); + binding.participant.name = getProperty(props, partiNameKey, true); binding.participant.pkPath = getProperty(props, partiPkPathKey, false); binding.participant.pk = getProperty(props, partiPKKey, false); binding.participant.password = getProperty(props, partiPwdKey, false); @@ -247,6 +267,10 @@ public class LedgerBindingConfig { String.format("No db connection config of participant of ledger binding[%s]!", ledgerHash)); } + // 设置账本名称 + String ledgerNameKey = String.join(ATTR_SEPERATOR, ledgerPrefix, LEDGER_NAME); + binding.ledgerName = getProperty(props, ledgerNameKey, true); + return binding; } @@ -296,6 +320,9 @@ public class LedgerBindingConfig { public static class BindingConfig { + private String ledgerName; + + // 账本名字 private ParticipantBindingConfig participant = new ParticipantBindingConfig(); private DBConnectionConfig dbConnection = new DBConnectionConfig(); @@ -308,18 +335,35 @@ public class LedgerBindingConfig { return dbConnection; } + public void setLedgerName(String ledgerName) { + this.ledgerName = ledgerName; + } + + public String getLedgerName() { + return ledgerName; + } } public static class ParticipantBindingConfig { private String address; + private String name; + private String pkPath; private String pk; private String password; + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + public String getAddress() { return address; } diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitCommand.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitCommand.java index 8077b6dc..0073a346 100644 --- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitCommand.java +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitCommand.java @@ -12,12 +12,13 @@ import org.springframework.context.ConfigurableApplicationContext; import com.jd.blockchain.crypto.AddressEncoding; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.ledger.core.impl.LedgerManager; +import com.jd.blockchain.ledger.LedgerInitProperties; +import com.jd.blockchain.ledger.LedgerInitProperties.ParticipantProperties; +import com.jd.blockchain.ledger.core.LedgerManager; import com.jd.blockchain.tools.initializer.LedgerBindingConfig.BindingConfig; -import com.jd.blockchain.tools.initializer.LedgerInitProperties.ConsensusParticipantConfig; -import com.jd.blockchain.tools.keygen.KeyGenCommand; import com.jd.blockchain.utils.ArgumentSet; import com.jd.blockchain.utils.ArgumentSet.ArgEntry; import com.jd.blockchain.utils.ArgumentSet.Setting; @@ -52,6 +53,8 @@ public class LedgerInitCommand { private static final Prompter ANSWER_PROMPTER = new PresetAnswerPrompter("Y"); + private static final Prompter LOG_PROMPTER = new LogPrompter(); + /** * 入口; * @@ -65,7 +68,7 @@ public class LedgerInitCommand { try { if (argSet.hasOption(MONITOR_OPT)) { - prompter = ANSWER_PROMPTER; + prompter = LOG_PROMPTER; } ArgEntry localArg = argSet.getArg(LOCAL_ARG); @@ -84,23 +87,23 @@ public class LedgerInitCommand { // load ledger init setting; LedgerInitProperties ledgerInitProperties = LedgerInitProperties.resolve(iniArg.getValue()); String localNodePubKeyString = localConf.getLocal().getPubKeyString(); - PubKey localNodePubKey = KeyGenCommand.decodePubKey(localNodePubKeyString); + PubKey localNodePubKey = KeyGenUtils.decodePubKey(localNodePubKeyString); // 地址根据公钥生成 String localNodeAddress = AddressEncoding.generateAddress(localNodePubKey).toBase58(); // 加载全部公钥; int currId = -1; for (int i = 0; i < ledgerInitProperties.getConsensusParticipantCount(); i++) { - ConsensusParticipantConfig partiConf = ledgerInitProperties.getConsensusParticipant(i); + ParticipantProperties partiConf = ledgerInitProperties.getConsensusParticipant(i); // String partiAddress = partiConf.getAddress(); // if (partiAddress == null) { // if (partiConf.getPubKeyPath() != null) { -// PubKey pubKey = KeyGenCommand.readPubKey(partiConf.getPubKeyPath()); +// PubKey pubKey = KeyGenUtils.readPubKey(partiConf.getPubKeyPath()); // partiConf.setPubKey(pubKey); // partiAddress = partiConf.getAddress(); // } // } - if (localNodeAddress.equals(partiConf.getAddress())) { + if (localNodeAddress.equals(partiConf.getAddress().toBase58())) { currId = i; } } @@ -112,9 +115,9 @@ public class LedgerInitCommand { // 加载当前节点的私钥; String base58Pwd = localConf.getLocal().getPassword(); if (base58Pwd == null) { - base58Pwd = KeyGenCommand.readPasswordString(); + base58Pwd = KeyGenUtils.readPasswordString(); } - PrivKey privKey = KeyGenCommand.decodePrivKey(localConf.getLocal().getPrivKeyString(), base58Pwd); + PrivKey privKey = KeyGenUtils.decodePrivKey(localConf.getLocal().getPrivKeyString(), base58Pwd); // Output ledger binding config of peer; if (!FileUtils.existDirectory(localConf.getBindingOutDir())) { @@ -178,8 +181,16 @@ public class LedgerInitCommand { // generate binding config; BindingConfig bindingConf = new BindingConfig(); - bindingConf.getParticipant().setAddress(ledgerInitProperties.getConsensusParticipant(currId).getAddress()); - String encodedPrivKey = KeyGenCommand.encodePrivKey(privKey, base58Pwd); + + // 设置账本名称 + bindingConf.setLedgerName(ledgerInitProperties.getLedgerName()); + + bindingConf.getParticipant() + .setAddress(ledgerInitProperties.getConsensusParticipant(currId).getAddress().toBase58()); + // 设置参与方名称 + bindingConf.getParticipant().setName(ledgerInitProperties.getConsensusParticipant(currId).getName()); + + String encodedPrivKey = KeyGenUtils.encodePrivKey(privKey, base58Pwd); bindingConf.getParticipant().setPk(encodedPrivKey); bindingConf.getParticipant().setPassword(base58Pwd); diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProcess.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProcess.java index 58b01af5..71cc6816 100644 --- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProcess.java +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProcess.java @@ -3,6 +3,8 @@ package com.jd.blockchain.tools.initializer; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.ledger.CryptoSetting; +import com.jd.blockchain.ledger.LedgerInitProperties; +import com.jd.blockchain.tools.initializer.web.LedgerInitConfiguration; /** * @@ -27,13 +29,13 @@ public interface LedgerInitProcess { /** * @param currentId * @param privKey - * @param ledgerInitProps + * @param ledgerInitConfig * @param dbConnConfig * @param prompter * @param cryptoSetting * @return */ - HashDigest initialize(int currentId, PrivKey privKey, LedgerInitProperties ledgerInitProps, - DBConnectionConfig dbConnConfig, Prompter prompter, CryptoSetting cryptoSetting); + HashDigest initialize(int currentId, PrivKey privKey, LedgerInitConfiguration ledgerInitConfig, + DBConnectionConfig dbConnConfig, Prompter prompter); } diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProperties.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProperties.java deleted file mode 100644 index fa29ba71..00000000 --- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProperties.java +++ /dev/null @@ -1,313 +0,0 @@ -package com.jd.blockchain.tools.initializer; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; - -import org.springframework.util.ResourceUtils; - -import com.jd.blockchain.crypto.AddressEncoding; -import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.ledger.ParticipantNode; -import com.jd.blockchain.tools.keygen.KeyGenCommand; -import com.jd.blockchain.utils.PropertiesUtils; -import com.jd.blockchain.utils.codec.HexUtils; -import com.jd.blockchain.utils.io.FileUtils; -import com.jd.blockchain.utils.net.NetworkAddress; - -public class LedgerInitProperties { - - // 账本种子; - public static final String LEDGER_SEED = "ledger.seed"; - - // 声明的账本建立时间; - public static final String CREATED_TIME = "created-time"; - // 创建时间的格式; - public static final String CREATED_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss.SSSZ"; - - // 共识参与方的个数,后续以 part.id 分别标识每一个参与方的配置; - public static final String PART_COUNT = "cons_parti.count"; - // 共识参与方的名称的模式; - 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_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_SERVICE_PROVIDERS_SPLITTER = ","; - - private byte[] ledgerSeed; - - private List consensusParticipants = new ArrayList<>(); - - private String consensusProvider; - - private Properties consensusConfig; - - private String[] cryptoProviders; - - private long createdTime; - - public byte[] getLedgerSeed() { - return ledgerSeed.clone(); - } - - 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 String[] getCryptoProviders() { - return cryptoProviders.clone(); - } - - public void setCryptoProviders(String[] cryptoProviders) { - this.cryptoProviders = cryptoProviders; - } - - /** - * 返回参与者; - * - * @param id 从 1 开始; 小于等于 {@link #getConsensusParticipantCount()}; - * @return - */ - public ConsensusParticipantConfig getConsensusParticipant(int id) { - for (ConsensusParticipantConfig p : consensusParticipants) { - if (p.getId() == id) { - return p; - } - } - return null; - } - - private LedgerInitProperties(byte[] ledgerSeed) { - this.ledgerSeed = ledgerSeed; - } - - public void addConsensusParticipant(ConsensusParticipantConfig participant) { - consensusParticipants.add(participant); - } - - private static String getKeyOfCsParti(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); - } - - public static LedgerInitProperties resolve(String dir, Properties props) { - String hexLedgerSeed = PropertiesUtils.getRequiredProperty(props, LEDGER_SEED).replace("-", ""); - byte[] ledgerSeed = HexUtils.decode(hexLedgerSeed); - LedgerInitProperties initProps = new LedgerInitProperties(ledgerSeed); - - // 创建时间; - String strCreatedTime = PropertiesUtils.getRequiredProperty(props, CREATED_TIME); - try { - initProps.createdTime = new SimpleDateFormat(CREATED_TIME_FORMAT).parse(strCreatedTime).getTime(); - } catch (ParseException ex) { - throw new IllegalArgumentException(ex.getMessage(), ex); - } - - // 解析共识相关的属性; - initProps.consensusProvider = PropertiesUtils.getRequiredProperty(props, CONSENSUS_SERVICE_PROVIDER); - String consensusConfigFilePath = PropertiesUtils.getRequiredProperty(props, CONSENSUS_CONFIG); - try { - File consensusConfigFile = FileUtils.getFile(dir, 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.cryptoProviders = cryptoProviders; - - // 解析参与方节点列表; - 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++) { - ConsensusParticipantConfig parti = new ConsensusParticipantConfig(); - - parti.setId(i); - - String nameKey = getKeyOfCsParti(i, PART_NAME); - parti.setName(PropertiesUtils.getRequiredProperty(props, nameKey)); - - String pubkeyPathKey = getKeyOfCsParti(i, PART_PUBKEY_PATH); - String pubkeyPath = PropertiesUtils.getProperty(props, pubkeyPathKey, false); - - String pubkeyKey = getKeyOfCsParti(i, PART_PUBKEY); - String base58PubKey = PropertiesUtils.getProperty(props, pubkeyKey, false); - if (base58PubKey != null) { - PubKey pubKey = KeyGenCommand.decodePubKey(base58PubKey); - parti.setPubKey(pubKey); - } else if (pubkeyPath != null) { - PubKey pubKey = KeyGenCommand.readPubKey(pubkeyPath); - parti.setPubKey(pubKey); - } else { - throw new IllegalArgumentException( - String.format("Property[%s] and property[%s] are all empty!", pubkeyKey, pubkeyPathKey)); - } - - String initializerHostKey = getKeyOfCsParti(i, PART_INITIALIZER_HOST); - String initializerHost = PropertiesUtils.getRequiredProperty(props, initializerHostKey); - - String initializerPortKey = getKeyOfCsParti(i, PART_INITIALIZER_PORT); - int initializerPort = getInt(PropertiesUtils.getRequiredProperty(props, initializerPortKey)); - - String initializerSecureKey = getKeyOfCsParti(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 int getInt(String strInt) { - return Integer.parseInt(strInt.trim()); - } - - /** - * 参与方配置信息; - * - * @author huanghaiquan - * - */ - public static class ConsensusParticipantConfig implements ParticipantNode { - - private int id; - - private String address; - - private String name; - -// private String pubKeyPath; - - private PubKey pubKey; - - // private NetworkAddress consensusAddress; - - private NetworkAddress initializerAddress; - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - @Override - public String 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).toBase58(); - } - - } - -} diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LogPrompter.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LogPrompter.java new file mode 100644 index 00000000..ccc6a850 --- /dev/null +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LogPrompter.java @@ -0,0 +1,52 @@ +package com.jd.blockchain.tools.initializer; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class LogPrompter implements Prompter { + + private static final Logger LOGGER = LoggerFactory.getLogger(LogPrompter.class); + + private static final String ANSWER_DEFAULT = "Yes"; + + private boolean debug = true; + + @Override + public void info(String format, Object... args) { + LOGGER.info(format, args); + } + + @Override + public void error(String format, Object... args) { + LOGGER.error(format, args); + } + + @Override + public void error(Exception error, String format, Object... args) { + if (debug) { + error.printStackTrace(); + LOGGER.error(error.toString()); + } + } + + @Override + public String confirm(String format, Object... args) { + return confirm("", format, args); + } + + @Override + public String confirm(String tag, String format, Object... args) { + String msg = String.format(format, args); + LOGGER.info(msg); + return ANSWER_DEFAULT; + } + + public boolean isDebug() { + return debug; + } + + public void setDebug(boolean debug) { + this.debug = debug; + } + +} \ No newline at end of file diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/DecisionResponseConverter.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/DecisionResponseConverter.java index ba60ec8c..e9d3017d 100644 --- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/DecisionResponseConverter.java +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/DecisionResponseConverter.java @@ -3,7 +3,7 @@ package com.jd.blockchain.tools.initializer.web; import java.io.InputStream; import com.jd.blockchain.binaryproto.BinaryProtocol; -import com.jd.blockchain.tools.initializer.LedgerInitException; +import com.jd.blockchain.ledger.LedgerInitException; import com.jd.blockchain.utils.http.HttpServiceContext; import com.jd.blockchain.utils.http.ResponseConverter; import com.jd.blockchain.utils.http.agent.ServiceRequest; diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/InitWebServerConfiguration.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/InitWebServerConfiguration.java index ec918972..69195dad 100644 --- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/InitWebServerConfiguration.java +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/InitWebServerConfiguration.java @@ -8,7 +8,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; -import com.jd.blockchain.ledger.core.impl.LedgerManager; +import com.jd.blockchain.ledger.core.LedgerManager; import com.jd.blockchain.utils.io.ByteArray; import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils; diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitConfiguration.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitConfiguration.java new file mode 100644 index 00000000..d453cc26 --- /dev/null +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitConfiguration.java @@ -0,0 +1,282 @@ +package com.jd.blockchain.tools.initializer.web; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Properties; +import java.util.Set; + +import com.jd.blockchain.consensus.ConsensusProvider; +import com.jd.blockchain.consensus.ConsensusProviders; +import com.jd.blockchain.consensus.ConsensusSettings; +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.CryptoSetting; +import com.jd.blockchain.ledger.LedgerInitException; +import com.jd.blockchain.ledger.LedgerInitProperties; +import com.jd.blockchain.ledger.LedgerInitProperties.CryptoProperties; +import com.jd.blockchain.ledger.LedgerInitProperties.ParticipantProperties; +import com.jd.blockchain.ledger.LedgerPermission; +import com.jd.blockchain.ledger.SecurityInitData; +import com.jd.blockchain.ledger.TransactionPermission; +import com.jd.blockchain.ledger.core.CryptoConfig; +import com.jd.blockchain.ledger.core.LedgerSecurityManager; +import com.jd.blockchain.transaction.LedgerInitData; +import com.jd.blockchain.utils.StringUtils; + +public class LedgerInitConfiguration { + + private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(), + SMCryptoService.class.getName() }; + + private static final String DEFAULT_HASH_ALGORITHM = "SHA256"; + + private ParticipantProperties[] participants; + + private ConsensusConfig consensusConfiguration; + + private CryptoConfig cryptoConfig; + + private ConsensusConfig consensusConfig; + + private LedgerInitData ledgerSettings; + + private SecurityInitData securitySettings; + + public ParticipantProperties[] getParticipants() { + return participants; + } + + public int getParticipantCount() { + return participants.length; + } + + /** + * @param id + * @return + */ + public ParticipantProperties getParticipant(int id) { + // 注:解析的过程确保了参与方列表是升序排列,且列表中第一个参与方的 id 为 0, id 以 1 递增; + return participants[id]; + } + + public ConsensusConfig getConsensusConfiguration() { + return consensusConfiguration; + } + + public CryptoConfig getCryptoConfig() { + return cryptoConfig; + } + + public ConsensusConfig getConsensusConfig() { + return consensusConfig; + } + + public LedgerInitData getLedgerSettings() { + return ledgerSettings; + } + + public SecurityInitData getSecuritySettings() { + return securitySettings; + } + + private LedgerInitConfiguration() { + } + + public void setConsensusSettings(ConsensusProvider consensusProvider, ConsensusSettings consensusSettings) { + byte[] consensusSettingBytes = encodeConsensusSettings(consensusProvider, consensusSettings); + ledgerSettings.setConsensusProvider(consensusProvider.getName()); + ledgerSettings.setConsensusSettings(consensusSettingBytes); + } + + public static LedgerInitConfiguration create(LedgerInitProperties ledgerInitProps) { + LedgerInitConfiguration ledgerConfig = new LedgerInitConfiguration(); + + CryptoConfig cryptoConfig = createCryptoConfig(ledgerInitProps.getCryptoProperties()); + ledgerConfig.cryptoConfig = cryptoConfig; + + ConsensusConfig consensusConfig = createConsensusConfig(ledgerInitProps); + ledgerConfig.consensusConfig = consensusConfig; + + ParticipantProperties[] participants = resolveParticipants(ledgerInitProps); + ledgerConfig.participants = participants; + + LedgerInitData ledgerSettings = createLedgerInitSettings(ledgerInitProps, cryptoConfig, consensusConfig, + participants); + ledgerConfig.ledgerSettings = ledgerSettings; + + SecurityInitData securitySettings = createSecurityInitSettings(ledgerInitProps, participants); + ledgerConfig.securitySettings = securitySettings; + + return ledgerConfig; + } + + private static ConsensusConfig createConsensusConfig(LedgerInitProperties initProps) { + ConsensusProvider consensusProvider = ConsensusProviders.getProvider(initProps.getConsensusProvider()); + + Properties csProps = initProps.getConsensusConfig(); + ConsensusSettings protocolSettings = consensusProvider.getSettingsFactory().getConsensusSettingsBuilder() + .createSettings(csProps, initProps.getConsensusParticipantNodes()); + + ConsensusConfig config = new ConsensusConfig(); + config.setProvider(consensusProvider); + config.setProtocolSettings(protocolSettings); + + return config; + } + + private static CryptoConfig createCryptoConfig(CryptoProperties cryptoProperties) { + // 总是包含默认的提供者; + Set cryptoProviderNames = new LinkedHashSet(); + for (String providerName : SUPPORTED_PROVIDERS) { + cryptoProviderNames.add(providerName); + } + if (cryptoProperties.getProviders() != null) { + for (String providerName : cryptoProperties.getProviders()) { + cryptoProviderNames.add(providerName); + } + } + CryptoProvider[] cryptoProviders = new CryptoProvider[cryptoProviderNames.size()]; + int i = 0; + for (String providerName : cryptoProviderNames) { + cryptoProviders[i] = Crypto.getProvider(providerName); + i++; + } + + String hashAlgorithmName = StringUtils.trim(cryptoProperties.getHashAlgorithm()); + hashAlgorithmName = hashAlgorithmName.length() == 0 ? DEFAULT_HASH_ALGORITHM : hashAlgorithmName; + CryptoAlgorithm hashAlgorithm = Crypto.getAlgorithm(hashAlgorithmName); + + CryptoConfig cryptoConfig = new CryptoConfig(); + cryptoConfig.setSupportedProviders(cryptoProviders); + cryptoConfig.setAutoVerifyHash(cryptoProperties.isVerifyHash()); + cryptoConfig.setHashAlgorithm(hashAlgorithm); + + return cryptoConfig; + } + + private static SecurityInitData createSecurityInitSettings(LedgerInitProperties ledgerInitProps, + ParticipantProperties[] participants) { + // 设置角色; + SecurityInitData securityInitData = new SecurityInitData(); + securityInitData.setRoles(ledgerInitProps.getRoles()); + // 如果没有默认角色,则创建“默认”角色; + if (securityInitData.getRolesCount() == 0) { + securityInitData.addRole(LedgerSecurityManager.DEFAULT_ROLE, LedgerPermission.values(), + TransactionPermission.values()); + } else if (!securityInitData.containsRole(LedgerSecurityManager.DEFAULT_ROLE)) { + // 如果定义了角色,则必须显式地定义“默认”角色; + throw new LedgerInitException("Miss definition of role[DEFAULT]!"); + } + + // 设置授权; + for (ParticipantProperties partiProps : participants) { + String[] roles = partiProps.getRoles(); + for (String role : roles) { + if (!securityInitData.containsRole(role)) { + throw new LedgerInitException( + String.format("The role[%s] authenticated to participant[%s-%s] is not defined!", role, + partiProps.getId(), partiProps.getName())); + } + } + //去掉对默认角色的授权; + + securityInitData.addUserAuthencation(partiProps.getAddress(), roles, partiProps.getRolesPolicy()); + } + + return securityInitData; + } + + private static LedgerInitData createLedgerInitSettings(LedgerInitProperties ledgerProps, + CryptoSetting cryptoSetting, ConsensusConfig consensusConfig, ParticipantProperties[] participants) { + // 创建初始化配置; + LedgerInitData initSetting = new LedgerInitData(); + initSetting.setLedgerSeed(ledgerProps.getLedgerSeed()); + initSetting.setCryptoSetting(cryptoSetting); + + initSetting.setConsensusParticipants(participants); + + initSetting.setCreatedTime(ledgerProps.getCreatedTime()); + + // 创建共识配置; + try { + byte[] consensusSettingsBytes = encodeConsensusSettings(consensusConfig.getProvider(), + consensusConfig.protocolSettings); + initSetting.setConsensusProvider(consensusConfig.getProvider().getName()); + initSetting.setConsensusSettings(consensusSettingsBytes); + } catch (Exception e) { + throw new LedgerInitException("Create default consensus config failed! --" + e.getMessage(), e); + } + + return initSetting; + } + + public static byte[] encodeConsensusSettings(ConsensusProvider consensusProvider, + ConsensusSettings consensusSettings) { + return consensusProvider.getSettingsFactory().getConsensusSettingsEncoder().encode(consensusSettings); + } + + /** + * 解析参与方列表; + * + * @param ledgerInitProps + * @return + */ + private static ParticipantProperties[] resolveParticipants(LedgerInitProperties ledgerInitProps) { + List partiList = ledgerInitProps.getConsensusParticipants(); + ParticipantProperties[] parties = new ParticipantProperties[partiList.size()]; + parties = partiList.toArray(parties); + ParticipantProperties[] orderedParties = sortAndVerify(parties); + + return orderedParties; + } + + /** + * 对参与者列表按照 id 进行升序排列,并校验id是否从 1 开始且没有跳跃; + * + * @param parties + * @return + */ + private static ParticipantProperties[] sortAndVerify(ParticipantProperties[] parties) { + Arrays.sort(parties, new Comparator() { + @Override + public int compare(ParticipantProperties o1, ParticipantProperties o2) { + return o1.getId() - o2.getId(); + } + }); + for (int i = 0; i < parties.length; i++) { + if (parties[i].getId() != i) { + throw new LedgerInitException( + "The ids of participants are not match their positions in the participant-list!"); + } + } + return parties; + } + + public static class ConsensusConfig { + + private ConsensusProvider provider; + + private ConsensusSettings protocolSettings; + + public ConsensusSettings getProtocolSettings() { + return protocolSettings; + } + + public void setProtocolSettings(ConsensusSettings protocolSettings) { + this.protocolSettings = protocolSettings; + } + + public ConsensusProvider getProvider() { + return provider; + } + + public void setProvider(ConsensusProvider provider) { + this.provider = provider; + } + } +} diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitConsensusService.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitConsensusService.java index d9699560..46ae01b5 100644 --- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitConsensusService.java +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitConsensusService.java @@ -2,7 +2,7 @@ package com.jd.blockchain.tools.initializer.web; import com.jd.blockchain.crypto.SignatureDigest; import com.jd.blockchain.ledger.core.LedgerInitDecision; -import com.jd.blockchain.ledger.core.LedgerInitPermission; +import com.jd.blockchain.ledger.core.LedgerInitProposal; import com.jd.blockchain.utils.http.HttpAction; import com.jd.blockchain.utils.http.HttpMethod; import com.jd.blockchain.utils.http.HttpService; @@ -21,7 +21,7 @@ public interface LedgerInitConsensusService { * 请求者的私钥对 “id” + “账本种子” 做出的签名;只有签名合法且参与者是初始化配置中的参与方才能获得有效返回,否则将被拒绝; */ @HttpAction(path = "/legerinit/permission/{requesterId}", method = HttpMethod.POST, contentType = LedgerInitMessageConverter.CONTENT_TYPE_VALUE, responseConverter = PermissionResponseConverter.class) - LedgerInitPermission requestPermission(@PathParam(name = "requesterId") int requesterId, + LedgerInitProposal requestPermission(@PathParam(name = "requesterId") int requesterId, @RequestBody(converter = SignatureDigestRequestBodyConverter.class) SignatureDigest signature); /** diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitMessageConverter.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitMessageConverter.java index 5658f9f6..6361d6a1 100644 --- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitMessageConverter.java +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitMessageConverter.java @@ -17,8 +17,8 @@ import com.jd.blockchain.binaryproto.BinaryProtocol; import com.jd.blockchain.binaryproto.DataContractRegistry; import com.jd.blockchain.crypto.SignatureDigest; import com.jd.blockchain.ledger.core.LedgerInitDecision; -import com.jd.blockchain.ledger.core.LedgerInitPermission; -import com.jd.blockchain.ledger.core.LedgerInitPermissionData; +import com.jd.blockchain.ledger.core.LedgerInitProposal; +import com.jd.blockchain.ledger.core.LedgerInitProposalData; import com.jd.blockchain.utils.io.BytesUtils; /** @@ -38,10 +38,10 @@ public class LedgerInitMessageConverter implements HttpMessageConverter private static final Map, Class> SUPPORTED_CONTRACT_TYPES = new HashMap<>(); static { - DataContractRegistry.register(LedgerInitPermission.class); + DataContractRegistry.register(LedgerInitProposal.class); DataContractRegistry.register(LedgerInitDecision.class); - SUPPORTED_CONTRACT_TYPES.put(LedgerInitPermission.class, LedgerInitPermissionData.class); + SUPPORTED_CONTRACT_TYPES.put(LedgerInitProposal.class, LedgerInitProposalData.class); SUPPORTED_CONTRACT_TYPES.put(LedgerInitDecision.class, LedgerInitDecisionData.class); // SUPPORTED_CONTRACT_TYPES.add(LedgerInitResponse.class); diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitializeWebController.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitializeWebController.java index 116a381a..0d4216ea 100644 --- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitializeWebController.java +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitializeWebController.java @@ -3,14 +3,12 @@ package com.jd.blockchain.tools.initializer.web; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; -import java.util.Comparator; import java.util.List; -import java.util.Properties; import java.util.Random; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; -import com.jd.blockchain.transaction.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; @@ -19,47 +17,31 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.consensus.ConsensusProvider; -import com.jd.blockchain.consensus.ConsensusProviders; -import com.jd.blockchain.consensus.ConsensusSettings; import com.jd.blockchain.crypto.Crypto; -import com.jd.blockchain.crypto.CryptoProvider; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.crypto.SignatureDigest; import com.jd.blockchain.crypto.SignatureFunction; -import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; -import com.jd.blockchain.crypto.service.sm.SMCryptoService; -import com.jd.blockchain.ledger.BlockchainIdentity; -import com.jd.blockchain.ledger.BlockchainIdentityData; -import com.jd.blockchain.ledger.CryptoSetting; -import com.jd.blockchain.ledger.LedgerBlock; -import com.jd.blockchain.ledger.LedgerInitSetting; -import com.jd.blockchain.ledger.Operation; +import com.jd.blockchain.ledger.DigitalSignature; +import com.jd.blockchain.ledger.LedgerInitException; +import com.jd.blockchain.ledger.LedgerInitProperties; +import com.jd.blockchain.ledger.LedgerInitProperties.ParticipantProperties; import com.jd.blockchain.ledger.ParticipantNode; -import com.jd.blockchain.ledger.TransactionBuilder; import com.jd.blockchain.ledger.TransactionContent; import com.jd.blockchain.ledger.TransactionRequest; -import com.jd.blockchain.ledger.TransactionState; -import com.jd.blockchain.ledger.UserRegisterOperation; -import com.jd.blockchain.ledger.core.CryptoConfig; -import com.jd.blockchain.ledger.core.LedgerEditor; import com.jd.blockchain.ledger.core.LedgerInitDecision; -import com.jd.blockchain.ledger.core.LedgerInitPermission; -import com.jd.blockchain.ledger.core.LedgerInitPermissionData; -import com.jd.blockchain.ledger.core.LedgerManage; -import com.jd.blockchain.ledger.core.LedgerTransactionContext; +import com.jd.blockchain.ledger.core.LedgerInitProposal; +import com.jd.blockchain.ledger.core.LedgerInitProposalData; +import com.jd.blockchain.ledger.core.LedgerInitializer; import com.jd.blockchain.storage.service.DbConnection; import com.jd.blockchain.storage.service.DbConnectionFactory; import com.jd.blockchain.tools.initializer.DBConnectionConfig; import com.jd.blockchain.tools.initializer.InitializingStep; -import com.jd.blockchain.tools.initializer.LedgerInitException; import com.jd.blockchain.tools.initializer.LedgerInitProcess; -import com.jd.blockchain.tools.initializer.LedgerInitProperties; -import com.jd.blockchain.tools.initializer.LedgerInitProperties.ConsensusParticipantConfig; import com.jd.blockchain.tools.initializer.Prompter; -import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.transaction.DigitalSignatureBlob; +import com.jd.blockchain.transaction.SignatureUtils; import com.jd.blockchain.utils.concurrent.InvocationResult; import com.jd.blockchain.utils.io.BytesUtils; import com.jd.blockchain.utils.net.NetworkAddress; @@ -77,42 +59,36 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI DataContractRegistry.register(TransactionRequest.class); } - private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(), - SMCryptoService.class.getName() }; - private static final String DEFAULT_SIGN_ALGORITHM = "ED25519"; + /** + * 决定值列表并发处理,必须等待Local释放 + * + */ + private final CountDownLatch decisionsCountDownLatch = new CountDownLatch(1); + private final SignatureFunction SIGN_FUNC; - private volatile LedgerInitPermission localPermission; + private volatile LedgerInitConfiguration ledgerInitConfig; - private TransactionContent initTxContent; + private volatile LedgerInitializer initializer; - private volatile int currentId = -1; + private volatile LedgerInitProposal localPermission; - private volatile LedgerInitSetting ledgerInitSetting; + private volatile int currentId = -1; - private volatile LedgerInitPermission[] permissions; + private volatile LedgerInitProposal[] permissions; private volatile NetworkAddress[] initializerAddresses; private volatile Prompter prompter; - private volatile ConsensusProvider consensusProvider; - - private volatile LedgerBlock genesisBlock; - private volatile LedgerInitDecision localDecision; private volatile DecisionResultHandle[] decisions; private volatile DbConnection dbConn; - private volatile LedgerEditor ledgerEditor; - - @Autowired - private LedgerManage ledgerManager; - @Autowired private DbConnectionFactory dbConnFactory; @@ -123,11 +99,10 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI this.SIGN_FUNC = Crypto.getSignatureFunction(DEFAULT_SIGN_ALGORITHM); } - public LedgerInitializeWebController(LedgerManage ledgerManager, DbConnectionFactory dbConnFactory, + public LedgerInitializeWebController(DbConnectionFactory dbConnFactory, InitConsensusServiceFactory initCsServiceFactory) { this.SIGN_FUNC = Crypto.getSignatureFunction(DEFAULT_SIGN_ALGORITHM); - this.ledgerManager = ledgerManager; this.dbConnFactory = dbConnFactory; this.initCsServiceFactory = initCsServiceFactory; } @@ -137,10 +112,10 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI } public TransactionContent getInitTxContent() { - return initTxContent; + return initializer.getTransactionContent(); } - public LedgerInitPermission getLocalPermission() { + public LedgerInitProposal getLocalPermission() { return localPermission; } @@ -152,40 +127,36 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI this.prompter = prompter; } -// private ConsensusProvider getConsensusProvider() { -// return consensusProvider; -// } - - private void setConsensusProvider(ConsensusProvider consensusProvider) { - this.consensusProvider = consensusProvider; - } - @Override public HashDigest initialize(int currentId, PrivKey privKey, LedgerInitProperties ledgerInitProps, DBConnectionConfig dbConnConfig, Prompter prompter) { - return initialize(currentId, privKey, ledgerInitProps, dbConnConfig, prompter, createDefaultCryptoSetting()); + LedgerInitConfiguration initConfig = LedgerInitConfiguration.create(ledgerInitProps); + return initialize(currentId, privKey, initConfig, dbConnConfig, prompter); } @Override - public HashDigest initialize(int currentId, PrivKey privKey, LedgerInitProperties ledgerInitProps, - DBConnectionConfig dbConnConfig, Prompter prompter, CryptoSetting cryptoSetting) { - - if (this.ledgerInitSetting != null) { + public HashDigest initialize(int currentId, PrivKey privKey, LedgerInitConfiguration initConfig, + DBConnectionConfig dbConnConfig, Prompter prompter) { + if (initConfig == null) { + throw new IllegalArgumentException("Ledger init configuration is null"); + } + if (this.ledgerInitConfig != null) { throw new IllegalStateException("ledger init process has already started."); } setPrompter(prompter); - Properties csProps = ledgerInitProps.getConsensusConfig(); - ConsensusProvider csProvider = ConsensusProviders.getProvider(ledgerInitProps.getConsensusProvider()); - ConsensusSettings csSettings = csProvider.getSettingsFactory() - .getConsensusSettingsBuilder() - .createSettings(csProps, ledgerInitProps.getConsensusParticipantNodes()); - setConsensusProvider(csProvider); +// Properties csProps = ledgerInitProps.getConsensusConfig(); +// ConsensusProvider csProvider = ConsensusProviders.getProvider(ledgerInitProps.getConsensusProvider()); +// ConsensusSettings csSettings = csProvider.getSettingsFactory().getConsensusSettingsBuilder() +// .createSettings(csProps, ledgerInitProps.getConsensusParticipantNodes()); +// setConsensusProvider(csProvider); prompter.info("Init settings and sign permision..."); - prepareLocalPermission(currentId, privKey, ledgerInitProps, csSettings, cryptoSetting); + this.ledgerInitConfig = initConfig; + + prepareLocalPermission(currentId, privKey, ledgerInitConfig); prompter.confirm(InitializingStep.PERMISSION_READY.toString(), "Ledger init permission has already prepared! Any key to continue..."); @@ -226,22 +197,40 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI } public LedgerInitDecision makeLocalDecision(PrivKey privKey) { - // 生成账本; - this.ledgerEditor = ledgerManager.newLedger(this.ledgerInitSetting, dbConn.getStorageService()); - this.genesisBlock = initLedgerDataset(ledgerEditor); - - // 生成签名决定; - this.localDecision = makeDecision(currentId, genesisBlock.getHash(), privKey); - this.decisions = new DecisionResultHandle[this.ledgerInitSetting.getConsensusParticipants().length]; - for (int i = 0; i < decisions.length; i++) { - // 参与者的 id 是依次递增的; - this.decisions[i] = new DecisionResultHandle(i); + + try { + // 生成账本; + initializer.prepareLedger(dbConn.getStorageService(), getNodesSignatures()); + + // 生成签名决定; + this.localDecision = makeDecision(currentId, initializer.getLedgerHash(), privKey); + this.decisions = new DecisionResultHandle[ledgerInitConfig.getParticipantCount()]; + for (int i = 0; i < decisions.length; i++) { + // 参与者的 id 是依次递增的; + this.decisions[i] = new DecisionResultHandle(i); + } + // 预置当前参与方的“决定”到列表,避免向自己发起请求; + this.decisions[currentId].setValue(localDecision); + } finally { + // 释放,以便于其他节点接收 + this.decisionsCountDownLatch.countDown(); } - // 预置当前参与方的“决定”到列表,避免向自己发起请求; - this.decisions[currentId].setValue(localDecision); + return localDecision; } + private DigitalSignature[] getNodesSignatures() { + ParticipantNode[] parties = this.ledgerInitConfig.getParticipants(); + DigitalSignature[] signatures = new DigitalSignature[parties.length]; + for (int i = 0; i < parties.length; i++) { + PubKey pubKey = parties[i].getPubKey(); + SignatureDigest signDigest = this.permissions[i].getTransactionSignature(); + signatures[i] = new DigitalSignatureBlob(pubKey, signDigest); + } + + return signatures; + } + public HashDigest consensusDecisions(PrivKey privKey) { // 获取其它参与方的账本生成结果; boolean allDecided = startRequestDecisions(privKey, prompter); @@ -249,13 +238,13 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI prompter.error( "Rollback ledger initialization because of not all nodes make same decision! --[Current Participant=%s]", currentId); - ledgerEditor.cancel(); + initializer.cancel(); return null; } // 执行提交提交; - ledgerEditor.commit(); - return genesisBlock.getHash(); + initializer.commit(); + return initializer.getLedgerHash(); } public void closeDb() { @@ -306,87 +295,57 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI return allPermitted; } - public CryptoSetting createDefaultCryptoSetting() { - CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length]; - for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) { - supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]); - } - CryptoConfig defCryptoSetting = new CryptoConfig(); - defCryptoSetting.setSupportedProviders(supportedProviders); - defCryptoSetting.setAutoVerifyHash(true); - defCryptoSetting.setHashAlgorithm(Crypto.getAlgorithm("SHA256")); - - return defCryptoSetting; - } - - public LedgerInitPermission prepareLocalPermission(int currentId, PrivKey privKey, LedgerInitProperties ledgerProps, - ConsensusSettings consensusProps) { - CryptoSetting defCryptoSetting = createDefaultCryptoSetting(); - return prepareLocalPermission(currentId, privKey, ledgerProps, consensusProps, defCryptoSetting); +// public CryptoSetting createDefaultCryptoSetting() { +// CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length]; +// for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) { +// supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]); +// } +// CryptoConfig defCryptoSetting = new CryptoConfig(); +// defCryptoSetting.setSupportedProviders(supportedProviders); +// defCryptoSetting.setAutoVerifyHash(true); +// defCryptoSetting.setHashAlgorithm(Crypto.getAlgorithm("SHA256")); +// +// return defCryptoSetting; +// } +// + public LedgerInitProposal prepareLocalPermission(int currentId, PrivKey privKey, + LedgerInitProperties ledgerInitProps) { + LedgerInitConfiguration ledgerInitConfiguration = LedgerInitConfiguration.create(ledgerInitProps); + return prepareLocalPermission(currentId, privKey, ledgerInitConfiguration); } - public LedgerInitPermission prepareLocalPermission(int currentId, PrivKey privKey, LedgerInitProperties ledgerProps, - ConsensusSettings csSettings, CryptoSetting cryptoSetting) { + public LedgerInitProposal prepareLocalPermission(int currentId, PrivKey privKey, + LedgerInitConfiguration ledgerInitConfig) { // 创建初始化配置; - LedgerInitSettingData initSetting = new LedgerInitSettingData(); - initSetting.setLedgerSeed(ledgerProps.getLedgerSeed()); - initSetting.setCryptoSetting(cryptoSetting); - - List partiList = ledgerProps.getConsensusParticipants(); - ConsensusParticipantConfig[] parties = new ConsensusParticipantConfig[partiList.size()]; - parties = partiList.toArray(parties); -// ConsensusParticipantConfig[] parties = partiList.toArray(new ConsensusParticipantConfig[partiList.size()]); - ConsensusParticipantConfig[] orderedParties = sortAndVerify(parties); - initSetting.setConsensusParticipants(orderedParties); - initSetting.setCreatedTime(ledgerProps.getCreatedTime()); - - // 创建默认的共识配置; - try { - // ConsensusConfig csConfig = new ConsensusConfig(); - byte[] csSettingBytes = consensusProvider.getSettingsFactory().getConsensusSettingsEncoder() - .encode(csSettings); - initSetting.setConsensusProvider(consensusProvider.getName()); - initSetting.setConsensusSettings(new Bytes(csSettingBytes)); - } catch (Exception e) { - throw new LedgerInitException("Create default consensus config failed! --" + e.getMessage(), e); - } - - if (currentId < 0 || currentId >= orderedParties.length) { + ParticipantProperties[] participants = ledgerInitConfig.getParticipants(); + if (currentId < 0 || currentId >= participants.length) { throw new LedgerInitException("Your id is out of bound of participant list!"); } this.currentId = currentId; - this.ledgerInitSetting = initSetting; // 校验当前的公钥、私钥是否匹配; byte[] testBytes = BytesUtils.toBytes(currentId); SignatureDigest testSign = SIGN_FUNC.sign(privKey, testBytes); - PubKey myPubKey = orderedParties[currentId].getPubKey(); + PubKey myPubKey = participants[currentId].getPubKey(); if (!SIGN_FUNC.verify(testSign, myPubKey, testBytes)) { throw new LedgerInitException("Your pub-key specified in the init-settings isn't match your priv-key!"); } - this.initializerAddresses = new NetworkAddress[orderedParties.length]; + this.initializerAddresses = new NetworkAddress[participants.length]; // 记录每个参与方的账本初始化服务地址; - for (int i = 0; i < orderedParties.length; i++) { - initializerAddresses[i] = orderedParties[i].getInitializerAddress(); + for (int i = 0; i < participants.length; i++) { + initializerAddresses[i] = participants[i].getInitializerAddress(); } - // 生成初始化交易,并签署许可; - TransactionBuilder initTxBuilder = new TxBuilder(null);// 账本初始化交易的账本 hash 为 null; - initTxBuilder.ledgers().create(initSetting); - for (ParticipantNode p : initSetting.getConsensusParticipants()) { - // TODO:暂时只支持注册用户的初始化操作; - BlockchainIdentity superUserId = new BlockchainIdentityData(p.getPubKey()); - initTxBuilder.users().register(superUserId); - } - // 账本初始化配置声明的创建时间来初始化交易时间戳;注:不能用本地时间,因为共识节点之间的本地时间系统不一致; - this.initTxContent = initTxBuilder.prepareContent(initSetting.getCreatedTime()); + // 初始化账本; + this.initializer = LedgerInitializer.create(ledgerInitConfig.getLedgerSettings(), + ledgerInitConfig.getSecuritySettings()); // 对初始交易签名,生成当前参与者的账本初始化许可; - SignatureDigest permissionSign = SignatureUtils.sign(initTxContent, privKey); - LedgerInitPermissionData permission = new LedgerInitPermissionData(currentId, permissionSign); + SignatureDigest permissionSign = initializer.signTransaction(privKey); + LedgerInitProposalData permission = new LedgerInitProposalData(currentId, permissionSign); this.currentId = currentId; - this.permissions = new LedgerInitPermission[initSetting.getConsensusParticipants().length]; + this.permissions = new LedgerInitProposal[ledgerInitConfig.getParticipantCount()]; this.permissions[currentId] = permission; this.localPermission = permission; @@ -405,33 +364,6 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI return decision; } - private LedgerBlock initLedgerDataset(LedgerEditor ledgerEditor) { - // 初始化时,自动将参与方注册为账本的用户; - TxRequestBuilder txReqBuilder = new TxRequestBuilder(this.initTxContent); - ParticipantNode[] parties = this.ledgerInitSetting.getConsensusParticipants(); - for (int i = 0; i < parties.length; i++) { - PubKey pubKey = parties[i].getPubKey(); - SignatureDigest signDigest = this.permissions[i].getTransactionSignature(); - DigitalSignatureBlob digitalSignature = new DigitalSignatureBlob(pubKey, signDigest); - txReqBuilder.addNodeSignature(digitalSignature); - } - TransactionRequest txRequest = txReqBuilder.buildRequest(); - - LedgerTransactionContext txCtx = ledgerEditor.newTransaction(txRequest); - Operation[] ops = txRequest.getTransactionContent().getOperations(); - // 注册用户; 注:第一个操作是 LedgerInitOperation; - // TODO:暂时只支持注册用户的初始化操作; - for (int i = 1; i < ops.length; i++) { - UserRegisterOperation userRegOP = (UserRegisterOperation) ops[i]; - txCtx.getDataSet().getUserAccountSet().register(userRegOP.getUserID().getAddress(), - userRegOP.getUserID().getPubKey()); - } - - txCtx.commit(TransactionState.SUCCESS, null); - - return ledgerEditor.prepare(); - } - /** * 请求所有其它参与方的账本创建许可; * @@ -441,7 +373,7 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI private boolean startRequestPermissions(int currentId, PrivKey privKey) { SignatureDigest reqAuthSign = signPermissionRequest(currentId, privKey); - ParticipantNode[] participants = ledgerInitSetting.getConsensusParticipants(); + ParticipantNode[] participants = ledgerInitConfig.getParticipants(); // 异步请求结果列表;不包括已经获得许可的参与方; InvocationResult[] results = new InvocationResult[participants.length]; @@ -493,7 +425,7 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI continue; } PubKey pubKey = participants[i].getPubKey(); - LedgerInitPermission permission = (LedgerInitPermission) results[i].getValue(); + LedgerInitProposal permission = (LedgerInitProposal) results[i].getValue(); if (permission.getParticipantId() != participants[i].getId()) { prompter.error("\r\nThe id of received permission isn't equal to it's participant ! --[Id=%s][name=%s]", participants[i].getAddress(), participants[i].getName()); @@ -501,7 +433,8 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI continue; } - if (!SignatureUtils.verifySignature(this.initTxContent, permission.getTransactionSignature(), pubKey)) { + if (!SignatureUtils.verifySignature(initializer.getTransactionContent(), + permission.getTransactionSignature(), pubKey)) { prompter.error("Invalid permission from participant! --[Id=%s][name=%s]", participants[i].getAddress(), participants[i].getName()); allPermitted = false; @@ -521,7 +454,8 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI } public SignatureDigest signPermissionRequest(int requesterId, PrivKey privKey) { - byte[] reqAuthBytes = BytesUtils.concat(BytesUtils.toBytes(requesterId), ledgerInitSetting.getLedgerSeed()); + byte[] reqAuthBytes = BytesUtils.concat(BytesUtils.toBytes(requesterId), + ledgerInitConfig.getLedgerSettings().getLedgerSeed()); SignatureDigest reqAuthSign = SIGN_FUNC.sign(privKey, reqAuthBytes); return reqAuthSign; } @@ -534,16 +468,16 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI * @param latch * @return */ - private InvocationResult doRequestPermission(int targetId, SignatureDigest reqAuthSign, + private InvocationResult doRequestPermission(int targetId, SignatureDigest reqAuthSign, CountDownLatch latch) { - InvocationResult result = new InvocationResult<>(); + InvocationResult result = new InvocationResult<>(); try { LedgerInitConsensusService initConsensus = connectToParticipant(targetId); Thread thrd = new Thread(new Runnable() { @Override public void run() { try { - LedgerInitPermission permission = initConsensus.requestPermission(currentId, reqAuthSign); + LedgerInitProposal permission = initConsensus.requestPermission(currentId, reqAuthSign); result.setValue(permission); } catch (Exception e) { result.setError(e); @@ -561,13 +495,13 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI @RequestMapping(path = "/legerinit/permission/{requesterId}", method = RequestMethod.POST, produces = LedgerInitMessageConverter.CONTENT_TYPE_VALUE, consumes = LedgerInitMessageConverter.CONTENT_TYPE_VALUE) @Override - public LedgerInitPermission requestPermission(@PathVariable(name = "requesterId") int requesterId, + public LedgerInitProposal requestPermission(@PathVariable(name = "requesterId") int requesterId, @RequestBody SignatureDigest signature) { if (requesterId == currentId) { throw new LedgerInitException("There is a id conflict!"); } int retry = 0; - while (currentId == -1 || ledgerInitSetting == null || localPermission == null) { + while (currentId == -1 || ledgerInitConfig == null || localPermission == null) { // 本地尚未完成初始化; if (retry < 30) { try { @@ -581,11 +515,12 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI retry++; } - ParticipantNode[] participants = ledgerInitSetting.getConsensusParticipants(); + ParticipantNode[] participants = ledgerInitConfig.getParticipants(); if (requesterId < 0 || requesterId >= participants.length) { throw new LedgerInitException("The id of requester is out of the bound of participant list!"); } - byte[] requestCodeBytes = BytesUtils.concat(BytesUtils.toBytes(requesterId), ledgerInitSetting.getLedgerSeed()); + byte[] requestCodeBytes = BytesUtils.concat(BytesUtils.toBytes(requesterId), + ledgerInitConfig.getLedgerSettings().getLedgerSeed()); PubKey requesterPubKey = participants[requesterId].getPubKey(); if (!SIGN_FUNC.verify(signature, requesterPubKey, requestCodeBytes)) { throw new LedgerInitException("The requester signature is invalid!"); @@ -724,8 +659,7 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI } // 检查签名; - PubKey targetPubKey = ledgerInitSetting.getConsensusParticipants()[targetDecision.getParticipantId()] - .getPubKey(); + PubKey targetPubKey = ledgerInitConfig.getParticipant(targetDecision.getParticipantId()).getPubKey(); byte[] deciBytes = getDecisionBytes(targetDecision.getParticipantId(), targetDecision.getLedgerHash()); if ((!SIGN_FUNC.verify(targetDecision.getSignature(), targetPubKey, deciBytes)) && resultHandle.getValue() == null) { @@ -748,7 +682,7 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI String.format("Reject decision because of self-synchronization! --[Id=%s]", remoteId)); } - if (this.genesisBlock == null) { + if (this.initializer == null) { // 当前参与者尚未准备就绪,返回 null; prompter.info("Not ready for genesis block! --[RemoteId=%s][CurrentId=%s]", remoteId, currentId); return null; @@ -758,6 +692,9 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI try { + // 必须等待本地处理完成,此处线程阻塞 + this.decisionsCountDownLatch.await(); + DecisionResultHandle resultHandle = this.decisions[remoteId]; if (!validateAndRecordDecision(initDecision, resultHandle)) { // 签名无效; @@ -777,28 +714,6 @@ public class LedgerInitializeWebController implements LedgerInitProcess, LedgerI } } - /** - * 对参与者列表按照 id 进行升序排列,并校验id是否从 1 开始且没有跳跃; - * - * @param parties - * @return - */ - private ConsensusParticipantConfig[] sortAndVerify(ConsensusParticipantConfig[] parties) { - Arrays.sort(parties, new Comparator() { - @Override - public int compare(ConsensusParticipantConfig o1, ConsensusParticipantConfig o2) { - return o1.getId() - o2.getId(); - } - }); - for (int i = 0; i < parties.length; i++) { - if (parties[i].getId() != i) { - throw new LedgerInitException( - "The ids of participants are not match their positions in the participant-list!"); - } - } - return parties; - } - private static class DecisionResultHandle extends InvocationResult { private final int PARTICIPANT_ID; diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/PermissionResponseConverter.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/PermissionResponseConverter.java index ab5b0308..f291d6c9 100644 --- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/PermissionResponseConverter.java +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/PermissionResponseConverter.java @@ -3,8 +3,8 @@ package com.jd.blockchain.tools.initializer.web; import java.io.InputStream; import com.jd.blockchain.binaryproto.BinaryProtocol; -import com.jd.blockchain.ledger.core.LedgerInitPermissionData; -import com.jd.blockchain.tools.initializer.LedgerInitException; +import com.jd.blockchain.ledger.LedgerInitException; +import com.jd.blockchain.ledger.core.LedgerInitProposalData; import com.jd.blockchain.utils.http.HttpServiceContext; import com.jd.blockchain.utils.http.ResponseConverter; import com.jd.blockchain.utils.http.agent.ServiceRequest; diff --git a/source/tools/tools-initializer/src/main/resources/application.properties b/source/tools/tools-initializer/src/main/resources/application.properties index 2090d209..16cdc6bf 100644 --- a/source/tools/tools-initializer/src/main/resources/application.properties +++ b/source/tools/tools-initializer/src/main/resources/application.properties @@ -1,17 +1,13 @@ server.address=127.0.0.1 server.port=8900 -#server.ssl.key-store=classpath:mykeys.jks -#server.ssl.key-store-password=abc123 -#server.ssl.key-password=abc123 - server.tomcat.accesslog.enabled=true debug=false +logging.config=classpath:log4j2-init.xml #logging.file=logs/peer.log logging.level.com.jd.blockchain=DEBUG logging.level.org.org.springframework=DEBUG -spring.mvc.favicon.enabled=false - +spring.mvc.favicon.enabled=false \ No newline at end of file diff --git a/source/tools/tools-initializer/src/main/resources/banner2.txt b/source/tools/tools-initializer/src/main/resources/banner2.txt deleted file mode 100644 index f1c960f7..00000000 --- a/source/tools/tools-initializer/src/main/resources/banner2.txt +++ /dev/null @@ -1,12 +0,0 @@ - - 888888 8888888b. 888888b. 888 888 .d8888b. 888 d8b - "88b 888 "Y88b 888 "88b 888 888 d88P Y88b 888 Y8P - 888 888 888 888 .88P 888 888 888 888 888 - 888 888 888 8888888K. 888 .d88b. .d8888b 888 888 888 88888b. 8888b. 888 88888b. - 888 888 888 888 "Y88b 888 d88""88b d88P" 888 .88P 888 888 "88b "88b 888 888 "88b - 888 888 888 888 888 888 888 888 888 888888K 888 888 888 888 .d888888 888 888 888 - 88P 888 .d88P 888 d88P 888 Y88..88P Y88b. 888 "88b Y88b d88P 888 888 888 888 888 888 888 - 888 8888888P" 8888888P" 888 "Y88P" "Y8888P 888 888 "Y8888P" 888 888 "Y888888 888 888 888 - .d88P - .d88P" -888P" diff --git a/source/tools/tools-initializer/src/main/resources/banner3.txt b/source/tools/tools-initializer/src/main/resources/banner3.txt deleted file mode 100644 index a8e93d02..00000000 --- a/source/tools/tools-initializer/src/main/resources/banner3.txt +++ /dev/null @@ -1,12 +0,0 @@ - - $$$$$\ $$$$$$$\ $$$$$$$\ $$\ $$\ $$$$$$\ $$\ $$\ - \__$$ |$$ __$$\ $$ __$$\ $$ | $$ | $$ __$$\ $$ | \__| - $$ |$$ | $$ | $$ | $$ |$$ | $$$$$$\ $$$$$$$\ $$ | $$\ $$ / \__|$$$$$$$\ $$$$$$\ $$\ $$$$$$$\ - $$ |$$ | $$ | $$$$$$$\ |$$ |$$ __$$\ $$ _____|$$ | $$ | $$ | $$ __$$\ \____$$\ $$ |$$ __$$\ -$$\ $$ |$$ | $$ | $$ __$$\ $$ |$$ / $$ |$$ / $$$$$$ / $$ | $$ | $$ | $$$$$$$ |$$ |$$ | $$ | -$$ | $$ |$$ | $$ | $$ | $$ |$$ |$$ | $$ |$$ | $$ _$$< $$ | $$\ $$ | $$ |$$ __$$ |$$ |$$ | $$ | -\$$$$$$ |$$$$$$$ | $$$$$$$ |$$ |\$$$$$$ |\$$$$$$$\ $$ | \$$\ \$$$$$$ |$$ | $$ |\$$$$$$$ |$$ |$$ | $$ | - \______/ \_______/ \_______/ \__| \______/ \_______|\__| \__| \______/ \__| \__| \_______|\__|\__| \__| - - - diff --git a/source/tools/tools-initializer/src/main/resources/log4j2-init.xml b/source/tools/tools-initializer/src/main/resources/log4j2-init.xml new file mode 100644 index 00000000..6ef49baf --- /dev/null +++ b/source/tools/tools-initializer/src/main/resources/log4j2-init.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/source/tools/tools-initializer/src/test/java/test/com/jd/blockchain/tools/initializer/LedgerInitPropertiesTest.java b/source/tools/tools-initializer/src/test/java/test/com/jd/blockchain/tools/initializer/LedgerInitPropertiesTest.java deleted file mode 100644 index 703b86b4..00000000 --- a/source/tools/tools-initializer/src/test/java/test/com/jd/blockchain/tools/initializer/LedgerInitPropertiesTest.java +++ /dev/null @@ -1,95 +0,0 @@ -package test.com.jd.blockchain.tools.initializer; - -import static org.junit.Assert.*; - -import java.io.IOException; -import java.io.InputStream; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; - -import com.jd.blockchain.crypto.AddressEncoding; -import org.junit.Test; -import org.springframework.core.io.ClassPathResource; - -import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.tools.initializer.LedgerInitProperties; -import com.jd.blockchain.tools.initializer.LedgerInitProperties.ConsensusParticipantConfig; -import com.jd.blockchain.tools.keygen.KeyGenCommand; -import com.jd.blockchain.utils.codec.HexUtils; - -public class LedgerInitPropertiesTest { - - private static String expectedCreatedTimeStr = "2019-08-01 14:26:58.069+0800"; - - @Test - public void testTimeFormat() throws ParseException { - SimpleDateFormat timeFormat = new SimpleDateFormat(LedgerInitProperties.CREATED_TIME_FORMAT); - Date time = timeFormat.parse(expectedCreatedTimeStr); - String actualTimeStr = timeFormat.format(time); - assertEquals(expectedCreatedTimeStr, actualTimeStr); - } - - @Test - public void testProperties() throws IOException, ParseException { - ClassPathResource ledgerInitSettingResource = new ClassPathResource("ledger.init"); - InputStream in = ledgerInitSettingResource.getInputStream(); - try { - LedgerInitProperties initProps = LedgerInitProperties.resolve(in); - assertEquals(4, initProps.getConsensusParticipantCount()); - 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); - long expectedTs = timeFormat.parse(expectedCreatedTimeStr).getTime(); - assertEquals(expectedTs, initProps.getCreatedTime()); - - String createdTimeStr = timeFormat.format(new Date(initProps.getCreatedTime())); - assertEquals(expectedCreatedTimeStr, createdTimeStr); - - assertEquals("com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider", - initProps.getConsensusProvider()); - - String[] cryptoProviders = initProps.getCryptoProviders(); - assertEquals(2, cryptoProviders.length); - assertEquals("com.jd.blockchain.crypto.service.classic.ClassicCryptoService", cryptoProviders[0]); - assertEquals("com.jd.blockchain.crypto.service.sm.SMCryptoService", cryptoProviders[1]); - - ConsensusParticipantConfig part0 = initProps.getConsensusParticipant(0); - assertEquals("jd.com", part0.getName()); - PubKey pubKey0 = KeyGenCommand.decodePubKey("3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9"); - assertEquals(pubKey0, part0.getPubKey()); - assertEquals("127.0.0.1", part0.getInitializerAddress().getHost()); - assertEquals(8800, part0.getInitializerAddress().getPort()); - assertEquals(true, part0.getInitializerAddress().isSecure()); - - ConsensusParticipantConfig part1 = initProps.getConsensusParticipant(1); - assertEquals(false, part1.getInitializerAddress().isSecure()); - PubKey pubKey1 = KeyGenCommand.decodePubKey("3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX"); - assertEquals(pubKey1, part1.getPubKey()); - - ConsensusParticipantConfig part2 = initProps.getConsensusParticipant(2); - assertEquals("7VeRAr3dSbi1xatq11ZcF7sEPkaMmtZhV9shonGJWk9T4pLe", part2.getPubKey().toBase58()); - - } finally { - in.close(); - } - } - - @Test - public void testPubKeyAddress() { - String[] pubKeys = TestConsts.PUB_KEYS; - int index = 0; - for (String pubKeyStr : pubKeys) { - System.out.println("[" + index + "][配置] = " + pubKeyStr); - PubKey pubKey = KeyGenCommand.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/tools/tools-initializer/src/test/resources/ledger-binding.conf b/source/tools/tools-initializer/src/test/resources/ledger-binding.conf index e4cf6c2b..82b1ba3d 100644 --- a/source/tools/tools-initializer/src/test/resources/ledger-binding.conf +++ b/source/tools/tools-initializer/src/test/resources/ledger-binding.conf @@ -6,7 +6,9 @@ j5kLUENMvcUooZjKfz2bEYU6zoK9DAqbdDDU8aZEZFR4qf #第1个账本[j5ptBmn67B2p3yki3ji1j2ZMjnJhrUvP4kFpGmcXgvrhmk]的配置; #账本的当前共识参与方的ID; +binding.j5ptBmn67B2p3yki3ji1j2ZMjnJhrUvP4kFpGmcXgvrhmk.name= PRODUCT-INFO binding.j5ptBmn67B2p3yki3ji1j2ZMjnJhrUvP4kFpGmcXgvrhmk.parti.address=1 +binding.j5ptBmn67B2p3yki3ji1j2ZMjnJhrUvP4kFpGmcXgvrhmk.parti.name=PARTI-01 #账本的当前共识参与方的私钥文件的保存路径; binding.j5ptBmn67B2p3yki3ji1j2ZMjnJhrUvP4kFpGmcXgvrhmk.parti.pk-path=keys/jd-com.priv #账本的当前共识参与方的私钥内容(Base58编码);如果指定了,优先选用此属性,其次是 pk-path 属性; @@ -21,7 +23,9 @@ binding.j5ptBmn67B2p3yki3ji1j2ZMjnJhrUvP4kFpGmcXgvrhmk.db.pwd=kksfweffj #第2个账本[j5kLUENMvcUooZjKfz2bEYU6zoK9DAqbdDDU8aZEZFR4qf]的配置; #账本的当前共识参与方的ID; +binding.j5kLUENMvcUooZjKfz2bEYU6zoK9DAqbdDDU8aZEZFR4qf.name= BASIC-INFO binding.j5kLUENMvcUooZjKfz2bEYU6zoK9DAqbdDDU8aZEZFR4qf.parti.address=2 +binding.j5kLUENMvcUooZjKfz2bEYU6zoK9DAqbdDDU8aZEZFR4qf.parti.name=PARTI-02 #账本的当前共识参与方的私钥文件的保存路径; binding.j5kLUENMvcUooZjKfz2bEYU6zoK9DAqbdDDU8aZEZFR4qf.parti.pk-path=keys/jd-com-1.priv #账本的当前共识参与方的私钥内容(Base58编码);如果指定了,优先选用此属性,其次是 pk-path 属性; diff --git a/source/tools/tools-initializer/src/test/resources/ledger.init b/source/tools/tools-initializer/src/test/resources/ledger.init index ad2b5f1f..ebbd8872 100644 --- a/source/tools/tools-initializer/src/test/resources/ledger.init +++ b/source/tools/tools-initializer/src/test/resources/ledger.init @@ -3,11 +3,54 @@ ledger.seed=932dfe23-fe23232f-283f32fa-dd32aa76-8322ca2f-56236cda-7136b322-cb323ffe #账本的描述名称;此属性不参与共识,仅仅在当前参与方的本地节点用于描述用途; -ledger.name= +ledger.name=test -#声明的账本创建时间;格式为 “yyyy-MM-dd HH:mm:ss.SSSZ”,表示”年-月-日 时:分:秒:毫秒时区“;例如:“2019-08-01 14:26:58.069+0800”,其中,+0800 表示时区是东8区 +#声明账本的创建时间;格式为 “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 @@ -28,6 +71,10 @@ cons_parti.0.name=jd.com 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个参与方的共识服务的端口; @@ -47,6 +94,10 @@ cons_parti.1.name=at.com 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个参与方的共识服务的端口; @@ -66,6 +117,10 @@ cons_parti.2.name=bt.com 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个参与方的共识服务的端口; @@ -85,6 +140,10 @@ cons_parti.3.name=xt.com 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个参与方的共识服务的端口; diff --git a/source/tools/tools-joiner/src/test/java/com/jd/blockchain/AppTest.java b/source/tools/tools-joiner/src/test/java/com/jd/blockchain/AppTest.java new file mode 100644 index 00000000..941b907f --- /dev/null +++ b/source/tools/tools-joiner/src/test/java/com/jd/blockchain/AppTest.java @@ -0,0 +1,20 @@ +package com.jd.blockchain; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +/** + * Unit test for simple App. + */ +public class AppTest +{ + /** + * Rigorous Test :-) + */ + @Test + public void shouldAnswerWithTrue() + { + assertTrue( true ); + } +} diff --git a/source/tools/tools-keygen/src/main/java/com/jd/blockchain/tools/keygen/KeyGenCommand.java b/source/tools/tools-keygen/src/main/java/com/jd/blockchain/tools/keygen/KeyGenCommand.java index e0c63a0b..cd2df93c 100644 --- a/source/tools/tools-keygen/src/main/java/com/jd/blockchain/tools/keygen/KeyGenCommand.java +++ b/source/tools/tools-keygen/src/main/java/com/jd/blockchain/tools/keygen/KeyGenCommand.java @@ -1,15 +1,19 @@ package com.jd.blockchain.tools.keygen; +import static com.jd.blockchain.crypto.KeyGenUtils.decodePubKey; +import static com.jd.blockchain.crypto.KeyGenUtils.decryptedPrivKeyBytes; +import static com.jd.blockchain.crypto.KeyGenUtils.encodePrivKey; +import static com.jd.blockchain.crypto.KeyGenUtils.encodePubKey; +import static com.jd.blockchain.crypto.KeyGenUtils.readPassword; + import java.io.File; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; -import javax.crypto.SecretKey; - import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.Crypto; +import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.utils.ArgumentSet; @@ -17,18 +21,11 @@ import com.jd.blockchain.utils.ArgumentSet.ArgEntry; import com.jd.blockchain.utils.ArgumentSet.Setting; import com.jd.blockchain.utils.ConsoleUtils; import com.jd.blockchain.utils.codec.Base58Utils; -import com.jd.blockchain.utils.io.BytesUtils; import com.jd.blockchain.utils.io.FileUtils; -import com.jd.blockchain.utils.security.AESUtils; import com.jd.blockchain.utils.security.DecryptionException; -import com.jd.blockchain.utils.security.ShaUtils; public class KeyGenCommand { - public static final byte[] PUB_KEY_FILE_MAGICNUM = { (byte) 0xFF, 112, 117, 98 }; - - public static final byte[] PRIV_KEY_FILE_MAGICNUM = { (byte) 0x00, 112, 114, 118 }; - // 指定 -r 参数时为“读取模式”,显示密钥文件; -r 参数之后紧跟着指定要读取的公钥或者私钥文件的路径; private static final String READ_ARG = "-r"; @@ -172,34 +169,6 @@ public class KeyGenCommand { } } - public static String encodePubKey(PubKey pubKey) { - byte[] pubKeyBytes = BytesUtils.concat(PUB_KEY_FILE_MAGICNUM, pubKey.toBytes()); - String base58PubKey = Base58Utils.encode(pubKeyBytes); - return base58PubKey; - } - - public static PubKey decodePubKey(String base58PubKey) { - byte[] keyBytes = Base58Utils.decode(base58PubKey); - return decodePubKey(keyBytes); - } - - public static String encodePrivKey(PrivKey privKey, String base58Pwd) { - byte[] pwdBytes = Base58Utils.decode(base58Pwd); - return encodePrivKey(privKey, pwdBytes); - } - - public static String encodePrivKey(PrivKey privKey, byte[] pwdBytes) { - byte[] encodedPrivKeyBytes = encryptPrivKey(privKey, pwdBytes); - String base58PrivKey = Base58Utils.encode(encodedPrivKeyBytes); - return base58PrivKey; - } - - public static byte[] encryptPrivKey(PrivKey privKey, byte[] pwdBytes) { - SecretKey userKey = AESUtils.generateKey128(pwdBytes); - byte[] encryptedPrivKeyBytes = AESUtils.encrypt(privKey.toBytes(), userKey); - return BytesUtils.concat(PRIV_KEY_FILE_MAGICNUM, encryptedPrivKeyBytes); - } - /** * 读取密钥;
* 如果是私钥,则需要输入密码; @@ -209,10 +178,10 @@ public class KeyGenCommand { public static void readKey(String keyFile, boolean decrypting) { String base58KeyString = FileUtils.readText(keyFile); byte[] keyBytes = Base58Utils.decode(base58KeyString); - if (BytesUtils.startsWith(keyBytes, PUB_KEY_FILE_MAGICNUM)) { + if (KeyGenUtils.isPubKeyBytes(keyBytes)) { if (decrypting) { // Try reading pubKey; - PubKey pubKey = doDecodePubKeyBytes(keyBytes); + PubKey pubKey = decodePubKey(keyBytes); ConsoleUtils.info( "======================== pub key ========================\r\n" + "[%s]\r\n" + "Raw:[%s][%s]\r\n", @@ -222,7 +191,7 @@ public class KeyGenCommand { base58KeyString); } return; - } else if (BytesUtils.startsWith(keyBytes, PRIV_KEY_FILE_MAGICNUM)) { + } else if (KeyGenUtils.isPrivKeyBytes(keyBytes)) { // Try reading privKye; try { if (decrypting) { @@ -246,119 +215,4 @@ public class KeyGenCommand { } } - private static PubKey doDecodePubKeyBytes(byte[] encodedPubKeyBytes) { - byte[] pubKeyBytes = Arrays.copyOfRange(encodedPubKeyBytes, PUB_KEY_FILE_MAGICNUM.length, - encodedPubKeyBytes.length); - return new PubKey(pubKeyBytes); - } - - public static PrivKey decryptedPrivKeyBytes(byte[] encodedPrivKeyBytes, byte[] pwdBytes) { - // Read privKye; - SecretKey userKey = AESUtils.generateKey128(pwdBytes); - byte[] encryptedKeyBytes = Arrays.copyOfRange(encodedPrivKeyBytes, PRIV_KEY_FILE_MAGICNUM.length, - encodedPrivKeyBytes.length); - try { - byte[] plainKeyBytes = AESUtils.decrypt(encryptedKeyBytes, userKey); - return new PrivKey(plainKeyBytes); - } catch (DecryptionException e) { - throw new DecryptionException("Invalid password!", e); - } - } - - public static PubKey readPubKey(String keyFile) { - String base58KeyString = FileUtils.readText(keyFile); - return decodePubKey(base58KeyString); - } - - public static PubKey decodePubKey(byte[] encodedPubKeyBytes) { - if (BytesUtils.startsWith(encodedPubKeyBytes, PUB_KEY_FILE_MAGICNUM)) { - // Read pubKey; - return doDecodePubKeyBytes(encodedPubKeyBytes); - } - - throw new IllegalArgumentException("The specified bytes is not valid PubKey generated by the KeyGen tool!"); - } - - /** - * 从控制台读取加密口令,以二进制数组形式返回原始口令的一次SHA256的结果; - * - * @return - */ - public static byte[] readPassword() { - byte[] pwdBytes = ConsoleUtils.readPassword(); - return ShaUtils.hash_256(pwdBytes); - } - - /** - * 对指定的原始密码进行编码生成用于加解密的密码; - * - * @param rawPassword - * @return - */ - public static byte[] encodePassword(String rawPassword) { - byte[] pwdBytes = BytesUtils.toBytes(rawPassword, "UTF-8"); - return ShaUtils.hash_256(pwdBytes); - } - - /** - * 对指定的原始密码进行编码生成用于加解密的密码; - * - * @param rawPassword - * @return - */ - public static String encodePasswordAsBase58(String rawPassword) { - return Base58Utils.encode(encodePassword(rawPassword)); - } - - /** - * 从控制台读取加密口令,以Base58字符串形式返回口令的一次SHA256的结果; - * - * @return - */ - public static String readPasswordString() { - return Base58Utils.encode(readPassword()); - } - - public static PrivKey readPrivKey(String keyFile, String base58Pwd) { - return readPrivKey(keyFile, Base58Utils.decode(base58Pwd)); - } - - /** - * 从文件读取私钥; - * - * @param keyFile - * @param pwdBytes - * @return - */ - public static PrivKey readPrivKey(String keyFile, byte[] pwdBytes) { - String base58KeyString = FileUtils.readText(keyFile); - byte[] keyBytes = Base58Utils.decode(base58KeyString); - if (!BytesUtils.startsWith(keyBytes, PRIV_KEY_FILE_MAGICNUM)) { - throw new IllegalArgumentException("The specified file is not a private key file!"); - } - return decryptedPrivKeyBytes(keyBytes, pwdBytes); - } - - public static PrivKey decodePrivKey(String base58Key, String base58Pwd) { - byte[] decryptedKey = Base58Utils.decode(base58Pwd); - return decodePrivKey(base58Key, decryptedKey); - } - - public static PrivKey decodePrivKey(String base58Key, byte[] pwdBytes) { - byte[] keyBytes = Base58Utils.decode(base58Key); - if (!BytesUtils.startsWith(keyBytes, PRIV_KEY_FILE_MAGICNUM)) { - throw new IllegalArgumentException("The specified file is not a private key file!"); - } - return decryptedPrivKeyBytes(keyBytes, pwdBytes); - } - - public static PrivKey decodePrivKeyWithRawPassword(String base58Key, String rawPassword) { - byte[] pwdBytes = encodePassword(rawPassword); - byte[] keyBytes = Base58Utils.decode(base58Key); - if (!BytesUtils.startsWith(keyBytes, PRIV_KEY_FILE_MAGICNUM)) { - throw new IllegalArgumentException("The specified file is not a private key file!"); - } - return decryptedPrivKeyBytes(keyBytes, pwdBytes); - } - } diff --git a/source/tools/tools-mocker/pom.xml b/source/tools/tools-mocker/pom.xml index 3b79b5b9..c78dcd31 100644 --- a/source/tools/tools-mocker/pom.xml +++ b/source/tools/tools-mocker/pom.xml @@ -39,7 +39,11 @@ crypto-classic ${project.version} - + + org.mockito + mockito-core + provided + diff --git a/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/MockerLedgerInitializer.java b/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/MockerLedgerInitializer.java index 0c2361fa..938e12bd 100644 --- a/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/MockerLedgerInitializer.java +++ b/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/MockerLedgerInitializer.java @@ -1,29 +1,54 @@ package com.jd.blockchain.mocker; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.Random; + +import org.springframework.web.bind.annotation.RequestBody; + import com.jd.blockchain.binaryproto.DataContractRegistry; import com.jd.blockchain.consensus.ConsensusProvider; import com.jd.blockchain.consensus.ConsensusProviders; import com.jd.blockchain.consensus.ConsensusSettings; -import com.jd.blockchain.crypto.*; +import com.jd.blockchain.crypto.Crypto; +import com.jd.blockchain.crypto.CryptoProvider; +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.PrivKey; +import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.crypto.SignatureDigest; +import com.jd.blockchain.crypto.SignatureFunction; import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; import com.jd.blockchain.crypto.service.sm.SMCryptoService; -import com.jd.blockchain.ledger.*; -import com.jd.blockchain.ledger.core.*; -import com.jd.blockchain.ledger.core.impl.LedgerManager; +import com.jd.blockchain.ledger.CryptoSetting; +import com.jd.blockchain.ledger.DigitalSignature; +import com.jd.blockchain.ledger.LedgerInitException; +import com.jd.blockchain.ledger.LedgerInitProperties; +import com.jd.blockchain.ledger.LedgerInitProperties.ParticipantProperties; +import com.jd.blockchain.ledger.LedgerInitSetting; +import com.jd.blockchain.ledger.ParticipantNode; +import com.jd.blockchain.ledger.TransactionContent; +import com.jd.blockchain.ledger.TransactionRequest; +import com.jd.blockchain.ledger.core.CryptoConfig; +import com.jd.blockchain.ledger.core.LedgerInitDecision; +import com.jd.blockchain.ledger.core.LedgerInitProposal; +import com.jd.blockchain.ledger.core.LedgerInitProposalData; +import com.jd.blockchain.ledger.core.LedgerInitializer; +import com.jd.blockchain.ledger.core.LedgerManager; import com.jd.blockchain.storage.service.DbConnection; import com.jd.blockchain.storage.service.DbConnectionFactory; -import com.jd.blockchain.tools.initializer.*; -import com.jd.blockchain.tools.initializer.LedgerInitProperties.ConsensusParticipantConfig; +import com.jd.blockchain.tools.initializer.DBConnectionConfig; +import com.jd.blockchain.tools.initializer.LedgerInitProcess; +import com.jd.blockchain.tools.initializer.Prompter; +import com.jd.blockchain.tools.initializer.web.LedgerInitConfiguration; import com.jd.blockchain.tools.initializer.web.LedgerInitConsensusService; import com.jd.blockchain.tools.initializer.web.LedgerInitDecisionData; -import com.jd.blockchain.transaction.*; +import com.jd.blockchain.transaction.DigitalSignatureBlob; +import com.jd.blockchain.transaction.LedgerInitData; +import com.jd.blockchain.transaction.SignatureUtils; import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.concurrent.InvocationResult; import com.jd.blockchain.utils.io.BytesUtils; -import org.springframework.web.bind.annotation.*; - -import java.io.IOException; -import java.util.*; /** * 账本初始化控制器; @@ -37,21 +62,20 @@ public class MockerLedgerInitializer implements LedgerInitProcess, LedgerInitCon DataContractRegistry.register(TransactionRequest.class); } - private static final String[] SUPPORTED_PROVIDERS = { - ClassicCryptoService.class.getName(), + private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(), SMCryptoService.class.getName() }; private static final String DEFAULT_SIGN_ALGORITHM = "ED25519"; private final SignatureFunction SIGN_FUNC; - private volatile LedgerInitPermission localPermission; + private volatile LedgerInitProposal localPermission; - private TransactionContent initTxContent; + private volatile LedgerInitializer initializer; private volatile int currentId = -1; - private volatile LedgerInitSetting ledgerInitSetting; + private volatile LedgerInitConfiguration ledgerInitConfig; // private volatile LedgerInitPermission[] permissions; // private volatile LedgerInitPermission permission; @@ -60,16 +84,12 @@ public class MockerLedgerInitializer implements LedgerInitProcess, LedgerInitCon private volatile ConsensusProvider consensusProvider; - private volatile LedgerBlock genesisBlock; - private volatile LedgerInitDecision localDecision; private volatile DecisionResultHandle[] decisions; private volatile DbConnection dbConn; - private volatile LedgerEditor ledgerEditor; - private LedgerManager ledgerManager; private DbConnectionFactory dbConnFactory; @@ -89,10 +109,10 @@ public class MockerLedgerInitializer implements LedgerInitProcess, LedgerInitCon } public TransactionContent getInitTxContent() { - return initTxContent; + return initializer.getTransactionContent(); } - public LedgerInitPermission getLocalPermission() { + public LedgerInitProposal getLocalPermission() { return localPermission; } @@ -111,25 +131,22 @@ public class MockerLedgerInitializer implements LedgerInitProcess, LedgerInitCon @Override public HashDigest initialize(int currentId, PrivKey privKey, LedgerInitProperties ledgerInitProps, DBConnectionConfig dbConnConfig, Prompter prompter) { - return initialize(currentId, privKey, ledgerInitProps, dbConnConfig, prompter, createDefaultCryptoSetting()); + LedgerInitConfiguration ledgerInitConfig = LedgerInitConfiguration.create(ledgerInitProps); + return initialize(currentId, privKey, ledgerInitConfig, dbConnConfig, prompter); } @Override - public synchronized HashDigest initialize(int currentId, PrivKey privKey, LedgerInitProperties ledgerInitProps, - DBConnectionConfig dbConnConfig, Prompter prompter, CryptoSetting cryptoSetting) { - - if (this.ledgerInitSetting != null) { + public synchronized HashDigest initialize(int currentId, PrivKey privKey, LedgerInitConfiguration ledgerInitProps, + DBConnectionConfig dbConnConfig, Prompter prompter) { + if (this.ledgerInitConfig != null) { throw new IllegalStateException("ledger init process has already started."); } setPrompter(prompter); - ConsensusProvider csProvider = ConsensusProviders.getProvider(ledgerInitProps.getConsensusProvider()); - setConsensusProvider(csProvider); - prompter.info("Init settings and sign permision..."); - prepareLocalPermission(currentId, privKey, ledgerInitProps, null, cryptoSetting); + prepareLocalProposal(currentId, privKey, ledgerInitProps); try { // 连接数据库; @@ -155,12 +172,13 @@ public class MockerLedgerInitializer implements LedgerInitProcess, LedgerInitCon public LedgerInitDecision makeLocalDecision(PrivKey privKey) { // 生成账本; - this.ledgerEditor = ledgerManager.newLedger(this.ledgerInitSetting, dbConn.getStorageService()); - this.genesisBlock = initLedgerDataset(ledgerEditor); +// this.ledgerEditor = ledgerManager.newLedger(this.ledgerInitSetting, dbConn.getStorageService()); +// this.genesisBlock = initLedgerDataset(ledgerEditor); + initializer.prepareLedger(dbConn.getStorageService(), getNodeSignatures()); // 生成签名决定; - this.localDecision = makeDecision(currentId, genesisBlock.getHash(), privKey); - this.decisions = new DecisionResultHandle[this.ledgerInitSetting.getConsensusParticipants().length]; + this.localDecision = makeDecision(currentId, initializer.getLedgerHash(), privKey); + this.decisions = new DecisionResultHandle[this.ledgerInitConfig.getParticipantCount()]; for (int i = 0; i < decisions.length; i++) { // 参与者的 id 是依次递增的; this.decisions[i] = new DecisionResultHandle(i); @@ -170,10 +188,19 @@ public class MockerLedgerInitializer implements LedgerInitProcess, LedgerInitCon return localDecision; } + private DigitalSignature getNodeSignatures() { + ParticipantNode parti = this.ledgerInitConfig.getParticipant(currentId); + PubKey pubKey = parti.getPubKey(); + SignatureDigest signDigest = this.localPermission.getTransactionSignature(); + DigitalSignatureBlob digitalSignature = new DigitalSignatureBlob(pubKey, signDigest); + + return digitalSignature; + } + public HashDigest consensusDecisions() { // 执行提交提交; - ledgerEditor.commit(); - return genesisBlock.getHash(); + initializer.commit(); + return initializer.getLedgerHash(); } public void closeDb() { @@ -201,55 +228,28 @@ public class MockerLedgerInitializer implements LedgerInitProcess, LedgerInitCon return defCryptoSetting; } - public LedgerInitPermission prepareLocalPermission(int currentId, PrivKey privKey, LedgerInitProperties ledgerProps, - ConsensusSettings csSettings, CryptoSetting cryptoSetting) { - // 创建初始化配置; - LedgerInitSettingData initSetting = new LedgerInitSettingData(); - initSetting.setLedgerSeed(ledgerProps.getLedgerSeed()); - initSetting.setCryptoSetting(cryptoSetting); + public LedgerInitProposal prepareLocalProposal(int currentId, PrivKey privKey, + LedgerInitConfiguration ledgerInitConfig) { - List partiList = ledgerProps.getConsensusParticipants(); - ConsensusParticipantConfig[] parties = partiList.toArray(new ConsensusParticipantConfig[partiList.size()]); - ConsensusParticipantConfig[] orderedParties = sortAndVerify(parties); - initSetting.setConsensusParticipants(orderedParties); - - // 创建默认的共识配置; - try { - byte[] csSettingBytes = new byte[1024]; - new Random().nextBytes(csSettingBytes); - - initSetting.setConsensusProvider(consensusProvider.getName()); - initSetting.setConsensusSettings(new Bytes(csSettingBytes)); - } catch (Exception e) { - throw new LedgerInitException("Create default consensus config failed! --" + e.getMessage(), e); - } - - if (currentId < 0 || currentId >= orderedParties.length) { + if (currentId < 0 || currentId >= ledgerInitConfig.getParticipantCount()) { throw new LedgerInitException("Your id is out of bound of participant list!"); } this.currentId = currentId; - this.ledgerInitSetting = initSetting; // 校验当前的公钥、私钥是否匹配; byte[] testBytes = BytesUtils.toBytes(currentId); SignatureDigest testSign = SIGN_FUNC.sign(privKey, testBytes); - PubKey myPubKey = orderedParties[currentId].getPubKey(); + PubKey myPubKey = ledgerInitConfig.getParticipant(currentId).getPubKey(); if (!SIGN_FUNC.verify(testSign, myPubKey, testBytes)) { throw new LedgerInitException("Your pub-key specified in the init-settings isn't match your priv-key!"); } - // 生成初始化交易,并签署许可; - TransactionBuilder initTxBuilder = new TxBuilder(null);// 账本初始化交易的账本 hash 为 null; - initTxBuilder.ledgers().create(initSetting); - for (ParticipantNode p : initSetting.getConsensusParticipants()) { - // TODO:暂时只支持注册用户的初始化操作; - BlockchainIdentity superUserId = new BlockchainIdentityData(p.getPubKey()); - initTxBuilder.users().register(superUserId); - } - this.initTxContent = initTxBuilder.prepareContent(); + // 初始化; + this.initializer = LedgerInitializer.create(ledgerInitConfig.getLedgerSettings(), + ledgerInitConfig.getSecuritySettings()); // 对初始交易签名,生成当前参与者的账本初始化许可; - SignatureDigest permissionSign = SignatureUtils.sign(initTxContent, privKey); - localPermission = new LedgerInitPermissionData(currentId, permissionSign); + SignatureDigest permissionSign = SignatureUtils.sign(initializer.getTransactionContent(), privKey); + localPermission = new LedgerInitProposalData(currentId, permissionSign); this.currentId = currentId; return localPermission; @@ -267,40 +267,40 @@ public class MockerLedgerInitializer implements LedgerInitProcess, LedgerInitCon return decision; } - private LedgerBlock initLedgerDataset(LedgerEditor ledgerEditor) { - // 初始化时,自动将参与方注册为账本的用户; - TxRequestBuilder txReqBuilder = new TxRequestBuilder(this.initTxContent); -// ParticipantNode[] parties = this.ledgerInitSetting.getConsensusParticipants(); - ParticipantNode parti = this.ledgerInitSetting.getConsensusParticipants()[currentId]; - - PubKey pubKey = parti.getPubKey(); - SignatureDigest signDigest = this.localPermission.getTransactionSignature(); - DigitalSignatureBlob digitalSignature = new DigitalSignatureBlob(pubKey, signDigest); - txReqBuilder.addNodeSignature(digitalSignature); - - TransactionRequest txRequest = txReqBuilder.buildRequest(); - - LedgerTransactionContext txCtx = ledgerEditor.newTransaction(txRequest); - Operation[] ops = txRequest.getTransactionContent().getOperations(); - // 注册用户; 注:第一个操作是 LedgerInitOperation; - // TODO:暂时只支持注册用户的初始化操作; - for (int i = 1; i < ops.length; i++) { - UserRegisterOperation userRegOP = (UserRegisterOperation) ops[i]; - txCtx.getDataSet().getUserAccountSet().register(userRegOP.getUserID().getAddress(), - userRegOP.getUserID().getPubKey()); - } - - txCtx.commit(TransactionState.SUCCESS, null); - - return ledgerEditor.prepare(); - } +// private LedgerBlock initLedgerDataset(LedgerEditor ledgerEditor) { +// // 初始化时,自动将参与方注册为账本的用户; +// TxRequestBuilder txReqBuilder = new TxRequestBuilder(this.initTxContent); +//// ParticipantNode[] parties = this.ledgerInitSetting.getConsensusParticipants(); +// ParticipantNode parti = this.ledgerInitSetting.getConsensusParticipants()[currentId]; +// +// PubKey pubKey = parti.getPubKey(); +// SignatureDigest signDigest = this.localPermission.getTransactionSignature(); +// DigitalSignatureBlob digitalSignature = new DigitalSignatureBlob(pubKey, signDigest); +// txReqBuilder.addNodeSignature(digitalSignature); +// +// TransactionRequest txRequest = txReqBuilder.buildRequest(); +// +// LedgerTransactionContext txCtx = ledgerEditor.newTransaction(txRequest); +// Operation[] ops = txRequest.getTransactionContent().getOperations(); +// // 注册用户; 注:第一个操作是 LedgerInitOperation; +// // TODO:暂时只支持注册用户的初始化操作; +// for (int i = 1; i < ops.length; i++) { +// UserRegisterOperation userRegOP = (UserRegisterOperation) ops[i]; +// txCtx.getDataset().getUserAccountSet().register(userRegOP.getUserID().getAddress(), +// userRegOP.getUserID().getPubKey()); +// } +// +// txCtx.commit(TransactionState.SUCCESS, null); +// +// return ledgerEditor.prepare(); +// } private byte[] getDecisionBytes(int participantId, HashDigest ledgerHash) { return BytesUtils.concat(BytesUtils.toBytes(participantId), ledgerHash.toBytes()); } @Override - public LedgerInitPermission requestPermission(int requesterId, SignatureDigest signature) { + public LedgerInitProposal requestPermission(int requesterId, SignatureDigest signature) { return localPermission; } @@ -315,7 +315,7 @@ public class MockerLedgerInitializer implements LedgerInitProcess, LedgerInitCon * @param parties * @return */ - private ConsensusParticipantConfig[] sortAndVerify(ConsensusParticipantConfig[] parties) { + private ParticipantProperties[] sortAndVerify(ParticipantProperties[] parties) { Arrays.sort(parties, (o1, o2) -> o1.getId() - o2.getId()); for (int i = 0; i < parties.length; i++) { if (parties[i].getId() != i) { diff --git a/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/MockerNodeContext.java b/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/MockerNodeContext.java index 82a79c61..266f7973 100644 --- a/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/MockerNodeContext.java +++ b/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/MockerNodeContext.java @@ -1,6 +1,8 @@ package com.jd.blockchain.mocker; import static java.lang.reflect.Proxy.newProxyInstance; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.when; import java.text.SimpleDateFormat; import java.util.Date; @@ -8,6 +10,10 @@ import java.util.HashMap; import java.util.Map; import java.util.Properties; +import com.jd.blockchain.ledger.*; +import org.mockito.Mockito; + +import com.jd.blockchain.binaryproto.DataContract; import com.jd.blockchain.binaryproto.DataContractRegistry; import com.jd.blockchain.consensus.ClientIdentification; import com.jd.blockchain.consensus.ClientIdentifications; @@ -16,30 +22,31 @@ import com.jd.blockchain.consensus.action.ActionResponse; import com.jd.blockchain.crypto.Crypto; import com.jd.blockchain.crypto.CryptoProvider; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm; import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; import com.jd.blockchain.crypto.service.sm.SMCryptoService; -import com.jd.blockchain.ledger.*; import com.jd.blockchain.ledger.core.CryptoConfig; -import com.jd.blockchain.ledger.core.LedgerDataSet; +import com.jd.blockchain.ledger.core.DefaultOperationHandleRegisteration; +import com.jd.blockchain.ledger.core.LedgerDataQuery; import com.jd.blockchain.ledger.core.LedgerEditor; +import com.jd.blockchain.ledger.core.LedgerManager; +import com.jd.blockchain.ledger.core.LedgerQueryService; import com.jd.blockchain.ledger.core.LedgerRepository; -import com.jd.blockchain.ledger.core.impl.LedgerManager; -import com.jd.blockchain.ledger.core.impl.LedgerQueryService; -import com.jd.blockchain.ledger.core.impl.TransactionBatchProcessor; +import com.jd.blockchain.ledger.core.LedgerSecurityManager; +import com.jd.blockchain.ledger.core.SecurityPolicy; +import com.jd.blockchain.ledger.core.TransactionBatchProcessor; import com.jd.blockchain.mocker.config.MockerConstant; import com.jd.blockchain.mocker.config.PresetAnswerPrompter; import com.jd.blockchain.mocker.handler.MockerContractExeHandle; -import com.jd.blockchain.mocker.handler.MockerOperationHandleRegister; import com.jd.blockchain.mocker.proxy.ContractProxy; import com.jd.blockchain.service.TransactionBatchResultHandle; import com.jd.blockchain.storage.service.DbConnectionFactory; import com.jd.blockchain.storage.service.utils.MemoryDBConnFactory; import com.jd.blockchain.tools.initializer.DBConnectionConfig; -import com.jd.blockchain.tools.initializer.LedgerInitProperties; -import com.jd.blockchain.tools.keygen.KeyGenCommand; +import com.jd.blockchain.tools.initializer.web.LedgerInitConfiguration; import com.jd.blockchain.transaction.BlockchainQueryService; import com.jd.blockchain.transaction.TxBuilder; import com.jd.blockchain.utils.Bytes; @@ -55,7 +62,7 @@ public class MockerNodeContext implements BlockchainQueryService { private DbConnectionFactory dbConnFactory = new MemoryDBConnFactory(); - private MockerOperationHandleRegister opHandler = new MockerOperationHandleRegister(); + private DefaultOperationHandleRegisteration opHandler = new DefaultOperationHandleRegisteration(); private MockerContractExeHandle contractExeHandle = new MockerContractExeHandle(); @@ -86,14 +93,18 @@ public class MockerNodeContext implements BlockchainQueryService { DataContractRegistry.register(ContractEventSendOperation.class); DataContractRegistry.register(DataAccountRegisterOperation.class); DataContractRegistry.register(UserRegisterOperation.class); + DataContractRegistry.register(ParticipantRegisterOperation.class); DataContractRegistry.register(DataAccountKVSetOperation.class); DataContractRegistry.register(DataAccountKVSetOperation.KVWriteEntry.class); + DataContractRegistry.register(ParticipantStateUpdateOperation.class); DataContractRegistry.register(ActionRequest.class); DataContractRegistry.register(ActionResponse.class); DataContractRegistry.register(ClientIdentifications.class); DataContractRegistry.register(ClientIdentification.class); +// DataContractRegistry.register(LedgerAdminInfo.class); + ByteArrayObjectUtil.init(); } @@ -125,16 +136,16 @@ public class MockerNodeContext implements BlockchainQueryService { boolean isExist = false; // 通过公钥进行判断 for (Map.Entry entry : participants.entrySet()) { - String existPubKey = KeyGenCommand.encodePubKey(entry.getValue().getPubKey()); + String existPubKey = KeyGenUtils.encodePubKey(entry.getValue().getPubKey()); if (pubKeyString.equals(existPubKey)) { isExist = true; } } if (!isExist) { // 加入系统中 - PrivKey privKey = KeyGenCommand.decodePrivKeyWithRawPassword(MockerConstant.PRIVATE_KEYS[i], + PrivKey privKey = KeyGenUtils.decodePrivKeyWithRawPassword(MockerConstant.PRIVATE_KEYS[i], MockerConstant.PASSWORD); - PubKey pubKey = KeyGenCommand.decodePubKey(MockerConstant.PUBLIC_KEYS[i]); + PubKey pubKey = KeyGenUtils.decodePubKey(MockerConstant.PUBLIC_KEYS[i]); participants(new BlockchainKeypair(pubKey, privKey)); } if (participants.size() >= 4) { @@ -147,16 +158,19 @@ public class MockerNodeContext implements BlockchainQueryService { MockerLedgerInitializer mockLedgerInitializer = new MockerLedgerInitializer(dbConnFactory, ledgerManager); - ledgerHash = mockLedgerInitializer.initialize(0, defaultKeypair.getPrivKey(), ledgerInitProperties, - dbConnectionConfig, new PresetAnswerPrompter("N"), cryptoConfig()); + LedgerInitConfiguration initConfig = LedgerInitConfiguration.create(ledgerInitProperties); + initConfig.getLedgerSettings().setCryptoSetting(cryptoConfig()); + + ledgerHash = mockLedgerInitializer.initialize(0, defaultKeypair.getPrivKey(), initConfig, dbConnectionConfig, + new PresetAnswerPrompter("N")); ledgerRepository = registerLedger(ledgerHash, dbConnectionConfig); - queryService = new LedgerQueryService(ledgerManager); + queryService = new LedgerQueryService(ledgerRepository); contractExeHandle.initLedger(ledgerManager, ledgerHash); - opHandler.registerHandler(contractExeHandle); + opHandler.registerHandle(contractExeHandle); return this; } @@ -244,6 +258,11 @@ public class MockerNodeContext implements BlockchainQueryService { return queryService.getLedger(ledgerHash); } + @Override + public LedgerAdminInfo getLedgerAdminInfo(HashDigest ledgerHash) { + return queryService.getLedgerAdminInfo(ledgerHash); + } + @Override public ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash) { return queryService.getConsensusParticipants(ledgerHash); @@ -375,7 +394,7 @@ public class MockerNodeContext implements BlockchainQueryService { } @Override - public ContractInfo getContract(HashDigest ledgerHash, String address) { + public ContractInfo getContract(HashDigest ledgerHash, String address) { return queryService.getContract(ledgerHash, address); } @@ -404,12 +423,26 @@ public class MockerNodeContext implements BlockchainQueryService { return reqBuilder.buildRequest(); } + 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 OperationResult[] txProcess(TransactionRequest txRequest) { LedgerEditor newEditor = ledgerRepository.createNextBlock(); LedgerBlock latestBlock = ledgerRepository.getLatestBlock(); - LedgerDataSet previousDataSet = ledgerRepository.getDataSet(latestBlock); - TransactionBatchProcessor txProc = new TransactionBatchProcessor(newEditor, previousDataSet, opHandler, - ledgerManager); + LedgerDataQuery previousDataSet = ledgerRepository.getLedgerData(latestBlock); + TransactionBatchProcessor txProc = new TransactionBatchProcessor(getSecurityManager(), newEditor, + ledgerRepository, opHandler); TransactionResponse txResp = txProc.schedule(txRequest); TransactionBatchResultHandle handle = txProc.prepare(); handle.commit(); @@ -466,7 +499,7 @@ public class MockerNodeContext implements BlockchainQueryService { ledgerProp.put(partiPrefix + LedgerInitProperties.PART_NAME, name); ledgerProp.put(partiPrefix + LedgerInitProperties.PART_PUBKEY_PATH, ""); ledgerProp.put(partiPrefix + LedgerInitProperties.PART_PUBKEY, - KeyGenCommand.encodePubKey(keypair.getPubKey())); + KeyGenUtils.encodePubKey(keypair.getPubKey())); ledgerProp.put(partiPrefix + LedgerInitProperties.PART_INITIALIZER_HOST, MockerConstant.LOCAL_ADDRESS); ledgerProp.put(partiPrefix + LedgerInitProperties.PART_INITIALIZER_PORT, String.valueOf(MockerConstant.LEDGER_INIT_PORT_START + partiIndex * 10)); diff --git a/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/handler/MockerContractExeHandle.java b/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/handler/MockerContractExeHandle.java index cb26ac92..dee8fe18 100644 --- a/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/handler/MockerContractExeHandle.java +++ b/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/handler/MockerContractExeHandle.java @@ -9,15 +9,21 @@ import com.jd.blockchain.contract.ContractException; import com.jd.blockchain.contract.EventProcessingAware; import com.jd.blockchain.contract.LedgerContext; import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.ledger.*; -import com.jd.blockchain.ledger.core.LedgerDataSet; -import com.jd.blockchain.ledger.core.LedgerService; +import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.BytesValue; +import com.jd.blockchain.ledger.BytesValueEncoding; +import com.jd.blockchain.ledger.BytesValueList; +import com.jd.blockchain.ledger.ContractEventSendOperation; +import com.jd.blockchain.ledger.Operation; +import com.jd.blockchain.ledger.TransactionRequest; +import com.jd.blockchain.ledger.core.LedgerDataset; +import com.jd.blockchain.ledger.core.LedgerManager; +import com.jd.blockchain.ledger.core.LedgerQuery; +import com.jd.blockchain.ledger.core.LedgerQueryService; import com.jd.blockchain.ledger.core.OperationHandle; -import com.jd.blockchain.ledger.core.TransactionRequestContext; -import com.jd.blockchain.ledger.core.impl.LedgerManager; -import com.jd.blockchain.ledger.core.impl.LedgerQueryService; -import com.jd.blockchain.ledger.core.impl.OperationHandleContext; -import com.jd.blockchain.ledger.core.impl.handles.ContractLedgerContext; +import com.jd.blockchain.ledger.core.OperationHandleContext; +import com.jd.blockchain.ledger.core.TransactionRequestExtension; +import com.jd.blockchain.ledger.core.handles.ContractLedgerContext; import com.jd.blockchain.mocker.proxy.ExecutorProxy; public class MockerContractExeHandle implements OperationHandle { @@ -29,21 +35,21 @@ public class MockerContractExeHandle implements OperationHandle { private HashDigest ledgerHash; @Override - public BytesValue process(Operation op, LedgerDataSet dataset, TransactionRequestContext requestContext, - LedgerDataSet previousBlockDataset, OperationHandleContext opHandleContext, LedgerService ledgerService) { + public BytesValue process(Operation op, LedgerDataset dataset, TransactionRequestExtension request, + LedgerQuery ledger, OperationHandleContext opHandleContext) { ContractEventSendOperation contractOP = (ContractEventSendOperation) op; - HashDigest txHash = requestContext.getRequest().getTransactionContent().getHash(); + HashDigest txHash = request.getTransactionContent().getHash(); ExecutorProxy executorProxy = executorProxyMap.get(txHash); Object result = null; if (executorProxy != null) { - LedgerQueryService queryService = new LedgerQueryService(ledgerManager); + LedgerQueryService queryService = new LedgerQueryService(ledger); ContractLedgerContext ledgerContext = new ContractLedgerContext(queryService, opHandleContext); MockerContractEventContext contractEventContext = new MockerContractEventContext(ledgerHash, - contractOP.getEvent(), requestContext.getRequest(), ledgerContext); + contractOP.getEvent(), request, ledgerContext); Object instance = executorProxy.getInstance(); EventProcessingAware awire = null; @@ -73,8 +79,8 @@ public class MockerContractExeHandle implements OperationHandle { } @Override - public boolean support(Class operationType) { - return ContractEventSendOperation.class.isAssignableFrom(operationType); + public Class getOperationType() { + return ContractEventSendOperation.class; } public void initLedger(LedgerManager ledgerManager, HashDigest ledgerHash) { diff --git a/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/handler/MockerNodeHandler.java b/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/handler/MockerNodeHandler.java index bd1bea24..b4d355fc 100644 --- a/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/handler/MockerNodeHandler.java +++ b/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/handler/MockerNodeHandler.java @@ -1,8 +1,10 @@ package com.jd.blockchain.mocker.handler; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.gateway.GatewayConfigProperties; +import com.jd.blockchain.ledger.LedgerInitProperties; import com.jd.blockchain.mocker.config.MockerConstant; import com.jd.blockchain.mocker.config.PresetAnswerPrompter; import com.jd.blockchain.mocker.node.GatewayNodeRunner; @@ -10,9 +12,7 @@ import com.jd.blockchain.mocker.node.NodeWebContext; import com.jd.blockchain.mocker.node.PeerNodeRunner; import com.jd.blockchain.tools.initializer.DBConnectionConfig; import com.jd.blockchain.tools.initializer.LedgerBindingConfig; -import com.jd.blockchain.tools.initializer.LedgerInitProperties; import com.jd.blockchain.tools.initializer.Prompter; -import com.jd.blockchain.tools.keygen.KeyGenCommand; import com.jd.blockchain.utils.concurrent.ThreadInvoker; import com.jd.blockchain.utils.net.NetworkAddress; import org.springframework.util.ResourceUtils; @@ -93,7 +93,7 @@ public class MockerNodeHandler { // 启动服务器; NetworkAddress initAddr = initSetting.getConsensusParticipant(nodeIndex).getInitializerAddress(); NodeWebContext node = new NodeWebContext(nodeIndex, initAddr); - PrivKey privkey = KeyGenCommand.decodePrivKeyWithRawPassword(PRIVATE_KEYS[nodeIndex], PASSWORD); + PrivKey privkey = KeyGenUtils.decodePrivKeyWithRawPassword(PRIVATE_KEYS[nodeIndex], PASSWORD); DBConnectionConfig dbConn = new DBConnectionConfig(); dbConn.setConnectionUri(MockerConstant.DB_MEMS[nodeIndex]); ThreadInvoker.AsyncCallback nodeCallback = node.startInit(privkey, initSetting, dbConn, consolePrompter, diff --git a/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/handler/MockerOperationHandleRegister.java b/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/handler/MockerOperationHandleRegister.java index f0819d72..d22c6174 100644 --- a/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/handler/MockerOperationHandleRegister.java +++ b/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/handler/MockerOperationHandleRegister.java @@ -1,54 +1,54 @@ -package com.jd.blockchain.mocker.handler; - -import java.util.ArrayList; -import java.util.List; - -import com.jd.blockchain.ledger.LedgerException; -import com.jd.blockchain.ledger.core.OperationHandle; -import com.jd.blockchain.ledger.core.impl.OperationHandleRegisteration; -import com.jd.blockchain.ledger.core.impl.handles.ContractCodeDeployOperationHandle; -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; - -public class MockerOperationHandleRegister implements OperationHandleRegisteration { - - private List opHandles = new ArrayList<>(); - - public MockerOperationHandleRegister() { - initDefaultHandles(); - } - - /** - * 针对不采用bean依赖注入的方式来处理; - */ - private void initDefaultHandles(){ - opHandles.add(new DataAccountKVSetOperationHandle()); - opHandles.add(new DataAccountRegisterOperationHandle()); - opHandles.add(new UserRegisterOperationHandle()); - opHandles.add(new ContractCodeDeployOperationHandle()); -// opHandles.add(new ContractEventSendOperationHandle()); - } - - public List getOpHandles() { - return opHandles; - } - - public void registerHandler(OperationHandle operationHandle) { - opHandles.add(operationHandle); - } - - public void removeHandler(OperationHandle operationHandle) { - opHandles.remove(operationHandle); - } - - @Override - public OperationHandle getHandle(Class operationType) { - for (OperationHandle handle : opHandles) { - if (handle.support(operationType)) { - return handle; - } - } - throw new LedgerException("Unsupported operation type[" + operationType.getName() + "]!"); - } -} +//package com.jd.blockchain.mocker.handler; +// +//import java.util.ArrayList; +//import java.util.List; +// +//import com.jd.blockchain.ledger.LedgerException; +//import com.jd.blockchain.ledger.core.OperationHandle; +//import com.jd.blockchain.ledger.core.OperationHandleRegisteration; +//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.UserRegisterOperationHandle; +// +//public class MockerOperationHandleRegister implements OperationHandleRegisteration { +// +// private List opHandles = new ArrayList<>(); +// +// public MockerOperationHandleRegister() { +// initDefaultHandles(); +// } +// +// /** +// * 针对不采用bean依赖注入的方式来处理; +// */ +// private void initDefaultHandles(){ +// opHandles.add(new DataAccountKVSetOperationHandle()); +// opHandles.add(new DataAccountRegisterOperationHandle()); +// opHandles.add(new UserRegisterOperationHandle()); +// opHandles.add(new ContractCodeDeployOperationHandle()); +//// opHandles.add(new ContractEventSendOperationHandle()); +// } +// +// public List getOpHandles() { +// return opHandles; +// } +// +// public void registerHandler(OperationHandle operationHandle) { +// opHandles.add(operationHandle); +// } +// +// public void removeHandler(OperationHandle operationHandle) { +// opHandles.remove(operationHandle); +// } +// +// @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/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/handler/MockerServiceHandler.java b/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/handler/MockerServiceHandler.java index 36308c0c..d7f1f43b 100644 --- a/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/handler/MockerServiceHandler.java +++ b/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/handler/MockerServiceHandler.java @@ -1,6 +1,7 @@ package com.jd.blockchain.mocker.handler; import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.ledger.*; @@ -9,7 +10,6 @@ import com.jd.blockchain.mocker.data.KvData; import com.jd.blockchain.mocker.data.ResponseData; import com.jd.blockchain.sdk.BlockchainService; import com.jd.blockchain.sdk.client.GatewayServiceFactory; -import com.jd.blockchain.tools.keygen.KeyGenCommand; public class MockerServiceHandler { @@ -115,8 +115,8 @@ public class MockerServiceHandler { } private BlockchainKeypair defaultParticipant() { - PrivKey privKey = KeyGenCommand.decodePrivKeyWithRawPassword(MockerConstant.PRIVATE_KEYS[0], MockerConstant.PASSWORD); - PubKey pubKey = KeyGenCommand.decodePubKey(MockerConstant.PUBLIC_KEYS[0]); + PrivKey privKey = KeyGenUtils.decodePrivKeyWithRawPassword(MockerConstant.PRIVATE_KEYS[0], MockerConstant.PASSWORD); + PubKey pubKey = KeyGenUtils.decodePubKey(MockerConstant.PUBLIC_KEYS[0]); return new BlockchainKeypair(pubKey, privKey); } diff --git a/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/node/NodeWebContext.java b/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/node/NodeWebContext.java index 93096613..24a6ee53 100644 --- a/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/node/NodeWebContext.java +++ b/source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/node/NodeWebContext.java @@ -2,17 +2,17 @@ package com.jd.blockchain.mocker.node; import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.PrivKey; +import com.jd.blockchain.ledger.LedgerInitProperties; import com.jd.blockchain.ledger.TransactionContent; import com.jd.blockchain.ledger.core.LedgerInitDecision; -import com.jd.blockchain.ledger.core.LedgerInitPermission; -import com.jd.blockchain.ledger.core.LedgerRepository; -import com.jd.blockchain.ledger.core.impl.LedgerManager; +import com.jd.blockchain.ledger.core.LedgerInitProposal; +import com.jd.blockchain.ledger.core.LedgerManager; +import com.jd.blockchain.ledger.core.LedgerQuery; import com.jd.blockchain.mocker.config.LedgerInitWebConfiguration; import com.jd.blockchain.storage.service.DbConnection; import com.jd.blockchain.storage.service.impl.composite.CompositeConnectionFactory; import com.jd.blockchain.tools.initializer.DBConnectionConfig; import com.jd.blockchain.tools.initializer.LedgerInitProcess; -import com.jd.blockchain.tools.initializer.LedgerInitProperties; import com.jd.blockchain.tools.initializer.Prompter; import com.jd.blockchain.tools.initializer.web.LedgerInitializeWebController; import com.jd.blockchain.utils.concurrent.ThreadInvoker; @@ -48,7 +48,7 @@ public class NodeWebContext { return controller.getInitTxContent(); } - public LedgerInitPermission getLocalPermission() { + public LedgerInitProposal getLocalPermission() { return controller.getLocalPermission(); } @@ -61,9 +61,9 @@ public class NodeWebContext { this.serverAddress = serverAddress; } - public LedgerRepository registLedger(HashDigest ledgerHash) { + public LedgerQuery registLedger(HashDigest ledgerHash) { DbConnection conn = db.connect(dbConnConfig.getUri()); - LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, conn.getStorageService()); + LedgerQuery ledgerRepo = ledgerManager.register(ledgerHash, conn.getStorageService()); return ledgerRepo; } diff --git a/source/utils/utils-common/pom.xml b/source/utils/utils-common/pom.xml index 5712cd4b..d7a6e83a 100644 --- a/source/utils/utils-common/pom.xml +++ b/source/utils/utils-common/pom.xml @@ -24,6 +24,12 @@ commons-codec + + commons-io + commons-io + 2.4 + + net.i2p.crypto eddsa @@ -37,6 +43,23 @@ spring-beans + + org.bitbucket.mstrobel + procyon-core + + + org.bitbucket.mstrobel + procyon-expressions + + + org.bitbucket.mstrobel + procyon-reflection + + + org.bitbucket.mstrobel + procyon-compilertools + + diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/ArrayUtils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/ArrayUtils.java index c787a014..79773915 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/ArrayUtils.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/ArrayUtils.java @@ -9,6 +9,7 @@ import java.util.*; */ public abstract class ArrayUtils { private ArrayUtils() { + } public static T[] singleton(T obj, Class clazz) { @@ -30,6 +31,13 @@ public abstract class ArrayUtils { return array; } + public static T[] toArray(Collection collection, Class clazz){ + @SuppressWarnings("unchecked") + T[] array = (T[]) Array.newInstance(clazz, collection.size()); + collection.toArray(array); + return array; + } + public static List asList(T[] array){ return asList(array, 0, array.length); } diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Int8Code.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Int8Code.java new file mode 100644 index 00000000..339c9c07 --- /dev/null +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Int8Code.java @@ -0,0 +1,8 @@ +package com.jd.blockchain.utils; + +public interface Int8Code { + + byte getCode(); + + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/PropertiesUtils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/PropertiesUtils.java index 994272b0..aaaed113 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/PropertiesUtils.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/PropertiesUtils.java @@ -251,6 +251,14 @@ public abstract class PropertiesUtils { String value = getRequiredProperty(props, key); return Boolean.parseBoolean(value); } + + public static boolean getBooleanOptional(Properties props, String key, boolean defaultValue) { + String value = getProperty(props, key, false); + if (value == null) { + return defaultValue; + } + return Boolean.parseBoolean(value); + } /** * 返回指定的属性;
@@ -263,6 +271,18 @@ public abstract class PropertiesUtils { public static String getRequiredProperty(Properties props, String key) { return getProperty(props, key, true); } + + public static String getOptionalProperty(Properties props, String key) { + return getProperty(props, key, false); + } + + public static String getOptionalProperty(Properties props, String key, String defaultValue) { + String value = getProperty(props, key, false); + if (value == null) { + return defaultValue; + } + return value; + } /** * 返回指定的属性;
diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/StringUtils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/StringUtils.java index 5ae1a856..480d1335 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/StringUtils.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/StringUtils.java @@ -1,24 +1,79 @@ package com.jd.blockchain.utils; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; import java.util.regex.Pattern; /** - * @Author zhaogw - * date 2018/11/26 20:46 + * @Author zhaogw date 2018/11/26 20:46 */ public class StringUtils { - public static boolean isEmpty(Object str) { - return str == null || "".equals(str); - } - - /* - * 判断是否为整数 - * @param str 传入的字符串 - * @return 是整数返回true,否则返回false - */ - - public static boolean isNumber(String str) { - Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$"); - return pattern.matcher(str).matches(); - } + + public static final String[] EMPTY_ARRAY = {}; + + public static boolean isEmpty(Object str) { + return str == null || "".equals(str); + } + + /* + * 判断是否为整数 + * + * @param str 传入的字符串 + * + * @return 是整数返回true,否则返回false + */ + + public static boolean isNumber(String str) { + Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$"); + return pattern.matcher(str).matches(); + } + + /** + * 按照指定的分隔符把字符串分解为字符数组,同时截掉每一个元素两端的空白字符,并忽略掉空字符元素; + * + * @param str 要被截断的字符串; + * @param delimiter 分隔符; + * @return + */ + public static String[] splitToArray(String str, String delimiter) { + return splitToArray(str, delimiter, true, true); + } + + /** + * 按照指定的分隔符把字符串分解为字符数组 + * + * @param str 要被截断的字符串; + * @param delimiter 分隔符; + * @param trimElement 是否截断元素两端的空白字符; + * @param ignoreEmptyElement 是否忽略空字符元素; + * @return + */ + public static String[] splitToArray(String str, String delimiter, boolean trimElement, boolean ignoreEmptyElement) { + if (str == null) { + return EMPTY_ARRAY; + } + if (trimElement) { + str = str.trim(); + } + if (str.length() == 0) { + return EMPTY_ARRAY; + } + StringTokenizer tokenizer = new StringTokenizer(str, delimiter); + List tokens = new ArrayList<>(); + while (tokenizer.hasMoreTokens()) { + String token = tokenizer.nextToken(); + if (trimElement) { + token = token.trim(); + } + if ((!ignoreEmptyElement) || token.length() > 0) { + tokens.add(token); + } + } + return tokens.toArray(new String[tokens.size()]); + } + + public static String trim(String str) { + return str == null ? "" : str.trim(); + } } \ No newline at end of file diff --git a/source/gateway/src/main/java/com/jd/blockchain/gateway/decompiler/loads/BytesTypeLoader.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/decompiler/loads/BytesTypeLoader.java similarity index 99% rename from source/gateway/src/main/java/com/jd/blockchain/gateway/decompiler/loads/BytesTypeLoader.java rename to source/utils/utils-common/src/main/java/com/jd/blockchain/utils/decompiler/loads/BytesTypeLoader.java index 8caf66f0..379aab08 100644 --- a/source/gateway/src/main/java/com/jd/blockchain/gateway/decompiler/loads/BytesTypeLoader.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/decompiler/loads/BytesTypeLoader.java @@ -1,4 +1,4 @@ -package com.jd.blockchain.gateway.decompiler.loads; +package com.jd.blockchain.utils.decompiler.loads; import com.strobel.assembler.ir.ConstantPool; import com.strobel.assembler.metadata.Buffer; diff --git a/source/gateway/src/main/java/com/jd/blockchain/gateway/decompiler/utils/DecompilerUtils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/decompiler/utils/DecompilerUtils.java similarity index 98% rename from source/gateway/src/main/java/com/jd/blockchain/gateway/decompiler/utils/DecompilerUtils.java rename to source/utils/utils-common/src/main/java/com/jd/blockchain/utils/decompiler/utils/DecompilerUtils.java index 0a66da9f..6d7729b4 100644 --- a/source/gateway/src/main/java/com/jd/blockchain/gateway/decompiler/utils/DecompilerUtils.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/decompiler/utils/DecompilerUtils.java @@ -1,6 +1,6 @@ -package com.jd.blockchain.gateway.decompiler.utils; +package com.jd.blockchain.utils.decompiler.utils; -import com.jd.blockchain.gateway.decompiler.loads.BytesTypeLoader; +import com.jd.blockchain.utils.decompiler.loads.BytesTypeLoader; import com.strobel.assembler.metadata.JarTypeLoader; import com.strobel.decompiler.Decompiler; import com.strobel.decompiler.DecompilerSettings; diff --git a/source/utils/utils-common/src/main/resources/complex.jar b/source/utils/utils-common/src/main/resources/complex.jar new file mode 100644 index 00000000..6f40ca02 Binary files /dev/null and b/source/utils/utils-common/src/main/resources/complex.jar differ diff --git a/source/utils/utils-common/src/test/resources/complex.jar b/source/utils/utils-common/src/test/resources/complex.jar new file mode 100644 index 00000000..6f40ca02 Binary files /dev/null and b/source/utils/utils-common/src/test/resources/complex.jar differ diff --git a/source/utils/utils-http/pom.xml b/source/utils/utils-http/pom.xml index 53053a54..e62e9564 100644 --- a/source/utils/utils-http/pom.xml +++ b/source/utils/utils-http/pom.xml @@ -43,6 +43,11 @@ org.springframework spring-beans + + org.springframework.boot + spring-boot-starter-log4j2 + test + - \ No newline at end of file + diff --git a/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/binary/BinarySerializeUtils.java b/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/binary/BinarySerializeUtils.java index f0e2edf2..d1b1439d 100644 --- a/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/binary/BinarySerializeUtils.java +++ b/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/binary/BinarySerializeUtils.java @@ -4,7 +4,6 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; @@ -46,9 +45,10 @@ public class BinarySerializeUtils { @SuppressWarnings("unchecked") public static T deserialize(InputStream in) { try { - ObjectInputStream objIn = new ObjectInputStream(in); - Object obj = objIn.readObject(); - return (T) obj; + try(FilteredObjectInputStream objIn = new FilteredObjectInputStream(in)){ + Object obj = objIn.readObject(); + return (T) obj; + } } catch (IOException e) { throw new RuntimeIOException(e.getMessage(), e); } catch (ClassNotFoundException e) { diff --git a/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/binary/FilteredObjectInputStream.java b/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/binary/FilteredObjectInputStream.java new file mode 100644 index 00000000..897aa115 --- /dev/null +++ b/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/binary/FilteredObjectInputStream.java @@ -0,0 +1,35 @@ +package com.jd.blockchain.utils.serialize.binary; + +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectStreamClass; +import java.util.HashSet; +import java.util.Set; + +public class FilteredObjectInputStream extends ObjectInputStream { + + private static final Set classBlacklist = new HashSet(); + + /** + * 把指定类型加入禁止反序列化的类型黑名单; + * + * @param className + */ + public static void addBlackList(String className) { + classBlacklist.add(className); + } + + public FilteredObjectInputStream(InputStream in) throws IOException { + super(in); + } + + @Override + protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { + if (classBlacklist.contains(desc.getName())) { + throw new SecurityException("Class["+desc.getName()+"] is forbidden to deserialize because it is in the blacklist!"); + } + return super.resolveClass(desc); + } + +} diff --git a/tools/core-0.1.4.jar b/tools/core-0.1.4.jar deleted file mode 100644 index 85ea3a4a..00000000 Binary files a/tools/core-0.1.4.jar and /dev/null differ