Browse Source

Merge remote-tracking branch 'origin/develop' into feature/1.0.0-contract-check2.0-local

# Conflicts:
#	source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServer.java
#	source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractDeployExeUtil.java
#	source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractDeployMojo.java
#	source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryServiceHandler.java
#	source/gateway/src/main/java/com/jd/blockchain/gateway/web/TxProcessingController.java
#	source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/AbstractContractEventHandle.java
#	source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/AbtractContractEventSendOperationHandle.java
#	source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/JVMContractEventSendOperationHandle.java
#	source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/AbtractContractEventHandle.java
#	source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractCodeDeployOperationHandle.java
#	source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/ContractInvokingHandle.java
#	source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/ContractInvokingTest.java
tags/1.1.0
shaozhuguang 5 years ago
parent
commit
76d0e4fcd1
100 changed files with 4617 additions and 1820 deletions
  1. +1
    -9
      source/base/pom.xml
  2. +41
    -14
      source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java
  3. +19
    -0
      source/base/src/main/java/com/jd/blockchain/consts/Global.java
  4. +1
    -1
      source/binary-proto/pom.xml
  5. +1
    -1
      source/consensus/consensus-bftsmart/pom.xml
  6. +13
    -9
      source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServer.java
  7. +1
    -1
      source/consensus/consensus-framework/pom.xml
  8. +1
    -1
      source/consensus/consensus-mq/pom.xml
  9. +2
    -2
      source/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/MsgQueueConsensusSettingsBuilder.java
  10. +1
    -1
      source/consensus/pom.xml
  11. +1
    -1
      source/contract/contract-framework/pom.xml
  12. +1
    -1
      source/contract/contract-jvm/pom.xml
  13. +25
    -0
      source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/InstantiatedContractCode.java
  14. +1
    -1
      source/contract/contract-maven-plugin/pom.xml
  15. +193
    -0
      source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractDeployExeUtil.java
  16. +119
    -0
      source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractDeployMojo.java
  17. +1
    -1
      source/contract/contract-samples/pom.xml
  18. +1
    -1
      source/contract/pom.xml
  19. +1
    -1
      source/crypto/crypto-adv/pom.xml
  20. +1
    -1
      source/crypto/crypto-classic/pom.xml
  21. +6
    -6
      source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/ECDSAUtils.java
  22. +20
    -0
      source/crypto/crypto-composite/src/test/java/com/jd/blockchain/AppTest.java
  23. +1
    -1
      source/crypto/crypto-framework/pom.xml
  24. +187
    -0
      source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/KeyGenUtils.java
  25. +1
    -1
      source/crypto/crypto-pki/pom.xml
  26. +62
    -13
      source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CSRBuilder.java
  27. +16
    -0
      source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CertParser.java
  28. +145
    -0
      source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunctionTest.java
  29. +186
    -0
      source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunctionTest.java
  30. +80
    -0
      source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SM3WITHSM2SignatureFunctionTest.java
  31. +8
    -4
      source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CertParserTest.java
  32. +1
    -1
      source/crypto/crypto-sm/pom.xml
  33. +6
    -13
      source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/utils/sm/SM2Utils.java
  34. +1
    -1
      source/crypto/pom.xml
  35. +20
    -0
      source/deployment/deployment-autotest/src/test/java/com/jd/blockchain/AppTest.java
  36. +0
    -0
      source/deployment/deployment-gateway/conf/application-gw.properties
  37. +1
    -1
      source/deployment/deployment-gateway/pom.xml
  38. +6
    -4
      source/deployment/deployment-gateway/src/main/java/com/jd/blockchain/gateway/boot/GatewayBooter.java
  39. +1
    -1
      source/deployment/deployment-gateway/src/main/resources/scripts/startup.sh
  40. +6
    -2
      source/deployment/deployment-peer/pom.xml
  41. +10
    -0
      source/deployment/deployment-peer/src/main/resources/assembly.xml
  42. +1
    -1
      source/deployment/deployment-peer/src/main/resources/docs/安装部署.MD
  43. +9
    -0
      source/deployment/deployment-peer/src/main/resources/scripts/jump-start.sh
  44. +16
    -0
      source/deployment/deployment-peer/src/main/resources/scripts/jump-stop.sh
  45. +3
    -3
      source/deployment/deployment-peer/src/main/resources/scripts/ledger-init.sh
  46. +1
    -1
      source/deployment/deployment-peer/src/main/resources/scripts/startup.sh
  47. +1
    -1
      source/deployment/pom.xml
  48. +4
    -10
      source/gateway/pom.xml
  49. +7
    -7
      source/gateway/src/main/java/com/jd/blockchain/gateway/GatewayServerBooter.java
  50. +0
    -1
      source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryService.java
  51. +12
    -9
      source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryServiceHandler.java
  52. +551
    -516
      source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java
  53. +1
    -0
      source/gateway/src/main/java/com/jd/blockchain/gateway/web/GatewayWebServerConfigurer.java
  54. +3
    -7
      source/gateway/src/main/java/com/jd/blockchain/gateway/web/TxProcessingController.java
  55. +9
    -9
      source/gateway/src/main/resources/log4j2.xml
  56. +29
    -39
      source/ledger/ledger-core/pom.xml
  57. +0
    -26
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountPrivilege.java
  58. +7
    -6
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountSet.java
  59. +0
    -168
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AuthorizableDataSet.java
  60. +0
    -40
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Authorization.java
  61. +0
    -42
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AuthorizationVO.java
  62. +4
    -3
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/BaseAccount.java
  63. +0
    -21
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Consensus.java
  64. +2
    -2
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java
  65. +29
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccountQuery.java
  66. +11
    -1
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccountSet.java
  67. +1
    -1
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/CryptoConfig.java
  68. +95
    -3
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java
  69. +32
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountQuery.java
  70. +23
    -4
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountSet.java
  71. +132
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DefaultOperationHandleRegisteration.java
  72. +209
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/EmptyLedgerDataset.java
  73. +98
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/FullPermissionedSecurityManager.java
  74. +0
    -22
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Gateway.java
  75. +1
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/GenesisLedgerStorageProxy.java
  76. +0
    -356
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminAccount.java
  77. +12
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminDataQuery.java
  78. +469
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminDataset.java
  79. +0
    -5
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminPrivilege.java
  80. +0
    -16
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdministration.java
  81. +14
    -2
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerBlockData.java
  82. +3
    -3
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerConfiguration.java
  83. +19
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerDataQuery.java
  84. +0
    -21
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerDataSet.java
  85. +22
    -17
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerDataset.java
  86. +37
    -4
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerEditor.java
  87. +2
    -2
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitProposal.java
  88. +4
    -3
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitProposalData.java
  89. +215
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitializer.java
  90. +12
    -10
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerManage.java
  91. +14
    -21
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerManager.java
  92. +49
    -39
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerQueryService.java
  93. +12
    -15
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerRepository.java
  94. +173
    -221
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerRepositoryImpl.java
  95. +20
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerSecurityManager.java
  96. +396
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerSecurityManagerImpl.java
  97. +10
    -3
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionContext.java
  98. +23
    -45
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionData.java
  99. +630
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionalEditor.java
  100. +1
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataEntry.java

+ 1
- 9
source/base/pom.xml View File

@@ -5,15 +5,7 @@
<parent>
<groupId>com.jd.blockchain</groupId>
<artifactId>jdchain-root</artifactId>
<version>1.0.0.RELEASE</version>
<version>1.1.0-SNAPSHOT</version>
</parent>
<artifactId>base</artifactId>

<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>

</dependencies>
</project>

+ 41
- 14
source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java View File

@@ -8,11 +8,11 @@ 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 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 +22,8 @@ public interface DataCodes {

public static final int DATA_SNAPSHOT = 0x130;

// public static final int LEDGER_ADMIN_DATA = 0x131;

public static final int TX = 0x200;

public static final int TX_LEDGER = 0x201;
@@ -52,12 +54,37 @@ public interface DataCodes {
public static final int TX_RESPONSE = 0x350;

public static final int TX_OP_RESULT = 0x360;
public static final int TX_OP_ROLE_CONFIGURE = 0x370;
public static final int TX_OP_ROLE_CONFIGURE_ENTRY = 0x371;
public static final int TX_OP_USER_ROLES_AUTHORIZE = 0x372;
public static final int TX_OP_USER_ROLE_AUTHORIZE_ENTRY = 0x373;

// 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 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,14 +92,14 @@ 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_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_CRYPTO_SETTING_PROVIDER = 0x643;

// public static final int ACCOUNT = 0x700;
@@ -83,11 +110,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;
@@ -152,4 +178,5 @@ public interface DataCodes {

public static final int CONSENSUS_MSGQUEUE_BLOCK_SETTINGS = CONSENSUS_MSGQUEUE | 0x05;

}

+ 19
- 0
source/base/src/main/java/com/jd/blockchain/consts/Global.java View File

@@ -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));
}
}

+ 1
- 1
source/binary-proto/pom.xml View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.jd.blockchain</groupId>
<artifactId>jdchain-root</artifactId>
<version>1.0.0.RELEASE</version>
<version>1.1.0-SNAPSHOT</version>
</parent>
<artifactId>binary-proto</artifactId>



+ 1
- 1
source/consensus/consensus-bftsmart/pom.xml View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.jd.blockchain</groupId>
<artifactId>consensus</artifactId>
<version>1.0.0.RELEASE</version>
<version>1.1.0-SNAPSHOT</version>
</parent>
<artifactId>consensus-bftsmart</artifactId>



+ 13
- 9
source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServer.java View File

@@ -6,6 +6,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import bftsmart.tom.*;
import com.jd.blockchain.utils.serialize.binary.BinarySerializeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.jd.blockchain.consensus.ConsensusManageService;
@@ -32,6 +33,8 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer

private static Logger LOGGER = LoggerFactory.getLogger(BftsmartNodeServer.class);

private static final String DEFAULT_BINDING_HOST = "0.0.0.0";

private List<StateHandle> stateHandles = new CopyOnWriteArrayList<>();

// TODO 暂不处理队列溢出问题
@@ -56,6 +59,8 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer

private TOMConfiguration tomConfig;

private TOMConfiguration outerTomConfig;

private HostsConfig hostsConfig;
private Properties systemConfig;

@@ -123,14 +128,13 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer
return;
}

// protected void initConfig(int id, String systemConfig, String hostsConfig) {
//
// this.tomConfig = new TOMConfiguration(id, systemConfig, hostsConfig);
//
// }

protected void initConfig(int id, Properties systemsConfig, HostsConfig hostConfig) {
byte[] serialHostConf = BinarySerializeUtils.serialize(hostConfig);
Properties sysConfClone = (Properties)systemsConfig.clone();
int port = hostConfig.getPort(id);
hostConfig.add(id, DEFAULT_BINDING_HOST, port);
this.tomConfig = new TOMConfiguration(id, systemsConfig, hostConfig);
this.outerTomConfig = new TOMConfiguration(id, sysConfClone, BinarySerializeUtils.deserialize(serialHostConf));
}

@Override
@@ -149,7 +153,7 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer
}

public TOMConfiguration getTomConfig() {
return tomConfig;
return outerTomConfig;
}

public int getId() {
@@ -161,7 +165,7 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer
throw new IllegalArgumentException("ReplicaID is negative!");
}
this.tomConfig.setProcessId(id);
this.outerTomConfig.setProcessId(id);
}

public BftsmartConsensusSettings getConsensusSetting() {
@@ -243,6 +247,7 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer
messageHandle.commitBatch(realmName, batchId);
} catch (Exception e) {
// todo 需要处理应答码 404
LOGGER.error("Error occurred while processing ordered messages! --" + e.getMessage(), e);
messageHandle.rollbackBatch(realmName, batchId, TransactionState.CONSENSUS_ERROR.CODE);
}

@@ -309,7 +314,6 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer

try {
LOGGER.debug("Start replica...[ID=" + getId() + "]");
// 调整绑定Host
this.replica = new ServiceReplica(tomConfig, this, this);
this.topology = new BftsmartTopology(replica.getReplicaContext().getCurrentView());
status = Status.RUNNING;


+ 1
- 1
source/consensus/consensus-framework/pom.xml View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.jd.blockchain</groupId>
<artifactId>consensus</artifactId>
<version>1.0.0.RELEASE</version>
<version>1.1.0-SNAPSHOT</version>
</parent>
<artifactId>consensus-framework</artifactId>



+ 1
- 1
source/consensus/consensus-mq/pom.xml View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.jd.blockchain</groupId>
<artifactId>consensus</artifactId>
<version>1.0.0.RELEASE</version>
<version>1.1.0-SNAPSHOT</version>
</parent>
<artifactId>consensus-mq</artifactId>



+ 2
- 2
source/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/MsgQueueConsensusSettingsBuilder.java View File

@@ -20,9 +20,9 @@ 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.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;
@@ -129,7 +129,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);


+ 1
- 1
source/consensus/pom.xml View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.jd.blockchain</groupId>
<artifactId>jdchain-root</artifactId>
<version>1.0.0.RELEASE</version>
<version>1.1.0-SNAPSHOT</version>
</parent>
<artifactId>consensus</artifactId>
<packaging>pom</packaging>


+ 1
- 1
source/contract/contract-framework/pom.xml View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.jd.blockchain</groupId>
<artifactId>contract</artifactId>
<version>1.0.0.RELEASE</version>
<version>1.1.0-SNAPSHOT</version>
</parent>
<artifactId>contract-framework</artifactId>



+ 1
- 1
source/contract/contract-jvm/pom.xml View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.jd.blockchain</groupId>
<artifactId>contract</artifactId>
<version>1.0.0.RELEASE</version>
<version>1.1.0-SNAPSHOT</version>
</parent>
<artifactId>contract-jvm</artifactId>



+ 25
- 0
source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/InstantiatedContractCode.java View File

@@ -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<T> extends AbstractContractCode {

private T instance;

public InstantiatedContractCode(Bytes address, long version, Class<T> 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;
}

}

+ 1
- 1
source/contract/contract-maven-plugin/pom.xml View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.jd.blockchain</groupId>
<artifactId>contract</artifactId>
<version>1.0.0.RELEASE</version>
<version>1.1.0-SNAPSHOT</version>
</parent>
<artifactId>contract-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>


+ 193
- 0
source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractDeployExeUtil.java View File

@@ -0,0 +1,193 @@
package com.jd.blockchain;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
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.sdk.BlockchainService;
import com.jd.blockchain.sdk.client.GatewayServiceFactory;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.codec.Base58Utils;
import com.jd.blockchain.utils.net.NetworkAddress;

/**
* @Author zhaogw
* @Date 2018/11/2 10:18
*/
public enum ContractDeployExeUtil {
instance;
private BlockchainService bcsrv;
private Bytes contractAddress;

public BlockchainKeypair getKeyPair(String pubPath, String prvPath, String rawPassword){
PubKey pub = null;
PrivKey prv = null;
try {
prv = KeyGenUtils.readPrivKey(prvPath, KeyGenUtils.encodePassword(rawPassword));
pub = KeyGenUtils.readPubKey(pubPath);

} catch (Exception e) {
e.printStackTrace();
}

return new BlockchainKeypair(pub, prv);
}

public PubKey getPubKey(String pubPath){
PubKey pub = null;
try {
if(pubPath == null){
BlockchainKeypair contractKeyPair = BlockchainKeyGenerator.getInstance().generate();
pub = contractKeyPair.getPubKey();
}else {
pub = KeyGenUtils.readPubKey(pubPath);
}

} catch (Exception e) {
e.printStackTrace();
}

return pub;
}
public byte[] getChainCode(String path){
byte[] chainCode = null;
File file = null;
InputStream input = null;
try {
file = new File(path);
input = new FileInputStream(file);
chainCode = new byte[input.available()];
input.read(chainCode);

} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(input!=null){
input.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return chainCode;
}

private void register(){
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);
}

public BlockchainService initBcsrv(String host, int port) {
if(bcsrv!=null){
return bcsrv;
}
NetworkAddress addr = new NetworkAddress(host, port);
GatewayServiceFactory gwsrvFact = GatewayServiceFactory.connect(addr);
bcsrv = gwsrvFact.getBlockchainService();
return bcsrv;
}

public boolean deploy(HashDigest ledgerHash, BlockchainIdentity contractIdentity, BlockchainKeypair ownerKey, byte[] chainCode){
register();

TransactionTemplate txTpl = bcsrv.newTransaction(ledgerHash);
txTpl.contracts().deploy(contractIdentity, chainCode);
PreparedTransaction ptx = txTpl.prepare();
ptx.sign(ownerKey);
// 提交并等待共识返回;
TransactionResponse txResp = ptx.commit();

// 验证结果;
contractAddress = contractIdentity.getAddress();
this.setContractAddress(contractAddress);
System.out.println("contract's address="+contractAddress);
return txResp.isSuccess();
}
public boolean deploy(String host, int port, HashDigest ledgerHash, BlockchainKeypair ownerKey, byte[] chainCode){
register();

BlockchainIdentity contractIdentity = BlockchainKeyGenerator.getInstance().generate().getIdentity();
initBcsrv(host,port);
return deploy(ledgerHash, contractIdentity, ownerKey, chainCode);
}

// 根据用户指定的公钥生成合约地址
public boolean deploy(String host, int port, String ledger,String ownerPubPath, String ownerPrvPath,
String ownerPassword, String chainCodePath,String pubPath){
PubKey pubKey = getPubKey(pubPath);
BlockchainIdentity contractIdentity = new BlockchainIdentityData(pubKey);
byte[] chainCode = getChainCode(chainCodePath);

BlockchainKeypair ownerKey = getKeyPair(ownerPubPath, ownerPrvPath, ownerPassword);
HashDigest ledgerHash = new HashDigest(Base58Utils.decode(ledger));
initBcsrv(host,port);
return deploy(ledgerHash, contractIdentity, ownerKey, chainCode);
}

// 暂不支持从插件执行合约;此外,由于合约参数调用的格式发生变化,故此方法被废弃;by: huanghaiquan at 2019-04-30;
// public boolean exeContract(String ledger,String ownerPubPath, String ownerPrvPath,
// String ownerPassword,String event,String contractArgs){
// BlockchainKeypair ownerKey = getKeyPair(ownerPubPath, ownerPrvPath, ownerPassword);
// HashDigest ledgerHash = new HashDigest(Base58Utils.decode(ledger));
//
// // 定义交易,传输最简单的数字、字符串、提取合约中的地址;
// TransactionTemplate txTpl = bcsrv.newTransaction(ledgerHash);
// txTpl.contractEvents().send(getContractAddress(),event,contractArgs.getBytes());
//
// // 签名;
// PreparedTransaction ptx = txTpl.prepare();
// ptx.sign(ownerKey);
//
// // 提交并等待共识返回;
// TransactionResponse txResp = ptx.commit();
//
// // 验证结果;
// return txResp.isSuccess();
// }

public Bytes getContractAddress() {
return contractAddress;
}

public void setContractAddress(Bytes contractAddress) {
this.contractAddress = contractAddress;
}
}

+ 119
- 0
source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractDeployMojo.java View File

