Browse Source

Merge branch 'developold' into feature/regist_participant

# Conflicts:
#	source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java
#	source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminAccount.java
#	source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantCertData.java
#	source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantDataset.java
#	source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/DefaultOperationHandleRegisteration.java
#	source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/ContractInvokingTest.java
#	source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerManagerTest.java
#	source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionSetTest.java
#	source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerInitProperties.java
#	source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ClientOperator.java
#	source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ConsensusParticipantData.java
#	source/peer/src/main/java/com/jd/blockchain/peer/web/ManagementController.java
#	source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/converters/ClientResolveUtil.java
#	source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerPerformanceTest.java
#	source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/Utils.java
#	source/tools/tools-capability/src/main/java/com/jd/blockchain/capability/service/SettingsInit.java
#	source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/MockerNodeContext.java
tags/1.1.0
huanghaiquan 5 years ago
parent
commit
467e7b513b
100 changed files with 4593 additions and 1876 deletions
  1. +6
    -0
      newfeatures-authorize.txt
  2. +0
    -8
      source/base/pom.xml
  3. +43
    -8
      source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java
  4. +2
    -2
      source/consensus/consensus-mq/src/main/java/com/jd/blockchain/consensus/mq/MsgQueueConsensusSettingsBuilder.java
  5. +4
    -4
      source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractDeployExeUtil.java
  6. +3
    -3
      source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractDeployMojo.java
  7. +187
    -0
      source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/KeyGenUtils.java
  8. +0
    -0
      source/deployment/deployment-gateway/conf/application-gw.properties
  9. +6
    -4
      source/deployment/deployment-gateway/src/main/java/com/jd/blockchain/gateway/boot/GatewayBooter.java
  10. +3
    -9
      source/gateway/pom.xml
  11. +7
    -7
      source/gateway/src/main/java/com/jd/blockchain/gateway/GatewayServerBooter.java
  12. +0
    -50
      source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryService.java
  13. +0
    -144
      source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryServiceHandler.java
  14. +550
    -516
      source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java
  15. +3
    -0
      source/gateway/src/main/java/com/jd/blockchain/gateway/web/GatewayWebServerConfigurer.java
  16. +0
    -26
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountPrivilege.java
  17. +5
    -4
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountSet.java
  18. +0
    -168
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AuthorizableDataSet.java
  19. +0
    -40
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Authorization.java
  20. +0
    -42
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AuthorizationVO.java
  21. +4
    -3
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/BaseAccount.java
  22. +0
    -21
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Consensus.java
  23. +2
    -2
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java
  24. +29
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccountQuery.java
  25. +11
    -1
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccountSet.java
  26. +1
    -1
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/CryptoConfig.java
  27. +1
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java
  28. +32
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountQuery.java
  29. +10
    -1
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountSet.java
  30. +132
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DefaultOperationHandleRegisteration.java
  31. +209
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/EmptyLedgerDataset.java
  32. +98
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/FullPermissionedSecurityManager.java
  33. +0
    -22
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Gateway.java
  34. +1
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/GenesisLedgerStorageProxy.java
  35. +12
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminDataQuery.java
  36. +469
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminDataset.java
  37. +0
    -5
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminPrivilege.java
  38. +0
    -16
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdministration.java
  39. +1
    -1
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerBlockData.java
  40. +3
    -3
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerConfiguration.java
  41. +19
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerDataQuery.java
  42. +0
    -21
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerDataSet.java
  43. +22
    -17
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerDataset.java
  44. +18
    -3
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerEditor.java
  45. +2
    -2
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitProposal.java
  46. +4
    -3
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitProposalData.java
  47. +215
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitializer.java
  48. +12
    -10
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerManage.java
  49. +14
    -21
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerManager.java
  50. +45
    -37
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerQueryService.java
  51. +12
    -15
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerRepository.java
  52. +153
    -211
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerRepositoryImpl.java
  53. +20
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerSecurityManager.java
  54. +396
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerSecurityManagerImpl.java
  55. +9
    -2
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionContext.java
  56. +1
    -1
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionData.java
  57. +52
    -87
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionalEditor.java
  58. +1
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataEntry.java
  59. +53
    -21
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataSet.java
  60. +1
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleProvable.java
  61. +3
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleTree.java
  62. +21
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MultiIDsPolicy.java
  63. +1
    -2
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OpeningAccessPolicy.java
  64. +10
    -32
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OperationHandle.java
  65. +15
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OperationHandleContext.java
  66. +9
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OperationHandleRegisteration.java
  67. +0
    -21
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/P2PRealm.java
  68. +4
    -3
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantCertData.java
  69. +21
    -10
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantDataset.java
  70. +0
    -2
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/PermissionService.java
  71. +0
    -21
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/PrivilegeDataSet.java
  72. +293
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RolePrivilegeDataset.java
  73. +38
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SecurityContext.java
  74. +142
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SecurityPolicy.java
  75. +51
    -51
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SettingContext.java
  76. +120
    -37
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionBatchProcessor.java
  77. +20
    -22
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionEngineImpl.java
  78. +0
    -70
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionRequestContext.java
  79. +115
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionRequestExtension.java
  80. +108
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionRequestExtensionImpl.java
  81. +5
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionSet.java
  82. +1
    -1
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionStagedSnapshot.java
  83. +31
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccountQuery.java
  84. +12
    -1
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccountSet.java
  85. +196
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRoleDataset.java
  86. +63
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRolesPrivileges.java
  87. +73
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/AbstractLedgerOperationHandle.java
  88. +34
    -18
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/AbtractContractEventSendOperationHandle.java
  89. +37
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ContractCodeDeployOperationHandle.java
  90. +7
    -2
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ContractLedgerContext.java
  91. +47
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/DataAccountKVSetOperationHandle.java
  92. +36
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/DataAccountRegisterOperationHandle.java
  93. +4
    -12
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/JVMContractEventSendOperationHandle.java
  94. +27
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/LedgerInitOperationHandle.java
  95. +0
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ParticipantRegisterOperationHandle.java
  96. +0
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ParticipantStateUpdateOperationHandle.java
  97. +50
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/RolesConfigureOperationHandle.java
  98. +78
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/UserAuthorizeOperationHandle.java
  99. +38
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/UserRegisterOperationHandle.java
  100. +0
    -9
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionContextImpl.java

+ 6
- 0
newfeatures-authorize.txt View File

@@ -0,0 +1,6 @@


1、网关节点移除查询接口 HTTP GET ledgers/{ledgerHash}/settings (出于设计合理性原因)


2、网关节点增加查询接口 HTTP GET ledgers/{ledgerHash}/admininfo ,接口返回指定账本管理配置信息;

+ 0
- 8
source/base/pom.xml View File

@@ -8,12 +8,4 @@
<version>1.1.0-SNAPSHOT</version>
</parent>
<artifactId>base</artifactId>

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

</dependencies>
</project>

+ 43
- 8
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;
@@ -55,12 +57,37 @@ public interface DataCodes {
public static final int TX_RESPONSE = 0x360;

public static final int TX_OP_RESULT = 0x370;
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;

@@ -68,6 +95,15 @@ public interface DataCodes {

public static final int METADATA_CONSENSUS_PARTICIPANT = 0x621;

// public static final int METADATA_CONSENSUS_NODE = 0x630;
//
// public static final int METADATA_CONSENSUS_SETTING = 0x631;
//
// public static final int METADATA_PARTICIPANT_INFO = 0x640;

public static final int METADATA_CRYPTO_SETTING = 0x642;


// public static final int METADATA_CONSENSUS_NODE = 0x630;

public static final int METADATA_CONSENSUS_SETTING = 0x631;
@@ -88,11 +124,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;


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

@@ -21,10 +21,10 @@ import com.jd.blockchain.consensus.mq.settings.MsgQueueConsensusSettings;
import com.jd.blockchain.consensus.mq.settings.MsgQueueNetworkSettings;
import com.jd.blockchain.consensus.mq.settings.MsgQueueNodeSettings;
import com.jd.blockchain.crypto.AddressEncoding;
import com.jd.blockchain.crypto.KeyGenUtils;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.ParticipantInfo;
import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.tools.keygen.KeyGenCommand;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.PropertiesUtils;
import com.jd.blockchain.utils.codec.Base58Utils;
@@ -134,7 +134,7 @@ public class MsgQueueConsensusSettingsBuilder implements ConsensusSettingsBuilde
String keyOfPubkey = nodeKey(PUBKEY_PATTERN, id);

String base58PubKey = PropertiesUtils.getRequiredProperty(resolvingProps, keyOfPubkey);
PubKey pubKey = KeyGenCommand.decodePubKey(base58PubKey);
PubKey pubKey = KeyGenUtils.decodePubKey(base58PubKey);

// PubKey pubKey = new PubKey(Base58Utils.decode(base58PubKey));
resolvingProps.remove(keyOfPubkey);


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

@@ -7,12 +7,12 @@ import java.io.InputStream;

import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.KeyGenUtils;
import com.jd.blockchain.crypto.PrivKey;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.*;
import com.jd.blockchain.sdk.BlockchainService;
import com.jd.blockchain.sdk.client.GatewayServiceFactory;
import com.jd.blockchain.tools.keygen.KeyGenCommand;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.codec.Base58Utils;
import com.jd.blockchain.utils.net.NetworkAddress;
@@ -30,8 +30,8 @@ public enum ContractDeployExeUtil {
PubKey pub = null;
PrivKey prv = null;
try {
prv = KeyGenCommand.readPrivKey(prvPath, KeyGenCommand.encodePassword(rawPassword));
pub = KeyGenCommand.readPubKey(pubPath);
prv = KeyGenUtils.readPrivKey(prvPath, KeyGenUtils.encodePassword(rawPassword));
pub = KeyGenUtils.readPubKey(pubPath);

} catch (Exception e) {
e.printStackTrace();
@@ -47,7 +47,7 @@ public enum ContractDeployExeUtil {
BlockchainKeypair contractKeyPair = BlockchainKeyGenerator.getInstance().generate();
pub = contractKeyPair.getPubKey();
}else {
pub = KeyGenCommand.readPubKey(pubPath);
pub = KeyGenUtils.readPubKey(pubPath);
}

} catch (Exception e) {


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

@@ -1,10 +1,10 @@
package com.jd.blockchain;

import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.KeyGenUtils;
import com.jd.blockchain.crypto.PrivKey;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.BlockchainKeypair;
import com.jd.blockchain.tools.keygen.KeyGenCommand;
import com.jd.blockchain.utils.StringUtils;
import com.jd.blockchain.utils.codec.Base58Utils;
import com.jd.blockchain.utils.io.FileUtils;
@@ -102,8 +102,8 @@ public class ContractDeployMojo extends AbstractMojo {
byte[] contractBytes = FileUtils.readBytes(contractPath);


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



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

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


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


+ 3
- 9
source/gateway/pom.xml View File

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

<dependency>
@@ -98,18 +97,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
- 50
source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayQueryService.java View File

@@ -1,50 +0,0 @@
package com.jd.blockchain.gateway.service;

import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.sdk.ContractSettings;
import com.jd.blockchain.sdk.LedgerInitSettings;
import com.jd.blockchain.utils.Bytes;

/**
* queryService only for gateway;
* @Author zhaogw
* @Date 2019/2/22 10:37
*/
public interface GatewayQueryService {
/**
* get all ledgers hashs;
* @param fromIndex
* @param count
*/
HashDigest[] getLedgersHash(int fromIndex, int count);

/**
* get the participants by range;
* @param ledgerHash
* @param fromIndex
* @param count
* @return
*/
ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash, int fromIndex, int count);

/**
* 获取账本初始化配置信息
*
* @param ledgerHash
* 账本Hash
* @return
*/
LedgerInitSettings getLedgerInitSettings(HashDigest ledgerHash);

/**
* 获取账本指定合约信息
*
* @param ledgerHash
* 账本Hash
* @param address
* 合约地址
* @return
*/
ContractSettings getContractSettings(HashDigest ledgerHash, String address);
}

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

@@ -1,144 +0,0 @@
package com.jd.blockchain.gateway.service;

import com.jd.blockchain.consensus.ConsensusProvider;
import com.jd.blockchain.consensus.ConsensusProviders;
import com.jd.blockchain.consensus.ConsensusSettings;
import com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider;
import com.jd.blockchain.consensus.mq.MsgQueueConsensusProvider;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.gateway.PeerService;
import com.jd.blockchain.gateway.decompiler.utils.DecompilerUtils;
import com.jd.blockchain.ledger.ContractInfo;
import com.jd.blockchain.ledger.LedgerMetadata;
import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.sdk.ContractSettings;
import com.jd.blockchain.sdk.LedgerInitSettings;
import com.jd.blockchain.utils.QueryUtil;
import com.jd.blockchain.utils.codec.HexUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;


/**
* @Author zhaogw
* @Date 2019/2/22 10:39
*/
@Component
public class GatewayQueryServiceHandler implements GatewayQueryService {

@Autowired
private PeerService peerService;

@Override
public HashDigest[] getLedgersHash(int fromIndex, int count) {
HashDigest ledgersHash[] = peerService.getQueryService().getLedgerHashs();
int indexAndCount[] = QueryUtil.calFromIndexAndCount(fromIndex,count,ledgersHash.length);
HashDigest ledgersHashNew[] = Arrays.copyOfRange(ledgersHash,indexAndCount[0],indexAndCount[0]+indexAndCount[1]);
return ledgersHashNew;
}

@Override
public ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash, int fromIndex, int count) {
ParticipantNode participantNode[] = peerService.getQueryService().getConsensusParticipants(ledgerHash);
int indexAndCount[] = QueryUtil.calFromIndexAndCount(fromIndex,count,participantNode.length);
ParticipantNode participantNodesNew[] = Arrays.copyOfRange(participantNode,indexAndCount[0],indexAndCount[0]+indexAndCount[1]);
return participantNodesNew;
}

@Override
public LedgerInitSettings getLedgerInitSettings(HashDigest ledgerHash) {

ParticipantNode[] participantNodes = peerService.getQueryService().getConsensusParticipants(ledgerHash);

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

return initLedgerInitSettings(participantNodes, ledgerMetadata);
}

@Override
public ContractSettings getContractSettings(HashDigest ledgerHash, String address) {
ContractInfo contractInfo = peerService.getQueryService().getContract(ledgerHash, address);
return contractSettings(contractInfo);
}

private ContractSettings contractSettings(ContractInfo contractInfo) {
ContractSettings contractSettings = new ContractSettings(contractInfo.getAddress(), contractInfo.getPubKey(), contractInfo.getRootHash());
byte[] chainCodeBytes = contractInfo.getChainCode();
// 将反编译chainCode
String mainClassJava = DecompilerUtils.decompileMainClassFromBytes(chainCodeBytes);
contractSettings.setChainCode(mainClassJava);
return contractSettings;
}

/**
* 初始化账本配置
*
* @param participantNodes
* 参与方列表
* @param ledgerMetadata
* 账本元数据
* @return
*/
private LedgerInitSettings initLedgerInitSettings(ParticipantNode[] participantNodes, LedgerMetadata ledgerMetadata) {
LedgerInitSettings ledgerInitSettings = new LedgerInitSettings();

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

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

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

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

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

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

return ledgerInitSettings;
}

/**
* 初始化账本种子信息
*
* @param seedBytes
* 种子的字节数组显示
* @return
* 种子以十六进制方式显示,为方便阅读,每隔八个字符中间以"-"分割
*/
private String initSeed(byte[] seedBytes) {
String seedString = HexUtils.encode(seedBytes);
// 每隔八个字符中加入一个一个横线
StringBuffer seed = new StringBuffer();

for( int i = 0; i < seedString.length(); i++) {
char c = seedString.charAt(i);
if (i != 0 && i % 8 == 0) {
seed.append("-");
}
seed.append(c);
}

return seed.toString();
}

/**
* 初始化共识配置
*
* @param ledgerMetadata
* 账本元数据
* @return
*/
private ConsensusSettings initConsensusSettings(LedgerMetadata ledgerMetadata) {
String consensusProvider = ledgerMetadata.getSetting().getConsensusProvider();
ConsensusProvider provider = ConsensusProviders.getProvider(consensusProvider);
byte[] consensusSettingsBytes = ledgerMetadata.getSetting().getConsensusSetting().toBytes();
return provider.getSettingsFactory().getConsensusSettingsEncoder().decode(consensusSettingsBytes);
}
}

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


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

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

DataContractRegistry.register(LedgerAdminInfo.class);
}




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

}

+ 5
- 4
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();


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


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

@@ -8,6 +8,7 @@ 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 {


+ 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);

}

+ 10
- 1
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountSet.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 DataAccountSet implements MerkleProvable, Transactional {
public class DataAccountSet implements MerkleProvable, Transactional, DataAccountQuery {
private AccountSet accountSet;
@@ -25,6 +26,7 @@ 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);
}
@@ -33,11 +35,16 @@ public class DataAccountSet implements MerkleProvable, Transactional {
return accountSet.isReadonly();
}
void setReadonly() {
accountSet.setReadonly();
}
@Override
public HashDigest getRootHash() {
return accountSet.getRootHash();
}
@Override
public long getTotalCount() {
return accountSet.getTotalCount();
}
@@ -63,6 +70,7 @@ public class DataAccountSet implements MerkleProvable, Transactional {
* @param address
* @return
*/
@Override
public DataAccount getDataAccount(Bytes address) {
BaseAccount accBase = accountSet.getAccount(address);
if (accBase == null) {
@@ -71,6 +79,7 @@ public class DataAccountSet implements MerkleProvable, Transactional {
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;

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

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

}

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

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

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

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

/**
* 开始新事务;<br>
*
* 方法返回之前,将会校验交易请求的用户签名列表和节点签名列表,并在后续对数据集
* {@link LedgerTransactionContext#getDataSet()} 的操作时,校验这些用户和节点是否具备权限;<br>
* {@link LedgerTransactionContext#getDataset()} 的操作时,校验这些用户和节点是否具备权限;<br>
*
* 校验失败将引发异常 {@link LedgerException};
* <p>
@@ -52,7 +66,8 @@ public interface LedgerEditor {
*
*
*
* 注:方法不解析、不执行交易中的操作;<p>
* 注:方法不解析、不执行交易中的操作;
* <p>
*
* @param txRequest 交易请求;
* @return


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,19 +1,25 @@
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;
@@ -42,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
@@ -93,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();
}

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

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

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

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

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

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

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

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

@@ -240,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);

}
@@ -249,7 +263,7 @@ 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));
}

@@ -260,7 +274,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];
@@ -308,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];
@@ -339,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());
@@ -351,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();
@@ -361,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));
}

@@ -369,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]);
}
@@ -378,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]);
}
@@ -387,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,23 +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.SettingContext;
import com.jd.blockchain.ledger.core.TransactionSet;
import com.jd.blockchain.ledger.core.UserAccountSet;
import com.jd.blockchain.ledger.BlockBody;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerAdminInfo;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerDataSnapshot;
import com.jd.blockchain.ledger.LedgerInitSetting;
import com.jd.blockchain.ledger.LedgerSettings;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes;
@@ -36,7 +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);

@@ -80,6 +74,8 @@ public class LedgerRepositoryImpl implements LedgerRepository {
if (getLatestBlockHeight() < 0) {
throw new RuntimeException("Ledger doesn't exist!");
}

retrieveLatestState();
}

/*
@@ -110,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
@@ -187,7 +185,7 @@ public class LedgerRepositoryImpl implements LedgerRepository {
if (height < 0) {
return null;
}
return innerGetBlock(getBlockHash(height));
return innerGetBlock(innerGetBlockHash(height));
}

@Override
@@ -209,26 +207,18 @@ public class LedgerRepositoryImpl implements LedgerRepository {
throw new RuntimeException("Block hash not equals to it's storage key!");
}

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

// verify height;
@@ -243,9 +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,140 +254,96 @@ 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
@@ -401,9 +356,8 @@ public class LedgerRepositoryImpl implements LedgerRepository {
"A new block is in process, cann't create another one until it finish by committing or canceling.");
}
LedgerBlock previousBlock = getLatestBlock();
LedgerTransactionalEditor editor = LedgerTransactionalEditor.createEditor(previousBlock,
getAdminInfo().getMetadata().getSetting(), keyPrefix, exPolicyStorage,
versioningStorage);
LedgerTransactionalEditor editor = LedgerTransactionalEditor.createEditor(previousBlock, getLatestSettings(),
keyPrefix, exPolicyStorage, versioningStorage);
NewBlockCommittingMonitor committingMonitor = new NewBlockCommittingMonitor(editor, this);
this.nextBlockEditor = committingMonitor;
return committingMonitor;
@@ -426,64 +380,39 @@ public class LedgerRepositoryImpl implements LedgerRepository {
}

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

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

return BLOCK_PREFIX.concat(blockHash);
}

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

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

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

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

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

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

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

return newDataSet;
}

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

String txsetKeyPrefix = keyPrefix + TRANSACTION_SET_PREFIX;

@@ -492,13 +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,
@@ -586,6 +498,16 @@ public class LedgerRepositoryImpl implements LedgerRepository {
return editor.getBlockHeight();
}

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

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

@Override
public LedgerTransactionContext newTransaction(TransactionRequest txRequest) {
return editor.newTransaction(txRequest);
@@ -601,7 +523,8 @@ public class LedgerRepositoryImpl implements LedgerRepository {
try {
editor.commit();
LedgerBlock latestBlock = editor.getCurrentBlock();
ledgerRepo.latestState = new LedgerState(latestBlock);
ledgerRepo.latestState = new LedgerState(latestBlock, editor.getLedgerDataset(),
editor.getTransactionSet());
} finally {
ledgerRepo.nextBlockEditor = null;
}
@@ -628,20 +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 + "]!");
}
}

}

}

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

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

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

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

/**
* 交易请求;


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,4 +1,4 @@
package com.jd.blockchain.ledger.core.impl;
package com.jd.blockchain.ledger.core;

import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.DigitalSignature;

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

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

import java.util.List;

@@ -8,29 +8,19 @@ import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.BlockBody;
import com.jd.blockchain.ledger.BlockRollbackException;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.DigitalSignature;
import com.jd.blockchain.ledger.IllegalTransactionException;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerDataSnapshot;
import com.jd.blockchain.ledger.LedgerInitSetting;
import com.jd.blockchain.ledger.LedgerSetting;
import com.jd.blockchain.ledger.LedgerSettings;
import com.jd.blockchain.ledger.LedgerTransaction;
import com.jd.blockchain.ledger.OperationResult;
import com.jd.blockchain.ledger.TransactionContent;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.ledger.TransactionRollbackException;
import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.ledger.core.LedgerDataSet;
import com.jd.blockchain.ledger.core.LedgerEditor;
import com.jd.blockchain.ledger.core.LedgerTransactionContext;
import com.jd.blockchain.ledger.core.SettingContext;
import com.jd.blockchain.ledger.core.TransactionSet;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.storage.service.utils.BufferedKVStorage;
import com.jd.blockchain.transaction.SignatureUtils;
import com.jd.blockchain.transaction.TxBuilder;
import com.jd.blockchain.transaction.TxRequestBuilder;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.codec.Base58Utils;

@@ -70,10 +60,8 @@ public class LedgerTransactionalEditor implements LedgerEditor {
private BufferedKVStorage baseStorage;

/**
* 上一个交易的上下文
* 上一个交易产生的账本快照
*/
// private LedgerTransactionContextImpl previousTxCtx;

private TxSnapshot previousTxSnapshot;

/**
@@ -81,6 +69,16 @@ public class LedgerTransactionalEditor implements LedgerEditor {
*/
private volatile LedgerTransactionContextImpl currentTxCtx;

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

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

/**
* @param ledgerHash
* @param cryptoSetting
@@ -115,7 +113,7 @@ public class LedgerTransactionalEditor implements LedgerEditor {
* @param verifyTx 是否校验交易请求;当外部调用者在调用前已经实施了验证时,将次参数设置为 false 能够提升性能;
* @return
*/
public static LedgerTransactionalEditor createEditor(LedgerBlock previousBlock, LedgerSetting ledgerSetting,
public static LedgerTransactionalEditor createEditor(LedgerBlock previousBlock, LedgerSettings ledgerSetting,
String ledgerKeyPrefix, ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage) {
// new block;
HashDigest ledgerHash = previousBlock.getLedgerHash();
@@ -160,6 +158,10 @@ public class LedgerTransactionalEditor implements LedgerEditor {

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

@@ -181,13 +183,23 @@ public class LedgerTransactionalEditor implements LedgerEditor {
return ledgerHash;
}

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

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

/**
* 检查当前账本是否是指定交易请求的账本;
*
* @param txRequest
* @return
*/
private boolean isRequestedLedger(TransactionRequest txRequest) {
private boolean isRequestMatched(TransactionRequest txRequest) {
HashDigest reqLedgerHash = txRequest.getTransactionContent().getLedgerHash();
if (ledgerHash == reqLedgerHash) {
return true;
@@ -198,49 +210,19 @@ public class LedgerTransactionalEditor implements LedgerEditor {
return ledgerHash.equals(reqLedgerHash);
}

private boolean verifyTxContent(TransactionRequest request) {
TransactionContent txContent = request.getTransactionContent();
if (!TxBuilder.verifyTxContentHash(txContent, txContent.getHash())) {
return false;
}
DigitalSignature[] endpointSignatures = request.getEndpointSignatures();
if (endpointSignatures != null) {
for (DigitalSignature signature : endpointSignatures) {
if (!SignatureUtils.verifyHashSignature(txContent.getHash(), signature.getDigest(),
signature.getPubKey())) {
return false;
}
}
}
DigitalSignature[] nodeSignatures = request.getNodeSignatures();
if (nodeSignatures != null) {
for (DigitalSignature signature : nodeSignatures) {
if (!SignatureUtils.verifyHashSignature(txContent.getHash(), signature.getDigest(),
signature.getPubKey())) {
return false;
}
}
}
return true;
}

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

// TODO: 把验签和创建交易并行化;
if (SettingContext.txSettings().verifySignature() && !verifyTxContent(txRequest)) {
// 抛弃哈希和签名校验失败的交易请求;
throw new IllegalTransactionException(
"Wrong transaction signature! --[TxHash=" + txRequest.getTransactionContent().getHash() + "]!",
TransactionState.IGNORED_BY_WRONG_CONTENT_SIGNATURE);
}

if (currentTxCtx != null) {
throw new IllegalStateException(
"Unable to open another new transaction before the current transaction is completed! --[TxHash="
@@ -253,7 +235,7 @@ public class LedgerTransactionalEditor implements LedgerEditor {
// init storage of new transaction;
BufferedKVStorage txBufferedStorage = new BufferedKVStorage(baseStorage, baseStorage, false);

LedgerDataSetImpl txDataset = null;
LedgerDataset txDataset = null;
TransactionSet txset = null;
if (previousTxSnapshot == null) {
// load the starting point of the new transaction;
@@ -262,18 +244,18 @@ public class LedgerTransactionalEditor implements LedgerEditor {
GenesisSnapshot snpht = (GenesisSnapshot) startingPoint;
txDataset = LedgerRepositoryImpl.newDataSet(snpht.initSetting, ledgerKeyPrefix, txBufferedStorage,
txBufferedStorage);
txset = LedgerRepositoryImpl.newTransactionSet(txDataset.getAdminAccount().getSetting(),
txset = LedgerRepositoryImpl.newTransactionSet(txDataset.getAdminDataset().getSettings(),
ledgerKeyPrefix, txBufferedStorage, txBufferedStorage);
} else if (startingPoint instanceof TxSnapshot) {
// 新的区块;
// TxSnapshot; reload dataset and txset;
TxSnapshot snpht = (TxSnapshot) startingPoint;
// load dataset;
txDataset = LedgerRepositoryImpl.loadDataSet(snpht.dataSnapshot, ledgerKeyPrefix, txBufferedStorage,
txBufferedStorage, false);
txDataset = LedgerRepositoryImpl.loadDataSet(snpht.dataSnapshot, cryptoSetting, ledgerKeyPrefix,
txBufferedStorage, txBufferedStorage, false);

// load txset;
txset = LedgerRepositoryImpl.loadTransactionSet(snpht.txsetHash, this.cryptoSetting, ledgerKeyPrefix,
txset = LedgerRepositoryImpl.loadTransactionSet(snpht.txsetHash, cryptoSetting, ledgerKeyPrefix,
txBufferedStorage, txBufferedStorage, false);
} else {
// Unreachable;
@@ -283,11 +265,11 @@ public class LedgerTransactionalEditor implements LedgerEditor {
} else {
// Reuse previous object to optimize performance;
// load dataset;
txDataset = LedgerRepositoryImpl.loadDataSet(previousTxSnapshot.dataSnapshot, ledgerKeyPrefix,
txBufferedStorage, txBufferedStorage, false);
txDataset = LedgerRepositoryImpl.loadDataSet(previousTxSnapshot.dataSnapshot, cryptoSetting,
ledgerKeyPrefix, txBufferedStorage, txBufferedStorage, false);

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

@@ -476,28 +458,6 @@ public class LedgerTransactionalEditor implements LedgerEditor {

}

// /**
// * 账本的数据上下文;
// *
// * @author huanghaiquan
// *
// */
// private static class LedgerDataContext {
//
// protected LedgerDataSetImpl dataset;
//
// protected TransactionSet txset;
//
// protected BufferedKVStorage storage;
//
// public LedgerDataContext(LedgerDataSetImpl dataset, TransactionSet txset, BufferedKVStorage storage) {
// this.dataset = dataset;
// this.txset = txset;
// this.storage = storage;
// }
//
// }

/**
* 交易的上下文;
*
@@ -510,7 +470,7 @@ public class LedgerTransactionalEditor implements LedgerEditor {

private TransactionRequest txRequest;

private LedgerDataSetImpl dataset;
private LedgerDataset dataset;

private TransactionSet txset;

@@ -524,7 +484,7 @@ public class LedgerTransactionalEditor implements LedgerEditor {

private HashDigest txRootHash;

private LedgerTransactionContextImpl(TransactionRequest txRequest, LedgerDataSetImpl dataset,
private LedgerTransactionContextImpl(TransactionRequest txRequest, LedgerDataset dataset,
TransactionSet txset, BufferedKVStorage storage, LedgerTransactionalEditor editor) {
this.txRequest = txRequest;
this.dataset = dataset;
@@ -534,10 +494,15 @@ public class LedgerTransactionalEditor implements LedgerEditor {
}

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

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

@Override
public TransactionRequest getTransactionRequest() {
return txRequest;
@@ -620,8 +585,8 @@ public class LedgerTransactionalEditor implements LedgerEditor {

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

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


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

@@ -3,11 +3,14 @@ package com.jd.blockchain.ledger.core;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.MerkleDataNode;
import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy;
import com.jd.blockchain.storage.service.VersioningKVEntry;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.storage.service.utils.BufferedKVStorage;
import com.jd.blockchain.storage.service.utils.VersioningKVData;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.Transactional;
import com.jd.blockchain.utils.io.BytesUtils;
@@ -62,12 +65,9 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
/**
* 创建一个新的 MerkleDataSet;
*
* @param setting
* 密码设置;
* @param exPolicyStorage
* 默克尔树的存储;
* @param versioningStorage
* 数据的存储;
* @param setting 密码设置;
* @param exPolicyStorage 默克尔树的存储;
* @param versioningStorage 数据的存储;
*/
public MerkleDataSet(CryptoSetting setting, String keyPrefix, ExPolicyKVStorage exPolicyStorage,
VersioningKVStorage versioningStorage) {
@@ -126,6 +126,10 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
return readonly;
}
void setReadonly() {
this.readonly = true;
}
public long getDataCount() {
return merkleTree.getDataCount();
}
@@ -150,8 +154,27 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
return values;
}
public VersioningKVEntry[] getLatestDataEntries(int fromIndex, int count) {
if (count > LedgerConsts.MAX_LIST_COUNT) {
throw new IllegalArgumentException("Count exceed the upper limit[" + LedgerConsts.MAX_LIST_COUNT + "]!");
}
if (fromIndex < 0 || (fromIndex + count) > merkleTree.getDataCount()) {
throw new IllegalArgumentException("Index out of bound!");
}
VersioningKVEntry[] values = new VersioningKVEntry[count];
byte[] bytesValue;
for (int i = 0; i < count; i++) {
MerkleDataNode dataNode = merkleTree.getData(fromIndex + i);
Bytes dataKey = encodeDataKey(dataNode.getKey());
bytesValue = valueStorage.get(dataKey, dataNode.getVersion());
values[i] = new VersioningKVData(dataNode.getKey(), dataNode.getVersion(), bytesValue);
}
return values;
}
/**
* get the data at the specific index;
*
* @param fromIndex
* @return
*/
@@ -163,6 +186,7 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
/**
* get the key at the specific index;
*
* @param fromIndex
* @return
*/
@@ -171,7 +195,6 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
return dataNode.getKey().toUTF8String();
}
/**
* Create or update the value associated the specified key if the version
* checking is passed.<br>
@@ -183,12 +206,9 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
* 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 latest version of the key.
* @param key The key of data;
* @param value The value of data;
* @param version The expected latest version of the key.
* @return The new version of the key. <br>
* If the key is new created success, then return 0; <br>
* If the key is updated success, then return the new version;<br>
@@ -210,12 +230,9 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
* 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 latest version of the key.
* @param key The key of data;
* @param value The value of data;
* @param version The expected latest version of the key.
* @return The new version of the key. <br>
* If the key is new created success, then return 0; <br>
* If the key is updated success, then return the new version;<br>
@@ -404,12 +421,22 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
return getDataEntry(Bytes.fromString(key));
}
/**
*
* @param key
* @return Null if the key doesn't exist!
*/
public VersioningKVEntry getDataEntry(Bytes key) {
long latestVersion = getMerkleVersion(key);
if (latestVersion < 0) {
return null;
}
return valueStorage.getEntry(key, latestVersion);
Bytes dataKey = encodeDataKey(key);
byte[] value = valueStorage.get(dataKey, latestVersion);
if (value == null) {
return null;
}
return new VersioningKVData(key, latestVersion, value);
}
public VersioningKVEntry getDataEntry(Bytes key, long version) {
@@ -420,7 +447,12 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
return null;
}
version = version < 0 ? latestVersion : version;
return valueStorage.getEntry(key, version);
Bytes dataKey = encodeDataKey(key);
byte[] value = valueStorage.get(dataKey, version);
if (value == null) {
return null;
}
return new VersioningKVData(key, version, value);
}
public MerkleDataEntry getMerkleEntry(Bytes key, long version) {


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

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

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

public interface MerkleProvable {


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

@@ -20,6 +20,9 @@ import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.HashFunction;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.MerkleDataNode;
import com.jd.blockchain.ledger.MerkleNode;
import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy;
import com.jd.blockchain.utils.Bytes;


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

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

/**
* 多重身份的校验策略;
*
* @author huanghaiquan
*
*/
public enum MultiIDsPolicy {

/**
* 至少有一个都能通过;
*/
AT_LEAST_ONE,

/**
* 每一个都能通过;
*/
ALL

}

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

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

import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.core.AccountAccessPolicy;
import com.jd.blockchain.utils.Bytes;

/**

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

@@ -2,8 +2,6 @@ package com.jd.blockchain.ledger.core;

import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.ledger.core.impl.OperationHandleContext;


public interface OperationHandle {

@@ -13,42 +11,22 @@ public interface OperationHandle {
* @param operationType
* @return
*/
boolean support(Class<?> operationType);
Class<?> getOperationType();

/**
* 同步解析和执行操作;
*
*
* @param op
* 操作实例;
* @param newBlockDataset
* 需要修改的新区块的数据集;
* @param requestContext
* 交易请求上下文;
* @param previousBlockDataset
* 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集;
* @param op 操作实例;
* @param newBlockDataset 需要修改的新区块的数据集;
* @param requestContext 交易请求上下文;
* @param previousBlockDataset 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集;注:此数据集是只读的;
*
* @return 操作执行结果
* @param handleContext 操作上下文;`
* @param ledgerService
* @return
*/
BytesValue process(Operation op, LedgerDataSet newBlockDataset, TransactionRequestContext requestContext,
LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService);
BytesValue process(Operation op, LedgerDataset newBlockDataset, TransactionRequestExtension requestContext,
LedgerDataQuery previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService);

// /**
// * 异步解析和执行操作;
// * TODO 未来规划实现
// *
// *
// * @param op
// * 操作实例;
// * @param newBlockDataset
// * 需要修改的新区块的数据集;
// * @param requestContext
// * 交易请求上下文;
// * @param previousBlockDataset
// * 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集;
// *
// * @return 操作执行结果
// */
// AsyncFuture<byte[]> asyncProcess(Operation op, LedgerDataSet newBlockDataset, TransactionRequestContext requestContext,
// LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService);
}

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

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

import com.jd.blockchain.ledger.Operation;

/**
* 在交易处理过程中,提供对多种交易操作处理器互相调用的机制;
*
* @author huanghaiquan
*
*/
public interface OperationHandleContext {

void handle(Operation operation);

}

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

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

import com.jd.blockchain.ledger.Operation;

public interface OperationHandleRegisteration {

OperationHandle getHandle(Class<? extends Operation> operationType);

}

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

@@ -1,21 +0,0 @@
package com.jd.blockchain.ledger.core;
/**
* @author hhq
* @version 1.0
* @created 14-6��-2018 12:13:33
*/
public class P2PRealm {
public Peer m_Peer;
public P2PRealm(){
}
public void finalize() throws Throwable {
}
}

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

@@ -2,6 +2,7 @@ package com.jd.blockchain.ledger.core;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.ledger.ParticipantNodeState;
/**
@@ -13,7 +14,7 @@ import com.jd.blockchain.ledger.ParticipantNodeState;
public class ParticipantCertData implements ParticipantNode {
private int id;
private String address;
private Bytes address;
private String name;
private PubKey pubKey;
private ParticipantNodeState participantNodeState;
@@ -29,14 +30,14 @@ public class ParticipantCertData implements ParticipantNode {
this.participantNodeState = participantNode.getParticipantNodeState();
}
public ParticipantCertData(String address, String name, PubKey pubKey) {
public ParticipantCertData(Bytes address, String name, PubKey pubKey) {
this.address = address;
this.name = name;
this.pubKey = pubKey;
}
@Override
public String getAddress() {
public Bytes getAddress() {
return address;
}


source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantDataSet.java → source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantDataset.java View File

@@ -4,14 +4,16 @@ import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.ledger.ParticipantDataQuery;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.Transactional;

public class ParticipantDataSet implements Transactional, MerkleProvable {
public class ParticipantDataset implements Transactional, MerkleProvable, ParticipantDataQuery {

static {
DataContractRegistry.register(ParticipantNode.class);
@@ -19,12 +21,12 @@ public class ParticipantDataSet implements Transactional, MerkleProvable {

private MerkleDataSet dataset;

public ParticipantDataSet(CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exPolicyStorage,
public ParticipantDataset(CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exPolicyStorage,
VersioningKVStorage verStorage) {
dataset = new MerkleDataSet(cryptoSetting, prefix, exPolicyStorage, verStorage);
}

public ParticipantDataSet(HashDigest merkleRootHash, CryptoSetting cryptoSetting, String prefix,
public ParticipantDataset(HashDigest merkleRootHash, CryptoSetting cryptoSetting, String prefix,
ExPolicyKVStorage exPolicyStorage, VersioningKVStorage verStorage, boolean readonly) {
dataset = new MerkleDataSet(merkleRootHash, cryptoSetting, prefix, exPolicyStorage, verStorage, readonly);
}
@@ -54,6 +56,7 @@ public class ParticipantDataSet implements Transactional, MerkleProvable {
dataset.cancel();
}

@Override
public long getParticipantCount() {
return dataset.getDataCount();
}
@@ -92,9 +95,15 @@ public class ParticipantDataSet implements Transactional, MerkleProvable {
}
}

private Bytes encodeKey(String address) {
// return id + "";
return Bytes.fromString(address);
private Bytes encodeKey(Bytes address) {
return address;
}

@Override
public boolean contains(Bytes address) {
Bytes key = encodeKey(address);
long latestVersion = dataset.getVersion(key);
return latestVersion > -1;
}

/**
@@ -106,7 +115,8 @@ public class ParticipantDataSet implements Transactional, MerkleProvable {
* @param address
* @return
*/
public ParticipantNode getParticipant(String address) {
@Override
public ParticipantNode getParticipant(Bytes address) {
Bytes key = encodeKey(address);
byte[] bytes = dataset.getValue(key);
if (bytes == null) {
@@ -114,11 +124,12 @@ public class ParticipantDataSet implements Transactional, MerkleProvable {
}
return BinaryProtocol.decode(bytes);
}

@Override
public ParticipantNode[] getParticipants() {
byte[][] bytes = dataset.getLatestValues(0, (int)dataset.getDataCount());
byte[][] bytes = dataset.getLatestValues(0, (int) dataset.getDataCount());
ParticipantNode[] pns = new ParticipantNode[bytes.length];
for (int i = 0; i < pns.length; i++) {
pns[i] = BinaryProtocol.decode(bytes[i]);
}

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

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

import java.util.SortedSet;

public interface PermissionService {
boolean checkLedgerPermission();


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

@@ -1,21 +0,0 @@
//package com.jd.blockchain.ledger.core;
//
//import com.jd.blockchain.crypto.hash.HashDigest;
//import com.jd.blockchain.ledger.data.DigitalSignatureBlob;
//
//import my.utils.io.ExistentialKVStorage;
//import my.utils.io.VersioningKVStorage;
//
//public class PrivilegeDataSet extends GenericMerkleDataSet<Authorization, AuthorizationVO> {
//
// public PrivilegeDataSet(CryptoSetting setting, ExistentialKVStorage merkleTreeStorage, VersioningKVStorage dataStorage) {
// this(null, setting, merkleTreeStorage, dataStorage, false);
// }
//
// public PrivilegeDataSet(HashDigest rootHash, CryptoSetting setting, ExistentialKVStorage merkleTreeStorage,
// VersioningKVStorage dataStorage, boolean readonly) {
// super(rootHash, setting, merkleTreeStorage, dataStorage, readonly, Authorization.class, AuthorizationVO.class,
// DigitalSignatureBlob.class);
// }
//
//}

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

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

import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.LedgerPermission;
import com.jd.blockchain.ledger.LedgerPrivilege;
import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.ledger.PrivilegeSet;
import com.jd.blockchain.ledger.Privileges;
import com.jd.blockchain.ledger.RolePrivilegeSettings;
import com.jd.blockchain.ledger.RolePrivileges;
import com.jd.blockchain.ledger.TransactionPermission;
import com.jd.blockchain.ledger.TransactionPrivilege;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVEntry;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.Transactional;

public class RolePrivilegeDataset implements Transactional, MerkleProvable, RolePrivilegeSettings {

private MerkleDataSet dataset;

public RolePrivilegeDataset(CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exPolicyStorage,
VersioningKVStorage verStorage) {
dataset = new MerkleDataSet(cryptoSetting, prefix, exPolicyStorage, verStorage);
}

public RolePrivilegeDataset(HashDigest merkleRootHash, CryptoSetting cryptoSetting, String prefix,
ExPolicyKVStorage exPolicyStorage, VersioningKVStorage verStorage, boolean readonly) {
dataset = new MerkleDataSet(merkleRootHash, cryptoSetting, prefix, exPolicyStorage, verStorage, readonly);
}

@Override
public HashDigest getRootHash() {
return dataset.getRootHash();
}

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

@Override
public boolean isUpdated() {
return dataset.isUpdated();
}

@Override
public void commit() {
dataset.commit();
}

@Override
public void cancel() {
dataset.cancel();
}

@Override
public long getRoleCount() {
return dataset.getDataCount();
}

@Override
public long addRolePrivilege(String roleName, Privileges privileges) {
return addRolePrivilege(roleName, privileges.getLedgerPrivilege(), privileges.getTransactionPrivilege());
}

@Override
public long addRolePrivilege(String roleName, LedgerPrivilege ledgerPrivilege, TransactionPrivilege txPrivilege) {
RolePrivileges roleAuth = new RolePrivileges(roleName, -1, ledgerPrivilege, txPrivilege);
long nv = setRolePrivilege(roleAuth);
if (nv < 0) {
throw new LedgerException("Role[" + roleName + "] already exist!");
}
return nv;
}

@Override
public long addRolePrivilege(String roleName, LedgerPermission[] ledgerPermissions,
TransactionPermission[] txPermissions) {
LedgerPrivilege ledgerPrivilege = new LedgerPrivilege();
for (LedgerPermission lp : ledgerPermissions) {
ledgerPrivilege.enable(lp);
}
TransactionPrivilege txPrivilege = new TransactionPrivilege();
for (TransactionPermission tp : txPermissions) {
txPrivilege.enable(tp);
}
return addRolePrivilege(roleName, ledgerPrivilege, txPrivilege);
}

/**
* 设置角色权限; <br>
* 如果版本校验不匹配,则返回 -1;
*
* @param roleAuth
* @return
*/
private long setRolePrivilege(RolePrivileges roleAuth) {
if (roleAuth.getRoleName().length() > MAX_ROLE_NAME_LENGTH) {
throw new LedgerException("Too long role name!");
}
Bytes key = encodeKey(roleAuth.getRoleName());
byte[] privilegeBytes = BinaryProtocol.encode(roleAuth, PrivilegeSet.class);
return dataset.setValue(key, privilegeBytes, roleAuth.getVersion());
}

/**
* 更新角色权限; <br>
* 如果指定的角色不存在,或者版本不匹配,则引发 {@link LedgerException} 异常;
*
* @param participant
*/
@Override
public void updateRolePrivilege(RolePrivileges roleAuth) {
long nv = setRolePrivilege(roleAuth);
if (nv < 0) {
throw new LedgerException("Update to RoleAuthorization[" + roleAuth.getRoleName()
+ "] failed due to wrong version[" + roleAuth.getVersion() + "] !");
}
}

/**
* 授权角色指定的权限; <br>
* 如果角色不存在,则返回 -1;
*
* @param roleName 角色;
* @param permissions 权限列表;
* @return
*/
@Override
public long enablePermissions(String roleName, LedgerPermission... permissions) {
RolePrivileges roleAuth = getRolePrivilege(roleName);
if (roleAuth == null) {
return -1;
}
roleAuth.getLedgerPrivilege().enable(permissions);
return setRolePrivilege(roleAuth);
}

/**
* 授权角色指定的权限; <br>
* 如果角色不存在,则返回 -1;
*
* @param roleName 角色;
* @param permissions 权限列表;
* @return
*/
@Override
public long enablePermissions(String roleName, TransactionPermission... permissions) {
RolePrivileges roleAuth = getRolePrivilege(roleName);
if (roleAuth == null) {
return -1;
}
roleAuth.getTransactionPrivilege().enable(permissions);
return setRolePrivilege(roleAuth);
}

/**
* 禁止角色指定的权限; <br>
* 如果角色不存在,则返回 -1;
*
* @param roleName 角色;
* @param permissions 权限列表;
* @return
*/
@Override
public long disablePermissions(String roleName, LedgerPermission... permissions) {
RolePrivileges roleAuth = getRolePrivilege(roleName);
if (roleAuth == null) {
return -1;
}
roleAuth.getLedgerPrivilege().disable(permissions);
return setRolePrivilege(roleAuth);
}

/**
* 禁止角色指定的权限; <br>
* 如果角色不存在,则返回 -1;
*
* @param roleName 角色;
* @param permissions 权限列表;
* @return
*/
@Override
public long disablePermissions(String roleName, TransactionPermission... permissions) {
RolePrivileges roleAuth = getRolePrivilege(roleName);
if (roleAuth == null) {
return -1;
}
roleAuth.getTransactionPrivilege().disable(permissions);
return setRolePrivilege(roleAuth);
}

/**
* 授权角色指定的权限; <br>
* 如果角色不存在,则返回 -1;
*
* @param roleName
* @param ledgerPermissions
* @param txPermissions
* @return
*/
@Override
public long enablePermissions(String roleName, LedgerPermission[] ledgerPermissions,
TransactionPermission[] txPermissions) {
RolePrivileges roleAuth = getRolePrivilege(roleName);
if (roleAuth == null) {
return -1;
}
roleAuth.getLedgerPrivilege().enable(ledgerPermissions);
roleAuth.getTransactionPrivilege().enable(txPermissions);
return setRolePrivilege(roleAuth);
}

/**
* 禁用角色指定的权限; <br>
* 如果角色不存在,则返回 -1;
*
* @param roleName
* @param ledgerPermissions
* @param txPermissions
* @return
*/
@Override
public long disablePermissions(String roleName, LedgerPermission[] ledgerPermissions,
TransactionPermission[] txPermissions) {
RolePrivileges roleAuth = getRolePrivilege(roleName);
if (roleAuth == null) {
return -1;
}
roleAuth.getLedgerPrivilege().disable(ledgerPermissions);
roleAuth.getTransactionPrivilege().disable(txPermissions);
return setRolePrivilege(roleAuth);
}

private Bytes encodeKey(String address) {
// return id + "";
return Bytes.fromString(address);
}

/**
* 查询角色权限;
*
* <br>
* 如果不存在,则返回 null;
*
* @param address
* @return
*/
@Override
public RolePrivileges getRolePrivilege(String roleName) {
// 只返回最新版本;
Bytes key = encodeKey(roleName);
VersioningKVEntry kv = dataset.getDataEntry(key);
if (kv == null) {
return null;
}
PrivilegeSet privilege = BinaryProtocol.decode(kv.getValue());
return new RolePrivileges(roleName, kv.getVersion(), privilege);
}

@Override
public RolePrivileges[] getRolePrivileges(int index, int count) {
VersioningKVEntry[] kvEntries = dataset.getLatestDataEntries(index, count);
RolePrivileges[] pns = new RolePrivileges[kvEntries.length];
PrivilegeSet privilege;
for (int i = 0; i < pns.length; i++) {
privilege = BinaryProtocol.decode(kvEntries[i].getValue());
pns[i] = new RolePrivileges(kvEntries[i].getKey().toUTF8String(), kvEntries[i].getVersion(), privilege);
}
return pns;
}

@Override
public RolePrivileges[] getRolePrivileges() {
return getRolePrivileges(0, (int) getRoleCount());
}

@Override
public boolean isReadonly() {
return dataset.isReadonly();
}

@Override
public boolean contains(String roleName) {
Bytes key = encodeKey(roleName);
return dataset.getVersion(key) > -1;
}
}

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

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

import java.util.Set;

import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.LedgerPermission;
import com.jd.blockchain.ledger.LedgerSecurityException;
import com.jd.blockchain.ledger.TransactionPermission;

public class SecurityContext {

private static ThreadLocal<SecurityPolicy> policyHolder = new ThreadLocal<SecurityPolicy>();

public static void setContextUsersPolicy(SecurityPolicy policy) {
policyHolder.set(policy);
}

public static SecurityPolicy removeContextUsersPolicy() {
SecurityPolicy p = policyHolder.get();
policyHolder.remove();
return p;
}

public static SecurityPolicy getContextUsersPolicy() {
return policyHolder.get();
}

/**
* 把上下文安全策略切换为指定的策略,并执行参数指定的 {@link Runnable} 操作,当操作完成后恢复原来的上下文策略;
*
* @param contextUsersPolicy
* @param runnable
*/
public static void switchContextUsersPolicy(SecurityPolicy contextUsersPolicy, Runnable runnable) {

}

}

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

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

import java.util.Set;

import com.jd.blockchain.ledger.LedgerPermission;
import com.jd.blockchain.ledger.LedgerSecurityException;
import com.jd.blockchain.ledger.TransactionPermission;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.utils.Bytes;

/**
* 针对特定交易请求的账本安全策略;
*
* @author huanghaiquan
*
*/
public interface SecurityPolicy {

/**
* 签署交易的终端用户的地址列表;(来自{@link TransactionRequest#getEndpointSignatures()})
*
* @return
*/
Set<Bytes> getEndpoints();

/**
* 签署交易的节点参与方的地址列表(来自{@link TransactionRequest#getNodeSignatures()})
*
* @return
*/
Set<Bytes> getNodes();

/**
* 终端身份是否合法;
*
* @param midPolicy
* @return
*/
boolean isEndpointValid(MultiIDsPolicy midPolicy);

/**
* 节点身份是否合法;
*
* @param midPolicy
* @return
*/
boolean isNodeValid(MultiIDsPolicy midPolicy);

/**
* 检查签署交易的终端用户(来自{@link TransactionRequest#getEndpointSignatures()})是否被授权了参数指定的权限;<br>
*
* @param permission 要检查的权限;
* @param midPolicy 针对多个签名用户的权限策略;
* @return 返回 true 表示获得授权; 返回 false 表示未获得授权;
*/
boolean isEndpointEnable(LedgerPermission permission, MultiIDsPolicy midPolicy);

/**
* 检查签署交易的终端用户(来自{@link TransactionRequest#getEndpointSignatures()})是否被授权了参数指定的权限;<br>
*
* @param permission 要检查的权限;
* @param midPolicy 针对多个签名用户的权限策略;
* @return 返回 true 表示获得授权; 返回 false 表示未获得授权;
*/
boolean isEndpointEnable(TransactionPermission permission, MultiIDsPolicy midPolicy);

/**
* 检查签署交易的节点参与方(来自{@link TransactionRequest#getNodeSignatures()})是否被授权了参数指定的权限;<br>
*
* @param permission 要检查的权限;
* @param midPolicy 针对多个签名用户的权限策略;
* @return 返回 true 表示获得授权; 返回 false 表示未获得授权;
*/
boolean isNodeEnable(LedgerPermission permission, MultiIDsPolicy midPolicy);

/**
* 检查签署交易的节点参与方(来自{@link TransactionRequest#getNodeSignatures()})是否被授权了参数指定的权限;<br>
*
* @param permission 要检查的权限;
* @param midPolicy 针对多个签名用户的权限策略;
* @return 返回 true 表示获得授权; 返回 false 表示未获得授权;
*/
boolean isNodeEnable(TransactionPermission permission, MultiIDsPolicy midPolicy);

/**
* 检查终端身份的合法性;
*
* @param midPolicy
* @throws LedgerSecurityException
*/
void checkEndpointValidity(MultiIDsPolicy midPolicy) throws LedgerSecurityException;
/**
* 检查节点身份的合法性;
*
* @param midPolicy
* @throws LedgerSecurityException
*/
void checkNodeValidity(MultiIDsPolicy midPolicy) throws LedgerSecurityException;

/**
* 检查签署交易的终端用户(来自{@link TransactionRequest#getEndpointSignatures()})是否被授权了参数指定的权限;<br>
* 如果未获授权,方法将引发 {@link LedgerSecurityException} 异常;
*
* @param permission 要检查的权限;
* @param midPolicy 针对多个签名用户的权限策略;
* @throws LedgerSecurityException
*/
void checkEndpointPermission(LedgerPermission permission, MultiIDsPolicy midPolicy) throws LedgerSecurityException;

/**
* 检查签署交易的终端用户(来自{@link TransactionRequest#getEndpointSignatures()})是否被授权了参数指定的权限;<br>
* 如果未获授权,方法将引发 {@link LedgerSecurityException} 异常;
*
* @param permission
* @param midPolicy
* @throws LedgerSecurityException
*/
void checkEndpointPermission(TransactionPermission permission, MultiIDsPolicy midPolicy)
throws LedgerSecurityException;

/**
* 检查签署交易的节点参与方(来自{@link TransactionRequest#getNodeSignatures()})是否被授权了参数指定的权限;<br>
* 如果未获授权,方法将引发 {@link LedgerSecurityException} 异常;
*
* @param permission
* @param midPolicy
* @throws LedgerSecurityException
*/
void checkNodePermission(LedgerPermission permission, MultiIDsPolicy midPolicy) throws LedgerSecurityException;

/**
* 检查签署交易的节点参与方(来自{@link TransactionRequest#getNodeSignatures()})是否被授权了参数指定的权限;<br>
* 如果未获授权,方法将引发 {@link LedgerSecurityException} 异常;
*
* @param permission
* @param midPolicy
* @throws LedgerSecurityException
*/
void checkNodePermission(TransactionPermission permission, MultiIDsPolicy midPolicy) throws LedgerSecurityException;

}

+ 51
- 51
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SettingContext.java View File

@@ -1,51 +1,51 @@
package com.jd.blockchain.ledger.core;
public class SettingContext {
private static final TxSettingContext txSettings = new TxSettingContext();
private static final QueryingSettingContext queryingSettings = new QueryingSettingContext();
public static TxSettingContext txSettings() {
return txSettings;
}
public static QueryingSettingContext queryingSettings() {
return queryingSettings;
}
/**
* 与交易处理相关的设置;
* @author huanghaiquan
*
*/
public static class TxSettingContext {
public boolean verifyLedger() {
return true;
}
public boolean verifySignature() {
return true;
}
}
/**
* 与账本查询相关的设置;
* @author huanghaiquan
*
*/
public static class QueryingSettingContext {
/**
* 查询区块等具有 hash 标识符的对象时是否重新校验哈希;
* @return
*/
public boolean verifyHash() {
return false;
}
}
}
//package com.jd.blockchain.ledger.core;
//
//public class SettingContext {
//
// private static final TxSettingContext txSettings = new TxSettingContext();
//
// private static final QueryingSettingContext queryingSettings = new QueryingSettingContext();
//
// public static TxSettingContext txSettings() {
// return txSettings;
// }
//
// public static QueryingSettingContext queryingSettings() {
// return queryingSettings;
// }
//
// /**
// * 与交易处理相关的设置;
// * @author huanghaiquan
// *
// */
// public static class TxSettingContext {
//
// public boolean verifyLedger() {
// return true;
// }
//
// public boolean verifySignature() {
// return true;
// }
//
// }
//
// /**
// * 与账本查询相关的设置;
// * @author huanghaiquan
// *
// */
// public static class QueryingSettingContext {
//
// /**
// * 查询区块等具有 hash 标识符的对象时是否重新校验哈希;
// * @return
// */
// public boolean verifyHash() {
// return false;
// }
//
// }
//
//}

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

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

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

@@ -15,35 +16,37 @@ import com.jd.blockchain.ledger.DataAccountDoesNotExistException;
import com.jd.blockchain.ledger.IllegalTransactionException;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.LedgerPermission;
import com.jd.blockchain.ledger.LedgerSecurityException;
import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.ledger.OperationResult;
import com.jd.blockchain.ledger.OperationResultData;
import com.jd.blockchain.ledger.ParticipantDoesNotExistException;
import com.jd.blockchain.ledger.TransactionContent;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.ledger.TransactionResponse;
import com.jd.blockchain.ledger.TransactionRollbackException;
import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.ledger.UserDoesNotExistException;
import com.jd.blockchain.ledger.core.LedgerDataSet;
import com.jd.blockchain.ledger.core.LedgerEditor;
import com.jd.blockchain.ledger.core.LedgerService;
import com.jd.blockchain.ledger.core.LedgerTransactionContext;
import com.jd.blockchain.ledger.core.OperationHandle;
import com.jd.blockchain.ledger.core.TransactionRequestContext;
import com.jd.blockchain.ledger.core.TransactionRequestExtension.Credential;
import com.jd.blockchain.service.TransactionBatchProcess;
import com.jd.blockchain.service.TransactionBatchResult;
import com.jd.blockchain.service.TransactionBatchResultHandle;
import com.jd.blockchain.transaction.SignatureUtils;
import com.jd.blockchain.transaction.TxBuilder;
import com.jd.blockchain.transaction.TxResponseMessage;
import com.jd.blockchain.utils.Bytes;

public class TransactionBatchProcessor implements TransactionBatchProcess {

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

private LedgerSecurityManager securityManager;

private LedgerService ledgerService;

private LedgerEditor newBlockEditor;

private LedgerDataSet previousBlockDataset;
private LedgerDataQuery ledgerQueryer;

private OperationHandleRegisteration opHandles;

@@ -57,14 +60,15 @@ public class TransactionBatchProcessor implements TransactionBatchProcess {
private TransactionBatchResult batchResult;

/**
* @param newBlockEditor 新区块的数据编辑器;
* @param previousBlockDataset 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集;
* @param opHandles 操作处理对象注册表;
* @param newBlockEditor 新区块的数据编辑器;
* @param ledgerQueryer 账本查询器,只包含新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集;
* @param opHandles 操作处理对象注册表;
*/
public TransactionBatchProcessor(LedgerEditor newBlockEditor, LedgerDataSet previousBlockDataset,
OperationHandleRegisteration opHandles, LedgerService ledgerService) {
public TransactionBatchProcessor(LedgerSecurityManager securityManager, LedgerEditor newBlockEditor,
LedgerDataQuery ledgerQueryer, OperationHandleRegisteration opHandles, LedgerService ledgerService) {
this.securityManager = securityManager;
this.newBlockEditor = newBlockEditor;
this.previousBlockDataset = previousBlockDataset;
this.ledgerQueryer = ledgerQueryer;
this.opHandles = opHandles;
this.ledgerService = ledgerService;
}
@@ -82,12 +86,26 @@ public class TransactionBatchProcessor implements TransactionBatchProcess {
try {
LOGGER.debug("Start handling transaction... --[BlockHeight={}][RequestHash={}][TxHash={}]",
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash());

TransactionRequestExtension reqExt = new TransactionRequestExtensionImpl(request);

// 初始化交易的用户安全策略;
SecurityPolicy securityPolicy = securityManager.createSecurityPolicy(reqExt.getEndpointAddresses(),
reqExt.getNodeAddresses());
SecurityContext.setContextUsersPolicy(securityPolicy);

// 安全校验;
checkSecurity(securityPolicy);

// 验证交易请求;
checkRequest(reqExt);

// 创建交易上下文;
// 此调用将会验证交易签名,验签失败将会抛出异常,同时,不记录签名错误的交易到链上;
LedgerTransactionContext txCtx = newBlockEditor.newTransaction(request);

// 处理交易;
resp = handleTx(request, txCtx);
resp = handleTx(reqExt, txCtx);

LOGGER.debug("Complete handling transaction. --[BlockHeight={}][RequestHash={}][TxHash={}]",
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash());
@@ -99,10 +117,9 @@ public class TransactionBatchProcessor implements TransactionBatchProcess {
"Ignore transaction caused by IllegalTransactionException! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(),
e.getMessage()), e);
} catch (BlockRollbackException e) {
// 抛弃发生处理异常的交易请求;
// resp = discard(request, TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK);
// 发生区块级别的处理异常,向上重新抛出异常进行处理,整个区块可能被丢弃;
LOGGER.error(String.format(
"Ignore transaction caused by BlockRollbackException! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(),
@@ -116,12 +133,79 @@ public class TransactionBatchProcessor implements TransactionBatchProcess {
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(),
e.getMessage()), e);

} finally {
// 清空交易的用户安全策略;
SecurityContext.removeContextUsersPolicy();
}

responseList.add(resp);
return resp;
}

/**
* 执行安全验证;
*/
private void checkSecurity(SecurityPolicy securityPolicy) {
// 验证节点和终端身份的合法性;
// 多重身份签署的必须全部身份都合法;
securityPolicy.checkEndpointValidity(MultiIDsPolicy.ALL);
securityPolicy.checkNodeValidity(MultiIDsPolicy.ALL);

// 验证参与方节点是否具有核准交易的权限;
securityPolicy.checkNodePermission(LedgerPermission.APPROVE_TX, MultiIDsPolicy.AT_LEAST_ONE);
}

private void checkRequest(TransactionRequestExtension reqExt) {
// TODO: 把验签和创建交易并行化;
checkTxContentHash(reqExt);
checkEndpointSignatures(reqExt);
checkNodeSignatures(reqExt);
}

private void checkTxContentHash(TransactionRequestExtension requestExt) {
TransactionContent txContent = requestExt.getTransactionContent();
if (!TxBuilder.verifyTxContentHash(txContent, txContent.getHash())) {
// 由于哈希校验失败,引发IllegalTransactionException,使外部调用抛弃此交易请求;
throw new IllegalTransactionException(
"Wrong transaction content hash! --[TxHash=" + requestExt.getTransactionContent().getHash() + "]!",
TransactionState.IGNORED_BY_WRONG_CONTENT_SIGNATURE);
}
}

private void checkNodeSignatures(TransactionRequestExtension request) {
TransactionContent txContent = request.getTransactionContent();
Collection<Credential> nodes = request.getNodes();
if (nodes != null) {
for (Credential node : nodes) {
if (!SignatureUtils.verifyHashSignature(txContent.getHash(), node.getSignature().getDigest(),
node.getPubKey())) {
// 由于签名校验失败,引发IllegalTransactionException,使外部调用抛弃此交易请求;
throw new IllegalTransactionException(
String.format("Wrong transaction node signature! --[Tx Hash=%s][Node Signer=%s]!",
request.getTransactionContent().getHash(), node.getAddress()),
TransactionState.IGNORED_BY_WRONG_CONTENT_SIGNATURE);
}
}
}
}

private void checkEndpointSignatures(TransactionRequestExtension request) {
TransactionContent txContent = request.getTransactionContent();
Collection<Credential> endpoints = request.getEndpoints();
if (endpoints != null) {
for (Credential endpoint : endpoints) {
if (!SignatureUtils.verifyHashSignature(txContent.getHash(), endpoint.getSignature().getDigest(),
endpoint.getPubKey())) {
// 由于签名校验失败,引发IllegalTransactionException,使外部调用抛弃此交易请求;
throw new IllegalTransactionException(
String.format("Wrong transaction endpoint signature! --[Tx Hash=%s][Endpoint Signer=%s]!",
request.getTransactionContent().getHash(), endpoint.getAddress()),
TransactionState.IGNORED_BY_WRONG_CONTENT_SIGNATURE);
}
}
}
}

/**
* 处理交易;<br>
*
@@ -131,23 +215,11 @@ public class TransactionBatchProcessor implements TransactionBatchProcess {
* @param txCtx
* @return
*/
private TransactionResponse handleTx(TransactionRequest request, LedgerTransactionContext txCtx) {
private TransactionResponse handleTx(TransactionRequestExtension request, LedgerTransactionContext txCtx) {
TransactionState result;
List<OperationResult> operationResults = new ArrayList<>();
try {
LedgerDataSet dataset = txCtx.getDataSet();
TransactionRequestContext reqCtx = new TransactionRequestContextImpl(request);
// TODO: 验证签名者的有效性;
for (Bytes edpAddr : reqCtx.getEndpoints()) {
if (!previousBlockDataset.getUserAccountSet().contains(edpAddr)) {
throw new LedgerException("The endpoint signer[" + edpAddr + "] was not registered!");
}
}
for (Bytes edpAddr : reqCtx.getNodes()) {
if (!previousBlockDataset.getUserAccountSet().contains(edpAddr)) {
throw new LedgerException("The node signer[" + edpAddr + "] was not registered!");
}
}
LedgerDataset dataset = txCtx.getDataset();

// 执行操作;
Operation[] ops = request.getTransactionContent().getOperations();
@@ -157,14 +229,14 @@ public class TransactionBatchProcessor implements TransactionBatchProcess {
// assert; Instance of operation are one of User related operations or
// DataAccount related operations;
OperationHandle hdl = opHandles.getHandle(operation.getClass());
hdl.process(operation, dataset, reqCtx, previousBlockDataset, this, ledgerService);
hdl.process(operation, dataset, request, ledgerQueryer, this, ledgerService);
}
};
OperationHandle opHandle;
int opIndex = 0;
for (Operation op : ops) {
opHandle = opHandles.getHandle(op.getClass());
BytesValue opResult = opHandle.process(op, dataset, reqCtx, previousBlockDataset, handleContext,
BytesValue opResult = opHandle.process(op, dataset, request, ledgerQueryer, handleContext,
ledgerService);
if (opResult != null) {
operationResults.add(new OperationResultData(opIndex, opResult));
@@ -183,6 +255,7 @@ public class TransactionBatchProcessor implements TransactionBatchProcess {
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(),
e.getMessage()), e);
} catch (BlockRollbackException e) {
// 回滚整个区块;
result = TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK;
txCtx.rollback();
LOGGER.error(
@@ -201,17 +274,27 @@ public class TransactionBatchProcessor implements TransactionBatchProcess {
result = TransactionState.USER_DOES_NOT_EXIST;
} else if (e instanceof ContractDoesNotExistException) {
result = TransactionState.CONTRACT_DOES_NOT_EXIST;
} else if (e instanceof ParticipantDoesNotExistException) {
result = TransactionState.PARTICIPANT_DOES_NOT_EXIST;
}
txCtx.discardAndCommit(result, operationResults);
LOGGER.error(String.format(
"Due to ledger exception, the data changes resulting from the transaction will be rolled back and the results of the transaction will be committed! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
"Due to ledger exception, the data changes resulting from transaction execution will be rolled back and the results of the transaction will be committed! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(),
e.getMessage()), e);
} catch (LedgerSecurityException e) {
// TODO: 识别更详细的异常类型以及执行对应的处理;
result = TransactionState.REJECTED_BY_SECURITY_POLICY;
txCtx.discardAndCommit(result, operationResults);
LOGGER.error(String.format(
"Due to ledger security exception, the data changes resulting from transaction execution will be rolled back and the results of the transaction will be committed! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(),
e.getMessage()), e);
} catch (Exception e) {
result = TransactionState.SYSTEM_ERROR;
txCtx.discardAndCommit(TransactionState.SYSTEM_ERROR, operationResults);
LOGGER.error(String.format(
"Due to system exception, the data changes resulting from the transaction will be rolled back and the results of the transaction will be committed! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
"Due to system exception, the data changes resulting from transaction execution will be rolled back and the results of the transaction will be committed! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(),
e.getMessage()), e);
}

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

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

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.LedgerBlock;
import org.springframework.beans.factory.annotation.Autowired;

import com.jd.blockchain.ledger.core.LedgerDataSet;
import com.jd.blockchain.ledger.core.LedgerEditor;
import com.jd.blockchain.ledger.core.LedgerRepository;
import com.jd.blockchain.ledger.core.LedgerService;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.service.TransactionBatchProcess;
import com.jd.blockchain.service.TransactionEngine;

@@ -44,9 +40,15 @@ public class TransactionEngineImpl implements TransactionEngine {

LedgerBlock ledgerBlock = ledgerRepo.getLatestBlock();
LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();
LedgerDataSet previousBlockDataset = ledgerRepo.getDataSet(ledgerBlock);
batch = new InnerTransactionBatchProcessor(ledgerHash, newBlockEditor, previousBlockDataset, opHdlRegs,
ledgerService, ledgerBlock.getHeight());
LedgerDataQuery previousBlockDataset = ledgerRepo.getDataSet(ledgerBlock);

LedgerAdminDataQuery previousAdminDataset = previousBlockDataset.getAdminDataset();
LedgerSecurityManager securityManager = new LedgerSecurityManagerImpl(
previousAdminDataset.getAdminInfo().getRolePrivileges(),
previousAdminDataset.getAdminInfo().getUserRoles(), previousAdminDataset.getParticipantDataset(),
previousBlockDataset.getUserAccountSet());
batch = new InnerTransactionBatchProcessor(ledgerHash, securityManager, newBlockEditor, previousBlockDataset,
opHdlRegs, ledgerService, ledgerBlock.getHeight());
batchs.put(ledgerHash, batch);
return batch;
}
@@ -69,19 +71,15 @@ public class TransactionEngineImpl implements TransactionEngine {
/**
* 创建交易批处理器;
*
* @param ledgerHash
* 账本哈希;
* @param newBlockEditor
* 新区块的数据编辑器;
* @param previousBlockDataset
* 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集;
* @param opHandles
* 操作处理对象注册表;
* @param ledgerHash 账本哈希;
* @param newBlockEditor 新区块的数据编辑器;
* @param previousBlockDataset 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集;
* @param opHandles 操作处理对象注册表;
*/
public InnerTransactionBatchProcessor(HashDigest ledgerHash, LedgerEditor newBlockEditor,
LedgerDataSet previousBlockDataset, OperationHandleRegisteration opHandles,
LedgerService ledgerService, long blockHeight) {
super(newBlockEditor, previousBlockDataset, opHandles, ledgerService);
public InnerTransactionBatchProcessor(HashDigest ledgerHash, LedgerSecurityManager securityManager,
LedgerEditor newBlockEditor, LedgerDataQuery previousBlockDataset,
OperationHandleRegisteration opHandles, LedgerService ledgerService, long blockHeight) {
super(securityManager, newBlockEditor, previousBlockDataset, opHandles, ledgerService);
this.ledgerHash = ledgerHash;
this.blockHeight = blockHeight;
}

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

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

import java.util.Set;

import com.jd.blockchain.ledger.DigitalSignature;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.utils.Bytes;

/**
* 交易请求上下文;
*
* @author huanghaiquan
*
*/
public interface TransactionRequestContext {

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

/**
* 签名发起请求的终端用户的地址列表;
*
* @return
*/
Set<Bytes> getEndpoints();

/**
* 签名发起请求的节点的地址列表;
*
* @return
*/
Set<Bytes> getNodes();
/**
* 请求的终端发起人列表中是否包含指定地址的终端用户;
*
* @param address
* @return
*/
boolean containsEndpoint(Bytes address);
/**
* 请求的经手节点列表中是否包含指定地址的节点;
*
* @param address
* @return
*/
boolean containsNode(Bytes address);

/**
* 获取交易请求中指定地址的终端的签名;
*
* @param address
* @return
*/
DigitalSignature getEndpointSignature(Bytes address);

/**
* 获取交易请求中指定地址的节点的签名;
*
* @param address
* @return
*/
DigitalSignature getNodeSignature(Bytes address);

}

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

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

import java.util.Collection;
import java.util.Set;

import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.BlockchainIdentityData;
import com.jd.blockchain.ledger.DigitalSignature;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.utils.Bytes;

/**
* 交易请求上下文;
*
* @author huanghaiquan
*
*/
public interface TransactionRequestExtension extends TransactionRequest {

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

/**
* 签名发起请求的终端用户的地址列表;
*
* @return
*/
Set<Bytes> getEndpointAddresses();

/**
* 签名发起请求的终端用户列表;
*
* @return
*/
Collection<Credential> getEndpoints();

/**
* 签名发起请求的节点的地址列表;
*
* @return
*/
Set<Bytes> getNodeAddresses();

/**
* 签名发起请求的节点列表;
*
* @return
*/
Collection<Credential> getNodes();

/**
* 请求的终端发起人列表中是否包含指定地址的终端用户;
*
* @param address
* @return
*/
boolean containsEndpoint(Bytes address);

/**
* 请求的经手节点列表中是否包含指定地址的节点;
*
* @param address
* @return
*/
boolean containsNode(Bytes address);

/**
* 获取交易请求中指定地址的终端的签名;
*
* @param address
* @return
*/
DigitalSignature getEndpointSignature(Bytes address);

/**
* 获取交易请求中指定地址的节点的签名;
*
* @param address
* @return
*/
DigitalSignature getNodeSignature(Bytes address);

public static class Credential {

private final BlockchainIdentity identity;

private final DigitalSignature signature;

Credential(DigitalSignature signature) {
this.identity = new BlockchainIdentityData(signature.getPubKey());
this.signature = signature;
}

public Bytes getAddress() {
return identity.getAddress();
}
public PubKey getPubKey() {
return identity.getPubKey();
}

public BlockchainIdentity getIdentity() {
return identity;
}

public DigitalSignature getSignature() {
return signature;
}
}
}

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

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

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.DigitalSignature;
import com.jd.blockchain.ledger.TransactionContent;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.utils.Bytes;

/**
* 交易请求的扩展信息;
*
* @author huanghaiquan
*
*/
public class TransactionRequestExtensionImpl implements TransactionRequestExtension {

private TransactionRequest request;

private Map<Bytes, Credential> endpointSignatures = new HashMap<>();

private Map<Bytes, Credential> nodeSignatures = new HashMap<>();

public TransactionRequestExtensionImpl(TransactionRequest request) {
this.request = request;
resolveSigners();
}

private void resolveSigners() {
if (request.getEndpointSignatures() != null) {
for (DigitalSignature signature : request.getEndpointSignatures()) {
Credential cred = new Credential(signature);
endpointSignatures.put(cred.getIdentity().getAddress(), cred);
}
}
if (request.getEndpointSignatures() != null) {
for (DigitalSignature signature : request.getNodeSignatures()) {
Credential cred = new Credential(signature);
nodeSignatures.put(cred.getIdentity().getAddress(), cred);
}
}
}

@Override
public Set<Bytes> getEndpointAddresses() {
return endpointSignatures.keySet();
}

@Override
public Set<Bytes> getNodeAddresses() {
return nodeSignatures.keySet();
}

@Override
public Collection<Credential> getEndpoints() {
return endpointSignatures.values();
}

@Override
public Collection<Credential> getNodes() {
return nodeSignatures.values();
}

@Override
public boolean containsEndpoint(Bytes address) {
return endpointSignatures.containsKey(address);
}

@Override
public boolean containsNode(Bytes address) {
return nodeSignatures.containsKey(address);
}

@Override
public DigitalSignature getEndpointSignature(Bytes address) {
return endpointSignatures.get(address).getSignature();
}

@Override
public DigitalSignature getNodeSignature(Bytes address) {
return nodeSignatures.get(address).getSignature();
}

@Override
public HashDigest getHash() {
return request.getHash();
}

@Override
public DigitalSignature[] getNodeSignatures() {
return request.getNodeSignatures();
}

@Override
public DigitalSignature[] getEndpointSignatures() {
return request.getEndpointSignatures();
}

@Override
public TransactionContent getTransactionContent() {
return request.getTransactionContent();
}

}

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

@@ -6,6 +6,7 @@ import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.LedgerTransaction;
import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage;
@@ -153,6 +154,10 @@ public class TransactionSet implements Transactional, MerkleProvable {
public boolean isReadonly() {
return txSet.isReadonly();
}
void setReadonly() {
txSet.setReadonly();
}

@Override
public boolean isUpdated() {


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

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

import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.LedgerDataSnapshot;

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

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

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

public interface UserAccountQuery {

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

/**
* 返回用户总数;
*
* @return
*/
long getTotalCount();

HashDigest getRootHash();

MerkleProof getProof(Bytes key);

UserAccount getUser(String address);

UserAccount getUser(Bytes address);

boolean contains(Bytes address);

UserAccount getUser(Bytes address, long version);

}

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

@@ -5,6 +5,7 @@ import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes;
@@ -14,7 +15,7 @@ import com.jd.blockchain.utils.Transactional;
* @author huanghaiquan
*
*/
public class UserAccountSet implements Transactional, MerkleProvable {
public class UserAccountSet implements Transactional, MerkleProvable, UserAccountQuery {
private AccountSet accountSet;
@@ -30,6 +31,7 @@ public class UserAccountSet implements Transactional, MerkleProvable {
accessPolicy);
}
@Override
public AccountHeader[] getAccounts(int fromIndex, int count) {
return accountSet.getAccounts(fromIndex,count);
}
@@ -39,6 +41,7 @@ public class UserAccountSet implements Transactional, MerkleProvable {
*
* @return
*/
@Override
public long getTotalCount() {
return accountSet.getTotalCount();
}
@@ -46,6 +49,10 @@ public class UserAccountSet implements Transactional, MerkleProvable {
public boolean isReadonly() {
return accountSet.isReadonly();
}
void setReadonly() {
accountSet.setReadonly();
}
@Override
public HashDigest getRootHash() {
@@ -57,19 +64,23 @@ public class UserAccountSet implements Transactional, MerkleProvable {
return accountSet.getProof(key);
}
@Override
public UserAccount getUser(String address) {
return getUser(Bytes.fromBase58(address));
}
@Override
public UserAccount getUser(Bytes address) {
BaseAccount baseAccount = accountSet.getAccount(address);
return new UserAccount(baseAccount);
}
@Override
public boolean contains(Bytes address) {
return accountSet.contains(address);
}
@Override
public UserAccount getUser(Bytes address, long version) {
BaseAccount baseAccount = accountSet.getAccount(address, version);
return new UserAccount(baseAccount);


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

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

import java.util.Collection;

import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.AuthorizationException;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.ledger.RoleSet;
import com.jd.blockchain.ledger.RolesPolicy;
import com.jd.blockchain.ledger.UserRoles;
import com.jd.blockchain.ledger.UserRolesSettings;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVEntry;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.Transactional;

/**
* User-Role authorization data set;
*
* @author huanghaiquan
*
*/
public class UserRoleDataset implements Transactional, MerkleProvable, UserRolesSettings {

private MerkleDataSet dataset;

public UserRoleDataset(CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exPolicyStorage,
VersioningKVStorage verStorage) {
dataset = new MerkleDataSet(cryptoSetting, prefix, exPolicyStorage, verStorage);
}

public UserRoleDataset(HashDigest merkleRootHash, CryptoSetting cryptoSetting, String prefix,
ExPolicyKVStorage exPolicyStorage, VersioningKVStorage verStorage, boolean readonly) {
dataset = new MerkleDataSet(merkleRootHash, cryptoSetting, prefix, exPolicyStorage, verStorage, readonly);
}

@Override
public HashDigest getRootHash() {
return dataset.getRootHash();
}

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

@Override
public boolean isUpdated() {
return dataset.isUpdated();
}

@Override
public void commit() {
dataset.commit();
}

@Override
public void cancel() {
dataset.cancel();
}

@Override
public long getUserCount() {
return dataset.getDataCount();
}

/**
* 加入新的用户角色授权; <br>
*
* 如果该用户的授权已经存在,则引发 {@link LedgerException} 异常;
*
* @param userAddress
* @param rolesPolicy
* @param roles
*/
@Override
public void addUserRoles(Bytes userAddress, RolesPolicy rolesPolicy, String... roles) {
UserRoles roleAuth = new UserRoles(userAddress, -1, rolesPolicy);
roleAuth.addRoles(roles);
long nv = setUserRolesAuthorization(roleAuth);
if (nv < 0) {
throw new AuthorizationException("Roles authorization of User[" + userAddress + "] already exists!");
}
}

/**
* 加入新的用户角色授权; <br>
*
* 如果该用户的授权已经存在,则引发 {@link LedgerException} 异常;
*
* @param userAddress
* @param rolesPolicy
* @param roles
*/
@Override
public void addUserRoles(Bytes userAddress, RolesPolicy rolesPolicy, Collection<String> roles) {
UserRoles roleAuth = new UserRoles(userAddress, -1, rolesPolicy);
roleAuth.addRoles(roles);
long nv = setUserRolesAuthorization(roleAuth);
if (nv < 0) {
throw new AuthorizationException("Roles authorization of User[" + userAddress + "] already exists!");
}
}

/**
* 设置用户角色授权; <br>
* 如果版本校验不匹配,则返回 -1;
*
* @param userRoles
* @return
*/
private long setUserRolesAuthorization(UserRoles userRoles) {
if (userRoles.getRoleCount() > MAX_ROLES_PER_USER) {
throw new AuthorizationException("The number of roles exceeds the maximum range!");
}
byte[] rolesetBytes = BinaryProtocol.encode(userRoles, RoleSet.class);
return dataset.setValue(userRoles.getUserAddress(), rolesetBytes, userRoles.getVersion());
}

/**
* 更新用户角色授权; <br>
* 如果指定用户的授权不存在,或者版本不匹配,则引发 {@link LedgerException} 异常;
*
* @param userRoles
*/
@Override
public void updateUserRoles(UserRoles userRoles) {
long nv = setUserRolesAuthorization(userRoles);
if (nv < 0) {
throw new AuthorizationException("Update to roles of user[" + userRoles.getUserAddress()
+ "] failed due to wrong version[" + userRoles.getVersion() + "] !");
}
}

/**
* 设置用户的角色; <br>
* 如果用户的角色授权不存在,则创建新的授权;
*
* @param userAddress 用户;
* @param policy 角色策略;
* @param roles 角色列表;
* @return
*/
@Override
public long setRoles(Bytes userAddress, RolesPolicy policy, String... roles) {
UserRoles userRoles = getUserRoles(userAddress);
if (userRoles == null) {
userRoles = new UserRoles(userAddress, -1, policy);
}
userRoles.setPolicy(policy);
userRoles.setRoles(roles);
return setUserRolesAuthorization(userRoles);
}

/**
* 查询角色授权;
*
* <br>
* 如果不存在,则返回 null;
*
* @param address
* @return
*/
@Override
public UserRoles getUserRoles(Bytes userAddress) {
// 只返回最新版本;
VersioningKVEntry kv = dataset.getDataEntry(userAddress);
if (kv == null) {
return null;
}
RoleSet roleSet = BinaryProtocol.decode(kv.getValue());
return new UserRoles(userAddress, kv.getVersion(), roleSet);
}

@Override
public UserRoles[] getUserRoles() {
VersioningKVEntry[] kvEntries = dataset.getLatestDataEntries(0, (int) dataset.getDataCount());
UserRoles[] pns = new UserRoles[kvEntries.length];
RoleSet roleset;
for (int i = 0; i < pns.length; i++) {
roleset = BinaryProtocol.decode(kvEntries[i].getValue());
pns[i] = new UserRoles(kvEntries[i].getKey(), kvEntries[i].getVersion(), roleset);
}
return pns;
}

@Override
public boolean isReadonly() {
return dataset.isReadonly();
}

}

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

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

import java.util.Collection;

import com.jd.blockchain.ledger.LedgerPermission;
import com.jd.blockchain.ledger.LedgerPrivilege;
import com.jd.blockchain.ledger.PrivilegeBitset;
import com.jd.blockchain.ledger.RolePrivileges;
import com.jd.blockchain.ledger.RolesPolicy;
import com.jd.blockchain.ledger.TransactionPermission;
import com.jd.blockchain.ledger.TransactionPrivilege;
import com.jd.blockchain.utils.Bytes;

/**
* {@link UserRolesPrivileges} 表示多角色用户的综合权限;
*
* @author huanghaiquan
*
*/
class UserRolesPrivileges {

private Bytes userAddress;

private PrivilegeBitset<LedgerPermission> ledgerPrivileges;

private PrivilegeBitset<TransactionPermission> transactionPrivileges;

public UserRolesPrivileges(Bytes userAddress, RolesPolicy policy, Collection<RolePrivileges> privilegesList) {
this.userAddress = userAddress;
LedgerPrivilege[] ledgerPrivileges = privilegesList.stream().map(p -> p.getLedgerPrivilege())
.toArray(LedgerPrivilege[]::new);
TransactionPrivilege[] transactionPrivileges = privilegesList.stream().map(p -> p.getTransactionPrivilege())
.toArray(TransactionPrivilege[]::new);

this.ledgerPrivileges = ledgerPrivileges[0].clone();
this.transactionPrivileges = transactionPrivileges[0].clone();

if (policy == RolesPolicy.UNION) {
this.ledgerPrivileges.union(ledgerPrivileges, 1, ledgerPrivileges.length - 1);
this.transactionPrivileges.union(transactionPrivileges, 1, transactionPrivileges.length - 1);

} else if (policy == RolesPolicy.INTERSECT) {
this.ledgerPrivileges.intersect(ledgerPrivileges, 1, ledgerPrivileges.length - 1);
this.transactionPrivileges.intersect(transactionPrivileges, 1, transactionPrivileges.length - 1);
} else {
throw new IllegalStateException("Unsupported roles policy[" + policy.toString() + "]!");
}

}

public Bytes getUserAddress() {
return userAddress;
}

public PrivilegeBitset<LedgerPermission> getLedgerPrivileges() {
return ledgerPrivileges;
}

public PrivilegeBitset<TransactionPermission> getTransactionPrivileges() {
return transactionPrivileges;
}

}

+ 73
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/AbstractLedgerOperationHandle.java View File

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

import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.ledger.TransactionPermission;
import com.jd.blockchain.ledger.core.LedgerDataQuery;
import com.jd.blockchain.ledger.core.LedgerDataset;
import com.jd.blockchain.ledger.core.LedgerService;
import com.jd.blockchain.ledger.core.MultiIDsPolicy;
import com.jd.blockchain.ledger.core.OperationHandle;
import com.jd.blockchain.ledger.core.OperationHandleContext;
import com.jd.blockchain.ledger.core.SecurityContext;
import com.jd.blockchain.ledger.core.SecurityPolicy;
import com.jd.blockchain.ledger.core.TransactionRequestExtension;

/**
* 执行直接账本操作的处理类;
*
* @author huanghaiquan
*
* @param <T>
*/
public abstract class AbstractLedgerOperationHandle<T extends Operation> implements OperationHandle {

static {
DataContractRegistry.register(BytesValue.class);
}

private final Class<T> SUPPORTED_OPERATION_TYPE;

public AbstractLedgerOperationHandle(Class<T> supportedOperationType) {
this.SUPPORTED_OPERATION_TYPE = supportedOperationType;
}

// @Override
// public final boolean support(Class<?> operationType) {
// return SUPPORTED_OPERATION_TYPE.isAssignableFrom(operationType);
// }
@Override
public Class<?> getOperationType() {
return SUPPORTED_OPERATION_TYPE;
}

@Override
public final BytesValue process(Operation op, LedgerDataset newBlockDataset,
TransactionRequestExtension requestContext, LedgerDataQuery previousBlockDataset,
OperationHandleContext handleContext, LedgerService ledgerService) {
// 权限校验;
SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy();
securityPolicy.checkEndpointPermission(TransactionPermission.DIRECT_OPERATION, MultiIDsPolicy.AT_LEAST_ONE);

// 操作账本;
@SuppressWarnings("unchecked")
T concretedOp = (T) op;
doProcess(concretedOp, newBlockDataset, requestContext, previousBlockDataset, handleContext, ledgerService);

// 账本操作没有返回值;
return null;
}

/**
* @param op
* @param newBlockDataset
* @param requestContext
* @param previousBlockDataset
* @param handleContext
* @param ledgerService
*/
protected abstract void doProcess(T op, LedgerDataset newBlockDataset, TransactionRequestExtension requestContext,
LedgerDataQuery previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService);
}

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/handles/AbtractContractEventSendOperationHandle.java View File

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

import org.springframework.stereotype.Service;

@@ -8,30 +8,48 @@ import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.ContractEventSendOperation;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.ledger.TransactionPermission;
import com.jd.blockchain.ledger.core.ContractAccount;
import com.jd.blockchain.ledger.core.ContractAccountSet;
import com.jd.blockchain.ledger.core.LedgerDataSet;
import com.jd.blockchain.ledger.core.ContractAccountQuery;
import com.jd.blockchain.ledger.core.LedgerDataQuery;
import com.jd.blockchain.ledger.core.LedgerDataset;
import com.jd.blockchain.ledger.core.LedgerQueryService;
import com.jd.blockchain.ledger.core.LedgerService;
import com.jd.blockchain.ledger.core.MultiIDsPolicy;
import com.jd.blockchain.ledger.core.OperationHandle;
import com.jd.blockchain.ledger.core.TransactionRequestContext;
import com.jd.blockchain.ledger.core.impl.LedgerQueryService;
import com.jd.blockchain.ledger.core.impl.OperationHandleContext;
import com.jd.blockchain.ledger.core.OperationHandleContext;
import com.jd.blockchain.ledger.core.SecurityContext;
import com.jd.blockchain.ledger.core.SecurityPolicy;
import com.jd.blockchain.ledger.core.TransactionRequestExtension;

@Service
public abstract class AbtractContractEventHandle implements OperationHandle {
public abstract class AbtractContractEventSendOperationHandle implements OperationHandle {
@Override
public boolean support(Class<?> operationType) {
return ContractEventSendOperation.class.isAssignableFrom(operationType);
public Class<?> getOperationType() {
return ContractEventSendOperation.class;
}

@Override
public BytesValue process(Operation op, LedgerDataSet dataset, TransactionRequestContext requestContext,
LedgerDataSet previousBlockDataset, OperationHandleContext opHandleContext, LedgerService ledgerService) {
public BytesValue process(Operation op, LedgerDataset newBlockDataset, TransactionRequestExtension requestContext,
LedgerDataQuery previousBlockDataset, OperationHandleContext opHandleContext, LedgerService ledgerService) {
// 权限校验;
SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy();
securityPolicy.checkEndpointPermission(TransactionPermission.CONTRACT_OPERATION, MultiIDsPolicy.AT_LEAST_ONE);

// 操作账本;
ContractEventSendOperation contractOP = (ContractEventSendOperation) op;

return doProcess(requestContext, contractOP, newBlockDataset, previousBlockDataset, opHandleContext,
ledgerService);
}

private BytesValue doProcess(TransactionRequestExtension request, ContractEventSendOperation contractOP,
LedgerDataset newBlockDataset, LedgerDataQuery previousBlockDataset, OperationHandleContext opHandleContext,
LedgerService ledgerService) {
// 先从账本校验合约的有效性;
// 注意:必须在前一个区块的数据集中进行校验,因为那是经过共识的数据;从当前新区块链数据集校验则会带来攻击风险:未经共识的合约得到执行;
ContractAccountSet contractSet = previousBlockDataset.getContractAccountSet();
ContractAccountQuery contractSet = previousBlockDataset.getContractAccountset();
if (!contractSet.contains(contractOP.getContractAddress())) {
throw new LedgerException(String.format("Contract was not registered! --[ContractAddress=%s]",
contractOP.getContractAddress()));
@@ -50,19 +68,17 @@ public abstract class AbtractContractEventHandle implements OperationHandle {

// 创建合约上下文;
LocalContractEventContext localContractEventContext = new LocalContractEventContext(
requestContext.getRequest().getTransactionContent().getLedgerHash(), contractOP.getEvent());
localContractEventContext.setArgs(contractOP.getArgs()).setTransactionRequest(requestContext.getRequest())
request.getTransactionContent().getLedgerHash(), contractOP.getEvent());
localContractEventContext.setArgs(contractOP.getArgs()).setTransactionRequest(request)
.setLedgerContext(ledgerContext);

// 装载合约;
ContractCode contractCode = loadContractCode(contract);

// 处理合约事件;
return contractCode.processEvent(localContractEventContext);
}
protected abstract ContractCode loadContractCode(ContractAccount contract);

protected abstract ContractCode loadContractCode(ContractAccount contract);

}

+ 37
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ContractCodeDeployOperationHandle.java View File

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

import com.jd.blockchain.ledger.ContractCodeDeployOperation;
import com.jd.blockchain.ledger.LedgerPermission;
import com.jd.blockchain.ledger.core.LedgerDataQuery;
import com.jd.blockchain.ledger.core.LedgerDataset;
import com.jd.blockchain.ledger.core.LedgerService;
import com.jd.blockchain.ledger.core.MultiIDsPolicy;
import com.jd.blockchain.ledger.core.OperationHandleContext;
import com.jd.blockchain.ledger.core.SecurityContext;
import com.jd.blockchain.ledger.core.SecurityPolicy;
import com.jd.blockchain.ledger.core.TransactionRequestExtension;

public class ContractCodeDeployOperationHandle extends AbstractLedgerOperationHandle<ContractCodeDeployOperation> {
public ContractCodeDeployOperationHandle() {
super(ContractCodeDeployOperation.class);
}

@Override
protected void doProcess(ContractCodeDeployOperation op, LedgerDataset newBlockDataset,
TransactionRequestExtension requestContext, LedgerDataQuery previousBlockDataset,
OperationHandleContext handleContext, LedgerService ledgerService) {
// TODO: 校验合约代码的正确性;

// TODO: 请求者应该提供合约账户的公钥签名,以确保注册人对注册的地址和公钥具有合法的使用权;

// 权限校验;
SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy();
securityPolicy.checkEndpointPermission(LedgerPermission.UPGRADE_CONTRACT, MultiIDsPolicy.AT_LEAST_ONE);

// 操作账本;
ContractCodeDeployOperation contractOP = (ContractCodeDeployOperation) op;
newBlockDataset.getContractAccountset().deploy(contractOP.getContractID().getAddress(),
contractOP.getContractID().getPubKey(), contractOP.getAddressSignature(), contractOP.getChainCode());
}

}

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

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

import java.util.ArrayList;
import java.util.List;
@@ -6,7 +6,7 @@ import java.util.List;
import com.jd.blockchain.contract.LedgerContext;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.*;
import com.jd.blockchain.ledger.core.impl.OperationHandleContext;
import com.jd.blockchain.ledger.core.OperationHandleContext;
import com.jd.blockchain.transaction.BlockchainQueryService;
import com.jd.blockchain.transaction.DataAccountKVSetOperationBuilder;
import com.jd.blockchain.transaction.DataAccountRegisterOperationBuilder;
@@ -38,6 +38,11 @@ public class ContractLedgerContext implements LedgerContext {
public LedgerInfo getLedger(HashDigest ledgerHash) {
return innerQueryService.getLedger(ledgerHash);
}
@Override
public LedgerAdminInfo getLedgerAdminInfo(HashDigest ledgerHash) {
return innerQueryService.getLedgerAdminInfo(ledgerHash);
}

@Override
public ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash) {

+ 47
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/DataAccountKVSetOperationHandle.java View File

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

import com.jd.blockchain.ledger.DataAccountDoesNotExistException;
import com.jd.blockchain.ledger.DataAccountKVSetOperation;
import com.jd.blockchain.ledger.DataAccountKVSetOperation.KVWriteEntry;
import com.jd.blockchain.ledger.DataVersionConflictException;
import com.jd.blockchain.ledger.LedgerPermission;
import com.jd.blockchain.ledger.core.DataAccount;
import com.jd.blockchain.ledger.core.LedgerDataQuery;
import com.jd.blockchain.ledger.core.LedgerDataset;
import com.jd.blockchain.ledger.core.LedgerService;
import com.jd.blockchain.ledger.core.MultiIDsPolicy;
import com.jd.blockchain.ledger.core.OperationHandleContext;
import com.jd.blockchain.ledger.core.SecurityContext;
import com.jd.blockchain.ledger.core.SecurityPolicy;
import com.jd.blockchain.ledger.core.TransactionRequestExtension;
import com.jd.blockchain.utils.Bytes;

public class DataAccountKVSetOperationHandle extends AbstractLedgerOperationHandle<DataAccountKVSetOperation> {
public DataAccountKVSetOperationHandle() {
super(DataAccountKVSetOperation.class);
}

@Override
protected void doProcess(DataAccountKVSetOperation kvWriteOp, LedgerDataset newBlockDataset,
TransactionRequestExtension requestContext, LedgerDataQuery previousBlockDataset,
OperationHandleContext handleContext, LedgerService ledgerService) {
// 权限校验;
SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy();
securityPolicy.checkEndpointPermission(LedgerPermission.WRITE_DATA_ACCOUNT, MultiIDsPolicy.AT_LEAST_ONE);

// 操作账本;
DataAccount account = newBlockDataset.getDataAccountSet().getDataAccount(kvWriteOp.getAccountAddress());
if (account == null) {
throw new DataAccountDoesNotExistException("DataAccount doesn't exist!");
}
KVWriteEntry[] writeSet = kvWriteOp.getWriteSet();
long v = -1;
for (KVWriteEntry kvw : writeSet) {
v = account.setBytes(Bytes.fromString(kvw.getKey()), kvw.getValue(), kvw.getExpectedVersion());
if (v < 0) {
throw new DataVersionConflictException();
}
}
}

}

+ 36
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/DataAccountRegisterOperationHandle.java View File

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

import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.DataAccountRegisterOperation;
import com.jd.blockchain.ledger.LedgerPermission;
import com.jd.blockchain.ledger.core.LedgerDataQuery;
import com.jd.blockchain.ledger.core.LedgerDataset;
import com.jd.blockchain.ledger.core.LedgerService;
import com.jd.blockchain.ledger.core.MultiIDsPolicy;
import com.jd.blockchain.ledger.core.OperationHandleContext;
import com.jd.blockchain.ledger.core.SecurityContext;
import com.jd.blockchain.ledger.core.SecurityPolicy;
import com.jd.blockchain.ledger.core.TransactionRequestExtension;

public class DataAccountRegisterOperationHandle extends AbstractLedgerOperationHandle<DataAccountRegisterOperation> {
public DataAccountRegisterOperationHandle() {
super(DataAccountRegisterOperation.class);
}
@Override
protected void doProcess(DataAccountRegisterOperation op, LedgerDataset newBlockDataset,
TransactionRequestExtension requestContext, LedgerDataQuery previousBlockDataset,
OperationHandleContext handleContext, LedgerService ledgerService) {
// TODO: 请求者应该提供数据账户的公钥签名,以更好地确保注册人对该地址和公钥具有合法使用权;

// 权限校验;
SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy();
securityPolicy.checkEndpointPermission(LedgerPermission.REGISTER_DATA_ACCOUNT, MultiIDsPolicy.AT_LEAST_ONE);

// 操作账本;
DataAccountRegisterOperation dataAccountRegOp = (DataAccountRegisterOperation) op;
BlockchainIdentity bid = dataAccountRegOp.getAccountID();
newBlockDataset.getDataAccountSet().register(bid.getAddress(), bid.getPubKey(), null);
}

}

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

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

import static com.jd.blockchain.utils.BaseConstant.CONTRACT_SERVICE_PROVIDER;

import com.jd.blockchain.contract.engine.ContractCode;
import com.jd.blockchain.contract.engine.ContractEngine;
import com.jd.blockchain.contract.engine.ContractServiceProviders;
import com.jd.blockchain.ledger.core.ContractAccount;

import static com.jd.blockchain.utils.BaseConstant.CONTRACT_SERVICE_PROVIDER;

public class JVMContractEventSendOperationHandle extends AbtractContractEventHandle {
public class JVMContractEventSendOperationHandle extends AbtractContractEventSendOperationHandle {

private static final ContractEngine JVM_ENGINE;

@@ -26,12 +26,4 @@ public class JVMContractEventSendOperationHandle extends AbtractContractEventHan
return contractCode;
}

// @Override
// public AsyncFuture<byte[]> asyncProcess(Operation op, LedgerDataSet newBlockDataset,
// TransactionRequestContext requestContext, LedgerDataSet previousBlockDataset,
// OperationHandleContext handleContext, LedgerService ledgerService) {
// // TODO Auto-generated method stub
// return null;
// }

}

+ 27
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/LedgerInitOperationHandle.java View File

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

import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.LedgerInitOperation;
import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.ledger.core.LedgerDataQuery;
import com.jd.blockchain.ledger.core.LedgerDataset;
import com.jd.blockchain.ledger.core.LedgerService;
import com.jd.blockchain.ledger.core.OperationHandle;
import com.jd.blockchain.ledger.core.OperationHandleContext;
import com.jd.blockchain.ledger.core.TransactionRequestExtension;

public class LedgerInitOperationHandle implements OperationHandle {

@Override
public Class<?> getOperationType() {
return LedgerInitOperation.class;
}

@Override
public BytesValue process(Operation op, LedgerDataset newBlockDataset, TransactionRequestExtension requestContext,
LedgerDataQuery previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) {
// 对初始化操作不需要做任何处理;
return null;
}

}

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


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


+ 50
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/RolesConfigureOperationHandle.java View File

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

import com.jd.blockchain.ledger.LedgerPermission;
import com.jd.blockchain.ledger.RolePrivilegeSettings;
import com.jd.blockchain.ledger.RolePrivileges;
import com.jd.blockchain.ledger.RolesConfigureOperation;
import com.jd.blockchain.ledger.RolesConfigureOperation.RolePrivilegeEntry;
import com.jd.blockchain.ledger.core.LedgerDataQuery;
import com.jd.blockchain.ledger.core.LedgerDataset;
import com.jd.blockchain.ledger.core.LedgerService;
import com.jd.blockchain.ledger.core.MultiIDsPolicy;
import com.jd.blockchain.ledger.core.OperationHandleContext;
import com.jd.blockchain.ledger.core.SecurityContext;
import com.jd.blockchain.ledger.core.SecurityPolicy;
import com.jd.blockchain.ledger.core.TransactionRequestExtension;

public class RolesConfigureOperationHandle extends AbstractLedgerOperationHandle<RolesConfigureOperation> {
public RolesConfigureOperationHandle() {
super(RolesConfigureOperation.class);
}

@Override
protected void doProcess(RolesConfigureOperation operation, LedgerDataset newBlockDataset,
TransactionRequestExtension request, LedgerDataQuery previousBlockDataset,
OperationHandleContext handleContext, LedgerService ledgerService) {
// 权限校验;
SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy();
securityPolicy.checkEndpointPermission(LedgerPermission.CONFIGURE_ROLES, MultiIDsPolicy.AT_LEAST_ONE);

// 操作账本;
RolePrivilegeEntry[] rpcfgs = operation.getRoles();
RolePrivilegeSettings rpSettings = newBlockDataset.getAdminDataset().getRolePrivileges();
if (rpcfgs != null) {
for (RolePrivilegeEntry rpcfg : rpcfgs) {
RolePrivileges rp = rpSettings.getRolePrivilege(rpcfg.getRoleName());
if (rp == null) {
rpSettings.addRolePrivilege(rpcfg.getRoleName(), rpcfg.getEnableLedgerPermissions(),
rpcfg.getEnableTransactionPermissions());
} else {
rp.enable(rpcfg.getEnableLedgerPermissions());
rp.enable(rpcfg.getEnableTransactionPermissions());

rp.disable(rpcfg.getDisableLedgerPermissions());
rp.disable(rpcfg.getDisableTransactionPermissions());
}
}
}
}

}

+ 78
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/UserAuthorizeOperationHandle.java View File

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

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

import com.jd.blockchain.ledger.LedgerPermission;
import com.jd.blockchain.ledger.RolePrivilegeSettings;
import com.jd.blockchain.ledger.RolesPolicy;
import com.jd.blockchain.ledger.UserAuthorizeOperation;
import com.jd.blockchain.ledger.UserAuthorizeOperation.UserRolesEntry;
import com.jd.blockchain.ledger.UserRoles;
import com.jd.blockchain.ledger.UserRolesSettings;
import com.jd.blockchain.ledger.core.LedgerDataQuery;
import com.jd.blockchain.ledger.core.LedgerDataset;
import com.jd.blockchain.ledger.core.LedgerService;
import com.jd.blockchain.ledger.core.MultiIDsPolicy;
import com.jd.blockchain.ledger.core.OperationHandleContext;
import com.jd.blockchain.ledger.core.SecurityContext;
import com.jd.blockchain.ledger.core.SecurityPolicy;
import com.jd.blockchain.ledger.core.TransactionRequestExtension;
import com.jd.blockchain.utils.Bytes;

public class UserAuthorizeOperationHandle extends AbstractLedgerOperationHandle<UserAuthorizeOperation> {
public UserAuthorizeOperationHandle() {
super(UserAuthorizeOperation.class);
}

@Override
protected void doProcess(UserAuthorizeOperation operation, LedgerDataset newBlockDataset,
TransactionRequestExtension request, LedgerDataQuery previousBlockDataset,
OperationHandleContext handleContext, LedgerService ledgerService) {
// 权限校验;
SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy();
securityPolicy.checkEndpointPermission(LedgerPermission.CONFIGURE_ROLES, MultiIDsPolicy.AT_LEAST_ONE);

// 操作账本;

UserRolesEntry[] urcfgs = operation.getUserRolesAuthorizations();
UserRolesSettings urSettings = newBlockDataset.getAdminDataset().getUserRoles();
RolePrivilegeSettings rolesSettings = newBlockDataset.getAdminDataset().getRolePrivileges();
if (urcfgs != null) {
for (UserRolesEntry urcfg : urcfgs) {
//
String[] authRoles = urcfg.getAuthorizedRoles();
List<String> validRoles = new ArrayList<String>();
if (authRoles != null) {
for (String r : authRoles) {
if (rolesSettings.contains(r)) {
validRoles.add(r);
}
}
}
for (Bytes address : urcfg.getUserAddresses()) {
UserRoles ur = urSettings.getUserRoles(address);
if (ur == null) {
// 这是新的授权;
RolesPolicy policy = urcfg.getPolicy();
if (policy == null) {
policy = RolesPolicy.UNION;
}
urSettings.addUserRoles(address, policy, validRoles);
} else {
// 更改之前的授权;
ur.addRoles(validRoles);
ur.removeRoles(urcfg.getUnauthorizedRoles());

// 如果请求中设置了策略,才进行更新;
RolesPolicy policy = urcfg.getPolicy();
if (policy != null) {
ur.setPolicy(policy);
}
}
}
}
}
}

}

+ 38
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/UserRegisterOperationHandle.java View File

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

import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.LedgerPermission;
import com.jd.blockchain.ledger.UserRegisterOperation;
import com.jd.blockchain.ledger.core.LedgerDataQuery;
import com.jd.blockchain.ledger.core.LedgerDataset;
import com.jd.blockchain.ledger.core.LedgerService;
import com.jd.blockchain.ledger.core.MultiIDsPolicy;
import com.jd.blockchain.ledger.core.OperationHandleContext;
import com.jd.blockchain.ledger.core.SecurityContext;
import com.jd.blockchain.ledger.core.SecurityPolicy;
import com.jd.blockchain.ledger.core.TransactionRequestExtension;
import com.jd.blockchain.utils.Bytes;

public class UserRegisterOperationHandle extends AbstractLedgerOperationHandle<UserRegisterOperation> {
public UserRegisterOperationHandle() {
super(UserRegisterOperation.class);
}

@Override
protected void doProcess(UserRegisterOperation op, LedgerDataset newBlockDataset,
TransactionRequestExtension requestContext, LedgerDataQuery previousBlockDataset,
OperationHandleContext handleContext, LedgerService ledgerService) {
// 权限校验;
SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy();
securityPolicy.checkEndpointPermission(LedgerPermission.REGISTER_USER, MultiIDsPolicy.AT_LEAST_ONE);

// 操作账本;
UserRegisterOperation userRegOp = (UserRegisterOperation) op;
BlockchainIdentity bid = userRegOp.getUserID();

Bytes userAddress = bid.getAddress();

newBlockDataset.getUserAccountSet().register(userAddress, bid.getPubKey());
}

}

+ 0
- 9
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionContextImpl.java View File

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

import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.ledger.LedgerTransaction;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.ledger.core.LedgerDataSet;
import com.jd.blockchain.ledger.core.LedgerTransactionContext;
import com.jd.blockchain.storage.service.utils.BufferedKVStorage;


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

Loading…
Cancel
Save