@@ -0,0 +1,119 @@
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.utils.StringUtils;
import com.jd.blockchain.utils.codec.Base58Utils;
import com.jd.blockchain.utils.io.FileUtils;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

/**
* for contract remote deploy;
* @goal contractDeploy
* @phase process-sources
* @Author zhaogw
* @Date 2018/10/18 10:12
*/

@Mojo(name = "deploy")
public class ContractDeployMojo extends AbstractMojo {
Logger logger = LoggerFactory.getLogger(ContractDeployMojo.class);

@Parameter
private File config;

@Override
public void execute()throws MojoFailureException {
Properties prop = new Properties();
InputStream input = null;

try {
input = new FileInputStream(config);
prop.load(input);

} catch (IOException ex) {
logger.error(ex.getMessage());
throw new MojoFailureException("io error");
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
logger.error(e.getMessage());
}
}
}
int port;
try {
port = Integer.parseInt(prop.getProperty("port"));
}catch (NumberFormatException e){
logger.error(e.getMessage());
throw new MojoFailureException("invalid port");
}
String host = prop.getProperty("host");
String ledger = prop.getProperty("ledger");
String pubKey = prop.getProperty("pubKey");
String prvKey = prop.getProperty("prvKey");
String password = prop.getProperty("password");
String contractPath = prop.getProperty("contractPath");


if(StringUtils.isEmpty(host)){
logger.info("host不能为空");
return;
}

if(StringUtils.isEmpty(ledger)){
logger.info("ledger不能为空.");
return;
}
if(StringUtils.isEmpty(pubKey)){
logger.info("pubKey不能为空.");
return;
}
if(StringUtils.isEmpty(prvKey)){
logger.info("prvKey不能为空.");
return;
}
if(StringUtils.isEmpty(contractPath)){
logger.info("contractPath不能为空.");
return;
}

File contract = new File(contractPath);
if (!contract.isFile()){
logger.info("文件"+contractPath+"不存在");
return;
}
byte[] contractBytes = FileUtils.readBytes(contractPath);


PrivKey prv = KeyGenUtils.decodePrivKeyWithRawPassword(prvKey, password);
PubKey pub = KeyGenUtils.decodePubKey(pubKey);
BlockchainKeypair blockchainKeyPair = new BlockchainKeypair(pub, prv);
HashDigest ledgerHash = new HashDigest(Base58Utils.decode(ledger));

StringBuffer sb = new StringBuffer();
sb.append("host:"+ host).append(",port:"+port).append(",ledgerHash:"+ledgerHash.toBase58()).
append(",pubKey:"+pubKey).append(",prvKey:"+prv).append(",contractPath:"+contractPath);
logger.info(sb.toString());
ContractDeployExeUtil.instance.deploy(host,port,ledgerHash, blockchainKeyPair, contractBytes);
}

}



+ 1
- 1
source/contract/contract-samples/pom.xml View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>contract</artifactId>
<groupId>com.jd.blockchain</groupId>
<version>1.0.0.RELEASE</version>
<version>1.1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>



+ 1
- 1
source/contract/pom.xml View File

@@ -4,7 +4,7 @@
<parent>
<groupId>com.jd.blockchain</groupId>
<artifactId>jdchain-root</artifactId>
<version>1.0.0.RELEASE</version>
<version>1.1.0-SNAPSHOT</version>
</parent>
<artifactId>contract</artifactId>
<packaging>pom</packaging>


+ 1
- 1
source/crypto/crypto-adv/pom.xml View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.jd.blockchain</groupId>
<artifactId>crypto</artifactId>
<version>1.0.0.RELEASE</version>
<version>1.1.0-SNAPSHOT</version>
</parent>
<artifactId>crypto-adv</artifactId>



+ 1
- 1
source/crypto/crypto-classic/pom.xml View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.jd.blockchain</groupId>
<artifactId>crypto</artifactId>
<version>1.0.0.RELEASE</version>
<version>1.1.0-SNAPSHOT</version>
</parent>
<artifactId>crypto-classic</artifactId>



+ 6
- 6
source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/ECDSAUtils.java View File

@@ -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-----------------


+ 20
- 0
source/crypto/crypto-composite/src/test/java/com/jd/blockchain/AppTest.java View File

@@ -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 );
}
}

+ 1
- 1
source/crypto/crypto-framework/pom.xml View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.jd.blockchain</groupId>
<artifactId>crypto</artifactId>
<version>1.0.0.RELEASE</version>
<version>1.1.0-SNAPSHOT</version>
</parent>
<artifactId>crypto-framework</artifactId>



+ 187
- 0
source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/KeyGenUtils.java View File

@@ -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);
}
}

+ 1
- 1
source/crypto/crypto-pki/pom.xml View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>crypto</artifactId>
<groupId>com.jd.blockchain</groupId>
<version>1.0.0.RELEASE</version>
<version>1.1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>



+ 62
- 13
source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CSRBuilder.java View File

@@ -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;
}
}

+ 16
- 0
source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/utils/CertParser.java View File

@@ -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;
}


+ 145
- 0
source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA2048SignatureFunctionTest.java View File

@@ -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));
}
}

+ 186
- 0
source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SHA1WITHRSA4096SignatureFunctionTest.java View File

@@ -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));
}
}

+ 80
- 0
source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/service/pki/SM3WITHSM2SignatureFunctionTest.java View File

@@ -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));
}
}

+ 8
- 4
source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/utils/CertParserTest.java View File

@@ -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());
}
}

+ 1
- 1
source/crypto/crypto-sm/pom.xml View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.jd.blockchain</groupId>
<artifactId>crypto</artifactId>
<version>1.0.0.RELEASE</version>
<version>1.1.0-SNAPSHOT</version>
</parent>
<artifactId>crypto-sm</artifactId>



+ 6
- 13
source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/utils/sm/SM2Utils.java View File

@@ -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-----------------


+ 1
- 1
source/crypto/pom.xml View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.jd.blockchain</groupId>
<artifactId>jdchain-root</artifactId>
<version>1.0.0.RELEASE</version>
<version>1.1.0-SNAPSHOT</version>
</parent>
<artifactId>crypto</artifactId>
<packaging>pom</packaging>


+ 20
- 0
source/deployment/deployment-autotest/src/test/java/com/jd/blockchain/AppTest.java View File

@@ -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 );
}
}

+ 0
- 0
source/deployment/deployment-gateway/conf/application-gw.properties View File


+ 1
- 1
source/deployment/deployment-gateway/pom.xml View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.jd.blockchain</groupId>
<artifactId>deployment</artifactId>
<version>1.0.0.RELEASE</version>
<version>1.1.0-SNAPSHOT</version>
</parent>
<artifactId>deployment-gateway</artifactId>



+ 6
- 4
source/deployment/deployment-gateway/src/main/java/com/jd/blockchain/gateway/boot/GatewayBooter.java View File

@@ -18,15 +18,13 @@ public class GatewayBooter {
writePID();
GatewayServerBooter.main(args);
} catch (Exception e) {
e.printStackTrace();
System.err.println("Error!!! --[" + e.getClass().getName() + "] " + e.getMessage());
}
}

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 +38,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();


+ 1
- 1
source/deployment/deployment-gateway/src/main/resources/scripts/startup.sh View File

@@ -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

+ 6
- 2
source/deployment/deployment-peer/pom.xml View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.jd.blockchain</groupId>
<artifactId>deployment</artifactId>
<version>1.0.0.RELEASE</version>
<version>1.1.0-SNAPSHOT</version>
</parent>
<artifactId>deployment-peer</artifactId>

@@ -25,7 +25,11 @@
<artifactId>runtime-modular-booter</artifactId>
<version>${project.version}</version>
</dependency>

<!--<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>ump-booter</artifactId>
<version>${project.version}</version>
</dependency>-->
<dependency>
<groupId>com.jd.blockchain</groupId>
<artifactId>storage-composite</artifactId>


+ 10
- 0
source/deployment/deployment-peer/src/main/resources/assembly.xml View File

@@ -55,6 +55,16 @@
<exclude>com.jd.blockchain:deployment-peer</exclude>
</excludes>
</dependencySet>

<!--<dependencySet>
<unpack>false</unpack>
<useProjectArtifact>true</useProjectArtifact>
<outputDirectory>ext</outputDirectory>
<includes>
<include>com.jd.blockchain:ump-booter</include>
</includes>
</dependencySet>-->

</dependencySets>

<moduleSets>


+ 1
- 1
source/deployment/deployment-peer/src/main/resources/docs/安装部署.MD View File

@@ -78,7 +78,7 @@ Peer打包程序解压完后的安装包结构如下:

其中目录说明如下:
+ **bin** :相关命令操作目录;
+ **config** :对应命令的配置目录,keys路径默认可能不存在,会在执行相关脚本时自动创建;
+ **config** :对应命令的配置目录,keys路径解压时不存在,会在执行keygen.sh脚本时自动创建;ledger-binding.conf文件解压时不存在,会在成功执行ledger-init.sh脚本后生成;
+ **docs** :相关文档保存目录;
+ **libs** :项目运行依赖第三方及非system依赖包保存路径;
+ **system** :项目运行系统包保存路径;


+ 9
- 0
source/deployment/deployment-peer/src/main/resources/scripts/jump-start.sh View File

@@ -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

+ 16
- 0
source/deployment/deployment-peer/src/main/resources/scripts/jump-stop.sh View File

@@ -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

+ 3
- 3
source/deployment/deployment-peer/src/main/resources/scripts/ledger-init.sh View File

@@ -1,9 +1,9 @@
#!/bin/bash

HOME=$(cd `dirname $0`;cd ../; pwd)
boot_file=$(ls ../libs | grep tools-initializer-booter-)
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

+ 1
- 1
source/deployment/deployment-peer/src/main/resources/scripts/startup.sh View File

@@ -5,5 +5,5 @@ 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 $* &
nohup java -jar -server -Xmx2g -Xms2g -Dpeer.log=$HOME $HOME/system/$PEER -home=$HOME -c $HOME/config/ledger-binding.conf -p 7080 $* >$HOME/bin/peer.out 2>&1 &
fi

+ 1
- 1
source/deployment/pom.xml View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.jd.blockchain</groupId>
<artifactId>jdchain-root</artifactId>
<version>1.0.0.RELEASE</version>
<version>1.1.0-SNAPSHOT</version>
</parent>
<artifactId>deployment</artifactId>
<packaging>pom</packaging>


+ 4
- 10
source/gateway/pom.xml View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.jd.blockchain</groupId>
<artifactId>jdchain-root</artifactId>
<version>1.0.0.RELEASE</version>
<version>1.1.0-SNAPSHOT</version>
</parent>
<artifactId>gateway</artifactId>

@@ -75,7 +75,6 @@
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
</dependency>


@@ -83,18 +82,13 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<!-- <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
</dependency> -->

<dependency>
<groupId>org.springframework.boot</groupId>


+ 7
- 7
source/gateway/src/main/java/com/jd/blockchain/gateway/GatewayServerBooter.java View File

@@ -5,20 +5,20 @@ import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import com.jd.blockchain.gateway.web.BlockBrowserController;
import org.apache.commons.io.FileUtils;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.io.ClassPathResource;
import com.jd.blockchain.crypto.AsymmetricKeypair;
import com.jd.blockchain.crypto.KeyGenUtils;
import com.jd.blockchain.crypto.PrivKey;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.tools.keygen.KeyGenCommand;
import com.jd.blockchain.gateway.web.BlockBrowserController;
import com.jd.blockchain.utils.ArgumentSet;
import com.jd.blockchain.utils.ArgumentSet.ArgEntry;
import com.jd.blockchain.utils.BaseConstant;
import com.jd.blockchain.utils.ConsoleUtils;
import com.jd.blockchain.utils.ArgumentSet.ArgEntry;
public class GatewayServerBooter {
@@ -88,19 +88,19 @@ public class GatewayServerBooter {
String base58Pwd = config.keys().getDefault().getPrivKeyPassword();
if (base58Pwd == null || base58Pwd.length() == 0) {
base58Pwd = KeyGenCommand.readPasswordString();
base58Pwd = KeyGenUtils.readPasswordString();
}
// 加载密钥;
PubKey pubKey = KeyGenCommand.decodePubKey(config.keys().getDefault().getPubKeyValue());
PubKey pubKey = KeyGenUtils.decodePubKey(config.keys().getDefault().getPubKeyValue());
PrivKey privKey = null;
String base58PrivKey = config.keys().getDefault().getPrivKeyValue();
if (base58PrivKey == null) {
//注:GatewayConfigProperties 确保了 PrivKeyValue 和 PrivKeyPath 必有其一;
privKey = KeyGenCommand.readPrivKey(config.keys().getDefault().getPrivKeyPath(), base58Pwd);
privKey = KeyGenUtils.readPrivKey(config.keys().getDefault().getPrivKeyPath(), base58Pwd);
} else {
privKey = KeyGenCommand.decodePrivKey(base58PrivKey, base58Pwd);
privKey = KeyGenUtils.decodePrivKey(base58PrivKey, base58Pwd);
}
defaultKeyPair = new AsymmetricKeypair(pubKey, privKey);
}


+ 0
- 1
source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryService.java View File

@@ -4,7 +4,6 @@ import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.sdk.ContractSettings;
import com.jd.blockchain.sdk.LedgerInitSettings;
import com.jd.blockchain.utils.Bytes;

/**
* queryService only for gateway;


+ 12
- 9
source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryServiceHandler.java View File

@@ -6,6 +6,7 @@ import com.jd.blockchain.consensus.ConsensusSettings;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.gateway.PeerService;
import com.jd.blockchain.ledger.ContractInfo;
import com.jd.blockchain.ledger.LedgerAdminInfo;
import com.jd.blockchain.ledger.LedgerMetadata;
import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.sdk.ContractSettings;
@@ -51,7 +52,9 @@ public class GatewayQueryServiceHandler implements GatewayQueryService {

LedgerMetadata ledgerMetadata = peerService.getQueryService().getLedgerMetadata(ledgerHash);

return initLedgerInitSettings(participantNodes, ledgerMetadata);
LedgerAdminInfo ledgerAdminInfo = peerService.getQueryService().getLedgerAdminInfo(ledgerHash);

return initLedgerInitSettings(participantNodes, ledgerMetadata, ledgerAdminInfo);
}

@Override
@@ -78,26 +81,26 @@ public class GatewayQueryServiceHandler implements GatewayQueryService {
* 账本元数据
* @return
*/
private LedgerInitSettings initLedgerInitSettings(ParticipantNode[] participantNodes, LedgerMetadata ledgerMetadata) {
private LedgerInitSettings initLedgerInitSettings(ParticipantNode[] participantNodes, LedgerMetadata ledgerMetadata, LedgerAdminInfo ledgerAdminInfo) {
LedgerInitSettings ledgerInitSettings = new LedgerInitSettings();

// 设置参与方
ledgerInitSettings.setParticipantNodes(participantNodes);

// 设置共识设置
ledgerInitSettings.setConsensusSettings(initConsensusSettings(ledgerMetadata));
ledgerInitSettings.setConsensusSettings(initConsensusSettings(ledgerAdminInfo));

// 设置参与方根Hash
ledgerInitSettings.setParticipantsHash(ledgerMetadata.getParticipantsHash());

// 设置算法配置
ledgerInitSettings.setCryptoSetting(ledgerMetadata.getSetting().getCryptoSetting());
ledgerInitSettings.setCryptoSetting(ledgerAdminInfo.getSettings().getCryptoSetting());

// 设置种子
ledgerInitSettings.setSeed(initSeed(ledgerMetadata.getSeed()));

// 设置共识协议
ledgerInitSettings.setConsensusProtocol(ledgerMetadata.getSetting().getConsensusProvider());
ledgerInitSettings.setConsensusProtocol(ledgerAdminInfo.getSettings().getConsensusProvider());

return ledgerInitSettings;
}
@@ -129,14 +132,14 @@ public class GatewayQueryServiceHandler implements GatewayQueryService {
/**
* 初始化共识配置
*
* @param ledgerMetadata
* @param ledgerAdminInfo
* 账本元数据
* @return
*/
private ConsensusSettings initConsensusSettings(LedgerMetadata ledgerMetadata) {
String consensusProvider = ledgerMetadata.getSetting().getConsensusProvider();
private ConsensusSettings initConsensusSettings(LedgerAdminInfo ledgerAdminInfo) {
String consensusProvider = ledgerAdminInfo.getSettings().getConsensusProvider();
ConsensusProvider provider = ConsensusProviders.getProvider(consensusProvider);
byte[] consensusSettingsBytes = ledgerMetadata.getSetting().getConsensusSetting().toBytes();
byte[] consensusSettingsBytes = ledgerAdminInfo.getSettings().getConsensusSetting().toBytes();
return provider.getSettingsFactory().getConsensusSettingsEncoder().decode(consensusSettingsBytes);
}
}

+ 551
- 516
source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java
File diff suppressed because it is too large
View File


+ 1
- 0
source/gateway/src/main/java/com/jd/blockchain/gateway/web/GatewayWebServerConfigurer.java View File

@@ -35,6 +35,7 @@ public class GatewayWebServerConfigurer implements WebMvcConfigurer {
JSONSerializeUtils.disableCircularReferenceDetect();
JSONSerializeUtils.configStringSerializer(ByteArray.class);
DataContractRegistry.register(BftsmartNodeSettings.class);
DataContractRegistry.register(LedgerAdminInfo.class);
}




+ 3
- 7
source/gateway/src/main/java/com/jd/blockchain/gateway/web/TxProcessingController.java View File

@@ -1,6 +1,8 @@
package com.jd.blockchain.gateway.web;

import com.jd.blockchain.crypto.*;
import com.jd.blockchain.gateway.service.GatewayInterceptService;
import com.jd.blockchain.transaction.SignatureUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -9,9 +11,6 @@ import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.SignatureFunction;
import com.jd.blockchain.gateway.PeerService;
import com.jd.blockchain.ledger.DigitalSignature;
import com.jd.blockchain.ledger.TransactionContent;
@@ -60,11 +59,8 @@ public class TxProcessingController implements TransactionService {
throw new IllegalStateException("Not implemented!");
} else {
// 验证签名;
byte[] content = BinaryProtocol.encode(txRequest.getTransactionContent(), TransactionContent.class);
for (DigitalSignature sign : partiSigns) {
SignatureFunction signFunc = Crypto
.getSignatureFunction(sign.getPubKey().getAlgorithm());
if (!signFunc.verify(sign.getDigest(), sign.getPubKey(), content)) {
if (!SignatureUtils.verifySignature(txRequest.getTransactionContent(), sign.getDigest(), sign.getPubKey())) {
throw new BusinessException("The validation of participant signatures fail!");
}
}


+ 9
- 9
source/gateway/src/main/resources/log4j2.xml View File

@@ -8,17 +8,17 @@
<!--这个输出控制台的配置-->
<console name="Console" target="SYSTEM_OUT">
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY"/>
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
<!--输出日志的格式-->
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
</console>
<!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,适合临时测试用-->
<File name="log" fileName="../logs/test.log" append="false">
<File name="log" fileName="${sys:gateway.log}/logs/gateway.temp.log" append="false">
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
</File>
<!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
<RollingFile name="GatewayRollingInfo" fileName="../logs/gateway.out.info.log"
filePattern="../logs/$${date:yyyy-MM}/gateway.out.info-%d{yyyy-MM-dd}-%i.log">
<RollingFile name="GatewayRollingInfo" fileName="${sys:gateway.log}/logs/gateway.info.log"
filePattern="${sys:gateway.log}/logs/$${date:yyyy-MM}/gateway.info-%d{yyyy-MM-dd}-%i.log">
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
@@ -27,8 +27,8 @@
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
</RollingFile>
<RollingFile name="GatewayRollingWarn" fileName="../logs/gateway.out.warn.log"
filePattern="../logs/$${date:yyyy-MM}/gateway.out.warn-%d{yyyy-MM-dd}-%i.log">
<RollingFile name="GatewayRollingWarn" fileName="${sys:gateway.log}/logs/gateway.warn.log"
filePattern="${sys:gateway.log}/logs/$${date:yyyy-MM}/gateway.out.warn-%d{yyyy-MM-dd}-%i.log">
<ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
<Policies>
@@ -38,8 +38,8 @@
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了20 -->
<DefaultRolloverStrategy max="20"/>
</RollingFile>
<RollingFile name="GatewayRollingError" fileName="../logs/gateway.out.error.log"
filePattern="../logs/$${date:yyyy-MM}/gateway.out.error-%d{yyyy-MM-dd}-%i.log">
<RollingFile name="GatewayRollingError" fileName="${sys:gateway.log}/logs/gateway.error.log"
filePattern="${sys:gateway.log}/logs/$${date:yyyy-MM}/gateway.error-%d{yyyy-MM-dd}-%i.log">
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
<Policies>
@@ -51,7 +51,7 @@
<!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
<loggers>
<!--过滤掉spring的一些DEBUG信息-->
<logger name="org.springframework" level="INFO"></logger>
<logger name="org.springframework" level="INFO"/>
<root level="all">
<appender-ref ref="Console"/>
<appender-ref ref="GatewayRollingInfo"/>


+ 29
- 39
source/ledger/ledger-core/pom.xml View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.jd.blockchain</groupId>
<artifactId>ledger</artifactId>
<version>1.0.0.RELEASE</version>
<version>1.1.0-SNAPSHOT</version>
</parent>
<artifactId>ledger-core</artifactId>

@@ -68,7 +68,7 @@
<scope>test</scope>
</dependency>

</dependencies>
</dependencies>

<build>
<plugins>
@@ -83,42 +83,32 @@
</plugins>
</build>

<!--<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.5</version>
<configuration>
<excludes>
<exclude>**/TransactionBatchProcessorTest.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>-->
<!--<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <version>2.5</version> <configuration>
<excludes> <exclude>**/TransactionBatchProcessorTest.java</exclude> </excludes>
</configuration> </plugin> </plugins> </build> -->

<!--<build>-->
<!--<plugins>-->
<!--<plugin>-->
<!--<groupId>org.apache.maven.plugins</groupId>-->
<!--<artifactId>maven-compiler-plugin</artifactId>-->
<!--<version>3.1</version>-->
<!--<configuration>-->
<!--<source>1.8</source>-->
<!--<target>1.8</target>-->
<!--<encoding>UTF-8</encoding>-->
<!--<compilerArgs>-->
<!--&lt;!&ndash;<arg>-verbose</arg>&ndash;&gt;-->
<!--&lt;!&ndash;<arg>-Xlint:unchecked</arg>&ndash;&gt;-->
<!--&lt;!&ndash;<arg>-Xlint:deprecation</arg>&ndash;&gt;-->
<!--&lt;!&ndash;<arg>-bootclasspath</arg>&ndash;&gt;-->
<!--&lt;!&ndash;<arg>${env.JAVA_HOME}/jre/lib/rt.jar</arg>&ndash;&gt;-->
<!--<arg>-extdirs</arg>-->
<!--<arg>${project.basedir}/../contract/contract-libs;$JAVA_HOME/jre/lib/ext</arg>-->
<!--</compilerArgs>-->
<!--</configuration>-->
<!--</plugin>-->
<!--</plugins>-->
<!--</build>-->
<!--<build> -->
<!--<plugins> -->
<!--<plugin> -->
<!--<groupId>org.apache.maven.plugins</groupId> -->
<!--<artifactId>maven-compiler-plugin</artifactId> -->
<!--<version>3.1</version> -->
<!--<configuration> -->
<!--<source>1.8</source> -->
<!--<target>1.8</target> -->
<!--<encoding>UTF-8</encoding> -->
<!--<compilerArgs> -->
<!--&lt;!&ndash;<arg>-verbose</arg>&ndash;&gt; -->
<!--&lt;!&ndash;<arg>-Xlint:unchecked</arg>&ndash;&gt; -->
<!--&lt;!&ndash;<arg>-Xlint:deprecation</arg>&ndash;&gt; -->
<!--&lt;!&ndash;<arg>-bootclasspath</arg>&ndash;&gt; -->
<!--&lt;!&ndash;<arg>${env.JAVA_HOME}/jre/lib/rt.jar</arg>&ndash;&gt; -->
<!--<arg>-extdirs</arg> -->
<!--<arg>${project.basedir}/../contract/contract-libs;$JAVA_HOME/jre/lib/ext</arg> -->
<!--</compilerArgs> -->
<!--</configuration> -->
<!--</plugin> -->
<!--</plugins> -->
<!--</build> -->
</project>

+ 0
- 26
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountPrivilege.java View File

@@ -1,26 +0,0 @@
package com.jd.blockchain.ledger.core;

public interface AccountPrivilege {

/**
* 数据“读”的操作码;
*
* @return
*/
byte getReadingOpCode();

/**
* “写”的操作码;
*
* @return
*/
byte getWrittingOpCode();

/**
* 其它的扩展操作码;
*
* @return
*/
byte[] getExtOpCodes();

}

+ 7
- 6
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountSet.java View File

@@ -12,6 +12,7 @@ import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes;
@@ -48,6 +49,10 @@ public class AccountSet implements Transactional, MerkleProvable {
public boolean isReadonly() {
return merkleDataset.isReadonly();
}
void setReadonly() {
merkleDataset.setReadonly();
}
public AccountSet(CryptoSetting cryptoSetting, String keyPrefix, ExPolicyKVStorage exStorage,
VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy) {
@@ -65,10 +70,6 @@ public class AccountSet implements Transactional, MerkleProvable {
this.accessPolicy = accessPolicy;
}
// public HashDigest getAccountRootHash() {
// return merkleDataset.getRootHash();
// }
@Override
public HashDigest getRootHash() {
return merkleDataset.getRootHash();
@@ -333,9 +334,9 @@ public class AccountSet implements Transactional, MerkleProvable {
if (!updated) {
return;
}
String[] addresses = new String[latestAccountsCache.size()];
Bytes[] addresses = new Bytes[latestAccountsCache.size()];
latestAccountsCache.keySet().toArray(addresses);
for (String address : addresses) {
for (Bytes address : addresses) {
VersioningAccount acc = latestAccountsCache.remove(address);
// cancel;
if (acc.isUpdated()) {


+ 0
- 168
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AuthorizableDataSet.java View File

@@ -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();
// }
//
//}

+ 0
- 40
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Authorization.java View File

@@ -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();

/**
* 授权码;<br>
*
* @return
*/
byte[] getCode();

/**
* 授权者的签名;
*
* @return
*/
DigitalSignature getSignature();

// /**
// * 授权生成的时间戳;
// * @return
// */
// long getTs();

}

+ 0
- 42
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AuthorizationVO.java View File

@@ -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;
}
}

+ 4
- 3
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/BaseAccount.java View File

@@ -8,6 +8,7 @@ import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.BlockchainIdentityData;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes;
@@ -64,13 +65,13 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional

/**
* Create a account instance with the specified address and pubkey and load it's
* merkle dataset with the specified root hash. which is used for storing data
* merkle dataset from the specified root hash. This merkle dateset is used for storing data
* of this account.<br>
*
* @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


+ 0
- 21
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Consensus.java View File

@@ -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 {
}
}

+ 2
- 2
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java View File

@@ -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 {


+ 29
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccountQuery.java View File

@@ -0,0 +1,29 @@
package com.jd.blockchain.ledger.core;

import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.utils.Bytes;

public interface ContractAccountQuery {

AccountHeader[] getAccounts(int fromIndex, int count);

HashDigest getRootHash();

/**
* 返回合约总数;
*
* @return
*/
long getTotalCount();

MerkleProof getProof(Bytes address);

boolean contains(Bytes address);

ContractAccount getContract(Bytes address);

ContractAccount getContract(Bytes address, long version);

}

+ 11
- 1
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccountSet.java View File

@@ -5,12 +5,13 @@ import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.DigitalSignature;
import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.Transactional;
public class ContractAccountSet implements MerkleProvable, Transactional {
public class ContractAccountSet implements MerkleProvable, Transactional, ContractAccountQuery {
private AccountSet accountSet;
@@ -25,6 +26,7 @@ public class ContractAccountSet implements MerkleProvable, Transactional {
accountSet = new AccountSet(dataRootHash, cryptoSetting, prefix, exStorage, verStorage, readonly, accessPolicy);
}
@Override
public AccountHeader[] getAccounts(int fromIndex, int count) {
return accountSet.getAccounts(fromIndex,count);
}
@@ -33,6 +35,10 @@ public class ContractAccountSet implements MerkleProvable, Transactional {
return accountSet.isReadonly();
}
void setReadonly() {
accountSet.setReadonly();
}
@Override
public HashDigest getRootHash() {
return accountSet.getRootHash();
@@ -43,6 +49,7 @@ public class ContractAccountSet implements MerkleProvable, Transactional {
*
* @return
*/
@Override
public long getTotalCount() {
return accountSet.getTotalCount();
}
@@ -52,15 +59,18 @@ public class ContractAccountSet implements MerkleProvable, Transactional {
return accountSet.getProof(address);
}
@Override
public boolean contains(Bytes address) {
return accountSet.contains(address);
}
@Override
public ContractAccount getContract(Bytes address) {
BaseAccount accBase = accountSet.getAccount(address);
return new ContractAccount(accBase);
}
@Override
public ContractAccount getContract(Bytes address, long version) {
BaseAccount accBase = accountSet.getAccount(address, version);
return new ContractAccount(accBase);


+ 1
- 1
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/CryptoConfig.java View File

@@ -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;
}


+ 95
- 3
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java View File

@@ -1,14 +1,14 @@
package com.jd.blockchain.ledger.core;
import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.BytesData;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.KVDataEntry;
import com.jd.blockchain.ledger.KVDataObject;
import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.utils.Bytes;
public class DataAccount implements AccountHeader, MerkleProvable {
@@ -43,16 +43,85 @@ public class DataAccount implements AccountHeader, MerkleProvable {
}
/**
* Create or update the value associated the specified key if the version
* checking is passed.<br>
*
* The value of the key will be updated only if it's latest version equals the
* specified version argument. <br>
* If the key doesn't exist, the version checking will be ignored, and key will
* be created with a new sequence number as id. <br>
* It also could specify the version argument to -1 to ignore the version
* checking.
* <p>
* If updating is performed, the version of the key increase by 1. <br>
* If creating is performed, the version of the key initialize by 0. <br>
*
* @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. <br>
* If the key is new created success, then return 0; <br>
* If the key is updated success, then return the new version;<br>
* 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.<br>
*
* The value of the key will be updated only if it's latest version equals the
* specified version argument. <br>
* If the key doesn't exist, the version checking will be ignored, and key will
* be created with a new sequence number as id. <br>
* It also could specify the version argument to -1 to ignore the version
* checking.
* <p>
* If updating is performed, the version of the key increase by 1. <br>
* If creating is performed, the version of the key initialize by 0. <br>
*
* @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. <br>
* If the key is new created success, then return 0; <br>
* If the key is updated success, then return the new version;<br>
* 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.<br>
*
* The value of the key will be updated only if it's latest version equals the
* specified version argument. <br>
* If the key doesn't exist, the version checking will be ignored, and key will
* be created with a new sequence number as id. <br>
* It also could specify the version argument to -1 to ignore the version
* checking.
* <p>
* If updating is performed, the version of the key increase by 1. <br>
* If creating is performed, the version of the key initialize by 0. <br>
*
* @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. <br>
* If the key is new created success, then return 0; <br>
* If the key is updated success, then return the new version;<br>
* If this operation fail by version checking or other reason, then
* return -1;
*/
public long setBytes(Bytes key, byte[] value, long version) {
BytesValue bytesValue = BytesData.fromBytes(value);
return baseAccount.setBytes(key, bytesValue, version);
@@ -121,6 +190,29 @@ public class DataAccount implements AccountHeader, MerkleProvable {
public BytesValue getBytes(Bytes key, long version) {
return baseAccount.getBytes(key, version);
}
/**
* @param key
* @param version
* @return
*/
public KVDataEntry getDataEntry(String key, long version) {
return getDataEntry(Bytes.fromString(key), version);
}
/**
* @param key
* @param version
* @return
*/
public KVDataEntry getDataEntry(Bytes key, long version) {
BytesValue value = baseAccount.getBytes(key, version);
if (value == null) {
return new KVDataObject(key.toUTF8String(), -1, null);
}else {
return new KVDataObject(key.toUTF8String(), version, value);
}
}
/**
* return the specified index's KVDataEntry;
@@ -131,7 +223,7 @@ public class DataAccount implements AccountHeader, MerkleProvable {
*/
public KVDataEntry[] getDataEntries(int fromIndex, int count) {
if (getDataEntriesTotalCount() == 0 || count == 0) {
if (count == 0 || getDataEntriesTotalCount() == 0) {
return null;
}


+ 32
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountQuery.java View File

@@ -0,0 +1,32 @@
package com.jd.blockchain.ledger.core;

import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.utils.Bytes;

public interface DataAccountQuery {

AccountHeader[] getAccounts(int fromIndex, int count);

HashDigest getRootHash();

long getTotalCount();

/**
* 返回账户的存在性证明;
*/
MerkleProof getProof(Bytes address);

/**
* 返回数据账户; <br>
* 如果不存在,则返回 null;
*
* @param address
* @return
*/
DataAccount getDataAccount(Bytes address);

DataAccount getDataAccount(Bytes address, long version);

}

+ 23
- 4
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountSet.java View File

@@ -5,18 +5,19 @@ import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.DigitalSignature;
import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.Transactional;
public class DataAccountSet implements MerkleProvable, Transactional {
public class DataAccountSet implements MerkleProvable, Transactional, DataAccountQuery {
private AccountSet accountSet;
public DataAccountSet(CryptoSetting cryptoSetting, String prefix,ExPolicyKVStorage exStorage,
public DataAccountSet(CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exStorage,
VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy) {
accountSet = new AccountSet(cryptoSetting,prefix, exStorage, verStorage, accessPolicy);
accountSet = new AccountSet(cryptoSetting, prefix, exStorage, verStorage, accessPolicy);
}
public DataAccountSet(HashDigest dataRootHash, CryptoSetting cryptoSetting, String prefix,
@@ -25,19 +26,25 @@ public class DataAccountSet implements MerkleProvable, Transactional {
accountSet = new AccountSet(dataRootHash, cryptoSetting, prefix, exStorage, verStorage, readonly, accessPolicy);
}
@Override
public AccountHeader[] getAccounts(int fromIndex, int count) {
return accountSet.getAccounts(fromIndex,count);
return accountSet.getAccounts(fromIndex, count);
}
public boolean isReadonly() {
return accountSet.isReadonly();
}
void setReadonly() {
accountSet.setReadonly();
}
@Override
public HashDigest getRootHash() {
return accountSet.getRootHash();
}
@Override
public long getTotalCount() {
return accountSet.getTotalCount();
}
@@ -56,11 +63,23 @@ public class DataAccountSet implements MerkleProvable, Transactional {
return new DataAccount(accBase);
}
/**
* 返回数据账户; <br>
* 如果不存在,则返回 null;
*
* @param address
* @return
*/
@Override
public DataAccount getDataAccount(Bytes address) {
BaseAccount accBase = accountSet.getAccount(address);
if (accBase == null) {
return null;
}
return new DataAccount(accBase);
}
@Override
public DataAccount getDataAccount(Bytes address, long version) {
BaseAccount accBase = accountSet.getAccount(address, version);
return new DataAccount(accBase);


+ 132
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DefaultOperationHandleRegisteration.java View File

@@ -0,0 +1,132 @@
package com.jd.blockchain.ledger.core;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.stereotype.Component;

import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.ledger.core.handles.ContractCodeDeployOperationHandle;
import com.jd.blockchain.ledger.core.handles.DataAccountKVSetOperationHandle;
import com.jd.blockchain.ledger.core.handles.DataAccountRegisterOperationHandle;
import com.jd.blockchain.ledger.core.handles.JVMContractEventSendOperationHandle;
import com.jd.blockchain.ledger.core.handles.LedgerInitOperationHandle;
import com.jd.blockchain.ledger.core.handles.RolesConfigureOperationHandle;
import com.jd.blockchain.ledger.core.handles.UserAuthorizeOperationHandle;
import com.jd.blockchain.ledger.core.handles.UserRegisterOperationHandle;
import com.jd.blockchain.transaction.ContractCodeDeployOpTemplate;
import com.jd.blockchain.transaction.ContractEventSendOpTemplate;
import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate;
import com.jd.blockchain.transaction.DataAccountRegisterOpTemplate;
import com.jd.blockchain.transaction.LedgerInitOpTemplate;
import com.jd.blockchain.transaction.RolesConfigureOpTemplate;
import com.jd.blockchain.transaction.UserAuthorizeOpTemplate;
import com.jd.blockchain.transaction.UserRegisterOpTemplate;

@Component
public class DefaultOperationHandleRegisteration implements OperationHandleRegisteration {

private static Map<Class<?>, OperationHandle> DEFAULT_HANDLES = new HashMap<>();

private Map<Class<?>, OperationHandle> handles = new ConcurrentHashMap<>();

static {
registerDefaultHandle(new LedgerInitOperationHandle());

registerDefaultHandle(new RolesConfigureOperationHandle());

registerDefaultHandle(new UserAuthorizeOperationHandle());

registerDefaultHandle(new UserRegisterOperationHandle());

registerDefaultHandle(new DataAccountKVSetOperationHandle());

registerDefaultHandle(new DataAccountRegisterOperationHandle());

registerDefaultHandle(new ContractCodeDeployOperationHandle());

registerDefaultHandle(new JVMContractEventSendOperationHandle());
}

private static void registerDefaultHandle(OperationHandle handle) {
DEFAULT_HANDLES.put(handle.getOperationType(), handle);
}

/**
* 注册操作处理器;此方法将覆盖默认的操作处理器配置;
*
* @param handle
*/
public void registerHandle(OperationHandle handle) {
List<Class<?>> opTypes = new ArrayList<Class<?>>();
for (Class<?> opType : handles.keySet()) {
if (opType.isAssignableFrom(handle.getOperationType())) {
opTypes.add(opType);
}
}

for (Class<?> opType : opTypes) {
handles.put(opType, handle);
}
handles.put(handle.getOperationType(), handle);
}

private OperationHandle getRegisteredHandle(Class<?> operationType) {
OperationHandle hdl = handles.get(operationType);
if (hdl == null) {
hdl = DEFAULT_HANDLES.get(operationType);
//按“操作类型”的继承关系匹配;
if (hdl == null) {
for (Class<?> opType : handles.keySet()) {
if (opType.isAssignableFrom(operationType)) {
hdl = handles.get(opType);
break;
}
}
}
if (hdl == null) {
for (Class<?> opType : DEFAULT_HANDLES.keySet()) {
if (opType.isAssignableFrom(operationType)) {
hdl = DEFAULT_HANDLES.get(opType);
break;
}
}
}
if (hdl != null) {
handles.put(operationType, hdl);
}
}
return hdl;
}

/*
* (non-Javadoc)
*
* @see
* com.jd.blockchain.ledger.core.impl.OperationHandleRegisteration#getHandle(
* java.lang.Class)
*/
@Override
public OperationHandle getHandle(Class<? extends Operation> operationType) {
OperationHandle hdl = getRegisteredHandle(operationType);
if (hdl == null) {
throw new LedgerException("Unsupported operation type[" + operationType.getName() + "]!");
}
return hdl;
}

private static class OpHandleStub {

private Class<? extends Operation> operationType;

private OperationHandle operationHandle;

}
}

+ 209
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/EmptyLedgerDataset.java View File

@@ -0,0 +1,209 @@
package com.jd.blockchain.ledger.core;

import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.LedgerAdminInfo;
import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.ledger.ParticipantDataQuery;
import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.utils.Bytes;

public class EmptyLedgerDataset implements LedgerDataQuery {
private static final LedgerAdminDataQuery EMPTY_ADMIN_DATA = new EmptyAdminData();
private static final UserAccountQuery EMPTY_USER_ACCOUNTS = new EmptyUserAccountSet();
private static final DataAccountQuery EMPTY_DATA_ACCOUNTS = new EmptyDataAccountSet();
private static final ContractAccountQuery EMPTY_CONTRACT_ACCOUNTS = new EmptyContractAccountSet();

private static final ParticipantDataQuery EMPTY_PARTICIPANTS = new EmptyParticipantData();

@Override
public LedgerAdminDataQuery getAdminDataset() {
return EMPTY_ADMIN_DATA;
}

@Override
public UserAccountQuery getUserAccountSet() {
return EMPTY_USER_ACCOUNTS;
}

@Override
public DataAccountQuery getDataAccountSet() {
return EMPTY_DATA_ACCOUNTS;
}

@Override
public ContractAccountQuery getContractAccountset() {
return EMPTY_CONTRACT_ACCOUNTS;
}


private static class EmptyAdminData implements LedgerAdminDataQuery{

@Override
public LedgerAdminInfo getAdminInfo() {
return null;
}

@Override
public ParticipantDataQuery getParticipantDataset() {
return EMPTY_PARTICIPANTS;
}
}
private static class EmptyParticipantData implements ParticipantDataQuery{

@Override
public HashDigest getRootHash() {
return null;
}

@Override
public MerkleProof getProof(Bytes key) {
return null;
}

@Override
public long getParticipantCount() {
return 0;
}

@Override
public boolean contains(Bytes address) {
return false;
}

@Override
public ParticipantNode getParticipant(Bytes address) {
return null;
}

@Override
public ParticipantNode[] getParticipants() {
return null;
}
}
private static class EmptyUserAccountSet implements UserAccountQuery{

@Override
public AccountHeader[] getAccounts(int fromIndex, int count) {
return null;
}

@Override
public long getTotalCount() {
return 0;
}

@Override
public HashDigest getRootHash() {
return null;
}

@Override
public MerkleProof getProof(Bytes key) {
return null;
}

@Override
public UserAccount getUser(String address) {
return null;
}

@Override
public UserAccount getUser(Bytes address) {
return null;
}

@Override
public boolean contains(Bytes address) {
return false;
}

@Override
public UserAccount getUser(Bytes address, long version) {
return null;
}
}
private static class EmptyDataAccountSet implements DataAccountQuery{

@Override
public AccountHeader[] getAccounts(int fromIndex, int count) {
return null;
}

@Override
public HashDigest getRootHash() {
return null;
}

@Override
public long getTotalCount() {
return 0;
}

@Override
public MerkleProof getProof(Bytes address) {
return null;
}

@Override
public DataAccount getDataAccount(Bytes address) {
return null;
}

@Override
public DataAccount getDataAccount(Bytes address, long version) {
return null;
}
}

private static class EmptyContractAccountSet implements ContractAccountQuery{

@Override
public AccountHeader[] getAccounts(int fromIndex, int count) {
return null;
}

@Override
public HashDigest getRootHash() {
return null;
}

@Override
public long getTotalCount() {
return 0;
}

@Override
public MerkleProof getProof(Bytes address) {
return null;
}

@Override
public boolean contains(Bytes address) {
return false;
}

@Override
public ContractAccount getContract(Bytes address) {
return null;
}

@Override
public ContractAccount getContract(Bytes address, long version) {
return null;
}
}
}

+ 98
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/FullPermissionedSecurityManager.java View File

@@ -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<Bytes> endpoints, Set<Bytes> nodes) {
return new FullPermissionedPolicy(endpoints, nodes);
}

private static class FullPermissionedPolicy implements SecurityPolicy {

private Set<Bytes> endpoints;
private Set<Bytes> nodes;

public FullPermissionedPolicy(Set<Bytes> endpoints, Set<Bytes> nodes) {
this.endpoints = endpoints;
this.nodes = nodes;
}

@Override
public Set<Bytes> getEndpoints() {
return endpoints;
}

@Override
public Set<Bytes> 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 {
}

}

}

+ 0
- 22
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Gateway.java View File

@@ -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();
}
}

source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/GenesisLedgerStorageProxy.java → source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/GenesisLedgerStorageProxy.java View File

@@ -1,3 +1,4 @@
package com.jd.blockchain.ledger.core;
//package com.jd.blockchain.ledger.core.impl;
//
//import com.jd.blockchain.storage.service.ExPolicyKVStorage;

+ 0
- 356
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminAccount.java View File

@@ -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;
/**
* 原来的账本设置;
*
* <br>
* 对 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;
}
/**
* 初始化账本的管理账户;
*
* <br>
*
* 只在新建账本时调用此方法;
*
* @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;
}
/**
* 返回原来的账本配置;
*
* <br>
* 此方法总是返回从上一个区块加载的账本配置,即时调用 {@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;
}
}
}

+ 12
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminDataQuery.java View File

@@ -0,0 +1,12 @@
package com.jd.blockchain.ledger.core;

import com.jd.blockchain.ledger.LedgerAdminInfo;
import com.jd.blockchain.ledger.ParticipantDataQuery;

public interface LedgerAdminDataQuery {
LedgerAdminInfo getAdminInfo();

ParticipantDataQuery getParticipantDataset();

}

+ 469
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminDataset.java View File

@@ -0,0 +1,469 @@
package com.jd.blockchain.ledger.core;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.HashFunction;
import com.jd.blockchain.ledger.LedgerAdminInfo;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.LedgerInitSetting;
import com.jd.blockchain.ledger.LedgerMetadata;
import com.jd.blockchain.ledger.LedgerMetadata_V2;
import com.jd.blockchain.ledger.LedgerSettings;
import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.ledger.RolePrivilegeSettings;
import com.jd.blockchain.ledger.UserRolesSettings;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.Transactional;
public class LedgerAdminDataset implements Transactional, LedgerAdminDataQuery, LedgerAdminInfo {
static {
DataContractRegistry.register(LedgerMetadata.class);
DataContractRegistry.register(LedgerMetadata_V2.class);
}
private static Logger LOGGER = LoggerFactory.getLogger(LedgerAdminDataset.class);
public static final String LEDGER_META_PREFIX = "MTA" + LedgerConsts.KEY_SEPERATOR;
public static final String LEDGER_PARTICIPANT_PREFIX = "PAR" + LedgerConsts.KEY_SEPERATOR;
public static final String LEDGER_SETTING_PREFIX = "SET" + LedgerConsts.KEY_SEPERATOR;
public static final String ROLE_PRIVILEGE_PREFIX = "RPV" + LedgerConsts.KEY_SEPERATOR;
public static final String USER_ROLE_PREFIX = "URO" + LedgerConsts.KEY_SEPERATOR;
private final Bytes metaPrefix;
private final Bytes settingPrefix;
private LedgerMetadata_V2 origMetadata;
private LedgerMetadataInfo metadata;
/**
* 原来的账本设置;
*
* <br>
* 对 LedgerMetadata 修改的新配置不能立即生效,需要达成共识后,在下一次区块计算中才生效;
*/
private LedgerSettings previousSettings;
private HashDigest previousSettingHash;
/**
* 账本的参与节点;
*/
private ParticipantDataset participants;
/**
* “角色-权限”数据集;
*/
private RolePrivilegeDataset rolePrivileges;
/**
* “用户-角色”数据集;
*/
private UserRoleDataset userRoles;
/**
* 账本参数配置;
*/
private LedgerSettings settings;
private ExPolicyKVStorage storage;
private HashDigest adminDataHash;
private boolean readonly;
private boolean updated;
public HashDigest getHash() {
return adminDataHash;
}
public boolean isReadonly() {
return readonly;
}
void setReadonly() {
this.readonly = true;
}
public LedgerSettings getPreviousSetting() {
return previousSettings;
}
@Override
public RolePrivilegeSettings getRolePrivileges() {
return rolePrivileges;
}
@Override
public UserRolesSettings getUserRoles() {
return userRoles;
}
@Override
public LedgerAdminInfo getAdminInfo() {
return this;
}
/**
* 初始化账本的管理账户;
*
* <br>
*
* 只在新建账本时调用此方法;
*
* @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;
}
// /**
// * 返回原来的账本配置;
// *
// * <br>
// * 此方法总是返回从上一个区块加载的账本配置,即时调用 {@link #setLedgerSetting(LedgerSettings)} 做出了新的更改;
// *
// * @return
// */
// public LedgerSettings getPreviousSetting() {
// return previousSettings;
// }
/**
* 返回当前设置的账本配置;
*
* @return
*/
public LedgerSettings getSettings() {
return settings;
}
/**
* 更新账本配置;
*
* @param ledgerSetting
*/
public void setLedgerSetting(LedgerSettings ledgerSetting) {
if (readonly) {
throw new IllegalArgumentException("This merkle dataset is readonly!");
}
settings = ledgerSetting;
updated = true;
}
@Override
public long getParticipantCount() {
return participants.getParticipantCount();
}
@Override
public ParticipantNode[] getParticipants() {
return participants.getParticipants();
}
@Override
public ParticipantDataset getParticipantDataset() {
return participants;
}
/**
* 加入新的参与方; 如果指定的参与方已经存在,则引发 LedgerException 异常;
*
* @param participant
*/
public void addParticipant(ParticipantNode participant) {
participants.addConsensusParticipant(participant);
}
@Override
public boolean isUpdated() {
return updated || participants.isUpdated() || rolePrivileges.isUpdated() || userRoles.isUpdated();
}
@Override
public void commit() {
if (!isUpdated()) {
return;
}
// 计算并更新参与方集合的根哈希;
participants.commit();
metadata.setParticipantsHash(participants.getRootHash());
// 计算并更新角色权限集合的根哈希;
rolePrivileges.commit();
metadata.setRolePrivilegesHash(rolePrivileges.getRootHash());
// 计算并更新用户角色授权集合的根哈希;
userRoles.commit();
metadata.setUserRolesHash(userRoles.getRootHash());
// 当前区块上下文的密码参数设置的哈希函数;
HashFunction hashFunc = Crypto.getHashFunction(previousSettings.getCryptoSetting().getHashAlgorithm());
// 计算并更新参数配置的哈希;
if (settings == null) {
throw new LedgerException("Missing ledger settings!");
}
byte[] settingsBytes = serializeSetting(settings);
HashDigest settingsHash = hashFunc.hash(settingsBytes);
metadata.setSettingsHash(settingsHash);
if (previousSettingHash == null || !previousSettingHash.equals(settingsHash)) {
Bytes settingsKey = encodeSettingsKey(settingsHash);
boolean nx = storage.set(settingsKey, settingsBytes, ExPolicy.NOT_EXISTING);
if (!nx) {
String base58MetadataHash = settingsHash.toBase58();
// 有可能发生了并发写入冲突,不同的节点都向同一个存储服务器上写入数据;
String errMsg = "Ledger metadata already exist! --[MetadataHash=" + base58MetadataHash + "]";
LOGGER.warn(errMsg);
throw new LedgerException(errMsg);
}
}
// 基于之前的密码配置来计算元数据的哈希;
byte[] metadataBytes = serializeMetadata(metadata);
HashDigest metadataHash = hashFunc.hash(metadataBytes);
if (adminDataHash == null || !adminDataHash.equals(metadataHash)) {
// update modify;
// String base58MetadataHash = metadataHash.toBase58();
// String metadataKey = encodeMetadataKey(base58MetadataHash);
Bytes metadataKey = encodeMetadataKey(metadataHash);
boolean nx = storage.set(metadataKey, metadataBytes, ExPolicy.NOT_EXISTING);
if (!nx) {
String base58MetadataHash = metadataHash.toBase58();
// 有可能发生了并发写入冲突,不同的节点都向同一个存储服务器上写入数据;
String errMsg = "Ledger metadata already exist! --[MetadataHash=" + base58MetadataHash + "]";
LOGGER.warn(errMsg);
throw new LedgerException(errMsg);
}
adminDataHash = metadataHash;
}
updated = false;
}
private LedgerMetadata_V2 deserializeMetadata(byte[] bytes) {
return BinaryProtocol.decode(bytes);
}
private byte[] serializeMetadata(LedgerMetadataInfo config) {
return BinaryProtocol.encode(config, LedgerMetadata_V2.class);
}
@Override
public void cancel() {
if (!isUpdated()) {
return;
}
participants.cancel();
metadata =origMetadata == null ? new LedgerMetadataInfo() : new LedgerMetadataInfo(origMetadata);
}
public static class LedgerMetadataInfo implements LedgerMetadata_V2 {
private byte[] seed;
// private LedgerSetting setting;
private HashDigest participantsHash;
private HashDigest settingsHash;
private HashDigest rolePrivilegesHash;
private HashDigest userRolesHash;
public LedgerMetadataInfo() {
}
public LedgerMetadataInfo(LedgerMetadata_V2 metadata) {
this.seed = metadata.getSeed();
this.participantsHash = metadata.getParticipantsHash();
this.settingsHash = metadata.getSettingsHash();
this.rolePrivilegesHash = metadata.getRolePrivilegesHash();
this.userRolesHash = metadata.getUserRolesHash();
}
@Override
public byte[] getSeed() {
return seed;
}
@Override
public HashDigest getSettingsHash() {
return settingsHash;
}
@Override
public HashDigest getParticipantsHash() {
return participantsHash;
}
@Override
public HashDigest getRolePrivilegesHash() {
return rolePrivilegesHash;
}
@Override
public HashDigest getUserRolesHash() {
return userRolesHash;
}
public void setSeed(byte[] seed) {
this.seed = seed;
}
public void setSettingsHash(HashDigest settingHash) {
this.settingsHash = settingHash;
}
public void setParticipantsHash(HashDigest participantsHash) {
this.participantsHash = participantsHash;
}
public void setRolePrivilegesHash(HashDigest rolePrivilegesHash) {
this.rolePrivilegesHash = rolePrivilegesHash;
}
public void setUserRolesHash(HashDigest userRolesHash) {
this.userRolesHash = userRolesHash;
}
}
}

+ 0
- 5
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminPrivilege.java View File

@@ -1,5 +0,0 @@
package com.jd.blockchain.ledger.core;

public enum LedgerAdminPrivilege {

}

+ 0
- 16
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdministration.java View File

@@ -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();
}

source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerBlockData.java → source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerBlockData.java View File

@@ -1,4 +1,4 @@
package com.jd.blockchain.ledger.core.impl;
package com.jd.blockchain.ledger.core;

import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.HashDigest;
@@ -33,7 +33,9 @@ public class LedgerBlockData implements LedgerBlock {
// private HashDigest contractPrivilegeHash;

private HashDigest transactionSetHash;

private long timestamp;
public LedgerBlockData() {
}

@@ -155,4 +157,14 @@ public class LedgerBlockData implements LedgerBlock {
this.ledgerHash = ledgerHash;
}

public long getTimestamp() {
return timestamp;
}

public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}

}

+ 3
- 3
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerConfiguration.java View File

@@ -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();


+ 19
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerDataQuery.java View File

@@ -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();

}

+ 0
- 21
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerDataSet.java View File

@@ -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();

}

source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerDataSetImpl.java → source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerDataset.java View File

@@ -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();
}

}

+ 37
- 4
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerEditor.java View File

@@ -1,5 +1,6 @@
package com.jd.blockchain.ledger.core;

import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.LedgerTransaction;
@@ -10,7 +11,7 @@ import com.jd.blockchain.ledger.TransactionRequest;
* <p>
*
* {@link LedgerEditor} 以上一个区块作为数据编辑的起点; <br>
* 对账本数据({@link #getDataSet()})的批量更改可以作为一个交易({@link LedgerTransaction})整体提交暂存,形成暂存点;
* 对账本数据({@link #getDataset()})的批量更改可以作为一个交易({@link LedgerTransaction})整体提交暂存,形成暂存点;
* <br>
*
* @author huanghaiquan
@@ -18,11 +19,39 @@ import com.jd.blockchain.ledger.TransactionRequest;
*/
public interface LedgerEditor {

/**
* 账本Hash;
*
* @return
*/
HashDigest getLedgerHash();

/**
* 新区块的高度;
*
* @return
*/
long getBlockHeight();

/**
* 最新的账本数据集;
*
* @return
*/
LedgerDataset getLedgerDataset();

/**
* 最新的交易集合;
*
* @return
*/
TransactionSet getTransactionSet();

/**
* 开始新事务;<br>
*
* 方法返回之前,将会校验交易请求的用户签名列表和节点签名列表,并在后续对数据集
* {@link LedgerTransactionContext#getDataSet()} 的操作时,校验这些用户和节点是否具备权限;<br>
* {@link LedgerTransactionContext#getDataset()} 的操作时,校验这些用户和节点是否具备权限;<br>
*
* 校验失败将引发异常 {@link LedgerException};
* <p>
@@ -32,11 +61,15 @@ public interface LedgerEditor {
* 或者全部回滚(通过方法 {@link LedgerTransactionContext#rollback()}),以此实现原子性写入;
* <p>
*
* 每一次事务性的账本写入操作在提交后,都会记录该事务相关的系统全局快照,以交易对象 {@link LedgerTransaction} 进行保存;<p>
* 每一次事务性的账本写入操作在提交后,都会记录该事务相关的系统全局快照,以交易对象 {@link LedgerTransaction} 进行保存;
* <p>
*
*
*
* 注:方法不解析、不执行交易中的操作;
* <p>
*
* @param txRequest
* @param txRequest 交易请求;
* @return
*/
LedgerTransactionContext newTransaction(TransactionRequest txRequest);


source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitPermission.java → source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitProposal.java View File

@@ -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;

source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitPermissionData.java → source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitProposalData.java View File

@@ -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;
}

+ 215
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitializer.java View File

@@ -0,0 +1,215 @@
package com.jd.blockchain.ledger.core;

import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PrivKey;
import com.jd.blockchain.crypto.SignatureDigest;
import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.BlockchainIdentityData;
import com.jd.blockchain.ledger.DigitalSignature;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerInitException;
import com.jd.blockchain.ledger.LedgerInitOperation;
import com.jd.blockchain.ledger.LedgerInitSetting;
import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.ledger.RoleInitSettings;
import com.jd.blockchain.ledger.RolesConfigureOperation;
import com.jd.blockchain.ledger.SecurityInitSettings;
import com.jd.blockchain.ledger.TransactionBuilder;
import com.jd.blockchain.ledger.TransactionContent;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.ledger.UserAuthInitSettings;
import com.jd.blockchain.ledger.UserAuthorizeOperation;
import com.jd.blockchain.ledger.UserRegisterOperation;
import com.jd.blockchain.service.TransactionBatchResultHandle;
import com.jd.blockchain.storage.service.KVStorageService;
import com.jd.blockchain.transaction.SignatureUtils;
import com.jd.blockchain.transaction.TxBuilder;
import com.jd.blockchain.transaction.TxRequestBuilder;

public class LedgerInitializer {

private static final FullPermissionedSecurityManager FULL_PERMISSION_SECURITY_MANAGER = new FullPermissionedSecurityManager();

private static final LedgerDataQuery EMPTY_LEDGER_DATA_QUERY = new EmptyLedgerDataset();

private static final OperationHandleRegisteration DEFAULT_OP_HANDLE_REG = new DefaultOperationHandleRegisteration();

private LedgerService EMPTY_LEDGERS = new LedgerManager();

private LedgerInitSetting initSetting;

private TransactionContent initTxContent;

private volatile LedgerBlock genesisBlock;

private volatile LedgerEditor ledgerEditor;

private volatile boolean committed = false;

private volatile boolean canceled = false;

private TransactionBatchResultHandle txResultsHandle;

/**
* 初始化生成的账本hash; <br>
*
* 在成功执行 {@link #prepareLedger(KVStorageService, DigitalSignature...)} 之前总是返回
* null;
*
* @return
*/
public HashDigest getLedgerHash() {
return genesisBlock == null ? null : genesisBlock.getHash();
}

/**
* @param initSetting
* @param initTxContent
*/
private LedgerInitializer(LedgerInitSetting initSetting, TransactionContent initTxContent) {
this.initSetting = initSetting;
this.initTxContent = initTxContent;
}

public TransactionContent getTransactionContent() {
return initTxContent;
}

private static SecurityInitSettings createDefaultSecurityInitSettings() {
// TODO throw new IllegalStateException("Not implemented!");
return null;
}

// public static LedgerInitializer create(LedgerInitSetting initSetting) {
// return create(initSetting, createDefaultSecurityInitSettings());
// }

public static LedgerInitializer create(LedgerInitSetting initSetting, SecurityInitSettings securityInitSettings) {
// 生成创世交易;
TransactionContent initTxContent = buildGenesisTransaction(initSetting, securityInitSettings);

return new LedgerInitializer(initSetting, initTxContent);
}

/**
* 根据初始化配置,生成创始交易;
* <p>
*
* “创世交易”按顺序由以下操作组成:<br>
* (1) 账本初始化 {@link LedgerInitOperation}:此操作仅用于锚定了原始的交易配置,对应的
* {@link OperationHandle} 执行空操作,由“创世交易”其余的操作来表达对账本的实际修改;<br>
* (2) 注册用户 {@link UserRegisterOperation}:有一项或者多项;<br>
* (3) 配置角色 {@link RolesConfigureOperation}:有一项或者多项;<br>
* (4) 授权用户 {@link UserAuthorizeOperation}:有一项或者多项;<br>
*
* @param initSetting
* @param securityInitSettings
* @return
*/
public static TransactionContent buildGenesisTransaction(LedgerInitSetting initSetting,
SecurityInitSettings securityInitSettings) {
// 账本初始化交易的账本 hash 为 null;
TransactionBuilder initTxBuilder = new TxBuilder(null);

// 定义账本初始化操作;
initTxBuilder.ledgers().create(initSetting);

// TODO: 注册参与方; 目前由 LedgerInitSetting 定义,在 LedgerAdminDataset 中解释执行;

//  注册用户;
for (ParticipantNode p : initSetting.getConsensusParticipants()) {
// TODO:暂时只支持注册用户的初始化操作;
BlockchainIdentity superUserId = new BlockchainIdentityData(p.getPubKey());
initTxBuilder.users().register(superUserId);
}

// 配置角色;
for (RoleInitSettings roleSettings : securityInitSettings.getRoles()) {
initTxBuilder.security().roles().configure(roleSettings.getRoleName())
.enable(roleSettings.getLedgerPermissions()).enable(roleSettings.getTransactionPermissions());
}

// 授权用户;
for (UserAuthInitSettings userAuthSettings : securityInitSettings.getUserAuthorizations()) {
initTxBuilder.security().authorziations().forUser(userAuthSettings.getUserAddress())
.authorize(userAuthSettings.getRoles())
.setPolicy(userAuthSettings.getPolicy());
}

// 账本初始化配置声明的创建时间来初始化交易时间戳;注:不能用本地时间,因为共识节点之间的本地时间系统不一致;
return initTxBuilder.prepareContent(initSetting.getCreatedTime());
}

public SignatureDigest signTransaction(PrivKey privKey) {
return SignatureUtils.sign(initTxContent, privKey);
}

/**
* 准备创建账本;
*
* @param storageService 存储服务;
* @param nodeSignatures 节点签名列表;
* @return
*/
public LedgerBlock prepareLedger(KVStorageService storageService, DigitalSignature... nodeSignatures) {
if (genesisBlock != null) {
throw new LedgerInitException("The ledger has been prepared!");
}
// 生成账本;
this.ledgerEditor = createLedgerEditor(this.initSetting, storageService);
this.genesisBlock = prepareLedger(ledgerEditor, nodeSignatures);

return genesisBlock;
}

public void commit() {
if (committed) {
throw new LedgerInitException("The ledger has been committed!");
}
if (canceled) {
throw new LedgerInitException("The ledger has been canceled!");
}
committed = true;
this.txResultsHandle.commit();
}

public void cancel() {
if (canceled) {
throw new LedgerInitException("The ledger has been canceled!");
}
if (committed) {
throw new LedgerInitException("The ledger has been committed!");
}
this.ledgerEditor.cancel();
}

public static LedgerEditor createLedgerEditor(LedgerInitSetting initSetting, KVStorageService storageService) {
LedgerEditor genesisBlockEditor = LedgerTransactionalEditor.createEditor(initSetting,
LedgerManage.LEDGER_PREFIX, storageService.getExPolicyKVStorage(),
storageService.getVersioningKVStorage());
return genesisBlockEditor;
}

/**
* 初始化账本数据,返回创始区块;
*
* @param ledgerEditor
* @return
*/
private LedgerBlock prepareLedger(LedgerEditor ledgerEditor, DigitalSignature... nodeSignatures) {
// 初始化时,自动将参与方注册为账本的用户;
TxRequestBuilder txReqBuilder = new TxRequestBuilder(this.initTxContent);
txReqBuilder.addNodeSignature(nodeSignatures);

TransactionRequest txRequest = txReqBuilder.buildRequest();

TransactionBatchProcessor txProcessor = new TransactionBatchProcessor(FULL_PERMISSION_SECURITY_MANAGER,
ledgerEditor, EMPTY_LEDGER_DATA_QUERY, DEFAULT_OP_HANDLE_REG, EMPTY_LEDGERS);

txProcessor.schedule(txRequest);

txResultsHandle = txProcessor.prepare();
return txResultsHandle.getBlock();
}

}

+ 12
- 10
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerManage.java View File

@@ -12,19 +12,21 @@ import com.jd.blockchain.storage.service.KVStorageService;
*/
public interface LedgerManage extends LedgerService {
static final String LEDGER_PREFIX = "LDG://";
LedgerRepository register(HashDigest ledgerHash, KVStorageService storageService);
void unregister(HashDigest ledgerHash);

/**
* 创建新账本;
*
* @param initSetting
* 初始化配置;
* @param initPermissions
* 参与者的初始化授权列表;与参与者列表一致;
* @return
*/
LedgerEditor newLedger(LedgerInitSetting initSetting, KVStorageService storageService);
// /**
// * 创建新账本;
// *
// * @param initSetting
// * 初始化配置;
// * @param initPermissions
// * 参与者的初始化授权列表;与参与者列表一致;
// * @return
// */
// LedgerEditor newLedger(LedgerInitSetting initSetting, KVStorageService storageService);

}

source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerManager.java → source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerManager.java View File

@@ -1,4 +1,4 @@
package com.jd.blockchain.ledger.core.impl;
package com.jd.blockchain.ledger.core;

import java.util.HashMap;
import java.util.Map;
@@ -9,11 +9,6 @@ import com.jd.blockchain.crypto.CryptoProvider;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.LedgerInitSetting;
import com.jd.blockchain.ledger.core.LedgerConsts;
import com.jd.blockchain.ledger.core.LedgerEditor;
import com.jd.blockchain.ledger.core.LedgerManage;
import com.jd.blockchain.ledger.core.LedgerRepository;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.KVStorageService;
import com.jd.blockchain.storage.service.VersioningKVStorage;
@@ -27,8 +22,6 @@ import com.jd.blockchain.utils.codec.Base58Utils;
*/
public class LedgerManager implements LedgerManage {

private static final String LEDGER_PREFIX = "LDG://";

// @Autowired
// private ExistentialKVStorage exPolicyStorage;
//
@@ -69,7 +62,7 @@ public class LedgerManager implements LedgerManage {
ledgerVersioningStorage);

// 校验 crypto service provider ;
CryptoSetting cryptoSetting = ledgerRepo.getAdminAccount().getSetting().getCryptoSetting();
CryptoSetting cryptoSetting = ledgerRepo.getAdminInfo().getSettings().getCryptoSetting();
checkCryptoSetting(cryptoSetting, ledgerHash);

// 创建账本上下文;
@@ -142,18 +135,18 @@ public class LedgerManager implements LedgerManage {
}
}

/*
* (non-Javadoc)
*
* @see com.jd.blockchain.ledger.core.LedgerManager#newLedger(com.jd.blockchain.
* ledger.core.ConsensusConfig, com.jd.blockchain.ledger.core.CryptoConfig)
*/
@Override
public LedgerEditor newLedger(LedgerInitSetting initSetting, KVStorageService storageService) {
LedgerEditor genesisBlockEditor = LedgerTransactionalEditor.createEditor(initSetting, LEDGER_PREFIX,
storageService.getExPolicyKVStorage(), storageService.getVersioningKVStorage());
return genesisBlockEditor;
}
// /*
// * (non-Javadoc)
// *
// * @see com.jd.blockchain.ledger.core.LedgerManager#newLedger(com.jd.blockchain.
// * ledger.core.ConsensusConfig, com.jd.blockchain.ledger.core.CryptoConfig)
// */
// @Override
// public LedgerEditor newLedger(LedgerInitSetting initSetting, KVStorageService storageService) {
// LedgerEditor genesisBlockEditor = LedgerTransactionalEditor.createEditor(initSetting, LEDGER_PREFIX,
// storageService.getExPolicyKVStorage(), storageService.getVersioningKVStorage());
// return genesisBlockEditor;
// }

static String getLedgerStoragePrefix(HashDigest ledgerHash) {
String base58LedgerHash = Base58Utils.encode(ledgerHash.toBytes());

source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java → source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerQueryService.java View File

@@ -1,25 +1,33 @@
package com.jd.blockchain.ledger.core.impl;
package com.jd.blockchain.ledger.core;

import java.util.ArrayList;
import java.util.List;

import com.jd.blockchain.contract.ContractException;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.*;
import com.jd.blockchain.ledger.core.ContractAccountSet;
import com.jd.blockchain.ledger.core.DataAccount;
import com.jd.blockchain.ledger.core.DataAccountSet;
import com.jd.blockchain.ledger.core.LedgerAdministration;
import com.jd.blockchain.ledger.core.LedgerRepository;
import com.jd.blockchain.ledger.core.LedgerService;
import com.jd.blockchain.ledger.core.TransactionSet;
import com.jd.blockchain.ledger.core.UserAccountSet;
import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.ContractInfo;
import com.jd.blockchain.ledger.KVDataEntry;
import com.jd.blockchain.ledger.KVDataObject;
import com.jd.blockchain.ledger.KVDataVO;
import com.jd.blockchain.ledger.KVInfoVO;
import com.jd.blockchain.ledger.LedgerAdminInfo;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerInfo;
import com.jd.blockchain.ledger.LedgerMetadata;
import com.jd.blockchain.ledger.LedgerTransaction;
import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.ledger.UserInfo;
import com.jd.blockchain.transaction.BlockchainQueryService;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.QueryUtil;

public class LedgerQueryService implements BlockchainQueryService {

private static final KVDataEntry[] EMPTY_ENTRIES = new KVDataEntry[0];

private LedgerService ledgerService;

public LedgerQueryService(LedgerService ledgerService) {
@@ -40,15 +48,23 @@ public class LedgerQueryService implements BlockchainQueryService {
ledgerInfo.setLatestBlockHeight(ledger.getLatestBlockHeight());
return ledgerInfo;
}
@Override
public LedgerAdminInfo getLedgerAdminInfo(HashDigest ledgerHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
LedgerAdminInfo administration = ledger.getAdminInfo(block);
return administration;
}

@Override
public ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash) {
return ledgerAdministration(ledgerHash).getParticipants();
return getLedgerAdminInfo(ledgerHash).getParticipants();
}

@Override
public LedgerMetadata getLedgerMetadata(HashDigest ledgerHash) {
return ledgerAdministration(ledgerHash).getMetadata();
return getLedgerAdminInfo(ledgerHash).getMetadata();
}

@Override
@@ -91,7 +107,7 @@ public class LedgerQueryService implements BlockchainQueryService {
public long getDataAccountCount(HashDigest ledgerHash, long height) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getBlock(height);
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
return dataAccountSet.getTotalCount();
}

@@ -99,7 +115,7 @@ public class LedgerQueryService implements BlockchainQueryService {
public long getDataAccountCount(HashDigest ledgerHash, HashDigest blockHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getBlock(blockHash);
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
return dataAccountSet.getTotalCount();
}

@@ -107,7 +123,7 @@ public class LedgerQueryService implements BlockchainQueryService {
public long getDataAccountTotalCount(HashDigest ledgerHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
return dataAccountSet.getTotalCount();
}

@@ -115,7 +131,7 @@ public class LedgerQueryService implements BlockchainQueryService {
public long getUserCount(HashDigest ledgerHash, long height) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getBlock(height);
UserAccountSet userAccountSet = ledger.getUserAccountSet(block);
UserAccountQuery userAccountSet = ledger.getUserAccountSet(block);
return userAccountSet.getTotalCount();
}

@@ -123,7 +139,7 @@ public class LedgerQueryService implements BlockchainQueryService {
public long getUserCount(HashDigest ledgerHash, HashDigest blockHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getBlock(blockHash);
UserAccountSet userAccountSet = ledger.getUserAccountSet(block);
UserAccountQuery userAccountSet = ledger.getUserAccountSet(block);
return userAccountSet.getTotalCount();
}

@@ -131,7 +147,7 @@ public class LedgerQueryService implements BlockchainQueryService {
public long getUserTotalCount(HashDigest ledgerHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
UserAccountSet userAccountSet = ledger.getUserAccountSet(block);
UserAccountQuery userAccountSet = ledger.getUserAccountSet(block);
return userAccountSet.getTotalCount();
}

@@ -139,7 +155,7 @@ public class LedgerQueryService implements BlockchainQueryService {
public long getContractCount(HashDigest ledgerHash, long height) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getBlock(height);
ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block);
ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block);
return contractAccountSet.getTotalCount();
}

@@ -147,7 +163,7 @@ public class LedgerQueryService implements BlockchainQueryService {
public long getContractCount(HashDigest ledgerHash, HashDigest blockHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getBlock(blockHash);
ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block);
ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block);
return contractAccountSet.getTotalCount();
}

@@ -155,7 +171,7 @@ public class LedgerQueryService implements BlockchainQueryService {
public long getContractTotalCount(HashDigest ledgerHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block);
ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block);
return contractAccountSet.getTotalCount();
}

@@ -238,7 +254,7 @@ public class LedgerQueryService implements BlockchainQueryService {
public UserInfo getUser(HashDigest ledgerHash, String address) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
UserAccountSet userAccountSet = ledger.getUserAccountSet(block);
UserAccountQuery userAccountSet = ledger.getUserAccountSet(block);
return userAccountSet.getUser(address);

}
@@ -247,18 +263,18 @@ public class LedgerQueryService implements BlockchainQueryService {
public AccountHeader getDataAccount(HashDigest ledgerHash, String address) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
return dataAccountSet.getDataAccount(Bytes.fromBase58(address));
}

@Override
public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys) {
if (keys == null || keys.length == 0) {
return null;
return EMPTY_ENTRIES;
}
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address));

KVDataEntry[] entries = new KVDataEntry[keys.length];
@@ -266,7 +282,7 @@ public class LedgerQueryService implements BlockchainQueryService {
for (int i = 0; i < entries.length; i++) {
final String currKey = keys[i];

ver = dataAccount.getDataVersion(Bytes.fromString(currKey));
ver = dataAccount == null ? -1 : dataAccount.getDataVersion(Bytes.fromString(currKey));

if (ver < 0) {
entries[i] = new KVDataObject(currKey, -1, null);
@@ -306,7 +322,7 @@ public class LedgerQueryService implements BlockchainQueryService {

LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address));

KVDataEntry[] entries = new KVDataEntry[keys.length];
@@ -337,7 +353,7 @@ public class LedgerQueryService implements BlockchainQueryService {

LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address));

int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccount.getDataEntriesTotalCount());
@@ -349,7 +365,7 @@ public class LedgerQueryService implements BlockchainQueryService {

LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address));

return dataAccount.getDataEntriesTotalCount();
@@ -359,7 +375,7 @@ public class LedgerQueryService implements BlockchainQueryService {
public ContractInfo getContract(HashDigest ledgerHash, String address) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block);
ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block);
return contractAccountSet.getContract(Bytes.fromBase58(address));
}

@@ -367,7 +383,7 @@ public class LedgerQueryService implements BlockchainQueryService {
public AccountHeader[] getUsers(HashDigest ledgerHash, int fromIndex, int count) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
UserAccountSet userAccountSet = ledger.getUserAccountSet(block);
UserAccountQuery userAccountSet = ledger.getUserAccountSet(block);
int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) userAccountSet.getTotalCount());
return userAccountSet.getAccounts(pages[0], pages[1]);
}
@@ -376,7 +392,7 @@ public class LedgerQueryService implements BlockchainQueryService {
public AccountHeader[] getDataAccounts(HashDigest ledgerHash, int fromIndex, int count) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccountSet.getTotalCount());
return dataAccountSet.getAccounts(pages[0], pages[1]);
}
@@ -385,15 +401,9 @@ public class LedgerQueryService implements BlockchainQueryService {
public AccountHeader[] getContractAccounts(HashDigest ledgerHash, int fromIndex, int count) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block);
ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block);
int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) contractAccountSet.getTotalCount());
return contractAccountSet.getAccounts(pages[0], pages[1]);
}

private LedgerAdministration ledgerAdministration(HashDigest ledgerHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
LedgerAdministration administration = ledger.getAdminAccount(block);
return administration;
}
}

+ 12
- 15
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerRepository.java View File

@@ -3,6 +3,7 @@ package com.jd.blockchain.ledger.core;
import java.io.Closeable;

import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.LedgerAdminInfo;
import com.jd.blockchain.ledger.LedgerBlock;

public interface LedgerRepository extends Closeable {
@@ -51,23 +52,23 @@ public interface LedgerRepository extends Closeable {
*/
LedgerBlock getBlock(long height);

LedgerAdministration getAdminInfo();
LedgerAdminInfo getAdminInfo();
LedgerAdminInfo getAdminInfo(LedgerBlock block);

LedgerBlock getBlock(HashDigest hash);

LedgerDataSet getDataSet(LedgerBlock block);
LedgerDataQuery getDataSet(LedgerBlock block);

TransactionSet getTransactionSet(LedgerBlock block);

LedgerAdminAccount getAdminAccount(LedgerBlock block);
UserAccountQuery getUserAccountSet(LedgerBlock block);

UserAccountSet getUserAccountSet(LedgerBlock block);
DataAccountQuery getDataAccountSet(LedgerBlock block);

DataAccountSet getDataAccountSet(LedgerBlock block);
ContractAccountQuery getContractAccountSet(LedgerBlock block);

ContractAccountSet getContractAccountSet(LedgerBlock block);

default LedgerDataSet getDataSet() {
default LedgerDataQuery getDataSet() {
return getDataSet(getLatestBlock());
}

@@ -75,19 +76,15 @@ public interface LedgerRepository extends Closeable {
return getTransactionSet(getLatestBlock());
}

default LedgerAdminAccount getAdminAccount() {
return getAdminAccount(getLatestBlock());
}

default UserAccountSet getUserAccountSet() {
default UserAccountQuery getUserAccountSet() {
return getUserAccountSet(getLatestBlock());
}

default DataAccountSet getDataAccountSet() {
default DataAccountQuery getDataAccountSet() {
return getDataAccountSet(getLatestBlock());
}

default ContractAccountSet getContractAccountSet() {
default ContractAccountQuery getContractAccountSet() {
return getContractAccountSet(getLatestBlock());
}



source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerRepositoryImpl.java → source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerRepositoryImpl.java View File

@@ -1,22 +1,17 @@
package com.jd.blockchain.ledger.core.impl;
package com.jd.blockchain.ledger.core;

import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.HashFunction;
import com.jd.blockchain.ledger.*;
import com.jd.blockchain.ledger.core.AccountAccessPolicy;
import com.jd.blockchain.ledger.core.ContractAccountSet;
import com.jd.blockchain.ledger.core.DataAccountSet;
import com.jd.blockchain.ledger.core.LedgerAdminAccount;
import com.jd.blockchain.ledger.core.LedgerAdministration;
import com.jd.blockchain.ledger.core.LedgerConsts;
import com.jd.blockchain.ledger.core.LedgerDataSet;
import com.jd.blockchain.ledger.core.LedgerEditor;
import com.jd.blockchain.ledger.core.LedgerRepository;
import com.jd.blockchain.ledger.core.LedgerTransactionContext;
import com.jd.blockchain.ledger.core.TransactionSet;
import com.jd.blockchain.ledger.core.UserAccountSet;
import com.jd.blockchain.ledger.BlockBody;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerAdminInfo;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerDataSnapshot;
import com.jd.blockchain.ledger.LedgerInitSetting;
import com.jd.blockchain.ledger.LedgerSettings;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes;
@@ -35,7 +30,7 @@ import com.jd.blockchain.utils.codec.Base58Utils;
* @author huanghaiquan
*
*/
public class LedgerRepositoryImpl implements LedgerRepository {
class LedgerRepositoryImpl implements LedgerRepository {

private static final Bytes LEDGER_PREFIX = Bytes.fromString("IDX" + LedgerConsts.KEY_SEPERATOR);

@@ -77,8 +72,10 @@ public class LedgerRepositoryImpl implements LedgerRepository {
this.ledgerIndexKey = encodeLedgerIndexKey(ledgerHash);

if (getLatestBlockHeight() < 0) {
throw new LedgerException("Ledger doesn't exist!");
throw new RuntimeException("Ledger doesn't exist!");
}

retrieveLatestState();
}

/*
@@ -109,25 +106,27 @@ public class LedgerRepositoryImpl implements LedgerRepository {

@Override
public LedgerBlock getLatestBlock() {
LedgerState state = getLatestState();
return state.block;
return latestState.block;
}

private LedgerState getLatestState() {
LedgerState state = latestState;
if (state == null) {
LedgerBlock latestBlock = innerGetBlock(innerGetLatestBlockHeight());
state = new LedgerState(latestBlock);
latestState = state;
}
return state;
/**
* 重新检索加载最新的状态;
*
* @return
*/
private LedgerState retrieveLatestState() {
LedgerBlock latestBlock = innerGetBlock(innerGetLatestBlockHeight());
LedgerDataset ledgerDataset = innerGetLedgerDataset(latestBlock);
TransactionSet txSet = loadTransactionSet(latestBlock.getTransactionSetHash(),
ledgerDataset.getAdminDataset().getSettings().getCryptoSetting(), keyPrefix, exPolicyStorage,
versioningStorage, true);
this.latestState = new LedgerState(latestBlock, ledgerDataset, txSet);
return latestState;
}

@Override
public LedgerBlock retrieveLatestBlock() {
LedgerBlock latestBlock = innerGetBlock(innerGetLatestBlockHeight());
latestState = new LedgerState(latestBlock);
return latestBlock;
return retrieveLatestState().block;
}

@Override
@@ -186,7 +185,7 @@ public class LedgerRepositoryImpl implements LedgerRepository {
if (height < 0) {
return null;
}
return innerGetBlock(getBlockHash(height));
return innerGetBlock(innerGetBlockHash(height));
}

@Override
@@ -205,36 +204,27 @@ public class LedgerRepositoryImpl implements LedgerRepository {
LedgerBlockData block = new LedgerBlockData(deserialize(blockBytes));

if (!blockHash.equals(block.getHash())) {
throw new LedgerException("Block hash not equals to it's storage key!");
}

// verify hash;
// boolean requiredVerifyHash =
// adminAccount.getMetadata().getSetting().getCryptoSetting().getAutoVerifyHash();
// TODO: 未实现从配置中加载是否校验 Hash 的设置;
boolean requiredVerifyHash = false;
if (requiredVerifyHash) {
byte[] blockBodyBytes = null;
if (block.getHeight() == 0) {
// 计算创世区块的 hash 时,不包括 ledgerHash 字段;
block.setLedgerHash(null);
blockBodyBytes = BinaryProtocol.encode(block, BlockBody.class);
// 恢复;
block.setLedgerHash(block.getHash());
} else {
blockBodyBytes = BinaryProtocol.encode(block, BlockBody.class);
}
HashFunction hashFunc = Crypto.getHashFunction(blockHash.getAlgorithm());
boolean pass = hashFunc.verify(blockHash, blockBodyBytes);
if (!pass) {
throw new LedgerException("Block hash verification fail!");
}
throw new RuntimeException("Block hash not equals to it's storage key!");
}

// verify block hash;
byte[] blockBodyBytes = null;
if (block.getHeight() == 0) {
// 计算创世区块的 hash 时,不包括 ledgerHash 字段;
blockBodyBytes = BinaryProtocol.encode(block, BlockBody.class);
} else {
blockBodyBytes = BinaryProtocol.encode(block, BlockBody.class);
}
HashFunction hashFunc = Crypto.getHashFunction(blockHash.getAlgorithm());
boolean pass = hashFunc.verify(blockHash, blockBodyBytes);
if (!pass) {
throw new RuntimeException("Block hash verification fail!");
}

// verify height;
HashDigest indexedHash = getBlockHash(block.getHeight());
if (indexedHash == null || !indexedHash.equals(blockHash)) {
throw new LedgerException(
throw new RuntimeException(
"Illegal ledger state in storage that ledger height index doesn't match it's block data in height["
+ block.getHeight() + "] and block hash[" + Base58Utils.encode(blockHash.toBytes())
+ "] !");
@@ -243,9 +233,18 @@ public class LedgerRepositoryImpl implements LedgerRepository {
return block;
}

/**
* 获取最新区块的账本参数;
*
* @return
*/
private LedgerSettings getLatestSettings() {
return getAdminInfo().getSettings();
}

@Override
public LedgerAdministration getAdminInfo() {
return getAdminAccount(getLatestBlock());
public LedgerAdminInfo getAdminInfo() {
return getAdminInfo(getLatestBlock());
}

private LedgerBlock deserialize(byte[] blockBytes) {
@@ -255,155 +254,110 @@ public class LedgerRepositoryImpl implements LedgerRepository {
@Override
public TransactionSet getTransactionSet(LedgerBlock block) {
long height = getLatestBlockHeight();
TransactionSet transactionSet = null;
if (height == block.getHeight()) {
// 缓存读;
LedgerState state = getLatestState();
transactionSet = state.transactionSet;
if (transactionSet == null) {
LedgerAdminAccount adminAccount = getAdminAccount(block);
transactionSet = loadTransactionSet(block.getTransactionSetHash(),
adminAccount.getMetadata().getSetting().getCryptoSetting(), keyPrefix, exPolicyStorage,
versioningStorage, true);
state.transactionSet = transactionSet;
}
return transactionSet;
// 从缓存中返回最新区块的数据集;
return latestState.getTransactionSet();
}
LedgerAdminAccount adminAccount = getAdminAccount(block);
LedgerAdminInfo adminAccount = getAdminInfo(block);
// All of existing block is readonly;
return loadTransactionSet(block.getTransactionSetHash(),
adminAccount.getMetadata().getSetting().getCryptoSetting(), keyPrefix, exPolicyStorage,
versioningStorage, true);
return loadTransactionSet(block.getTransactionSetHash(), adminAccount.getSettings().getCryptoSetting(),
keyPrefix, exPolicyStorage, versioningStorage, true);
}

@Override
public LedgerAdminAccount getAdminAccount(LedgerBlock block) {
public LedgerAdminDataset getAdminInfo(LedgerBlock block) {
long height = getLatestBlockHeight();
LedgerAdminAccount adminAccount = null;
if (height == block.getHeight()) {
// 缓存读;
LedgerState state = getLatestState();
adminAccount = state.adminAccount;
if (adminAccount == null) {
adminAccount = new LedgerAdminAccount(block.getAdminAccountHash(), keyPrefix, exPolicyStorage,
versioningStorage, true);
state.adminAccount = adminAccount;
}
return adminAccount;
return latestState.getAdminDataset();
}

return new LedgerAdminAccount(block.getAdminAccountHash(), keyPrefix, exPolicyStorage, versioningStorage, true);
return createAdminDataset(block);
}

private LedgerAdminDataset createAdminDataset(LedgerBlock block) {
return new LedgerAdminDataset(block.getAdminAccountHash(), keyPrefix, exPolicyStorage, versioningStorage, true);
}

@Override
public UserAccountSet getUserAccountSet(LedgerBlock block) {
public UserAccountQuery getUserAccountSet(LedgerBlock block) {
long height = getLatestBlockHeight();
UserAccountSet userAccountSet = null;
if (height == block.getHeight()) {
// 缓存读;
LedgerState state = getLatestState();
userAccountSet = state.userAccountSet;
if (userAccountSet == null) {
LedgerAdminAccount adminAccount = getAdminAccount(block);
userAccountSet = loadUserAccountSet(block.getUserAccountSetHash(),
adminAccount.getPreviousSetting().getCryptoSetting(), keyPrefix, exPolicyStorage,
versioningStorage, true);
state.userAccountSet = userAccountSet;
}
return userAccountSet;
return latestState.getUserAccountSet();
}
LedgerAdminAccount adminAccount = getAdminAccount(block);
return loadUserAccountSet(block.getUserAccountSetHash(), adminAccount.getPreviousSetting().getCryptoSetting(),
keyPrefix, exPolicyStorage, versioningStorage, true);
LedgerAdminDataset adminAccount = getAdminInfo(block);
return createUserAccountSet(block, adminAccount.getSettings().getCryptoSetting());
}

private UserAccountSet createUserAccountSet(LedgerBlock block, CryptoSetting cryptoSetting) {
return loadUserAccountSet(block.getUserAccountSetHash(), cryptoSetting, keyPrefix, exPolicyStorage,
versioningStorage, true);
}

@Override
public DataAccountSet getDataAccountSet(LedgerBlock block) {
public DataAccountQuery getDataAccountSet(LedgerBlock block) {
long height = getLatestBlockHeight();
DataAccountSet dataAccountSet = null;
if (height == block.getHeight()) {
// 缓存读;
LedgerState state = getLatestState();
dataAccountSet = state.dataAccountSet;
if (dataAccountSet == null) {
LedgerAdminAccount adminAccount = getAdminAccount(block);
dataAccountSet = loadDataAccountSet(block.getDataAccountSetHash(),
adminAccount.getPreviousSetting().getCryptoSetting(), keyPrefix, exPolicyStorage,
versioningStorage, true);
state.dataAccountSet = dataAccountSet;
}
return dataAccountSet;
return latestState.getDataAccountSet();
}

LedgerAdminAccount adminAccount = getAdminAccount(block);
return loadDataAccountSet(block.getDataAccountSetHash(), adminAccount.getPreviousSetting().getCryptoSetting(),
keyPrefix, exPolicyStorage, versioningStorage, true);
LedgerAdminDataset adminAccount = getAdminInfo(block);
return createDataAccountSet(block, adminAccount.getSettings().getCryptoSetting());
}

private DataAccountSet createDataAccountSet(LedgerBlock block, CryptoSetting setting) {
return loadDataAccountSet(block.getDataAccountSetHash(), setting, keyPrefix, exPolicyStorage, versioningStorage,
true);
}

@Override
public ContractAccountSet getContractAccountSet(LedgerBlock block) {
public ContractAccountQuery getContractAccountSet(LedgerBlock block) {
long height = getLatestBlockHeight();
ContractAccountSet contractAccountSet = null;
if (height == block.getHeight()) {
// 缓存读;
LedgerState state = getLatestState();
contractAccountSet = state.contractAccountSet;
if (contractAccountSet == null) {
LedgerAdminAccount adminAccount = getAdminAccount(block);
contractAccountSet = loadContractAccountSet(block.getContractAccountSetHash(),
adminAccount.getPreviousSetting().getCryptoSetting(), keyPrefix, exPolicyStorage,
versioningStorage, true);
state.contractAccountSet = contractAccountSet;
}
return contractAccountSet;
return latestState.getContractAccountSet();
}

LedgerAdminAccount adminAccount = getAdminAccount(block);
return loadContractAccountSet(block.getContractAccountSetHash(),
adminAccount.getPreviousSetting().getCryptoSetting(), keyPrefix, exPolicyStorage, versioningStorage,
true);
LedgerAdminDataset adminAccount = getAdminInfo(block);
return createContractAccountSet(block, adminAccount.getSettings().getCryptoSetting());
}

private ContractAccountSet createContractAccountSet(LedgerBlock block, CryptoSetting cryptoSetting) {
return loadContractAccountSet(block.getContractAccountSetHash(), cryptoSetting, keyPrefix, exPolicyStorage,
versioningStorage, true);
}

@Override
public LedgerDataSet getDataSet(LedgerBlock block) {
public LedgerDataset getDataSet(LedgerBlock block) {
long height = getLatestBlockHeight();
LedgerDataSet ledgerDataSet = null;
if (height == block.getHeight()) {
// 缓存读;
LedgerState state = getLatestState();
ledgerDataSet = state.ledgerDataSet;
if (ledgerDataSet == null) {
ledgerDataSet = innerDataSet(block);
state.ledgerDataSet = ledgerDataSet;
}
return ledgerDataSet;
return latestState.getLedgerDataset();
}

// All of existing block is readonly;
return innerDataSet(block);
return innerGetLedgerDataset(block);
}

private LedgerDataSet innerDataSet(LedgerBlock block) {
LedgerAdminAccount adminAccount = getAdminAccount(block);
UserAccountSet userAccountSet = getUserAccountSet(block);
DataAccountSet dataAccountSet = getDataAccountSet(block);
ContractAccountSet contractAccountSet = getContractAccountSet(block);
return new LedgerDataSetImpl(adminAccount, userAccountSet, dataAccountSet, contractAccountSet, true);
private LedgerDataset innerGetLedgerDataset(LedgerBlock block) {
LedgerAdminDataset adminDataset = createAdminDataset(block);
CryptoSetting cryptoSetting = adminDataset.getSettings().getCryptoSetting();

UserAccountSet userAccountSet = createUserAccountSet(block, cryptoSetting);
DataAccountSet dataAccountSet = createDataAccountSet(block, cryptoSetting);
ContractAccountSet contractAccountSet = createContractAccountSet(block, cryptoSetting);
return new LedgerDataset(adminDataset, userAccountSet, dataAccountSet, contractAccountSet, true);
}

@Override
public synchronized LedgerEditor createNextBlock() {
if (closed) {
throw new LedgerException("Ledger repository has been closed!");
throw new RuntimeException("Ledger repository has been closed!");
}
if (this.nextBlockEditor != null) {
throw new LedgerException(
throw new RuntimeException(
"A new block is in process, cann't create another one until it finish by committing or canceling.");
}
LedgerBlock previousBlock = getLatestBlock();
LedgerTransactionalEditor editor = LedgerTransactionalEditor.createEditor(
getAdminInfo().getMetadata().getSetting(), previousBlock, keyPrefix, exPolicyStorage,
versioningStorage);
LedgerTransactionalEditor editor = LedgerTransactionalEditor.createEditor(previousBlock, getLatestSettings(),
keyPrefix, exPolicyStorage, versioningStorage);
NewBlockCommittingMonitor committingMonitor = new NewBlockCommittingMonitor(editor, this);
this.nextBlockEditor = committingMonitor;
return committingMonitor;
@@ -420,70 +374,45 @@ public class LedgerRepositoryImpl implements LedgerRepository {
return;
}
if (this.nextBlockEditor != null) {
throw new LedgerException("A new block is in process, cann't close the ledger repository!");
throw new RuntimeException("A new block is in process, cann't close the ledger repository!");
}
closed = true;
}

static Bytes encodeLedgerIndexKey(HashDigest ledgerHash) {
// return LEDGER_PREFIX + Base58Utils.encode(ledgerHash.toBytes());
// return new Bytes(ledgerHash.toBytes()).concatTo(LEDGER_PREFIX);
return LEDGER_PREFIX.concat(ledgerHash);
}

static Bytes encodeBlockStorageKey(HashDigest blockHash) {
// String key = ByteArray.toBase58(blockHash.toBytes());
// return BLOCK_PREFIX + key;

return BLOCK_PREFIX.concat(blockHash);
}

static LedgerDataSetImpl newDataSet(LedgerInitSetting initSetting, String keyPrefix,
static LedgerDataset newDataSet(LedgerInitSetting initSetting, String keyPrefix,
ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage) {
LedgerAdminAccount adminAccount = new LedgerAdminAccount(initSetting, keyPrefix, ledgerExStorage,
LedgerAdminDataset adminAccount = new LedgerAdminDataset(initSetting, keyPrefix, ledgerExStorage,
ledgerVerStorage);

String usersetKeyPrefix = keyPrefix + USER_SET_PREFIX;
String datasetKeyPrefix = keyPrefix + DATA_SET_PREFIX;
String contractsetKeyPrefix = keyPrefix + CONTRACT_SET_PREFIX;
// String txsetKeyPrefix = keyPrefix + TRANSACTION_SET_PREFIX;

// UserAccountSet userAccountSet = new
// UserAccountSet(adminAccount.getSetting().getCryptoSetting(),
// PrefixAppender.prefix(USER_SET_PREFIX, ledgerExStorage),
// PrefixAppender.prefix(USER_SET_PREFIX, ledgerVerStorage),
// DEFAULT_ACCESS_POLICY);
UserAccountSet userAccountSet = new UserAccountSet(adminAccount.getSetting().getCryptoSetting(),

UserAccountSet userAccountSet = new UserAccountSet(adminAccount.getSettings().getCryptoSetting(),
usersetKeyPrefix, ledgerExStorage, ledgerVerStorage, DEFAULT_ACCESS_POLICY);

// DataAccountSet dataAccountSet = new
// DataAccountSet(adminAccount.getSetting().getCryptoSetting(),
// PrefixAppender.prefix(DATA_SET_PREFIX, ledgerExStorage),
// PrefixAppender.prefix(DATA_SET_PREFIX, ledgerVerStorage),
// DEFAULT_ACCESS_POLICY);
DataAccountSet dataAccountSet = new DataAccountSet(adminAccount.getSetting().getCryptoSetting(),
DataAccountSet dataAccountSet = new DataAccountSet(adminAccount.getSettings().getCryptoSetting(),
datasetKeyPrefix, ledgerExStorage, ledgerVerStorage, DEFAULT_ACCESS_POLICY);

// ContractAccountSet contractAccountSet = new
// ContractAccountSet(adminAccount.getSetting().getCryptoSetting(),
// PrefixAppender.prefix(CONTRACT_SET_PREFIX, ledgerExStorage),
// PrefixAppender.prefix(CONTRACT_SET_PREFIX, ledgerVerStorage),
// DEFAULT_ACCESS_POLICY);
ContractAccountSet contractAccountSet = new ContractAccountSet(adminAccount.getSetting().getCryptoSetting(),
ContractAccountSet contractAccountSet = new ContractAccountSet(adminAccount.getSettings().getCryptoSetting(),
contractsetKeyPrefix, ledgerExStorage, ledgerVerStorage, DEFAULT_ACCESS_POLICY);

LedgerDataSetImpl newDataSet = new LedgerDataSetImpl(adminAccount, userAccountSet, dataAccountSet,
LedgerDataset newDataSet = new LedgerDataset(adminAccount, userAccountSet, dataAccountSet,
contractAccountSet, false);

return newDataSet;
}

static TransactionSet newTransactionSet(LedgerSetting ledgerSetting, String keyPrefix,
ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage) {
// TransactionSet transactionSet = new
// TransactionSet(ledgerSetting.getCryptoSetting(),
// PrefixAppender.prefix(TRANSACTION_SET_PREFIX, ledgerExStorage),
// PrefixAppender.prefix(TRANSACTION_SET_PREFIX, ledgerVerStorage));
static TransactionSet newTransactionSet(LedgerSettings ledgerSetting, String keyPrefix,
ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage) {

String txsetKeyPrefix = keyPrefix + TRANSACTION_SET_PREFIX;

@@ -492,13 +421,11 @@ public class LedgerRepositoryImpl implements LedgerRepository {
return transactionSet;
}

static LedgerDataSetImpl loadDataSet(LedgerDataSnapshot dataSnapshot, String keyPrefix,
static LedgerDataset loadDataSet(LedgerDataSnapshot dataSnapshot, CryptoSetting cryptoSetting, String keyPrefix,
ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage, boolean readonly) {
LedgerAdminAccount adminAccount = new LedgerAdminAccount(dataSnapshot.getAdminAccountHash(), keyPrefix,
LedgerAdminDataset adminAccount = new LedgerAdminDataset(dataSnapshot.getAdminAccountHash(), keyPrefix,
ledgerExStorage, ledgerVerStorage, readonly);

CryptoSetting cryptoSetting = adminAccount.getPreviousSetting().getCryptoSetting();

UserAccountSet userAccountSet = loadUserAccountSet(dataSnapshot.getUserAccountSetHash(), cryptoSetting,
keyPrefix, ledgerExStorage, ledgerVerStorage, readonly);

@@ -508,7 +435,7 @@ public class LedgerRepositoryImpl implements LedgerRepository {
ContractAccountSet contractAccountSet = loadContractAccountSet(dataSnapshot.getContractAccountSetHash(),
cryptoSetting, keyPrefix, ledgerExStorage, ledgerVerStorage, readonly);

LedgerDataSetImpl dataset = new LedgerDataSetImpl(adminAccount, userAccountSet, dataAccountSet,
LedgerDataset dataset = new LedgerDataset(adminAccount, userAccountSet, dataAccountSet,
contractAccountSet, readonly);

return dataset;
@@ -517,10 +444,6 @@ public class LedgerRepositoryImpl implements LedgerRepository {
static UserAccountSet loadUserAccountSet(HashDigest userAccountSetHash, CryptoSetting cryptoSetting,
String keyPrefix, ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage,
boolean readonly) {
// return new UserAccountSet(userAccountSetHash, cryptoSetting,
// PrefixAppender.prefix(USER_SET_PREFIX, ledgerExStorage),
// PrefixAppender.prefix(USER_SET_PREFIX, ledgerVerStorage), readonly,
// DEFAULT_ACCESS_POLICY);

String usersetKeyPrefix = keyPrefix + USER_SET_PREFIX;
return new UserAccountSet(userAccountSetHash, cryptoSetting, usersetKeyPrefix, ledgerExStorage,
@@ -530,10 +453,6 @@ public class LedgerRepositoryImpl implements LedgerRepository {
static DataAccountSet loadDataAccountSet(HashDigest dataAccountSetHash, CryptoSetting cryptoSetting,
String keyPrefix, ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage,
boolean readonly) {
// return new DataAccountSet(dataAccountSetHash, cryptoSetting,
// PrefixAppender.prefix(DATA_SET_PREFIX, ledgerExStorage,
// PrefixAppender.prefix(DATA_SET_PREFIX, ledgerVerStorage), readonly,
// DEFAULT_ACCESS_POLICY);

String datasetKeyPrefix = keyPrefix + DATA_SET_PREFIX;
return new DataAccountSet(dataAccountSetHash, cryptoSetting, datasetKeyPrefix, ledgerExStorage,
@@ -543,10 +462,6 @@ public class LedgerRepositoryImpl implements LedgerRepository {
static ContractAccountSet loadContractAccountSet(HashDigest contractAccountSetHash, CryptoSetting cryptoSetting,
String keyPrefix, ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage,
boolean readonly) {
// return new ContractAccountSet(contractAccountSetHash, cryptoSetting,
// PrefixAppender.prefix(CONTRACT_SET_PREFIX, ledgerExStorage,
// PrefixAppender.prefix(CONTRACT_SET_PREFIX, ledgerVerStorage), readonly,
// DEFAULT_ACCESS_POLICY);

String contractsetKeyPrefix = keyPrefix + CONTRACT_SET_PREFIX;
return new ContractAccountSet(contractAccountSetHash, cryptoSetting, contractsetKeyPrefix, ledgerExStorage,
@@ -555,9 +470,6 @@ public class LedgerRepositoryImpl implements LedgerRepository {

static TransactionSet loadTransactionSet(HashDigest txsetHash, CryptoSetting cryptoSetting, String keyPrefix,
ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage, boolean readonly) {
// return new TransactionSet(txsetHash, cryptoSetting,
// PrefixAppender.prefix(TRANSACTION_SET_PREFIX, ledgerExStorage),
// PrefixAppender.prefix(TRANSACTION_SET_PREFIX, ledgerVerStorage), readonly);

String txsetKeyPrefix = keyPrefix + TRANSACTION_SET_PREFIX;
return new TransactionSet(txsetHash, cryptoSetting, txsetKeyPrefix, ledgerExStorage, ledgerVerStorage,
@@ -576,6 +488,26 @@ public class LedgerRepositoryImpl implements LedgerRepository {
this.ledgerRepo = ledgerRepo;
}

@Override
public HashDigest getLedgerHash() {
return editor.getLedgerHash();
}

@Override
public long getBlockHeight() {
return editor.getBlockHeight();
}

@Override
public LedgerDataset getLedgerDataset() {
return editor.getLedgerDataset();
}

@Override
public TransactionSet getTransactionSet() {
return editor.getTransactionSet();
}

@Override
public LedgerTransactionContext newTransaction(TransactionRequest txRequest) {
return editor.newTransaction(txRequest);
@@ -590,8 +522,9 @@ public class LedgerRepositoryImpl implements LedgerRepository {
public void commit() {
try {
editor.commit();
LedgerBlock latestBlock = editor.getNewlyBlock();
ledgerRepo.latestState = new LedgerState(latestBlock);
LedgerBlock latestBlock = editor.getCurrentBlock();
ledgerRepo.latestState = new LedgerState(latestBlock, editor.getLedgerDataset(),
editor.getTransactionSet());
} finally {
ledgerRepo.nextBlockEditor = null;
}
@@ -618,20 +551,39 @@ public class LedgerRepositoryImpl implements LedgerRepository {

private final LedgerBlock block;

private volatile LedgerAdminAccount adminAccount;
private final TransactionSet transactionSet;

private volatile UserAccountSet userAccountSet;
private final LedgerDataset ledgerDataset;

private volatile DataAccountSet dataAccountSet;
public LedgerState(LedgerBlock block, LedgerDataset ledgerDataset, TransactionSet transactionSet) {
this.block = block;
this.ledgerDataset = ledgerDataset;
this.transactionSet = transactionSet;

private volatile ContractAccountSet contractAccountSet;
}

private volatile TransactionSet transactionSet;
public LedgerAdminDataset getAdminDataset() {
return ledgerDataset.getAdminDataset();
}

private volatile LedgerDataSet ledgerDataSet;
public LedgerDataset getLedgerDataset() {
return ledgerDataset;
}

public LedgerState(LedgerBlock block) {
this.block = block;
public ContractAccountQuery getContractAccountSet() {
return ledgerDataset.getContractAccountset();
}

public DataAccountQuery getDataAccountSet() {
return ledgerDataset.getDataAccountSet();
}

public UserAccountQuery getUserAccountSet() {
return ledgerDataset.getUserAccountSet();
}

public TransactionSet getTransactionSet() {
return transactionSet;
}

}

+ 20
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerSecurityManager.java View File

@@ -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<Bytes> endpoints, Set<Bytes> nodes);

}

+ 396
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerSecurityManagerImpl.java View File

@@ -0,0 +1,396 @@
package com.jd.blockchain.ledger.core;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import com.jd.blockchain.ledger.LedgerPermission;
import com.jd.blockchain.ledger.LedgerSecurityException;
import com.jd.blockchain.ledger.ParticipantDataQuery;
import com.jd.blockchain.ledger.ParticipantDoesNotExistException;
import com.jd.blockchain.ledger.RolePrivilegeSettings;
import com.jd.blockchain.ledger.RolePrivileges;
import com.jd.blockchain.ledger.RolesPolicy;
import com.jd.blockchain.ledger.TransactionPermission;
import com.jd.blockchain.ledger.UserDoesNotExistException;
import com.jd.blockchain.ledger.UserRoles;
import com.jd.blockchain.ledger.UserRolesSettings;
import com.jd.blockchain.utils.Bytes;

/**
* 账本安全管理器;
*
* @author huanghaiquan
*
*/
public class LedgerSecurityManagerImpl implements LedgerSecurityManager {

private RolePrivilegeSettings rolePrivilegeSettings;

private UserRolesSettings userRolesSettings;

// 用户的权限配置
private Map<Bytes, UserRolesPrivileges> userPrivilegesCache = new ConcurrentHashMap<>();

private Map<Bytes, UserRoles> userRolesCache = new ConcurrentHashMap<>();
private Map<String, RolePrivileges> rolesPrivilegeCache = new ConcurrentHashMap<>();

private ParticipantDataQuery participantsQuery;
private UserAccountQuery userAccountsQuery;

public LedgerSecurityManagerImpl(RolePrivilegeSettings rolePrivilegeSettings, UserRolesSettings userRolesSettings,
ParticipantDataQuery participantsQuery, UserAccountQuery userAccountsQuery) {
this.rolePrivilegeSettings = rolePrivilegeSettings;
this.userRolesSettings = userRolesSettings;
this.participantsQuery = participantsQuery;
this.userAccountsQuery = userAccountsQuery;
}

@Override
public SecurityPolicy createSecurityPolicy(Set<Bytes> endpoints, Set<Bytes> nodes) {
Map<Bytes, UserRolesPrivileges> endpointPrivilegeMap = new HashMap<>();
Map<Bytes, UserRolesPrivileges> 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<RolePrivileges> 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<Bytes, UserRolesPrivileges> endpointPrivilegeMap = new HashMap<>();

/**
* 节点参与方的权限表;
*/
private Map<Bytes, UserRolesPrivileges> nodePrivilegeMap = new HashMap<>();

private ParticipantDataQuery participantsQuery;

private UserAccountQuery userAccountsQuery;

public UserRolesSecurityPolicy(Map<Bytes, UserRolesPrivileges> endpointPrivilegeMap,
Map<Bytes, UserRolesPrivileges> 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<Bytes> getEndpoints() {
return endpointPrivilegeMap.keySet();
}

@Override
public Set<Bytes> 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 + "]!");
}
}

}

}

+ 10
- 3
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionContext.java View File

@@ -13,18 +13,25 @@ import java.util.List;
public interface LedgerTransactionContext {

/**
* 账本数据;
* 账本数据集合
*
* @return
*/
LedgerDataSet getDataSet();
LedgerDataset getDataset();

/**
* 事务集合;
*
* @return
*/
TransactionSet getTransactionSet();

/**
* 交易请求;
*
* @return
*/
TransactionRequest getRequestTX();
TransactionRequest getTransactionRequest();

/**
* 提交对账本数据的修改,以指定的交易状态提交交易;


source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionData.java → source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionData.java View File

@@ -1,7 +1,4 @@
package com.jd.blockchain.ledger.core.impl;

import java.util.Arrays;
import java.util.Comparator;
package com.jd.blockchain.ledger.core;

import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.DigitalSignature;
@@ -29,48 +26,27 @@ public class LedgerTransactionData implements LedgerTransaction {

private OperationResult[] operationResults;

// private HashDigest adminAccountHash;
//
// private HashDigest userAccountSetHash;
//
// private HashDigest dataAccountSetHash;
//
// private HashDigest contractAccountSetHash;

/**
* Declare a private no-arguments constructor for deserializing purpose;
*/
@SuppressWarnings("unused")
private LedgerTransactionData() {
// this.txSnapshot = new TransactionStagedSnapshot();
}

/**
* @param blockHeight
* 区块链高度;
* @param txReq
* 交易请求;
* @param execState
* 执行状态;
* @param txSnapshot
* 交易级的系统快照;
* @param blockHeight 区块链高度;
* @param txReq 交易请求;
* @param execState 执行状态;
* @param txSnapshot 交易级的系统快照;
*/
public LedgerTransactionData(long blockHeight, TransactionRequest txReq, TransactionState execState,
TransactionStagedSnapshot txSnapshot, OperationResult... opResults) {
this.blockHeight = blockHeight;
// this.txSnapshot = txSnapshot == null ? new TransactionStagedSnapshot() : txSnapshot;
this.txSnapshot = txSnapshot;
this.transactionContent = txReq.getTransactionContent();
this.endpointSignatures = txReq.getEndpointSignatures();
this.nodeSignatures = txReq.getNodeSignatures();
this.executionState = execState;
if (opResults != null) {
Arrays.sort(opResults, new Comparator<OperationResult>() {
@Override
public int compare(OperationResult o1, OperationResult o2) {
return o1.getIndex() - o2.getIndex();
}
});
}
this.operationResults = opResults;
}

@@ -116,17 +92,17 @@ public class LedgerTransactionData implements LedgerTransaction {

@Override
public HashDigest getUserAccountSetHash() {
return txSnapshot == null ? null :txSnapshot.getUserAccountSetHash();
return txSnapshot == null ? null : txSnapshot.getUserAccountSetHash();
}

@Override
public HashDigest getDataAccountSetHash() {
return txSnapshot == null ? null :txSnapshot.getDataAccountSetHash();
return txSnapshot == null ? null : txSnapshot.getDataAccountSetHash();
}

@Override
public HashDigest getContractAccountSetHash() {
return txSnapshot == null ? null :txSnapshot.getContractAccountSetHash();
return txSnapshot == null ? null : txSnapshot.getContractAccountSetHash();
}

public void setTxSnapshot(TransactionStagedSnapshot txSnapshot) {
@@ -140,20 +116,22 @@ public class LedgerTransactionData implements LedgerTransaction {
this.transactionContent = content;
}

public void setEndpointSignatures(Object[] participantSignatures) {
int length = participantSignatures.length;
this.endpointSignatures = new DigitalSignature[length];
for (int i = 0; i < length; i++) {
this.endpointSignatures[i] = (DigitalSignature) participantSignatures[i];
}
public void setEndpointSignatures(DigitalSignature[] participantSignatures) {
this.endpointSignatures = participantSignatures;
// int length = participantSignatures.length;
// this.endpointSignatures = new DigitalSignature[length];
// for (int i = 0; i < length; i++) {
// this.endpointSignatures[i] = (DigitalSignature) participantSignatures[i];
// }
}

public void setNodeSignatures(Object[] nodeSignatures) {
int length = nodeSignatures.length;
this.nodeSignatures = new DigitalSignature[length];
for (int i = 0; i < length; i++) {
this.nodeSignatures[i] = (DigitalSignature) nodeSignatures[i];
}
public void setNodeSignatures(DigitalSignature[] nodeSignatures) {
this.nodeSignatures = nodeSignatures;
// int length = nodeSignatures.length;
// this.nodeSignatures = new DigitalSignature[length];
// for (int i = 0; i < length; i++) {
// this.nodeSignatures[i] = (DigitalSignature) nodeSignatures[i];
// }
}

public void setExecutionState(TransactionState executionState) {

+ 630
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionalEditor.java View File

@@ -0,0 +1,630 @@
package com.jd.blockchain.ledger.core;

import java.util.List;

import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.BlockBody;
import com.jd.blockchain.ledger.BlockRollbackException;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.IllegalTransactionException;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerDataSnapshot;
import com.jd.blockchain.ledger.LedgerInitSetting;
import com.jd.blockchain.ledger.LedgerSettings;
import com.jd.blockchain.ledger.LedgerTransaction;
import com.jd.blockchain.ledger.OperationResult;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.ledger.TransactionRollbackException;
import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.storage.service.utils.BufferedKVStorage;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.codec.Base58Utils;

public class LedgerTransactionalEditor implements LedgerEditor {

private static final boolean PARALLEL_DB_WRITE;

static {
PARALLEL_DB_WRITE = Boolean.getBoolean("parallel-dbwrite");
System.out.println("------ [[ parallel-dbwrite=" + PARALLEL_DB_WRITE + " ]] ------");
}

/**
* 账本Hash,创世区块的编辑器则返回 null;
*/
private HashDigest ledgerHash;

private final String ledgerKeyPrefix;

private CryptoSetting cryptoSetting;

private LedgerBlockData currentBlock;

// private Stack<StagedSnapshot> stagedSnapshots = new Stack<>();

private boolean prepared = false;

private boolean canceled = false;

private boolean committed = false;

private StagedSnapshot startingPoint;

/**
* 当前区块的存储;
*/
private BufferedKVStorage baseStorage;

/**
* 上一个交易产生的账本快照;
*/
private TxSnapshot previousTxSnapshot;

/**
* 当前交易的上下文;
*/
private volatile LedgerTransactionContextImpl currentTxCtx;

/**
* 最后提交的账本数据集;
*/
private volatile LedgerDataset latestLedgerDataset;

/**
* 最后提交的交易集合;
*/
private volatile TransactionSet latestTransactionSet;

/**
* @param ledgerHash
* @param cryptoSetting
* @param currentBlock
* @param startingPoint
* @param ledgerKeyPrefix
* @param bufferedStorage
* @param verifyTx 是否校验交易请求;当外部调用者在调用前已经实施了验证时,将次参数设置为 false 能够提升性能;
*/
private LedgerTransactionalEditor(HashDigest ledgerHash, CryptoSetting cryptoSetting, LedgerBlockData currentBlock,
StagedSnapshot startingPoint, String ledgerKeyPrefix, BufferedKVStorage bufferedStorage) {
this.ledgerHash = ledgerHash;
this.ledgerKeyPrefix = ledgerKeyPrefix;
this.cryptoSetting = cryptoSetting;
this.currentBlock = currentBlock;
this.baseStorage = bufferedStorage;

this.startingPoint = startingPoint;

// this.stagedSnapshots.push(startingPoint);
}

/**
* 创建账本新区块的编辑器;
*
* @param ledgerHash 账本哈希;
* @param ledgerSetting 账本设置;
* @param previousBlock 前置区块;
* @param ledgerKeyPrefix 账本数据前缀;
* @param ledgerExStorage 账本数据存储;
* @param ledgerVerStorage 账本数据版本化存储;
* @param verifyTx 是否校验交易请求;当外部调用者在调用前已经实施了验证时,将次参数设置为 false 能够提升性能;
* @return
*/
public static LedgerTransactionalEditor createEditor(LedgerBlock previousBlock, LedgerSettings ledgerSetting,
String ledgerKeyPrefix, ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage) {
// new block;
HashDigest ledgerHash = previousBlock.getLedgerHash();
if (ledgerHash == null) {
ledgerHash = previousBlock.getHash();
}
if (ledgerHash == null) {
throw new IllegalArgumentException("Illegal previous block was specified!");
}
LedgerBlockData currBlock = new LedgerBlockData(previousBlock.getHeight() + 1, ledgerHash,
previousBlock.getHash());

// init storage;
BufferedKVStorage txStagedStorage = new BufferedKVStorage(ledgerExStorage, ledgerVerStorage, PARALLEL_DB_WRITE);

StagedSnapshot startingPoint = new TxSnapshot(previousBlock, previousBlock.getTransactionSetHash());

// instantiate editor;
return new LedgerTransactionalEditor(ledgerHash, ledgerSetting.getCryptoSetting(), currBlock, startingPoint,
ledgerKeyPrefix, txStagedStorage);
}

/**
* 创建创世区块的编辑器;
*
* @param initSetting
* @param ledgerKeyPrefix
* @param ledgerExStorage
* @param ledgerVerStorage
* @param verifyTx 是否校验交易请求;当外部调用者在调用前已经实施了验证时,将次参数设置为 false 能够提升性能;
* @return
*/
public static LedgerTransactionalEditor createEditor(LedgerInitSetting initSetting, String ledgerKeyPrefix,
ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage) {
LedgerBlockData genesisBlock = new LedgerBlockData(0, null, null);
StagedSnapshot startingPoint = new GenesisSnapshot(initSetting);
// init storage;
BufferedKVStorage txStagedStorage = new BufferedKVStorage(ledgerExStorage, ledgerVerStorage, false);
return new LedgerTransactionalEditor(null, initSetting.getCryptoSetting(), genesisBlock, startingPoint,
ledgerKeyPrefix, txStagedStorage);
}

private void commitTxSnapshot(TxSnapshot snapshot) {
previousTxSnapshot = snapshot;
latestLedgerDataset = currentTxCtx.getDataset();
latestLedgerDataset.setReadonly();
latestTransactionSet = currentTxCtx.getTransactionSet();
latestTransactionSet.setReadonly();
currentTxCtx = null;
}

private void rollbackCurrentTx() {
currentTxCtx = null;
}

LedgerBlock getCurrentBlock() {
return currentBlock;
}

@Override
public long getBlockHeight() {
return currentBlock.getHeight();
}

@Override
public HashDigest getLedgerHash() {
return ledgerHash;
}

@Override
public LedgerDataset getLedgerDataset() {
return latestLedgerDataset;
}

@Override
public TransactionSet getTransactionSet() {
return latestTransactionSet;
}

/**
* 检查当前账本是否是指定交易请求的账本;
*
* @param txRequest
* @return
*/
private boolean isRequestMatched(TransactionRequest txRequest) {
HashDigest reqLedgerHash = txRequest.getTransactionContent().getLedgerHash();
if (ledgerHash == reqLedgerHash) {
return true;
}
if (ledgerHash == null || reqLedgerHash == null) {
return false;
}
return ledgerHash.equals(reqLedgerHash);
}

/**
* 注:此方法不验证交易完整性和签名有效性,仅仅设计为进行交易记录的管理;调用者应在此方法之外进行数据完整性和签名有效性的检查;
*/
@Override
public synchronized LedgerTransactionContext newTransaction(TransactionRequest txRequest) {
// if (SettingContext.txSettings().verifyLedger() && !isRequestMatched(txRequest)) {
if (!isRequestMatched(txRequest)) {
throw new IllegalTransactionException(
"Transaction request is dispatched to a wrong ledger! --[TxHash="
+ txRequest.getTransactionContent().getHash() + "]!",
TransactionState.IGNORED_BY_WRONG_LEDGER);
}

if (currentTxCtx != null) {
throw new IllegalStateException(
"Unable to open another new transaction before the current transaction is completed! --[TxHash="
+ txRequest.getTransactionContent().getHash() + "]!");
}

// 检查状态是否允许创建新的交易请求;;
checkState();

// init storage of new transaction;
BufferedKVStorage txBufferedStorage = new BufferedKVStorage(baseStorage, baseStorage, false);

LedgerDataset txDataset = null;
TransactionSet txset = null;
if (previousTxSnapshot == null) {
// load the starting point of the new transaction;
if (startingPoint instanceof GenesisSnapshot) {
// 准备生成创世区块;
GenesisSnapshot snpht = (GenesisSnapshot) startingPoint;
txDataset = LedgerRepositoryImpl.newDataSet(snpht.initSetting, ledgerKeyPrefix, txBufferedStorage,
txBufferedStorage);
txset = LedgerRepositoryImpl.newTransactionSet(txDataset.getAdminDataset().getSettings(),
ledgerKeyPrefix, txBufferedStorage, txBufferedStorage);
} else if (startingPoint instanceof TxSnapshot) {
// 新的区块;
// TxSnapshot; reload dataset and txset;
TxSnapshot snpht = (TxSnapshot) startingPoint;
// load dataset;
txDataset = LedgerRepositoryImpl.loadDataSet(snpht.dataSnapshot, cryptoSetting, ledgerKeyPrefix,
txBufferedStorage, txBufferedStorage, false);

// load txset;
txset = LedgerRepositoryImpl.loadTransactionSet(snpht.txsetHash, cryptoSetting, ledgerKeyPrefix,
txBufferedStorage, txBufferedStorage, false);
} else {
// Unreachable;
throw new IllegalStateException("Unreachable code was accidentally executed!");
}

} else {
// Reuse previous object to optimize performance;
// load dataset;
txDataset = LedgerRepositoryImpl.loadDataSet(previousTxSnapshot.dataSnapshot, cryptoSetting,
ledgerKeyPrefix, txBufferedStorage, txBufferedStorage, false);

// load txset;
txset = LedgerRepositoryImpl.loadTransactionSet(previousTxSnapshot.txsetHash, cryptoSetting,
ledgerKeyPrefix, txBufferedStorage, txBufferedStorage, false);
}

currentTxCtx = new LedgerTransactionContextImpl(txRequest, txDataset, txset, txBufferedStorage, this);

return currentTxCtx;
}

@Override
public LedgerBlock prepare() {
checkState();

if (currentTxCtx != null) {
// 有进行中的交易尚未提交或回滚;
throw new IllegalStateException(
"There is an ongoing transaction that has been not committed or rolled back!");
}
if (previousTxSnapshot == null) {
// 当前区块没有加入过交易,不允许产生空区块;
throw new IllegalStateException(
"There is no transaction in the current block, and no empty blocks is allowed!");
}

// do commit when transaction isolation level is BLOCK;
currentBlock.setAdminAccountHash(previousTxSnapshot.getAdminAccountHash());
currentBlock.setUserAccountSetHash(previousTxSnapshot.getUserAccountSetHash());
currentBlock.setDataAccountSetHash(previousTxSnapshot.getDataAccountSetHash());
currentBlock.setContractAccountSetHash(previousTxSnapshot.getContractAccountSetHash());
currentBlock.setTransactionSetHash(previousTxSnapshot.getTransactionSetHash());

// TODO: 根据所有交易的时间戳的平均值来生成区块的时间戳;
// long timestamp =
// currentBlock.setTimestamp(timestamp);

// compute block hash;
byte[] blockBodyBytes = BinaryProtocol.encode(currentBlock, BlockBody.class);
HashDigest blockHash = Crypto.getHashFunction(cryptoSetting.getHashAlgorithm()).hash(blockBodyBytes);
currentBlock.setHash(blockHash);

// if (currentBlock.getLedgerHash() == null) {
// // init GenesisBlock's ledger hash;
// currentBlock.setLedgerHash(blockHash);
// }

// persist block bytes;
// only one version per block;
byte[] blockBytes = BinaryProtocol.encode(currentBlock, LedgerBlock.class);
Bytes blockStorageKey = LedgerRepositoryImpl.encodeBlockStorageKey(currentBlock.getHash());
long v = baseStorage.set(blockStorageKey, blockBytes, -1);
if (v < 0) {
throw new IllegalStateException(
"Block already exist! --[BlockHash=" + Base58Utils.encode(currentBlock.getHash().toBytes()) + "]");
}

// persist block hash to ledger index;
HashDigest ledgerHash = currentBlock.getLedgerHash();
if (ledgerHash == null) {
ledgerHash = blockHash;
}
Bytes ledgerIndexKey = LedgerRepositoryImpl.encodeLedgerIndexKey(ledgerHash);
long expectedVersion = currentBlock.getHeight() - 1;
v = baseStorage.set(ledgerIndexKey, currentBlock.getHash().toBytes(), expectedVersion);
if (v < 0) {
throw new IllegalStateException(
String.format("Index of BlockHash already exist! --[BlockHeight=%s][BlockHash=%s]",
currentBlock.getHeight(), currentBlock.getHash()));
}

prepared = true;
return currentBlock;
}

@Override
public void commit() {
if (committed) {
throw new IllegalStateException("The current block has been committed!");
}
if (canceled) {
throw new IllegalStateException("The current block has been canceled!");
}
if (!prepared) {
// 未就绪;
throw new IllegalStateException("The current block is not ready yet!");
}

baseStorage.flush();

committed = true;
}

@Override
public void cancel() {
if (committed) {
throw new IllegalStateException("The current block has been committed!");
}
if (canceled) {
return;
}

canceled = true;

baseStorage.cancel();
}

private void checkState() {
if (prepared) {
throw new IllegalStateException("The current block is ready!");
}
if (committed) {
throw new IllegalStateException("The current block has been committed!");
}
if (canceled) {
throw new IllegalStateException("The current block has been canceled!");
}
}

// --------------------------- inner type --------------------------

/**
* 用于暂存交易上下文数据的快照对象;
*
* @author huanghaiquan
*
*/
private static interface StagedSnapshot {

}

/**
* 创世区块的快照对象;
*
* @author huanghaiquan
*
*/
private static class GenesisSnapshot implements StagedSnapshot {

private LedgerInitSetting initSetting;

public GenesisSnapshot(LedgerInitSetting initSetting) {
this.initSetting = initSetting;
}
}

/**
* 交易执行完毕后的快照对象;
*
* @author huanghaiquan
*
*/
private static class TxSnapshot implements StagedSnapshot {

/**
* 账本数据的快照;
*/
private LedgerDataSnapshot dataSnapshot;

/**
* 交易集合的快照(根哈希);
*/
private HashDigest txsetHash;

public HashDigest getAdminAccountHash() {
return dataSnapshot.getAdminAccountHash();
}

public HashDigest getUserAccountSetHash() {
return dataSnapshot.getUserAccountSetHash();
}

public HashDigest getDataAccountSetHash() {
return dataSnapshot.getDataAccountSetHash();
}

public HashDigest getContractAccountSetHash() {
return dataSnapshot.getContractAccountSetHash();
}

public HashDigest getTransactionSetHash() {
return txsetHash;
}

public TxSnapshot(LedgerDataSnapshot dataSnapshot, HashDigest txsetHash) {
this.dataSnapshot = dataSnapshot;
this.txsetHash = txsetHash;
}

}

/**
* 交易的上下文;
*
* @author huanghaiquan
*
*/
private static class LedgerTransactionContextImpl implements LedgerTransactionContext {

private LedgerTransactionalEditor blockEditor;

private TransactionRequest txRequest;

private LedgerDataset dataset;

private TransactionSet txset;

private BufferedKVStorage storage;

private boolean committed = false;

private boolean rollbacked = false;

private LedgerTransaction transaction;

private HashDigest txRootHash;

private LedgerTransactionContextImpl(TransactionRequest txRequest, LedgerDataset dataset,
TransactionSet txset, BufferedKVStorage storage, LedgerTransactionalEditor editor) {
this.txRequest = txRequest;
this.dataset = dataset;
this.txset = txset;
this.storage = storage;
this.blockEditor = editor;
}

@Override
public LedgerDataset getDataset() {
return dataset;
}

@Override
public TransactionSet getTransactionSet() {
return txset;
}

@Override
public TransactionRequest getTransactionRequest() {
return txRequest;
}

@Override
public LedgerTransaction commit(TransactionState txResult) {
return commit(txResult, null);
}

@Override
public LedgerTransaction commit(TransactionState txResult, List<OperationResult> operationResults) {
checkTxState();

// capture snapshot
this.dataset.commit();
TransactionStagedSnapshot txDataSnapshot = takeDataSnapshot();

LedgerTransactionData tx;
try {
tx = new LedgerTransactionData(blockEditor.getBlockHeight(), txRequest, txResult, txDataSnapshot,
operationResultArray(operationResults));
this.txset.add(tx);
this.txset.commit();
} catch (Exception e) {
throw new TransactionRollbackException(e.getMessage(), e);
}

try {
this.storage.flush();
} catch (Exception e) {
throw new BlockRollbackException(e.getMessage(), e);
}

// put snapshot into stack;
TxSnapshot snapshot = new TxSnapshot(txDataSnapshot, txset.getRootHash());
blockEditor.commitTxSnapshot(snapshot);

committed = true;
return tx;
}

@Override
public LedgerTransaction discardAndCommit(TransactionState txResult) {
return discardAndCommit(txResult, null);
}

@Override
public LedgerTransaction discardAndCommit(TransactionState txResult, List<OperationResult> operationResults) {
checkTxState();

// 未处理
dataset.cancel();

TransactionStagedSnapshot txDataSnapshot = takeDataSnapshot();

LedgerTransactionData tx;
try {
tx = new LedgerTransactionData(blockEditor.getBlockHeight(), txRequest, txResult, txDataSnapshot,
operationResultArray(operationResults));
this.txset.add(tx);
this.txset.commit();
} catch (Exception e) {
throw new TransactionRollbackException(e.getMessage(), e);
}

try {
this.storage.flush();
} catch (Exception e) {
throw new BlockRollbackException(e.getMessage(), e);
}

// put snapshot into stack;
TxSnapshot snapshot = new TxSnapshot(txDataSnapshot, txset.getRootHash());
blockEditor.commitTxSnapshot(snapshot);

committed = true;
return tx;
}

private TransactionStagedSnapshot takeDataSnapshot() {
TransactionStagedSnapshot txDataSnapshot = new TransactionStagedSnapshot();
txDataSnapshot.setAdminAccountHash(dataset.getAdminDataset().getHash());
txDataSnapshot.setContractAccountSetHash(dataset.getContractAccountset().getRootHash());
txDataSnapshot.setDataAccountSetHash(dataset.getDataAccountSet().getRootHash());
txDataSnapshot.setUserAccountSetHash(dataset.getUserAccountSet().getRootHash());
return txDataSnapshot;
}

private OperationResult[] operationResultArray(List<OperationResult> operationResults) {
OperationResult[] operationResultArray = null;
if (operationResults != null && !operationResults.isEmpty()) {
operationResultArray = new OperationResult[operationResults.size()];
operationResults.toArray(operationResultArray);
}
return operationResultArray;
}

@Override
public void rollback() {
if (this.rollbacked) {
return;
}
if (this.committed) {
throw new IllegalStateException("This transaction had been committed!");
}
dataset.cancel();
storage.cancel();

blockEditor.rollbackCurrentTx();

rollbacked = true;
}

private void checkTxState() {
if (this.committed) {
throw new IllegalStateException("This transaction had been committed!");
}
if (this.rollbacked) {
throw new IllegalStateException("This transaction had been rollbacked!");
}
}
}

}

+ 1
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataEntry.java View File

@@ -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 {


Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save