Browse Source

Merge branch 'feature/authorize' into develop

# Conflicts:
#	source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractLedgerContext.java
#	source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilderImpl.java
#	source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/IntegrationTest.java
#	source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java
#	source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestAll4Redis.java
tags/1.0.0
huanghaiquan 5 years ago
parent
commit
d60c5d4cb1
68 changed files with 1959 additions and 1552 deletions
  1. +2
    -2
      source/binary-proto/src/main/java/com/jd/blockchain/binaryproto/PrimitiveType.java
  2. +1
    -0
      source/contract/contract-framework/src/main/java/com/jd/blockchain/contract/engine/ContractEngine.java
  3. +1
    -0
      source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JVMContractEngine.java
  4. +1
    -1
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountAccessPolicy.java
  5. +13
    -17
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountSet.java
  6. +29
    -32
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/BaseAccount.java
  7. +12
    -7
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java
  8. +1
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/CryptoConfig.java
  9. +19
    -9
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java
  10. +1
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminAccount.java
  11. +1
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerEditor.java
  12. +1
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerService.java
  13. +1
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataSet.java
  14. +1
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleTree.java
  15. +1
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantDataSet.java
  16. +9
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/PermissionService.java
  17. +0
    -11
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Privilege.java
  18. +1
    -1
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/PrivilegeModelSetting.java
  19. +1
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionSet.java
  20. +11
    -8
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccount.java
  21. +1
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccountSet.java
  22. +1
    -1
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/DefaultOperationHandleRegisteration.java
  23. +1
    -1
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerManager.java
  24. +60
    -53
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java
  25. +0
    -1
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerRepositoryImpl.java
  26. +1
    -1
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/OpeningAccessPolicy.java
  27. +1
    -1
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionBatchProcessor.java
  28. +1
    -1
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractEventSendOperationHandle.java
  29. +84
    -35
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractLedgerContext.java
  30. +1
    -2
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/DataAccountKVSetOperationHandle.java
  31. +9
    -11
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/BaseAccountTest.java
  32. +57
    -23
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerEditerTest.java
  33. +1
    -1
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerTransactionDataTest.java
  34. +1
    -1
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TransactionSetTest.java
  35. +2
    -2
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValue.java
  36. +107
    -24
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValueEntry.java
  37. +2
    -3
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValueType.java
  38. +2
    -3
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataEntry.java
  39. +53
    -61
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataObject.java
  40. +1
    -1
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerException.java
  41. +15
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerPermissionException.java
  42. +68
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/PermissionType.java
  43. +0
    -42
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/PrivilegeType.java
  44. +17
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ValueTypeCastException.java
  45. +58
    -21
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainOperationFactory.java
  46. +95
    -8
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilder.java
  47. +51
    -20
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilderImpl.java
  48. +4
    -2
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountOperator.java
  49. +4
    -4
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PrivilegeSettingOperationBuilder.java
  50. +9
    -10
      source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/DataAccountKVSetOpTemplateTest.java
  51. +28
    -29
      source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/KVDataTest.java
  52. +1
    -2
      source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/TxContentBlobTest.java
  53. +1
    -2
      source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/TxRequestMessageTest.java
  54. +127
    -109
      source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java
  55. +2
    -2
      source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/PrivilegeSetting.java
  56. +3
    -4
      source/sdk/sdk-samples/src/main/java/com/jd/blockchain/contract/samples/AssetContractImpl.java
  57. +1
    -1
      source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_InsertData.java
  58. +4
    -4
      source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_BatchInsertData_Test_.java
  59. +2
    -2
      source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_InsertData_Test_.java
  60. +117
    -99
      source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/IntegrationTest.java
  61. +3
    -4
      source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerPerformanceTest.java
  62. +435
    -432
      source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java
  63. +27
    -30
      source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestAll4Redis.java
  64. +2
    -2
      source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestDataAccount.java
  65. +319
    -317
      source/tools/tools-capability/src/main/java/com/jd/blockchain/capability/service/RemoteTransactionService.java
  66. +1
    -1
      source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitException.java
  67. +4
    -0
      source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Bytes.java
  68. +68
    -91
      source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesUtils.java

+ 2
- 2
source/binary-proto/src/main/java/com/jd/blockchain/binaryproto/PrimitiveType.java View File

@@ -30,9 +30,9 @@ public enum PrimitiveType {
INT64((byte) (DataType.NUMERIC | 0x04)), INT64((byte) (DataType.NUMERIC | 0x04)),
/** /**
* 日期时间;
* 时间
*/ */
DATETIME((byte) (DataType.NUMERIC | 0x08)),
TIMESTAMP((byte) (DataType.NUMERIC | 0x08)),
/** /**
* 文本数据; * 文本数据;


+ 1
- 0
source/contract/contract-framework/src/main/java/com/jd/blockchain/contract/engine/ContractEngine.java View File

@@ -1,5 +1,6 @@
package com.jd.blockchain.contract.engine; package com.jd.blockchain.contract.engine;


import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.Bytes;


/** /**


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

@@ -2,6 +2,7 @@ package com.jd.blockchain.contract.jvm;


import com.jd.blockchain.contract.engine.ContractCode; import com.jd.blockchain.contract.engine.ContractCode;
import com.jd.blockchain.contract.engine.ContractEngine; import com.jd.blockchain.contract.engine.ContractEngine;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.runtime.Module; import com.jd.blockchain.runtime.Module;
import com.jd.blockchain.runtime.RuntimeContext; import com.jd.blockchain.runtime.RuntimeContext;
import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.Bytes;


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

@@ -19,7 +19,7 @@ public interface AccountAccessPolicy {
* @param account * @param account
* @return Return true if it satisfies this policy, or false if it doesn't; * @return Return true if it satisfies this policy, or false if it doesn't;
*/ */
boolean checkCommitting(AccountHeader account);
boolean checkDataWriting(AccountHeader account);


boolean checkRegistering(Bytes address, PubKey pubKey); boolean checkRegistering(Bytes address, PubKey pubKey);




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

@@ -9,7 +9,9 @@ import com.jd.blockchain.crypto.AddressEncoding;
import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.AccountHeader; import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.CryptoSetting; import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.storage.service.ExPolicyKVStorage; import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage; import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.Bytes;
@@ -160,10 +162,8 @@ public class AccountSet implements Transactional, MerkleProvable {
* *
* 只有最新版本的账户才能可写的,其它都是只读; * 只有最新版本的账户才能可写的,其它都是只读;
* *
* @param address
* 账户地址;
* @param version
* 账户版本;如果指定为 -1,则返回最新版本;
* @param address 账户地址;
* @param version 账户版本;如果指定为 -1,则返回最新版本;
* @return * @return
*/ */
public BaseAccount getAccount(Bytes address, long version) { public BaseAccount getAccount(Bytes address, long version) {
@@ -226,10 +226,8 @@ public class AccountSet implements Transactional, MerkleProvable {
* *
* 如果指定的地址和公钥不匹配,则会引发 {@link LedgerException} 异常; * 如果指定的地址和公钥不匹配,则会引发 {@link LedgerException} 异常;
* *
* @param address
* 区块链地址;
* @param pubKey
* 公钥;
* @param address 区块链地址;
* @param pubKey 公钥;
* @return 注册成功的账户对象; * @return 注册成功的账户对象;
*/ */
public BaseAccount register(Bytes address, PubKey pubKey) { public BaseAccount register(Bytes address, PubKey pubKey) {
@@ -283,15 +281,14 @@ public class AccountSet implements Transactional, MerkleProvable {
private VersioningAccount createInstance(Bytes address, PubKey pubKey, CryptoSetting cryptoSetting, private VersioningAccount createInstance(Bytes address, PubKey pubKey, CryptoSetting cryptoSetting,
String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, long version) { String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, long version) {
return new VersioningAccount(address, pubKey, cryptoSetting, keyPrefix, exStorage, verStorage, accessPolicy,
version);
return new VersioningAccount(address, pubKey, cryptoSetting, keyPrefix, exStorage, verStorage, version);
} }
private VersioningAccount deserialize(byte[] bytes, CryptoSetting cryptoSetting, String keyPrefix, private VersioningAccount deserialize(byte[] bytes, CryptoSetting cryptoSetting, String keyPrefix,
ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, long version) { ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, long version) {
AccountHeader accInfo = BinaryProtocol.decode(bytes); AccountHeader accInfo = BinaryProtocol.decode(bytes);
return new VersioningAccount(accInfo.getAddress(), accInfo.getPubKey(), accInfo.getRootHash(), cryptoSetting, return new VersioningAccount(accInfo.getAddress(), accInfo.getPubKey(), accInfo.getRootHash(), cryptoSetting,
keyPrefix, exStorage, verStorage, readonly, accessPolicy, version);
keyPrefix, exStorage, verStorage, readonly, version);
} }
private byte[] serialize(AccountHeader account) { private byte[] serialize(AccountHeader account) {
@@ -388,15 +385,14 @@ public class AccountSet implements Transactional, MerkleProvable {
public VersioningAccount(Bytes address, PubKey pubKey, HashDigest rootHash, CryptoSetting cryptoSetting, public VersioningAccount(Bytes address, PubKey pubKey, HashDigest rootHash, CryptoSetting cryptoSetting,
String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly,
AccountAccessPolicy accessPolicy, long version) {
super(address, pubKey, rootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly, accessPolicy);
long version) {
super(address, pubKey, rootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly);
this.version = version; this.version = version;
} }
public VersioningAccount(Bytes address, PubKey pubKey, CryptoSetting cryptoSetting, String keyPrefix, public VersioningAccount(Bytes address, PubKey pubKey, CryptoSetting cryptoSetting, String keyPrefix,
ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy,
long version) {
super(address, pubKey, cryptoSetting, keyPrefix, exStorage, verStorage, accessPolicy);
ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, long version) {
super(address, pubKey, cryptoSetting, keyPrefix, exStorage, verStorage);
this.version = version; this.version = version;
} }
@@ -426,7 +422,7 @@ public class AccountSet implements Transactional, MerkleProvable {
// } // }
@Override @Override
public long setBytes(Bytes key, byte[] value, long version) {
public long setBytes(Bytes key, BytesValue value, long version) {
long v = super.setBytes(key, value, version); long v = super.setBytes(key, value, version);
if (v > -1) { if (v > -1) {
updated = true; updated = true;


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

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


import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.AccountHeader; import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.BlockchainIdentity; import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.BlockchainIdentityData; import com.jd.blockchain.ledger.BlockchainIdentityData;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.CryptoSetting; import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.storage.service.ExPolicyKVStorage; import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage; import com.jd.blockchain.storage.service.VersioningKVStorage;
@@ -23,8 +25,6 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional


protected MerkleDataSet dataset; protected MerkleDataSet dataset;


private AccountAccessPolicy accessPolicy;

/** /**
* Create a new Account with the specified address and pubkey; <br> * Create a new Account with the specified address and pubkey; <br>
* *
@@ -38,8 +38,8 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional
* @param pubKey * @param pubKey
*/ */
public BaseAccount(Bytes address, PubKey pubKey, CryptoSetting cryptoSetting, String keyPrefix, public BaseAccount(Bytes address, PubKey pubKey, CryptoSetting cryptoSetting, String keyPrefix,
ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy) {
this(address, pubKey, null, cryptoSetting, keyPrefix, exStorage, verStorage, false, accessPolicy);
ExPolicyKVStorage exStorage, VersioningKVStorage verStorage) {
this(address, pubKey, null, cryptoSetting, keyPrefix, exStorage, verStorage, false);
} }


/** /**
@@ -58,8 +58,8 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional
* @param accessPolicy * @param accessPolicy
*/ */
public BaseAccount(BlockchainIdentity bcid, CryptoSetting cryptoSetting, String keyPrefix, public BaseAccount(BlockchainIdentity bcid, CryptoSetting cryptoSetting, String keyPrefix,
ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy) {
this(bcid, null, cryptoSetting, keyPrefix, exStorage, verStorage, false, accessPolicy);
ExPolicyKVStorage exStorage, VersioningKVStorage verStorage) {
this(bcid, null, cryptoSetting, keyPrefix, exStorage, verStorage, false);
} }


/** /**
@@ -69,9 +69,8 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional
* *
* @param address * @param address
* @param pubKey * @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 null be set,
* create a new empty merkle dataset;
* @param cryptoSetting * @param cryptoSetting
* @param exStorage * @param exStorage
* @param verStorage * @param verStorage
@@ -79,18 +78,15 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional
* @param accessPolicy * @param accessPolicy
*/ */
public BaseAccount(Bytes address, PubKey pubKey, HashDigest dataRootHash, CryptoSetting cryptoSetting, public BaseAccount(Bytes address, PubKey pubKey, HashDigest dataRootHash, CryptoSetting cryptoSetting,
String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly,
AccountAccessPolicy accessPolicy) {
String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly) {
this(new BlockchainIdentityData(address, pubKey), dataRootHash, cryptoSetting, keyPrefix, exStorage, verStorage, this(new BlockchainIdentityData(address, pubKey), dataRootHash, cryptoSetting, keyPrefix, exStorage, verStorage,
readonly, accessPolicy);
readonly);
} }


public BaseAccount(BlockchainIdentity bcid, HashDigest dataRootHash, CryptoSetting cryptoSetting, String keyPrefix, public BaseAccount(BlockchainIdentity bcid, HashDigest dataRootHash, CryptoSetting cryptoSetting, String keyPrefix,
ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly,
AccountAccessPolicy accessPolicy) {
ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly) {
this.bcid = bcid; this.bcid = bcid;
this.dataset = new MerkleDataSet(dataRootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly); this.dataset = new MerkleDataSet(dataRootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly);
this.accessPolicy = accessPolicy;
} }


/* /*
@@ -151,21 +147,18 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional
* If updating is performed, the version of the key increase by 1. <br> * 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> * If creating is performed, the version of the key initialize by 0. <br>
* *
* @param key
* The key of data;
* @param value
* The value of data;
* @param version
* The expected version of the key.
* @param key The key of data;
* @param value The value of data;
* @param version The expected version of the key.
* @return The new version of the key. <br> * @return The new version of the key. <br>
* If the key is new created success, then return 0; <br> * If the key is new created success, then return 0; <br>
* If the key is updated success, then return the new version;<br> * If the key is updated success, then return the new version;<br>
* If this operation fail by version checking or other reason, then * If this operation fail by version checking or other reason, then
* return -1; * return -1;
*/ */
public long setBytes(Bytes key, byte[] value, long version) {
// TODO: 支持多种数据类型;
return dataset.setValue(key, value, version);
public long setBytes(Bytes key, BytesValue value, long version) {
byte[] bytesValue = BinaryProtocol.encode(value, BytesValue.class);
return dataset.setValue(key, bytesValue, version);
} }


/** /**
@@ -185,8 +178,12 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional
* @param key * @param key
* @return return null if not exist; * @return return null if not exist;
*/ */
public byte[] getBytes(Bytes key) {
return dataset.getValue(key);
public BytesValue getBytes(Bytes key) {
byte[] bytesValue = dataset.getValue(key);
if (bytesValue == null) {
return null;
}
return BinaryProtocol.decodeAs(bytesValue, BytesValue.class);
} }


/** /**
@@ -196,8 +193,12 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional
* @param version * @param version
* @return return null if not exist; * @return return null if not exist;
*/ */
public byte[] getBytes(Bytes key, long version) {
return dataset.getValue(key, version);
public BytesValue getBytes(Bytes key, long version) {
byte[] bytesValue = dataset.getValue(key, version);
if (bytesValue == null) {
return null;
}
return BinaryProtocol.decodeAs(bytesValue, BytesValue.class);
} }


@Override @Override
@@ -207,10 +208,6 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional


@Override @Override
public void commit() { public void commit() {
if (!accessPolicy.checkCommitting(this)) {
throw new LedgerException("Account Committing was rejected for the access policy!");
}

dataset.commit(); dataset.commit();
} }




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

@@ -3,8 +3,9 @@ package com.jd.blockchain.ledger.core;
import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.AccountHeader; import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.BytesValueEntry;
import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.io.BytesUtils;
public class ContractAccount implements AccountHeader { public class ContractAccount implements AccountHeader {
@@ -42,15 +43,16 @@ public class ContractAccount implements AccountHeader {
} }
public long setChaincode(byte[] chaincode, long version) { public long setChaincode(byte[] chaincode, long version) {
return accBase.setBytes(CHAIN_CODE_KEY, chaincode, version);
BytesValue bytesValue = BytesValueEntry.fromBytes(chaincode);
return accBase.setBytes(CHAIN_CODE_KEY, bytesValue, version);
} }
public byte[] getChainCode() { public byte[] getChainCode() {
return accBase.getBytes(CHAIN_CODE_KEY);
return accBase.getBytes(CHAIN_CODE_KEY).getValue().toBytes();
} }
public byte[] getChainCode(long version) { public byte[] getChainCode(long version) {
return accBase.getBytes(CHAIN_CODE_KEY, version);
return accBase.getBytes(CHAIN_CODE_KEY, version).getValue().toBytes();
} }
public long getChaincodeVersion() { public long getChaincodeVersion() {
@@ -58,15 +60,18 @@ public class ContractAccount implements AccountHeader {
} }
public long setProperty(Bytes key, String value, long version) { public long setProperty(Bytes key, String value, long version) {
return accBase.setBytes(encodePropertyKey(key), BytesUtils.toBytes(value), version);
BytesValue bytesValue = BytesValueEntry.fromText(value);
return accBase.setBytes(encodePropertyKey(key), bytesValue, version);
} }
public String getProperty(Bytes key) { public String getProperty(Bytes key) {
return BytesUtils.toString(accBase.getBytes(encodePropertyKey(key)));
BytesValue bytesValue = accBase.getBytes(encodePropertyKey(key));
return BytesValueEntry.toText(bytesValue);
} }
public String getProperty(Bytes key, long version) { public String getProperty(Bytes key, long version) {
return BytesUtils.toString(accBase.getBytes(encodePropertyKey(key), version));
BytesValue bytesValue = accBase.getBytes(encodePropertyKey(key), version);
return BytesValueEntry.toText(bytesValue);
} }
private Bytes encodePropertyKey(Bytes key) { private Bytes encodePropertyKey(Bytes key) {


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

@@ -5,6 +5,7 @@ import java.util.HashMap;
import com.jd.blockchain.crypto.CryptoAlgorithm; import com.jd.blockchain.crypto.CryptoAlgorithm;
import com.jd.blockchain.crypto.CryptoProvider; import com.jd.blockchain.crypto.CryptoProvider;
import com.jd.blockchain.ledger.CryptoSetting; import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;


public class CryptoConfig implements CryptoSetting { public class CryptoConfig implements CryptoSetting {




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

@@ -6,10 +6,10 @@ import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.AccountHeader; import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.BytesValue; import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.BytesValueEntry;
import com.jd.blockchain.ledger.KVDataEntry; import com.jd.blockchain.ledger.KVDataEntry;
import com.jd.blockchain.ledger.KVDataObject; import com.jd.blockchain.ledger.KVDataObject;
import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.serialize.binary.BinarySerializeUtils;
public class DataAccount implements AccountHeader, MerkleProvable { public class DataAccount implements AccountHeader, MerkleProvable {
@@ -41,10 +41,22 @@ public class DataAccount implements AccountHeader, MerkleProvable {
public MerkleProof getProof(Bytes key) { public MerkleProof getProof(Bytes key) {
return baseAccount.getProof(key); return baseAccount.getProof(key);
} }
public long setBytes(Bytes key, byte[] value, long version) {
public long setBytes(Bytes key, BytesValue value, long version) {
return baseAccount.setBytes(key, value, version); return baseAccount.setBytes(key, value, version);
} }
public long setBytes(Bytes key, String value, long version) {
BytesValue bytesValue = BytesValueEntry.fromText(value);
return baseAccount.setBytes(key, bytesValue, version);
}
public long setBytes(Bytes key, byte[] value, long version) {
BytesValue bytesValue = BytesValueEntry.fromBytes(value);
return baseAccount.setBytes(key, bytesValue, version);
}
/** /**
* Return the latest version entry associated the specified key; If the key * Return the latest version entry associated the specified key; If the key
@@ -74,7 +86,7 @@ public class DataAccount implements AccountHeader, MerkleProvable {
* @param key * @param key
* @return return null if not exist; * @return return null if not exist;
*/ */
public byte[] getBytes(String key) {
public BytesValue getBytes(String key) {
return baseAccount.getBytes(Bytes.fromString(key)); return baseAccount.getBytes(Bytes.fromString(key));
} }
@@ -84,7 +96,7 @@ public class DataAccount implements AccountHeader, MerkleProvable {
* @param key * @param key
* @return return null if not exist; * @return return null if not exist;
*/ */
public byte[] getBytes(Bytes key) {
public BytesValue getBytes(Bytes key) {
return baseAccount.getBytes(key); return baseAccount.getBytes(key);
} }
@@ -95,7 +107,7 @@ public class DataAccount implements AccountHeader, MerkleProvable {
* @param version * @param version
* @return return null if not exist; * @return return null if not exist;
*/ */
public byte[] getBytes(String key, long version) {
public BytesValue getBytes(String key, long version) {
return baseAccount.getBytes(Bytes.fromString(key), version); return baseAccount.getBytes(Bytes.fromString(key), version);
} }
@@ -106,7 +118,7 @@ public class DataAccount implements AccountHeader, MerkleProvable {
* @param version * @param version
* @return return null if not exist; * @return return null if not exist;
*/ */
public byte[] getBytes(Bytes key, long version) {
public BytesValue getBytes(Bytes key, long version) {
return baseAccount.getBytes(key, version); return baseAccount.getBytes(key, version);
} }
@@ -119,7 +131,6 @@ public class DataAccount implements AccountHeader, MerkleProvable {
*/ */
public KVDataEntry[] getDataEntries(int fromIndex, int count) { public KVDataEntry[] getDataEntries(int fromIndex, int count) {
if (getDataEntriesTotalCount() == 0 || count == 0) { if (getDataEntriesTotalCount() == 0 || count == 0) {
return null; return null;
} }
@@ -142,7 +153,7 @@ public class DataAccount implements AccountHeader, MerkleProvable {
key = baseAccount.dataset.getKeyAtIndex(fromIndex); key = baseAccount.dataset.getKeyAtIndex(fromIndex);
ver = baseAccount.dataset.getVersion(key); ver = baseAccount.dataset.getVersion(key);
BytesValue decodeData = BinaryProtocol.decode(value); BytesValue decodeData = BinaryProtocol.decode(value);
kvDataEntries[i] = new KVDataObject(key, ver, PrimitiveType.valueOf(decodeData.getType().CODE), decodeData.getValue().toBytes());
kvDataEntries[i] = new KVDataObject(key, ver, decodeData);
fromIndex++; fromIndex++;
} }
@@ -162,5 +173,4 @@ public class DataAccount implements AccountHeader, MerkleProvable {
} }
return baseAccount.dataset.getDataCount(); return baseAccount.dataset.getDataCount();
} }
} }

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

@@ -10,6 +10,7 @@ import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.Crypto; import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.HashFunction; import com.jd.blockchain.crypto.HashFunction;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.LedgerInitSetting; import com.jd.blockchain.ledger.LedgerInitSetting;
import com.jd.blockchain.ledger.ParticipantNode; import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.storage.service.ExPolicyKVStorage; import com.jd.blockchain.storage.service.ExPolicyKVStorage;


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

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


import com.jd.blockchain.ledger.LedgerBlock; import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.LedgerTransaction; import com.jd.blockchain.ledger.LedgerTransaction;
import com.jd.blockchain.ledger.TransactionRequest; import com.jd.blockchain.ledger.TransactionRequest;




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

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


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


/** /**
* 账本管理器; * 账本管理器;


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

@@ -2,6 +2,7 @@ package com.jd.blockchain.ledger.core;
import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.CryptoSetting; import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.storage.service.ExPolicyKVStorage; import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy; import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy;
import com.jd.blockchain.storage.service.VersioningKVEntry; import com.jd.blockchain.storage.service.VersioningKVEntry;


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

@@ -19,6 +19,7 @@ import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.HashFunction; import com.jd.blockchain.crypto.HashFunction;
import com.jd.blockchain.ledger.CryptoSetting; import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.storage.service.ExPolicyKVStorage; import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy; import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy;
import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.Bytes;


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

@@ -5,6 +5,7 @@ import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.ParticipantNode; import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.ledger.CryptoSetting; import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.storage.service.ExPolicyKVStorage; import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage; import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.Bytes;


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

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

import java.util.SortedSet;

public interface PermissionService {
boolean checkLedgerPermission();
}

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

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

import java.util.SortedSet;

public interface Privilege {
SortedSet<Byte> getOpCodes();
long getVersion();
}

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

@@ -4,6 +4,6 @@ public interface PrivilegeModelSetting {
long getLatestVersion(); long getLatestVersion();
Privilege getPrivilege(long version);
PermissionService getPrivilege(long version);
} }

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

@@ -4,6 +4,7 @@ import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.binaryproto.DataContractRegistry; import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.CryptoSetting; import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.LedgerTransaction; import com.jd.blockchain.ledger.LedgerTransaction;
import com.jd.blockchain.ledger.TransactionState; import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.storage.service.ExPolicyKVStorage; import com.jd.blockchain.storage.service.ExPolicyKVStorage;


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

@@ -2,9 +2,10 @@ package com.jd.blockchain.ledger.core;
import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.BytesValueEntry;
import com.jd.blockchain.ledger.UserInfo; import com.jd.blockchain.ledger.UserInfo;
import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.io.BytesUtils;
/** /**
* 用户账户; * 用户账户;
@@ -40,21 +41,21 @@ public class UserAccount implements UserInfo {
} }
public PubKey getDataPubKey() { public PubKey getDataPubKey() {
byte[] pkBytes = baseAccount.getBytes(DATA_PUB_KEY);
BytesValue pkBytes = baseAccount.getBytes(DATA_PUB_KEY);
if (pkBytes == null) { if (pkBytes == null) {
return null; return null;
} }
return new PubKey(pkBytes);
return new PubKey(pkBytes.getValue().toBytes());
} }
public long setDataPubKey(PubKey pubKey) { public long setDataPubKey(PubKey pubKey) {
byte[] pkBytes = pubKey.toBytes(); byte[] pkBytes = pubKey.toBytes();
return baseAccount.setBytes(DATA_PUB_KEY, pkBytes, -1);
return baseAccount.setBytes(DATA_PUB_KEY, BytesValueEntry.fromBytes(pkBytes), -1);
} }
public long setDataPubKey(PubKey pubKey, long version) { public long setDataPubKey(PubKey pubKey, long version) {
byte[] pkBytes = pubKey.toBytes(); byte[] pkBytes = pubKey.toBytes();
return baseAccount.setBytes(DATA_PUB_KEY, pkBytes, version);
return baseAccount.setBytes(DATA_PUB_KEY, BytesValueEntry.fromBytes(pkBytes), version);
} }
public long setProperty(String key, String value, long version) { public long setProperty(String key, String value, long version) {
@@ -62,15 +63,17 @@ public class UserAccount implements UserInfo {
} }
public long setProperty(Bytes key, String value, long version) { public long setProperty(Bytes key, String value, long version) {
return baseAccount.setBytes(encodePropertyKey(key), BytesUtils.toBytes(value), version);
return baseAccount.setBytes(encodePropertyKey(key), BytesValueEntry.fromText(value), version);
} }
public String getProperty(Bytes key) { public String getProperty(Bytes key) {
return BytesUtils.toString(baseAccount.getBytes(encodePropertyKey(key)));
BytesValue value = baseAccount.getBytes(encodePropertyKey(key));
return value == null ? null : value.getValue().toUTF8String();
} }
public String getProperty(Bytes key, long version) { public String getProperty(Bytes key, long version) {
return BytesUtils.toString(baseAccount.getBytes(encodePropertyKey(key), version));
BytesValue value = baseAccount.getBytes(encodePropertyKey(key), version);
return value == null ? null : value.getValue().toUTF8String();
} }
private Bytes encodePropertyKey(Bytes key) { private Bytes encodePropertyKey(Bytes key) {


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

@@ -4,6 +4,7 @@ import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.AccountHeader; import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.CryptoSetting; import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.storage.service.ExPolicyKVStorage; import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage; import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.Bytes;


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

@@ -8,8 +8,8 @@ import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;


import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.UserRegisterOperation; import com.jd.blockchain.ledger.UserRegisterOperation;
import com.jd.blockchain.ledger.core.LedgerException;
import com.jd.blockchain.ledger.core.OperationHandle; import com.jd.blockchain.ledger.core.OperationHandle;
import com.jd.blockchain.ledger.core.impl.handles.ContractCodeDeployOperationHandle; import com.jd.blockchain.ledger.core.impl.handles.ContractCodeDeployOperationHandle;
import com.jd.blockchain.ledger.core.impl.handles.ContractEventSendOperationHandle; import com.jd.blockchain.ledger.core.impl.handles.ContractEventSendOperationHandle;


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

@@ -8,10 +8,10 @@ import com.jd.blockchain.crypto.CryptoAlgorithm;
import com.jd.blockchain.crypto.CryptoProvider; import com.jd.blockchain.crypto.CryptoProvider;
import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.CryptoSetting; import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.LedgerInitSetting; import com.jd.blockchain.ledger.LedgerInitSetting;
import com.jd.blockchain.ledger.core.LedgerConsts; import com.jd.blockchain.ledger.core.LedgerConsts;
import com.jd.blockchain.ledger.core.LedgerEditor; import com.jd.blockchain.ledger.core.LedgerEditor;
import com.jd.blockchain.ledger.core.LedgerException;
import com.jd.blockchain.ledger.core.LedgerManage; import com.jd.blockchain.ledger.core.LedgerManage;
import com.jd.blockchain.ledger.core.LedgerRepository; import com.jd.blockchain.ledger.core.LedgerRepository;
import com.jd.blockchain.storage.service.ExPolicyKVStorage; import com.jd.blockchain.storage.service.ExPolicyKVStorage;


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

@@ -1,10 +1,23 @@
package com.jd.blockchain.ledger.core.impl; package com.jd.blockchain.ledger.core.impl;
import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.binaryproto.PrimitiveType;
import java.util.ArrayList;
import java.util.List;
import com.jd.blockchain.contract.ContractException; import com.jd.blockchain.contract.ContractException;
import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.*;
import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.BytesValue;
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.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.ledger.core.ContractAccountSet; import com.jd.blockchain.ledger.core.ContractAccountSet;
import com.jd.blockchain.ledger.core.DataAccount; import com.jd.blockchain.ledger.core.DataAccount;
import com.jd.blockchain.ledger.core.DataAccountSet; import com.jd.blockchain.ledger.core.DataAccountSet;
@@ -16,16 +29,12 @@ import com.jd.blockchain.ledger.core.UserAccountSet;
import com.jd.blockchain.transaction.BlockchainQueryService; import com.jd.blockchain.transaction.BlockchainQueryService;
import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.QueryUtil; import com.jd.blockchain.utils.QueryUtil;
import com.jd.blockchain.utils.StringUtils;
import java.util.ArrayList;
import java.util.List;
public class LedgerQueryService implements BlockchainQueryService { public class LedgerQueryService implements BlockchainQueryService {
private LedgerService ledgerService;
public LedgerQueryService(LedgerService ledgerService) {
private LedgerService ledgerService;
public LedgerQueryService(LedgerService ledgerService) {
this.ledgerService = ledgerService; this.ledgerService = ledgerService;
} }
@@ -37,7 +46,7 @@ public class LedgerQueryService implements BlockchainQueryService {
@Override @Override
public LedgerInfo getLedger(HashDigest ledgerHash) { public LedgerInfo getLedger(HashDigest ledgerHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerInfo ledgerInfo =new LedgerInfo();
LedgerInfo ledgerInfo = new LedgerInfo();
ledgerInfo.setHash(ledger.getHash()); ledgerInfo.setHash(ledger.getHash());
ledgerInfo.setLatestBlockHash(ledger.getLatestBlockHash()); ledgerInfo.setLatestBlockHash(ledger.getLatestBlockHash());
ledgerInfo.setLatestBlockHeight(ledger.getLatestBlockHeight()); ledgerInfo.setLatestBlockHeight(ledger.getLatestBlockHeight());
@@ -173,8 +182,8 @@ public class LedgerQueryService implements BlockchainQueryService {
lastHeightTxTotalNums = (int) ledger.getTransactionSet(ledger.getBlock(height - 1)).getTotalCount(); lastHeightTxTotalNums = (int) ledger.getTransactionSet(ledger.getBlock(height - 1)).getTotalCount();
} }
int currentHeightTxTotalNums = (int)ledger.getTransactionSet(ledger.getBlock(height)).getTotalCount();
//取当前高度的增量交易数,在增量交易里进行查找
int currentHeightTxTotalNums = (int) ledger.getTransactionSet(ledger.getBlock(height)).getTotalCount();
// 取当前高度的增量交易数,在增量交易里进行查找
int currentHeightTxNums = currentHeightTxTotalNums - lastHeightTxTotalNums; int currentHeightTxNums = currentHeightTxTotalNums - lastHeightTxTotalNums;
// //
// if (fromIndex < 0 || fromIndex >= currentHeightTxNums) { // if (fromIndex < 0 || fromIndex >= currentHeightTxNums) {
@@ -187,8 +196,8 @@ public class LedgerQueryService implements BlockchainQueryService {
// if (count > currentHeightTxNums) { // if (count > currentHeightTxNums) {
// count = currentHeightTxNums - fromIndex; // count = currentHeightTxNums - fromIndex;
// } // }
int indexAndCount [] = QueryUtil.calFromIndexAndCount(fromIndex,count,currentHeightTxNums);
return transactionSet.getTxs(lastHeightTxTotalNums + indexAndCount[0] , indexAndCount[1]);
int indexAndCount[] = QueryUtil.calFromIndexAndCount(fromIndex, count, currentHeightTxNums);
return transactionSet.getTxs(lastHeightTxTotalNums + indexAndCount[0], indexAndCount[1]);
} }
@Override @Override
@@ -203,8 +212,8 @@ public class LedgerQueryService implements BlockchainQueryService {
lastHeightTxTotalNums = (int) ledger.getTransactionSet(ledger.getBlock(height - 1)).getTotalCount(); lastHeightTxTotalNums = (int) ledger.getTransactionSet(ledger.getBlock(height - 1)).getTotalCount();
} }
int currentHeightTxTotalNums = (int)ledger.getTransactionSet(ledger.getBlock(height)).getTotalCount();
//取当前块hash的增量交易数,在增量交易里进行查找
int currentHeightTxTotalNums = (int) ledger.getTransactionSet(ledger.getBlock(height)).getTotalCount();
// 取当前块hash的增量交易数,在增量交易里进行查找
int currentHeightTxNums = currentHeightTxTotalNums - lastHeightTxTotalNums; int currentHeightTxNums = currentHeightTxTotalNums - lastHeightTxTotalNums;
// if (fromIndex < 0 || fromIndex >= currentHeightTxNums) { // if (fromIndex < 0 || fromIndex >= currentHeightTxNums) {
@@ -217,8 +226,8 @@ public class LedgerQueryService implements BlockchainQueryService {
// if (count > currentHeightTxNums) { // if (count > currentHeightTxNums) {
// count = currentHeightTxNums - fromIndex; // count = currentHeightTxNums - fromIndex;
// } // }
int indexAndCount [] = QueryUtil.calFromIndexAndCount(fromIndex,count,currentHeightTxNums);
return transactionSet.getTxs(lastHeightTxTotalNums + indexAndCount[0] , indexAndCount[1]);
int indexAndCount[] = QueryUtil.calFromIndexAndCount(fromIndex, count, currentHeightTxNums);
return transactionSet.getTxs(lastHeightTxTotalNums + indexAndCount[0], indexAndCount[1]);
} }
@Override @Override
@@ -228,7 +237,7 @@ public class LedgerQueryService implements BlockchainQueryService {
TransactionSet txset = ledger.getTransactionSet(block); TransactionSet txset = ledger.getTransactionSet(block);
return txset.get(contentHash); return txset.get(contentHash);
} }
@Override @Override
public TransactionState getTransactionStateByContentHash(HashDigest ledgerHash, HashDigest contentHash) { public TransactionState getTransactionStateByContentHash(HashDigest ledgerHash, HashDigest contentHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
@@ -243,7 +252,7 @@ public class LedgerQueryService implements BlockchainQueryService {
LedgerBlock block = ledger.getLatestBlock(); LedgerBlock block = ledger.getLatestBlock();
UserAccountSet userAccountSet = ledger.getUserAccountSet(block); UserAccountSet userAccountSet = ledger.getUserAccountSet(block);
return userAccountSet.getUser(address); return userAccountSet.getUser(address);
} }
@Override @Override
@@ -263,33 +272,32 @@ public class LedgerQueryService implements BlockchainQueryService {
LedgerBlock block = ledger.getLatestBlock(); LedgerBlock block = ledger.getLatestBlock();
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address)); DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address));
KVDataEntry[] entries = new KVDataEntry[keys.length]; KVDataEntry[] entries = new KVDataEntry[keys.length];
long ver; long ver;
for (int i = 0; i < entries.length; i++) { for (int i = 0; i < entries.length; i++) {
ver = dataAccount.getDataVersion(Bytes.fromString(keys[i])); ver = dataAccount.getDataVersion(Bytes.fromString(keys[i]));
dataAccount.getBytes(Bytes.fromString(keys[i]),1);
dataAccount.getBytes(Bytes.fromString(keys[i]), 1);
if (ver < 0) { if (ver < 0) {
entries[i] = new KVDataObject(keys[i], -1, PrimitiveType.NIL, null);
}else {
byte[] value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver);
BytesValue decodeData = BinaryProtocol.decode(value);
entries[i] = new KVDataObject(keys[i], ver, PrimitiveType.valueOf(decodeData.getType().CODE), decodeData.getValue().toBytes());
entries[i] = new KVDataObject(keys[i], -1, null);
} else {
BytesValue value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver);
entries[i] = new KVDataObject(keys[i], ver, value);
} }
} }
return entries; return entries;
} }
public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) { public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) {
//parse kvInfoVO;
// parse kvInfoVO;
List<String> keyList = new ArrayList<>(); List<String> keyList = new ArrayList<>();
List<Long> versionList = new ArrayList<>(); List<Long> versionList = new ArrayList<>();
if(kvInfoVO != null){
for(KVDataVO kvDataVO : kvInfoVO.getData()){
for(Long version : kvDataVO.getVersion()){
if (kvInfoVO != null) {
for (KVDataVO kvDataVO : kvInfoVO.getData()) {
for (Long version : kvDataVO.getVersion()) {
keyList.add(kvDataVO.getKey()); keyList.add(kvDataVO.getKey());
versionList.add(version); versionList.add(version);
} }
@@ -301,12 +309,12 @@ public class LedgerQueryService implements BlockchainQueryService {
if (keys == null || keys.length == 0) { if (keys == null || keys.length == 0) {
return null; return null;
} }
if (versions == null || versions.length == 0) {
return null;
}
if(keys.length != versions.length){
throw new ContractException("keys.length!=versions.length!");
}
if (versions == null || versions.length == 0) {
return null;
}
if (keys.length != versions.length) {
throw new ContractException("keys.length!=versions.length!");
}
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock(); LedgerBlock block = ledger.getLatestBlock();
@@ -314,22 +322,21 @@ public class LedgerQueryService implements BlockchainQueryService {
DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address)); DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address));
KVDataEntry[] entries = new KVDataEntry[keys.length]; KVDataEntry[] entries = new KVDataEntry[keys.length];
long ver = -1;
long ver = -1;
for (int i = 0; i < entries.length; i++) { for (int i = 0; i < entries.length; i++) {
// ver = dataAccount.getDataVersion(Bytes.fromString(keys[i])); // ver = dataAccount.getDataVersion(Bytes.fromString(keys[i]));
// dataAccount.getBytes(Bytes.fromString(keys[i]),1); // dataAccount.getBytes(Bytes.fromString(keys[i]),1);
ver = versions[i]; ver = versions[i];
if (ver < 0) { if (ver < 0) {
entries[i] = new KVDataObject(keys[i], -1, PrimitiveType.NIL, null);
}else {
if(dataAccount.getDataEntriesTotalCount()==0 ||
dataAccount.getBytes(Bytes.fromString(keys[i]), ver) == null){
//is the address is not exist; the result is null;
entries[i] = new KVDataObject(keys[i], -1, PrimitiveType.NIL, null);
entries[i] = new KVDataObject(keys[i], -1, null);
} else {
if (dataAccount.getDataEntriesTotalCount() == 0
|| dataAccount.getBytes(Bytes.fromString(keys[i]), ver) == null) {
// is the address is not exist; the result is null;
entries[i] = new KVDataObject(keys[i], -1, null);
} else { } else {
byte[] value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver);
BytesValue decodeData = BinaryProtocol.decode(value);
entries[i] = new KVDataObject(keys[i], ver, PrimitiveType.valueOf(decodeData.getType().CODE), decodeData.getValue().toBytes());
BytesValue value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver);
entries[i] = new KVDataObject(keys[i], ver, value);
} }
} }
} }
@@ -381,8 +388,8 @@ public class LedgerQueryService implements BlockchainQueryService {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock(); LedgerBlock block = ledger.getLatestBlock();
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
int pages[] = QueryUtil.calFromIndexAndCount(fromIndex,count,(int)dataAccountSet.getTotalCount());
return dataAccountSet.getAccounts(pages[0],pages[1]);
int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccountSet.getTotalCount());
return dataAccountSet.getAccounts(pages[0], pages[1]);
} }
@Override @Override
@@ -390,8 +397,8 @@ public class LedgerQueryService implements BlockchainQueryService {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock(); LedgerBlock block = ledger.getLatestBlock();
ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block);
int pages[] = QueryUtil.calFromIndexAndCount(fromIndex,count,(int)contractAccountSet.getTotalCount());
return contractAccountSet.getAccounts(pages[0],pages[1]);
int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) contractAccountSet.getTotalCount());
return contractAccountSet.getAccounts(pages[0], pages[1]);
} }
private LedgerAdministration ledgerAdministration(HashDigest ledgerHash) { private LedgerAdministration ledgerAdministration(HashDigest ledgerHash) {


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

@@ -13,7 +13,6 @@ import com.jd.blockchain.ledger.core.LedgerAdministration;
import com.jd.blockchain.ledger.core.LedgerConsts; import com.jd.blockchain.ledger.core.LedgerConsts;
import com.jd.blockchain.ledger.core.LedgerDataSet; import com.jd.blockchain.ledger.core.LedgerDataSet;
import com.jd.blockchain.ledger.core.LedgerEditor; import com.jd.blockchain.ledger.core.LedgerEditor;
import com.jd.blockchain.ledger.core.LedgerException;
import com.jd.blockchain.ledger.core.LedgerRepository; import com.jd.blockchain.ledger.core.LedgerRepository;
import com.jd.blockchain.ledger.core.LedgerTransactionContext; import com.jd.blockchain.ledger.core.LedgerTransactionContext;
import com.jd.blockchain.ledger.core.TransactionSet; import com.jd.blockchain.ledger.core.TransactionSet;


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

@@ -16,7 +16,7 @@ import com.jd.blockchain.utils.Bytes;
public class OpeningAccessPolicy implements AccountAccessPolicy { public class OpeningAccessPolicy implements AccountAccessPolicy {


@Override @Override
public boolean checkCommitting(AccountHeader account) {
public boolean checkDataWriting(AccountHeader account) {
return true; return true;
} }




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

@@ -9,13 +9,13 @@ import org.slf4j.LoggerFactory;


import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.LedgerBlock; import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.Operation; import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.ledger.TransactionRequest; import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.ledger.TransactionResponse; import com.jd.blockchain.ledger.TransactionResponse;
import com.jd.blockchain.ledger.TransactionState; import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.ledger.core.LedgerDataSet; import com.jd.blockchain.ledger.core.LedgerDataSet;
import com.jd.blockchain.ledger.core.LedgerEditor; import com.jd.blockchain.ledger.core.LedgerEditor;
import com.jd.blockchain.ledger.core.LedgerException;
import com.jd.blockchain.ledger.core.LedgerService; import com.jd.blockchain.ledger.core.LedgerService;
import com.jd.blockchain.ledger.core.LedgerTransactionContext; import com.jd.blockchain.ledger.core.LedgerTransactionContext;
import com.jd.blockchain.ledger.core.OperationHandle; import com.jd.blockchain.ledger.core.OperationHandle;


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

@@ -9,11 +9,11 @@ import com.jd.blockchain.contract.engine.ContractCode;
import com.jd.blockchain.contract.engine.ContractEngine; import com.jd.blockchain.contract.engine.ContractEngine;
import com.jd.blockchain.contract.engine.ContractServiceProviders; import com.jd.blockchain.contract.engine.ContractServiceProviders;
import com.jd.blockchain.ledger.ContractEventSendOperation; import com.jd.blockchain.ledger.ContractEventSendOperation;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.Operation; import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.ledger.core.ContractAccount; import com.jd.blockchain.ledger.core.ContractAccount;
import com.jd.blockchain.ledger.core.ContractAccountSet; import com.jd.blockchain.ledger.core.ContractAccountSet;
import com.jd.blockchain.ledger.core.LedgerDataSet; import com.jd.blockchain.ledger.core.LedgerDataSet;
import com.jd.blockchain.ledger.core.LedgerException;
import com.jd.blockchain.ledger.core.LedgerService; import com.jd.blockchain.ledger.core.LedgerService;
import com.jd.blockchain.ledger.core.OperationHandle; import com.jd.blockchain.ledger.core.OperationHandle;
import com.jd.blockchain.ledger.core.TransactionRequestContext; import com.jd.blockchain.ledger.core.TransactionRequestContext;


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

@@ -3,10 +3,25 @@ package com.jd.blockchain.ledger.core.impl.handles;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;


import com.alibaba.fastjson.JSON;
import com.jd.blockchain.contract.LedgerContext; import com.jd.blockchain.contract.LedgerContext;
import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.*;
import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.BytesValueEntry;
import com.jd.blockchain.ledger.DataAccountKVSetOperation;
import com.jd.blockchain.ledger.DataAccountRegisterOperation;
import com.jd.blockchain.ledger.KVDataEntry;
import com.jd.blockchain.ledger.KVInfoVO;
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.Operation;
import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.ledger.UserInfo;
import com.jd.blockchain.ledger.UserRegisterOperation;
import com.jd.blockchain.ledger.core.impl.OperationHandleContext; import com.jd.blockchain.ledger.core.impl.OperationHandleContext;
import com.jd.blockchain.transaction.BlockchainQueryService; import com.jd.blockchain.transaction.BlockchainQueryService;
import com.jd.blockchain.transaction.DataAccountKVSetOperationBuilder; import com.jd.blockchain.transaction.DataAccountKVSetOperationBuilder;
@@ -16,7 +31,6 @@ import com.jd.blockchain.transaction.KVData;
import com.jd.blockchain.transaction.UserRegisterOperationBuilder; import com.jd.blockchain.transaction.UserRegisterOperationBuilder;
import com.jd.blockchain.transaction.UserRegisterOperationBuilderImpl; import com.jd.blockchain.transaction.UserRegisterOperationBuilderImpl;
import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.io.BytesUtils;


public class ContractLedgerContext implements LedgerContext { public class ContractLedgerContext implements LedgerContext {


@@ -250,60 +264,95 @@ public class ContractLedgerContext implements LedgerContext {
this.accountAddress = accountAddress; this.accountAddress = accountAddress;
} }


public boolean isJson(String str) {
boolean result = false;
try {
Object obj = JSON.parse(str);
result = true;
} catch (Exception e) {
result = false;
}
return result;
}

@Override @Override
public DataAccountKVSetOperation getOperation() { public DataAccountKVSetOperation getOperation() {
return op; return op;
} }


// @Override
// public DataAccountKVSetOperationBuilder set(String key, byte[] value, long expVersion) {
// BytesValue bytesValue = BytesValueEntry.fromBytes(value);
// this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion);
// handle(op);
// return this;
// }

@Override @Override
public DataAccountKVSetOperationBuilder set(String key, byte[] value, long expVersion) {
BytesValue bytesValue = new BytesValueEntry(BytesValueType.BYTES, value);
public DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromText(value);
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion);
generatedOpList.add(op);
opHandleContext.handle(op);
handle(op);
return this; return this;
} }

@Override @Override
public DataAccountKVSetOperationBuilder set(String key, String value, long expVersion) {
BytesValue bytesValue;
if (isJson(value)) {
public DataAccountKVSetOperationBuilder setBytes(String key, Bytes value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromBytes(value);
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion);
handle(op);
return this;
}


bytesValue = new BytesValueEntry(BytesValueType.JSON, BytesUtils.toBytes(value));
}
else {
bytesValue = new BytesValueEntry(BytesValueType.TEXT, BytesUtils.toBytes(value));
}
@Override
public DataAccountKVSetOperationBuilder setInt64(String key, long value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromInt64(value);
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion);
generatedOpList.add(op);
opHandleContext.handle(op);
handle(op);
return this; return this;
} }
// @Deprecated
// @Override
// public DataAccountKVSetOperationBuilder set(String key, String value, long expVersion) {
// BytesValue bytesValue = BytesValueEntry.fromText(value);
// this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion);
// handle(op);
// return this;
// }
@Override @Override
public DataAccountKVSetOperationBuilder set(String key, Bytes value, long expVersion) {
BytesValue bytesValue = new BytesValueEntry(BytesValueType.BYTES, value.toBytes());
public DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromJSON(value);
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion);
generatedOpList.add(op);
opHandleContext.handle(op);
handle(op);
return this;
}
@Override
public DataAccountKVSetOperationBuilder setXML(String key, String value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromXML(value);
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion);
handle(op);
return this;
}
@Override
public DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromBytes(value);
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion);
handle(op);
return this;
}
@Override
public DataAccountKVSetOperationBuilder setImage(String key, byte[] value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromImage(value);
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion);
handle(op);
return this; return this;
} }
@Override @Override
public DataAccountKVSetOperationBuilder set(String key, long value, long expVersion) {
BytesValue bytesValue = new BytesValueEntry(BytesValueType.INT64, BytesUtils.toBytes(value));
public DataAccountKVSetOperationBuilder setTimestamp(String key, long value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromTimestamp(value);
this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion); this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion);
handle(op);
return this;
}
private void handle(Operation op) {
generatedOpList.add(op); generatedOpList.add(op);
opHandleContext.handle(op); opHandleContext.handle(op);
return this;
} }


/** /**


+ 1
- 2
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/DataAccountKVSetOperationHandle.java View File

@@ -24,8 +24,7 @@ public class DataAccountKVSetOperationHandle implements OperationHandle{
DataAccount account = dataset.getDataAccountSet().getDataAccount(kvWriteOp.getAccountAddress()); DataAccount account = dataset.getDataAccountSet().getDataAccount(kvWriteOp.getAccountAddress());
KVWriteEntry[] writeset = kvWriteOp.getWriteSet(); KVWriteEntry[] writeset = kvWriteOp.getWriteSet();
for (KVWriteEntry kvw : writeset) { for (KVWriteEntry kvw : writeset) {
byte[] value = BinaryProtocol.encode(kvw.getValue(), BytesValue.class);
account.setBytes(Bytes.fromString(kvw.getKey()), value, kvw.getExpectedVersion());
account.setBytes(Bytes.fromString(kvw.getKey()), kvw.getValue(), kvw.getExpectedVersion());
} }
} }




+ 9
- 11
source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/BaseAccountTest.java View File

@@ -12,12 +12,11 @@ import com.jd.blockchain.crypto.service.classic.ClassicCryptoService;
import com.jd.blockchain.crypto.service.sm.SMCryptoService; import com.jd.blockchain.crypto.service.sm.SMCryptoService;
import com.jd.blockchain.ledger.BlockchainKeyGenerator; import com.jd.blockchain.ledger.BlockchainKeyGenerator;
import com.jd.blockchain.ledger.BlockchainKeypair; import com.jd.blockchain.ledger.BlockchainKeypair;
import com.jd.blockchain.ledger.BytesValueEntry;
import com.jd.blockchain.ledger.core.BaseAccount; import com.jd.blockchain.ledger.core.BaseAccount;
import com.jd.blockchain.ledger.core.CryptoConfig; import com.jd.blockchain.ledger.core.CryptoConfig;
import com.jd.blockchain.ledger.core.impl.OpeningAccessPolicy;
import com.jd.blockchain.storage.service.utils.MemoryKVStorage; import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.io.BytesUtils;


/** /**
* *
@@ -44,44 +43,43 @@ public class BaseAccountTest {
cryptoConf.setAutoVerifyHash(true); cryptoConf.setAutoVerifyHash(true);
cryptoConf.setHashAlgorithm(ClassicAlgorithm.SHA256); cryptoConf.setHashAlgorithm(ClassicAlgorithm.SHA256);


OpeningAccessPolicy accPlc = new OpeningAccessPolicy();
// OpeningAccessPolicy accPlc = new OpeningAccessPolicy();


BlockchainKeypair bck = BlockchainKeyGenerator.getInstance().generate(); BlockchainKeypair bck = BlockchainKeyGenerator.getInstance().generate();


// 新建账户; // 新建账户;
BaseAccount baseAccount = new BaseAccount(bck.getIdentity(), cryptoConf, keyPrefix, testStorage, testStorage,
accPlc);
BaseAccount baseAccount = new BaseAccount(bck.getIdentity(), cryptoConf, keyPrefix, testStorage, testStorage);
assertFalse(baseAccount.isUpdated());// 空的账户; assertFalse(baseAccount.isUpdated());// 空的账户;
assertFalse(baseAccount.isReadonly()); assertFalse(baseAccount.isReadonly());


// 在空白状态下写入数据; // 在空白状态下写入数据;
long v = baseAccount.setBytes(Bytes.fromString("A"), BytesUtils.toBytes("VALUE_A"), 0);
long v = baseAccount.setBytes(Bytes.fromString("A"), BytesValueEntry.fromText("VALUE_A"), 0);
// 预期失败; // 预期失败;
assertEquals(-1, v); assertEquals(-1, v);


v = baseAccount.setBytes(Bytes.fromString("A"), BytesUtils.toBytes("VALUE_A"), 1);
v = baseAccount.setBytes(Bytes.fromString("A"), BytesValueEntry.fromText("VALUE_A"), 1);
// 预期失败; // 预期失败;
assertEquals(-1, v); assertEquals(-1, v);


v = baseAccount.setBytes(Bytes.fromString("A"), BytesUtils.toBytes("VALUE_A"), -1);
v = baseAccount.setBytes(Bytes.fromString("A"), BytesValueEntry.fromText("VALUE_A"), -1);
// 预期成功; // 预期成功;
assertEquals(0, v); assertEquals(0, v);


v = baseAccount.setBytes(Bytes.fromString("A"), BytesUtils.toBytes("VALUE_A-1"), -1);
v = baseAccount.setBytes(Bytes.fromString("A"), BytesValueEntry.fromText("VALUE_A-1"), -1);
// 已经存在版本,指定版本号-1,预期导致失败; // 已经存在版本,指定版本号-1,预期导致失败;
assertEquals(-1, v); assertEquals(-1, v);


baseAccount.commit(); baseAccount.commit();
v = 0; v = 0;
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
long s = baseAccount.setBytes(Bytes.fromString("A"), BytesUtils.toBytes("VALUE_A_" + i), v);
long s = baseAccount.setBytes(Bytes.fromString("A"), BytesValueEntry.fromText("VALUE_A_" + i), v);
baseAccount.commit(); baseAccount.commit();
// 预期成功; // 预期成功;
assertEquals(v + 1, s); assertEquals(v + 1, s);
v++; v++;
} }


v = baseAccount.setBytes(Bytes.fromString("A"), BytesUtils.toBytes("VALUE_A_" + v), v + 1);
v = baseAccount.setBytes(Bytes.fromString("A"), BytesValueEntry.fromText("VALUE_A_" + v), v + 1);
// 预期成功; // 预期成功;
assertEquals(-1, v); assertEquals(-1, v);




+ 57
- 23
source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerEditerTest.java View File

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


import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;


import org.junit.Before;
import org.junit.Test; import org.junit.Test;


import com.jd.blockchain.binaryproto.DataContractRegistry; import com.jd.blockchain.binaryproto.DataContractRegistry;
@@ -17,6 +17,8 @@ import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
import com.jd.blockchain.crypto.service.classic.ClassicCryptoService; import com.jd.blockchain.crypto.service.classic.ClassicCryptoService;
import com.jd.blockchain.crypto.service.sm.SMCryptoService; import com.jd.blockchain.crypto.service.sm.SMCryptoService;
import com.jd.blockchain.ledger.BlockchainKeypair; import com.jd.blockchain.ledger.BlockchainKeypair;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.BytesValueType;
import com.jd.blockchain.ledger.LedgerBlock; import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerInitSetting; import com.jd.blockchain.ledger.LedgerInitSetting;
import com.jd.blockchain.ledger.LedgerTransaction; import com.jd.blockchain.ledger.LedgerTransaction;
@@ -37,67 +39,99 @@ import com.jd.blockchain.utils.io.BytesUtils;
import com.jd.blockchain.utils.net.NetworkAddress; import com.jd.blockchain.utils.net.NetworkAddress;


public class LedgerEditerTest { public class LedgerEditerTest {
private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(), private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(),
SMCryptoService.class.getName() }; SMCryptoService.class.getName() };



static { static {
DataContractRegistry.register(com.jd.blockchain.ledger.TransactionContent.class); DataContractRegistry.register(com.jd.blockchain.ledger.TransactionContent.class);
DataContractRegistry.register(com.jd.blockchain.ledger.UserRegisterOperation.class); DataContractRegistry.register(com.jd.blockchain.ledger.UserRegisterOperation.class);
DataContractRegistry.register(com.jd.blockchain.ledger.BlockBody.class); DataContractRegistry.register(com.jd.blockchain.ledger.BlockBody.class);
} }


String ledgerKeyPrefix = "LDG://";
SignatureFunction signatureFunction = Crypto.getSignatureFunction("ED25519");
private static final String LEDGER_KEY_PREFIX = "LDG://";
private SignatureFunction signatureFunction;


// 存储;
MemoryKVStorage storage = new MemoryKVStorage();
/**
* 初始化一个;
*/
@Before
public void beforeTest() {
signatureFunction = Crypto.getSignatureFunction("ED25519");
}


TransactionRequest genesisTxReq = LedgerTestUtils.createTxRequest(null, signatureFunction);
/**
* @return
*/
private LedgerEditor createLedgerInitEditor() {
// 存储;
MemoryKVStorage storage = new MemoryKVStorage();


// 创建初始化配置;
LedgerInitSetting initSetting = createLedgerInitSetting();
// 创建初始化配置;
LedgerInitSetting initSetting = createLedgerInitSetting();


// 创建账本;
LedgerEditor ldgEdt = LedgerTransactionalEditor.createEditor(initSetting, ledgerKeyPrefix, storage, storage);
LedgerTransactionContext txCtx = ldgEdt.newTransaction(genesisTxReq);
LedgerDataSet ldgDS = txCtx.getDataSet();
// 创建账本;
return LedgerTransactionalEditor.createEditor(initSetting, LEDGER_KEY_PREFIX, storage, storage);
}


AsymmetricKeypair cryptoKeyPair = signatureFunction.generateKeypair();
private LedgerTransactionContext createGenisisTx(LedgerEditor ldgEdt) {
TransactionRequest genesisTxReq = LedgerTestUtils.createTxRequest(null, signatureFunction);

LedgerTransactionContext txCtx = ldgEdt.newTransaction(genesisTxReq);
return txCtx;
}


@SuppressWarnings("unused") @SuppressWarnings("unused")
@Test @Test
public void testWriteDataAccoutKvOp() { public void testWriteDataAccoutKvOp() {

LedgerEditor ldgEdt = createLedgerInitEditor();
LedgerTransactionContext genisisTxCtx = createGenisisTx(ldgEdt);
LedgerDataSet ldgDS = genisisTxCtx.getDataSet();
AsymmetricKeypair cryptoKeyPair = signatureFunction.generateKeypair();
BlockchainKeypair dataKP = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey()); BlockchainKeypair dataKP = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey());


DataAccount dataAccount = ldgDS.getDataAccountSet().register(dataKP.getAddress(), dataKP.getPubKey(), null); DataAccount dataAccount = ldgDS.getDataAccountSet().register(dataKP.getAddress(), dataKP.getPubKey(), null);


dataAccount.setBytes(Bytes.fromString("A"), "abc".getBytes(), -1);
dataAccount.setBytes(Bytes.fromString("A"), "abc", -1);


LedgerTransaction tx = txCtx.commit(TransactionState.SUCCESS);
LedgerTransaction tx = genisisTxCtx.commit(TransactionState.SUCCESS);
LedgerBlock block = ldgEdt.prepare(); LedgerBlock block = ldgEdt.prepare();
// 提交数据,写入存储; // 提交数据,写入存储;
ldgEdt.commit(); ldgEdt.commit();


byte[] bytes = dataAccount.getBytes("A");
assertArrayEquals("abc".getBytes(), bytes);
// 预期这是第1个区块;
assertNotNull(block);
assertNotNull(block.getHash());
assertEquals(0, block.getHeight());

// 验证数据读写的一致性;
BytesValue bytes = dataAccount.getBytes("A");
assertEquals(BytesValueType.TEXT, bytes.getType());
String textValue = bytes.getValue().toUTF8String();
assertEquals("abc", textValue);
} }


/** /**
* 测试创建账本; * 测试创建账本;
*/ */
@Test @Test
public void testLedgerEditorCreation() {
public void testGennesisBlockCreation() {
LedgerEditor ldgEdt = createLedgerInitEditor();
LedgerTransactionContext genisisTxCtx = createGenisisTx(ldgEdt);
LedgerDataSet ldgDS = genisisTxCtx.getDataSet();


AsymmetricKeypair cryptoKeyPair = signatureFunction.generateKeypair();
BlockchainKeypair userKP = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey()); BlockchainKeypair userKP = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey());
UserAccount userAccount = ldgDS.getUserAccountSet().register(userKP.getAddress(), userKP.getPubKey()); UserAccount userAccount = ldgDS.getUserAccountSet().register(userKP.getAddress(), userKP.getPubKey());
userAccount.setProperty("Name", "孙悟空", -1); userAccount.setProperty("Name", "孙悟空", -1);
userAccount.setProperty("Age", "10000", -1); userAccount.setProperty("Age", "10000", -1);


LedgerTransaction tx = txCtx.commit(TransactionState.SUCCESS);
LedgerTransaction tx = genisisTxCtx.commit(TransactionState.SUCCESS);


TransactionRequest genesisTxReq = genisisTxCtx.getRequestTX();
assertEquals(genesisTxReq.getTransactionContent().getHash(), tx.getTransactionContent().getHash()); assertEquals(genesisTxReq.getTransactionContent().getHash(), tx.getTransactionContent().getHash());
assertEquals(0, tx.getBlockHeight()); assertEquals(0, tx.getBlockHeight());


@@ -116,7 +150,7 @@ public class LedgerEditerTest {


private LedgerInitSetting createLedgerInitSetting() { private LedgerInitSetting createLedgerInitSetting() {
SignatureFunction signFunc = Crypto.getSignatureFunction("ED25519"); SignatureFunction signFunc = Crypto.getSignatureFunction("ED25519");
CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length]; CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length];
for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) { for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) {
supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]); supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]);


+ 1
- 1
source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerTransactionDataTest.java View File

@@ -257,7 +257,7 @@ public class LedgerTransactionDataTest {
// contentBlob.setSubjectAccount(id.getAddress()); // contentBlob.setSubjectAccount(id.getAddress());
// contentBlob.setSequenceNumber(1); // contentBlob.setSequenceNumber(1);
DataAccountKVSetOperation kvsetOP = opFactory.dataAccount(id.getAddress()) DataAccountKVSetOperation kvsetOP = opFactory.dataAccount(id.getAddress())
.set("Name", ByteArray.fromString("AAA", "UTF-8"), -1).getOperation();
.setText("Name", "AAA", -1).getOperation();
contentBlob.addOperation(kvsetOP); contentBlob.addOperation(kvsetOP);
return contentBlob; return contentBlob;
} }

+ 1
- 1
source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TransactionSetTest.java View File

@@ -68,7 +68,7 @@ public class TransactionSetTest {
DataAccountRegisterOperation dataAccRegOp = txBuilder.dataAccounts().register(dataKey.getIdentity()); DataAccountRegisterOperation dataAccRegOp = txBuilder.dataAccounts().register(dataKey.getIdentity());


DataAccountKVSetOperation kvsetOP = txBuilder.dataAccount(dataKey.getAddress()) DataAccountKVSetOperation kvsetOP = txBuilder.dataAccount(dataKey.getAddress())
.set("A", "Value_A_0".getBytes(), -1).set("B", "Value_B_0".getBytes(), -1).getOperation();
.setText("A", "Value_A_0", -1).setText("B", "Value_B_0", -1).getOperation();


byte[] chainCode = new byte[128]; byte[] chainCode = new byte[128];
rand.nextBytes(chainCode); rand.nextBytes(chainCode);


+ 2
- 2
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValue.java View File

@@ -4,7 +4,7 @@ import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.binaryproto.DataField; import com.jd.blockchain.binaryproto.DataField;
import com.jd.blockchain.binaryproto.PrimitiveType; import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.consts.DataCodes; import com.jd.blockchain.consts.DataCodes;
import com.jd.blockchain.utils.io.BytesSlice;
import com.jd.blockchain.utils.Bytes;


/** /**
* BytesValue is the base structure of Value in Blockchain Account; * BytesValue is the base structure of Value in Blockchain Account;
@@ -29,6 +29,6 @@ public interface BytesValue {
* @return * @return
*/ */
@DataField(order = 1, primitiveType = PrimitiveType.BYTES) @DataField(order = 1, primitiveType = PrimitiveType.BYTES)
BytesSlice getValue();
Bytes getValue();
} }

+ 107
- 24
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValueEntry.java View File

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


import com.jd.blockchain.utils.io.BytesSlice;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.io.BytesUtils;


/** /**
* Created by zhangshuang3 on 2018/12/3.
*
* @author huanghaiquan
*
*/ */
public class BytesValueEntry implements BytesValue{
BytesValueType type;
BytesSlice slice;

public BytesValueEntry(BytesValueType type, byte[] bytes) {
this.type = type;
this.slice = new BytesSlice(bytes);
}

@Override
public BytesValueType getType() {
return this.type;
}

public void setType(BytesValueType type) {
this.type = type;
}

@Override
public BytesSlice getValue() {
return this.slice;
}
public class BytesValueEntry implements BytesValue {
BytesValueType type;
Bytes value;

private BytesValueEntry(BytesValueType type, byte[] bytes) {
this.type = type;
this.value = new Bytes(bytes);
}

private BytesValueEntry(BytesValueType type, Bytes bytes) {
this.type = type;
this.value = bytes;
}

public static BytesValue fromBytes(byte[] value) {
return new BytesValueEntry(BytesValueType.BYTES, value);
}

public static BytesValue fromBytes(Bytes value) {
return new BytesValueEntry(BytesValueType.BYTES, value);
}

public static BytesValue fromImage(byte[] value) {
return new BytesValueEntry(BytesValueType.IMG, value);
}

public static BytesValue fromImage(Bytes value) {
return new BytesValueEntry(BytesValueType.IMG, value);
}

/**
* 以 UTF-8 编码从字符串转换为字节数组值;
*
* @param value
* @return
*/
public static BytesValue fromText(String value) {
return new BytesValueEntry(BytesValueType.TEXT, BytesUtils.toBytes(value));
}

/**
* 以 UTF-8 编码把字节数组值转换为字符串;
*
* @param bytesValue
* @return
*/
public static String toText(BytesValue bytesValue) {
if (bytesValue == null) {
return null;
}
if (bytesValue.getType() != BytesValueType.TEXT) {
throw new ValueTypeCastException("The expected value type is " + BytesValueType.TEXT.toString()
+ ", but it is actually " + bytesValue.getType().toString() + "!");
}
return bytesValue.getValue().toUTF8String();
}

public static BytesValue fromJSON(String value) {
return new BytesValueEntry(BytesValueType.JSON, BytesUtils.toBytes(value));
}

public static BytesValue fromXML(String value) {
return new BytesValueEntry(BytesValueType.XML, BytesUtils.toBytes(value));
}

public static BytesValue fromInt32(int value) {
return new BytesValueEntry(BytesValueType.INT32, BytesUtils.toBytes(value));
}

public static BytesValue fromInt64(long value) {
return new BytesValueEntry(BytesValueType.INT64, BytesUtils.toBytes(value));
}

public static BytesValue fromInt16(short value) {
return new BytesValueEntry(BytesValueType.INT16, BytesUtils.toBytes(value));
}

public static BytesValue fromInt8(byte value) {
return new BytesValueEntry(BytesValueType.INT8, BytesUtils.toBytes(value));
}

public static BytesValue fromTimestamp(long value) {
return new BytesValueEntry(BytesValueType.TIMESTAMP, BytesUtils.toBytes(value));
}

public static BytesValue fromBoolean(boolean value) {
return new BytesValueEntry(BytesValueType.BOOLEAN, BytesUtils.toBytes(value));
}

@Override
public BytesValueType getType() {
return this.type;
}

public void setType(BytesValueType type) {
this.type = type;
}

@Override
public Bytes getValue() {
return this.value;
}


} }

+ 2
- 3
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValueType.java View File

@@ -37,9 +37,9 @@ public enum BytesValueType {
INT64(PrimitiveType.INT64.CODE), INT64(PrimitiveType.INT64.CODE),
/** /**
* 日期时间;
* 时间
*/ */
DATETIME(PrimitiveType.DATETIME.CODE),
TIMESTAMP(PrimitiveType.TIMESTAMP.CODE),
/** /**
* 文本数据; * 文本数据;
@@ -81,7 +81,6 @@ public enum BytesValueType {
*/ */
LOCATION(PrimitiveType.LOCATION.CODE); LOCATION(PrimitiveType.LOCATION.CODE);
@EnumField(type = PrimitiveType.INT8) @EnumField(type = PrimitiveType.INT8)
public final byte CODE; public final byte CODE;


+ 2
- 3
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataEntry.java View File

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


import com.jd.blockchain.binaryproto.PrimitiveType;

public interface KVDataEntry { public interface KVDataEntry {


/** /**
@@ -27,11 +25,12 @@ public interface KVDataEntry {
* *
* @return * @return
*/ */
PrimitiveType getType();
BytesValueType getType();
/** /**
* 值; * 值;
* @return * @return
*/ */
Object getValue(); Object getValue();
} }

+ 53
- 61
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataObject.java View File

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


import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.Date; import java.util.Date;


import com.jd.blockchain.binaryproto.PrimitiveType; import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.io.ByteArray; import com.jd.blockchain.utils.io.ByteArray;
import com.jd.blockchain.utils.io.BytesUtils; import com.jd.blockchain.utils.io.BytesUtils;


@@ -25,13 +24,10 @@ public class KVDataObject implements KVDataEntry {


private long version; private long version;


private PrimitiveType type;
private BytesValue bytesValue;


private byte[] bytesValue;

public KVDataObject(String key, long version, PrimitiveType type, byte[] bytesValue) {
public KVDataObject(String key, long version, BytesValue bytesValue) {
this.key = key; this.key = key;
this.type = type;
this.version = version < 0 ? -1 : version; this.version = version < 0 ? -1 : version;
this.bytesValue = bytesValue; this.bytesValue = bytesValue;
} }
@@ -62,8 +58,8 @@ public class KVDataObject implements KVDataEntry {
* @see com.jd.blockchain.ledger.KVDataEntry#getType() * @see com.jd.blockchain.ledger.KVDataEntry#getType()
*/ */
@Override @Override
public PrimitiveType getType() {
return type;
public BytesValueType getType() {
return bytesValue == null ? BytesValueType.NIL : bytesValue.getType();
} }


@Override @Override
@@ -72,24 +68,20 @@ public class KVDataObject implements KVDataEntry {
return null; return null;
} }


try {
switch (type) {
case NIL:
return null;
case TEXT:
return new String(bytesValue, "UTF-8");
case BYTES:
return ByteArray.toHex(bytesValue);
case INT64:
return BytesUtils.readLong(new ByteArrayInputStream(bytesValue));
case JSON:
return new String(bytesValue, "UTF-8");
switch (getType()) {
case NIL:
return null;
case TEXT:
return bytesValue.getValue().toUTF8String();
case BYTES:
return ByteArray.toHex(bytesValue.getValue().toBytes());
case INT64:
return BytesUtils.toLong(bytesValue.getValue().toBytes());
case JSON:
return bytesValue.getValue().toUTF8String();


default:
throw new IllegalStateException("Unsupported value type[" + type + "] to resolve!");
}
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException(e.getMessage(), e);
default:
throw new IllegalStateException("Unsupported value type[" + getType() + "] to resolve!");
} }
} }


@@ -103,7 +95,7 @@ public class KVDataObject implements KVDataEntry {
* @return * @return
*/ */
public boolean isNil() { public boolean isNil() {
return PrimitiveType.NIL == type;
return bytesValue == null || BytesValueType.NIL == bytesValue.getType();
} }


/** /**
@@ -111,8 +103,8 @@ public class KVDataObject implements KVDataEntry {
* *
* @return * @return
*/ */
ByteArray bytesArray() {
return ByteArray.wrapReadonly(bytesValue);
Bytes bytesArray() {
return bytesValue.getValue();
} }


/** /**
@@ -127,10 +119,10 @@ public class KVDataObject implements KVDataEntry {
* @return * @return
*/ */
public byte tinyValue() { public byte tinyValue() {
if (PrimitiveType.INT8 == type) {
return bytesValue[0];
if (BytesValueType.INT8 == getType()) {
return bytesValue.getValue().toBytes()[0];
} }
throw new IllegalStateException(String.format("Expected type [%s], but [%s]", PrimitiveType.INT8, type));
throw new IllegalStateException(String.format("Expected type [%s], but [%s]", BytesValueType.INT8, getType()));
} }


/** /**
@@ -145,10 +137,10 @@ public class KVDataObject implements KVDataEntry {
* @return * @return
*/ */
public short shortValue() { public short shortValue() {
if (PrimitiveType.INT16 == type) {
return BytesUtils.toShort(bytesValue, 0);
if (BytesValueType.INT16 == getType()) {
return BytesUtils.toShort(bytesValue.getValue().toBytes(), 0);
} }
throw new IllegalStateException(String.format("Expected type [%s], but [%s]", PrimitiveType.INT16, type));
throw new IllegalStateException(String.format("Expected type [%s], but [%s]", BytesValueType.INT16, getType()));
} }


/** /**
@@ -163,10 +155,10 @@ public class KVDataObject implements KVDataEntry {
* @return * @return
*/ */
public int intValue() { public int intValue() {
if (PrimitiveType.INT32 == type) {
return BytesUtils.toInt(bytesValue, 0);
if (BytesValueType.INT32 == getType()) {
return BytesUtils.toInt(bytesValue.getValue().toBytes(), 0);
} }
throw new IllegalStateException(String.format("Expected type [%s], but [%s]", PrimitiveType.INT32, type));
throw new IllegalStateException(String.format("Expected type [%s], but [%s]", BytesValueType.INT32, getType()));
} }


/** /**
@@ -181,10 +173,10 @@ public class KVDataObject implements KVDataEntry {
* @return * @return
*/ */
public long longValue() { public long longValue() {
if (PrimitiveType.INT64 == type) {
return BytesUtils.toLong(bytesValue, 0);
if (BytesValueType.INT64 == getType()) {
return BytesUtils.toLong(bytesValue.getValue().toBytes(), 0);
} }
throw new IllegalStateException(String.format("Expected type [%s], but [%s]", PrimitiveType.INT64, type));
throw new IllegalStateException(String.format("Expected type [%s], but [%s]", BytesValueType.INT64, getType()));


} }


@@ -200,10 +192,11 @@ public class KVDataObject implements KVDataEntry {
* @return * @return
*/ */
public BigInteger bigIntValue() { public BigInteger bigIntValue() {
if (PrimitiveType.BIG_INT == type) {
return new BigInteger(bytesValue);
if (BytesValueType.BIG_INT == getType()) {
return new BigInteger(bytesValue.getValue().toBytes());
} }
throw new IllegalStateException(String.format("Expected type [%s], but [%s]", PrimitiveType.BIG_INT, type));
throw new IllegalStateException(
String.format("Expected type [%s], but [%s]", BytesValueType.BIG_INT, getType()));
} }


/** /**
@@ -218,17 +211,18 @@ public class KVDataObject implements KVDataEntry {
* @return * @return
*/ */
public boolean boolValue() { public boolean boolValue() {
if (PrimitiveType.BOOLEAN == type) {
return bytesValue[0] != 0;
if (BytesValueType.BOOLEAN == getType()) {
return BytesUtils.toBoolean(bytesValue.getValue().toBytes()[0]);
} }
throw new IllegalStateException(String.format("Expected type [%s], but [%s]", PrimitiveType.BOOLEAN, type));
throw new IllegalStateException(
String.format("Expected type [%s], but [%s]", BytesValueType.BOOLEAN, getType()));
} }


/** /**
* 返回日期时间值; * 返回日期时间值;
* <p> * <p>
* *
* 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#DATETIME} 有效;
* 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#TIMESTAMP} 有效;
* <p> * <p>
* *
* 无效类型将引发 {@link IllegalStateException} 异常; * 无效类型将引发 {@link IllegalStateException} 异常;
@@ -236,19 +230,20 @@ public class KVDataObject implements KVDataEntry {
* @return * @return
*/ */
public Date datetimeValue() { public Date datetimeValue() {
if (PrimitiveType.DATETIME == type) {
long ts = BytesUtils.toLong(bytesValue);
if (BytesValueType.TIMESTAMP == getType()) {
long ts = BytesUtils.toLong(bytesValue.getValue().toBytes());
return new Date(ts); return new Date(ts);
} }
throw new IllegalStateException(String.format("Expected type [%s], but [%s]", PrimitiveType.DATETIME, type));
throw new IllegalStateException(
String.format("Expected type [%s], but [%s]", BytesValueType.TIMESTAMP, getType()));
} }


/** /**
* 返回大整数值; * 返回大整数值;
* <p> * <p>
* *
* 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#TEXT} / {@link PrimitiveType#JSON} /
* {@link PrimitiveType#XML} 有效;
* 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#TEXT} /
* {@link PrimitiveType#JSON} / {@link PrimitiveType#XML} 有效;
* <p> * <p>
* *
* 无效类型将引发 {@link IllegalStateException} 异常; * 无效类型将引发 {@link IllegalStateException} 异常;
@@ -256,15 +251,12 @@ public class KVDataObject implements KVDataEntry {
* @return * @return
*/ */
public String stringValue() { public String stringValue() {
if (PrimitiveType.TEXT == type || PrimitiveType.JSON == type || PrimitiveType.XML == type) {
try {
return new String(bytesValue, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException(e.getMessage(), e);
}
BytesValueType type = getType();
if (BytesValueType.TEXT == type || BytesValueType.JSON == type || BytesValueType.XML == type) {
return bytesValue.getValue().toUTF8String();
} }
throw new IllegalStateException(String.format("Expected type [%s] or [%s] or [%s] , but [%s]", PrimitiveType.TEXT,
PrimitiveType.JSON, PrimitiveType.XML, type));
throw new IllegalStateException(String.format("Expected type [%s] or [%s] or [%s] , but [%s]",
PrimitiveType.TEXT, BytesValueType.JSON, BytesValueType.XML, type));
} }


// // ---------------- // // ----------------


source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerException.java → source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerException.java View File

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


public class LedgerException extends RuntimeException { public class LedgerException extends RuntimeException {



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

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

public class LedgerPermissionException extends LedgerException {

private static final long serialVersionUID = 6077975401474519117L;

public LedgerPermissionException(String message) {
super(message);
}

public LedgerPermissionException(String message, Throwable cause) {
super(message, cause);
}

}

+ 68
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/PermissionType.java View File

@@ -0,0 +1,68 @@
package com.jd.blockchain.ledger;
/**
* 权限类型;
*
* @author huanghaiquan
*
*/
public enum PermissionType {
/**
* 账户权限配置;
*/
SET_PRIVILEGE(1),
/**
* 注册参与方;
*/
REG_PARTICIPANT(2),
/**
* 配置账本;包括除了{@link #SET_PRIVILEGE}、 {@link #REG_PARTICIPANT} 之外的其它账本设置,例如:设置密码参数、共识参数等;
*/
CONFIG_LEDGER(4),
/**
* 用户注册;
*/
REG_USER(8),
/**
* 注册数据账户;
*/
REG_DATA_ACCOUNT(16),
/**
* 部署新的合约代码;
*/
DEPLOY_CONTRACT(32),
/**
* 写入用户信息;
*/
SET_USER(1024),
/**
* 写入数据;
*/
SET_DATA(2048),
/**
* 写入数据;
*/
INVOKE_CONTRACT(4096),
/**
* 升级合约代码;
*/
UPDATE_CONTRACT(8192);
public final int CODE;
private PermissionType(int code) {
this.CODE = code;
}
}

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

@@ -1,42 +0,0 @@
package com.jd.blockchain.ledger;
/**
* 权限类型;
*
* @author huanghaiquan
*
*/
public enum PrivilegeType {
/**
* 账户注册;
*/
ACCOUNT_REGISTER(1),
/**
* 账户权限配置;
*/
PRIVILEGE_CONFIG(2),
/**
* 状态数据写入;
*/
STATE_WRITE(4),
/**
* 合约应用部署;
*/
CONTRACT_APP_DEPLOY(8),
/**
* 合约应用调用;
*/
CONTRACT_APP_INVOKE(16);
public final int CODE;
private PrivilegeType(int code) {
this.CODE = code;
}
}

+ 17
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ValueTypeCastException.java View File

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

public class ValueTypeCastException extends LedgerException {


private static final long serialVersionUID = 6641080037721006099L;

public ValueTypeCastException(String message) {
super(message);
}

public ValueTypeCastException(String message, Throwable cause) {
super(message, cause);
}

}

+ 58
- 21
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainOperationFactory.java View File

@@ -148,43 +148,80 @@ public class BlockchainOperationFactory implements ClientOperator, LedgerInitOpe
return innerBuilder.getOperation(); return innerBuilder.getOperation();
} }
@Override
public DataAccountKVSetOperationBuilder set(String key, byte[] value, long expVersion) {
innerBuilder.set(key, value, expVersion);
private void addOperation() {
if (op == null) { if (op == null) {
op = innerBuilder.getOperation(); op = innerBuilder.getOperation();
operationList.add(op); operationList.add(op);
} }
}
// @Override
// public DataAccountKVSetOperationBuilder set(String key, byte[] value, long expVersion) {
// innerBuilder.set(key, value, expVersion);
// addOperation();
// return this;
// }
@Override
public DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion) {
innerBuilder.setText(key, value, expVersion);
addOperation();
return this; return this;
} }
@Override @Override
public DataAccountKVSetOperationBuilder set(String key, String value, long expVersion) {
innerBuilder.set(key, value, expVersion);
if (op == null) {
op = innerBuilder.getOperation();
operationList.add(op);
}
public DataAccountKVSetOperationBuilder setInt64(String key, long value, long expVersion) {
innerBuilder.setInt64(key, value, expVersion);
addOperation();
return this; return this;
} }
@Override @Override
public DataAccountKVSetOperationBuilder set(String key, long value, long expVersion) {
innerBuilder.set(key, value, expVersion);
if (op == null) {
op = innerBuilder.getOperation();
operationList.add(op);
}
public DataAccountKVSetOperationBuilder setBytes(String key, Bytes value, long expVersion) {
innerBuilder.setBytes(key, value, expVersion);
addOperation();
return this; return this;
} }
@Override @Override
public DataAccountKVSetOperationBuilder set(String key, Bytes value, long expVersion) {
innerBuilder.set(key, value, expVersion);
if (op == null) {
op = innerBuilder.getOperation();
operationList.add(op);
}
public DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion) {
innerBuilder.setBytes(key, value, expVersion);
addOperation();
return this;
}
@Override
public DataAccountKVSetOperationBuilder setImage(String key, byte[] value, long expVersion) {
innerBuilder.setImage(key, value, expVersion);
addOperation();
return this;
}
// @Override
// public DataAccountKVSetOperationBuilder set(String key, String value, long expVersion) {
// innerBuilder.setText(key, value, expVersion);
// addOperation();
// return this;
// }
@Override
public DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion) {
innerBuilder.setJSON(key, value, expVersion);
addOperation();
return this;
}
@Override
public DataAccountKVSetOperationBuilder setXML(String key, String value, long expVersion) {
innerBuilder.setXML(key, value, expVersion);
addOperation();
return this;
}
@Override
public DataAccountKVSetOperationBuilder setTimestamp(String key, long value, long expVersion) {
innerBuilder.setTimestamp(key, value, expVersion);
addOperation();
return this; return this;
} }


+ 95
- 8
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilder.java View File

@@ -3,6 +3,10 @@ package com.jd.blockchain.transaction;
import com.jd.blockchain.ledger.DataAccountKVSetOperation; import com.jd.blockchain.ledger.DataAccountKVSetOperation;
import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.Bytes;
/**
* @author huanghaiquan
*
*/
public interface DataAccountKVSetOperationBuilder { public interface DataAccountKVSetOperationBuilder {
/** /**
@@ -12,8 +16,22 @@ public interface DataAccountKVSetOperationBuilder {
*/ */
DataAccountKVSetOperation getOperation(); DataAccountKVSetOperation getOperation();
// /**
// * 写入字节数组;
// *
// * @param key
// * 键;
// * @param value
// * 值;byte[]格式
// * @param expVersion
// * 预期的当前版本;如果版本不匹配,则写入失败;
// * @return
// */
// @Deprecated
// DataAccountKVSetOperationBuilder set(String key, byte[] value, long expVersion);
/** /**
* 写入键值;
* 写入字节数组
* *
* @param key * @param key
* 键; * 键;
@@ -23,7 +41,21 @@ public interface DataAccountKVSetOperationBuilder {
* 预期的当前版本;如果版本不匹配,则写入失败; * 预期的当前版本;如果版本不匹配,则写入失败;
* @return * @return
*/ */
DataAccountKVSetOperationBuilder set(String key, byte[] value, long expVersion);
DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion);
/**
* 写入字节数组;
*
* @param key
* 键;
* @param value
* 值;Bytes格式
* @param expVersion
* 预期的当前版本;如果版本不匹配,则写入失败;
* @return
*/
DataAccountKVSetOperationBuilder setBytes(String key, Bytes value, long expVersion);
/** /**
* 写入键值; * 写入键值;
* *
@@ -35,21 +67,76 @@ public interface DataAccountKVSetOperationBuilder {
* 预期的当前版本;如果版本不匹配,则写入失败; * 预期的当前版本;如果版本不匹配,则写入失败;
* @return * @return
*/ */
DataAccountKVSetOperationBuilder set(String key, String value, long expVersion);
DataAccountKVSetOperationBuilder setImage(String key, byte[] value, long expVersion);
// /**
// * 写入文本键值;
// *
// * @param key
// * 键;
// * @param value
// * 值;String格式
// * @param expVersion
// * 预期的当前版本;如果版本不匹配,则写入失败;
// * @return
// */
// @Deprecated
// DataAccountKVSetOperationBuilder set(String key, String value, long expVersion);
/** /**
* 写入键值;
* 写入文本键值;
* *
* @param key * @param key
* 键; * 键;
* @param value * @param value
* 值;Bytes格式
* 值;String格式
* @param expVersion * @param expVersion
* 预期的当前版本;如果版本不匹配,则写入失败; * 预期的当前版本;如果版本不匹配,则写入失败;
* @return * @return
*/ */
DataAccountKVSetOperationBuilder set(String key, Bytes value, long expVersion);
DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion);
/** /**
* 写入键值;
* 写入JSON键值;
*
* @param key
* 键;
* @param value
* 值;String格式
* @param expVersion
* 预期的当前版本;如果版本不匹配,则写入失败;
* @return
*/
DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion);
/**
* 写入XML键值;
*
* @param key
* 键;
* @param value
* 值;String格式
* @param expVersion
* 预期的当前版本;如果版本不匹配,则写入失败;
* @return
*/
DataAccountKVSetOperationBuilder setXML(String key, String value, long expVersion);
/**
* 写入64位整数;
*
* @param key
* 键;
* @param value
* 值;long格式
* @param expVersion
* 预期的当前版本;如果版本不匹配,则写入失败;
* @return
*/
DataAccountKVSetOperationBuilder setInt64(String key, long value, long expVersion);
/**
* 写入时间戳;
* *
* @param key * @param key
* 键; * 键;
@@ -59,6 +146,6 @@ public interface DataAccountKVSetOperationBuilder {
* 预期的当前版本;如果版本不匹配,则写入失败; * 预期的当前版本;如果版本不匹配,则写入失败;
* @return * @return
*/ */
DataAccountKVSetOperationBuilder set(String key, long value, long expVersion);
DataAccountKVSetOperationBuilder setTimestamp(String key, long value, long expVersion);
} }

+ 51
- 20
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilderImpl.java View File

@@ -3,15 +3,12 @@ package com.jd.blockchain.transaction;
import com.jd.blockchain.ledger.BytesValue; import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.BytesValueEntry; import com.jd.blockchain.ledger.BytesValueEntry;
import com.jd.blockchain.ledger.DataAccountKVSetOperation; import com.jd.blockchain.ledger.DataAccountKVSetOperation;
import com.jd.blockchain.ledger.BytesValueType;
import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.io.BytesUtils;
import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils;
public class DataAccountKVSetOperationBuilderImpl implements DataAccountKVSetOperationBuilder{
public class DataAccountKVSetOperationBuilderImpl implements DataAccountKVSetOperationBuilder {
private DataAccountKVSetOpTemplate operation; private DataAccountKVSetOpTemplate operation;
public DataAccountKVSetOperationBuilderImpl(Bytes accountAddress) { public DataAccountKVSetOperationBuilderImpl(Bytes accountAddress) {
operation = new DataAccountKVSetOpTemplate(accountAddress); operation = new DataAccountKVSetOpTemplate(accountAddress);
} }
@@ -21,35 +18,69 @@ public class DataAccountKVSetOperationBuilderImpl implements DataAccountKVSetOpe
return operation; return operation;
} }
// @Deprecated
// @Override
// public DataAccountKVSetOperationBuilder set(String key, byte[] value, long expVersion) {
// return setBytes(key, value, expVersion);
// }
@Override @Override
public DataAccountKVSetOperationBuilder set(String key, byte[] value, long expVersion) {
BytesValue bytesValue = new BytesValueEntry(BytesValueType.BYTES, value);
public DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromBytes(value);
operation.set(key, bytesValue, expVersion); operation.set(key, bytesValue, expVersion);
return this; return this;
} }
@Override @Override
public DataAccountKVSetOperationBuilder set(String key, String value, long expVersion) {
BytesValue bytesValue;
if (JSONSerializeUtils.isJSON(value)) {
bytesValue = new BytesValueEntry(BytesValueType.JSON, BytesUtils.toBytes(value));
}
else {
bytesValue = new BytesValueEntry(BytesValueType.TEXT, BytesUtils.toBytes(value));
}
public DataAccountKVSetOperationBuilder setImage(String key, byte[] value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromImage(value);
operation.set(key, bytesValue, expVersion); operation.set(key, bytesValue, expVersion);
return this; return this;
} }
// @Override
// public DataAccountKVSetOperationBuilder set(String key, String value, long expVersion) {
// return setText(key, value, expVersion);
// }
@Override @Override
public DataAccountKVSetOperationBuilder set(String key, Bytes value, long expVersion) {
BytesValue bytesValue = new BytesValueEntry(BytesValueType.BYTES, value.toBytes());
public DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromText(value);
operation.set(key, bytesValue, expVersion); operation.set(key, bytesValue, expVersion);
return this; return this;
} }
@Override
public DataAccountKVSetOperationBuilder setBytes(String key, Bytes value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromBytes(value);
operation.set(key, bytesValue, expVersion);
return this;
}
@Override
public DataAccountKVSetOperationBuilder setInt64(String key, long value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromInt64(value);
operation.set(key, bytesValue, expVersion);
return this;
}
@Override
public DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromJSON(value);
operation.set(key, bytesValue, expVersion);
return this;
}
@Override
public DataAccountKVSetOperationBuilder setXML(String key, String value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromXML(value);
operation.set(key, bytesValue, expVersion);
return this;
}
@Override @Override
public DataAccountKVSetOperationBuilder set(String key, long value, long expVersion) {
BytesValue bytesValue = new BytesValueEntry(BytesValueType.INT64, BytesUtils.toBytes(value));
public DataAccountKVSetOperationBuilder setTimestamp(String key, long value, long expVersion) {
BytesValue bytesValue = BytesValueEntry.fromTimestamp(value);
operation.set(key, bytesValue, expVersion); operation.set(key, bytesValue, expVersion);
return this; return this;
} }


+ 4
- 2
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountOperator.java View File

@@ -13,14 +13,16 @@ public interface DataAccountOperator {
DataAccountRegisterOperationBuilder dataAccounts(); DataAccountRegisterOperationBuilder dataAccounts();


/** /**
* 写入数据;
* 写入数据; <br>
*
* @param accountAddress * @param accountAddress
* @return * @return
*/ */
DataAccountKVSetOperationBuilder dataAccount(String accountAddress); DataAccountKVSetOperationBuilder dataAccount(String accountAddress);
/** /**
* 写入数据; * 写入数据;
*
* @param accountAddress * @param accountAddress
* @return * @return
*/ */


+ 4
- 4
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PrivilegeSettingOperationBuilder.java View File

@@ -1,6 +1,6 @@
package com.jd.blockchain.transaction; package com.jd.blockchain.transaction;
import com.jd.blockchain.ledger.PrivilegeType;
import com.jd.blockchain.ledger.PermissionType;
/** /**
* 账户权限设置操作; * 账户权限设置操作;
@@ -16,10 +16,10 @@ import com.jd.blockchain.ledger.PrivilegeType;
*/ */
public interface PrivilegeSettingOperationBuilder { public interface PrivilegeSettingOperationBuilder {
PrivilegeSettingOperationBuilder setThreshhold(PrivilegeType privilege, long threshhold);
PrivilegeSettingOperationBuilder setThreshhold(PermissionType privilege, long threshhold);
PrivilegeSettingOperationBuilder enable(PrivilegeType privilege, String address, int weight);
PrivilegeSettingOperationBuilder enable(PermissionType privilege, String address, int weight);
PrivilegeSettingOperationBuilder disable(PrivilegeType privilege, String address);
PrivilegeSettingOperationBuilder disable(PermissionType privilege, String address);
} }

+ 9
- 10
source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/DataAccountKVSetOpTemplateTest.java View File

@@ -8,22 +8,21 @@
*/ */
package test.com.jd.blockchain.ledger.data; package test.com.jd.blockchain.ledger.data;


import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;

import org.junit.Before;
import org.junit.Test;

import com.jd.blockchain.binaryproto.BinaryProtocol; import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.binaryproto.DataContractRegistry; import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.ledger.BytesValueEntry; import com.jd.blockchain.ledger.BytesValueEntry;
import com.jd.blockchain.ledger.DataAccountKVSetOperation; import com.jd.blockchain.ledger.DataAccountKVSetOperation;
import com.jd.blockchain.ledger.BytesValueType;
import com.jd.blockchain.ledger.Operation; import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate; import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate;
import com.jd.blockchain.transaction.KVData; import com.jd.blockchain.transaction.KVData;
import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.Bytes;


import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;

/** /**
* *
* @author shaozhuguang * @author shaozhuguang
@@ -43,11 +42,11 @@ public class DataAccountKVSetOpTemplateTest {
String accountAddress = "zhangsandhakhdkah"; String accountAddress = "zhangsandhakhdkah";
data = new DataAccountKVSetOpTemplate(Bytes.fromString(accountAddress)); data = new DataAccountKVSetOpTemplate(Bytes.fromString(accountAddress));
KVData kvData1 = KVData kvData1 =
new KVData("test1", new BytesValueEntry(BytesValueType.TEXT, "zhangsan".getBytes()), 9999L);
new KVData("test1", BytesValueEntry.fromText("zhangsan"), 9999L);
KVData kvData2 = KVData kvData2 =
new KVData("test2", new BytesValueEntry(BytesValueType.TEXT, "lisi".getBytes()), 9990L);
new KVData("test2", BytesValueEntry.fromText("lisi"), 9990L);
KVData kvData3 = KVData kvData3 =
new KVData("test3", new BytesValueEntry(BytesValueType.TEXT, "wangwu".getBytes()), 1990L);
new KVData("test3", BytesValueEntry.fromText("wangwu"), 1990L);
data.set(kvData1); data.set(kvData1);
data.set(kvData2); data.set(kvData2);
data.set(kvData3); data.set(kvData3);


+ 28
- 29
source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/KVDataTest.java View File

@@ -8,20 +8,19 @@
*/ */
package test.com.jd.blockchain.ledger.data; package test.com.jd.blockchain.ledger.data;


import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;

import org.junit.Before;
import org.junit.Test;

import com.jd.blockchain.binaryproto.BinaryProtocol; import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.binaryproto.DataContractRegistry; import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.ledger.BytesValueEntry; import com.jd.blockchain.ledger.BytesValueEntry;
import com.jd.blockchain.ledger.DataAccountKVSetOperation; import com.jd.blockchain.ledger.DataAccountKVSetOperation;
import com.jd.blockchain.ledger.BytesValueType;
import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate; import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate;
import com.jd.blockchain.transaction.KVData; import com.jd.blockchain.transaction.KVData;


import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;

/** /**
* *
* @author shaozhuguang * @author shaozhuguang
@@ -30,26 +29,26 @@ import static org.junit.Assert.assertEquals;
*/ */


public class KVDataTest { public class KVDataTest {
private KVData kvData;
@Before
public void initKVData() throws Exception {
DataContractRegistry.register(DataAccountKVSetOperation.KVWriteEntry.class);
String key = "test-key";
byte[] value = "test-value".getBytes();
long expectedVersion = 9999L;
kvData = new KVData(key, new BytesValueEntry(BytesValueType.BYTES, value), expectedVersion);
}
@Test
public void testSerialize_KVEntry() throws Exception {
byte[] serialBytes = BinaryProtocol.encode(kvData, DataAccountKVSetOperation.KVWriteEntry.class);
DataAccountKVSetOpTemplate.KVWriteEntry resolvedKvData = BinaryProtocol.decode(serialBytes);
System.out.println("------Assert start ------");
assertEquals(resolvedKvData.getKey(), kvData.getKey());
assertEquals(resolvedKvData.getExpectedVersion(), kvData.getExpectedVersion());
assertArrayEquals(resolvedKvData.getValue().getValue().toBytes(), kvData.getValue().getValue().toBytes());
System.out.println("------Assert OK ------");
}
private KVData kvData;
@Before
public void initKVData() throws Exception {
DataContractRegistry.register(DataAccountKVSetOperation.KVWriteEntry.class);
String key = "test-key";
byte[] value = "test-value".getBytes();
long expectedVersion = 9999L;
kvData = new KVData(key, BytesValueEntry.fromBytes(value), expectedVersion);
}
@Test
public void testSerialize_KVEntry() throws Exception {
byte[] serialBytes = BinaryProtocol.encode(kvData, DataAccountKVSetOperation.KVWriteEntry.class);
DataAccountKVSetOpTemplate.KVWriteEntry resolvedKvData = BinaryProtocol.decode(serialBytes);
System.out.println("------Assert start ------");
assertEquals(resolvedKvData.getKey(), kvData.getKey());
assertEquals(resolvedKvData.getExpectedVersion(), kvData.getExpectedVersion());
assertArrayEquals(resolvedKvData.getValue().getValue().toBytes(), kvData.getValue().getValue().toBytes());
System.out.println("------Assert OK ------");
}
} }

+ 1
- 2
source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/TxContentBlobTest.java View File

@@ -22,7 +22,6 @@ import com.jd.blockchain.ledger.TransactionContent;
import com.jd.blockchain.ledger.TransactionContentBody; import com.jd.blockchain.ledger.TransactionContentBody;
import com.jd.blockchain.transaction.BlockchainOperationFactory; import com.jd.blockchain.transaction.BlockchainOperationFactory;
import com.jd.blockchain.transaction.TxContentBlob; import com.jd.blockchain.transaction.TxContentBlob;
import com.jd.blockchain.utils.io.ByteArray;
public class TxContentBlobTest { public class TxContentBlobTest {
@@ -48,7 +47,7 @@ public class TxContentBlobTest {
contentBlob.setHash(contentHash); contentBlob.setHash(contentHash);
DataAccountKVSetOperation kvsetOP = opFactory.dataAccount(id.getAddress()) DataAccountKVSetOperation kvsetOP = opFactory.dataAccount(id.getAddress())
.set("Name", ByteArray.fromString("AAA", "UTF-8"), -1).getOperation();
.setText("Name", "AAA", -1).getOperation();
contentBlob.addOperation(kvsetOP); contentBlob.addOperation(kvsetOP);
} }


+ 1
- 2
source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/TxRequestMessageTest.java View File

@@ -37,7 +37,6 @@ import com.jd.blockchain.transaction.BlockchainOperationFactory;
import com.jd.blockchain.transaction.DigitalSignatureBlob; import com.jd.blockchain.transaction.DigitalSignatureBlob;
import com.jd.blockchain.transaction.TxContentBlob; import com.jd.blockchain.transaction.TxContentBlob;
import com.jd.blockchain.transaction.TxRequestMessage; import com.jd.blockchain.transaction.TxRequestMessage;
import com.jd.blockchain.utils.io.ByteArray;


/** /**
* *
@@ -204,7 +203,7 @@ public class TxRequestMessageTest {
// contentBlob.setSubjectAccount(id.getAddress()); // contentBlob.setSubjectAccount(id.getAddress());
// contentBlob.setSequenceNumber(1); // contentBlob.setSequenceNumber(1);
DataAccountKVSetOperation kvsetOP = opFactory.dataAccount(id.getAddress()) DataAccountKVSetOperation kvsetOP = opFactory.dataAccount(id.getAddress())
.set("Name", ByteArray.fromString("AAA", "UTF-8"), -1).getOperation();
.setText("Name","AAA", -1).getOperation();
contentBlob.addOperation(kvsetOP); contentBlob.addOperation(kvsetOP);
return contentBlob; return contentBlob;
} }

+ 127
- 109
source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java View File

@@ -1,14 +1,31 @@
package com.jd.blockchain.peer.web; package com.jd.blockchain.peer.web;
import com.jd.blockchain.contract.ContractException;
import com.jd.blockchain.ledger.*;
import com.jd.blockchain.utils.StringUtils;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.contract.ContractException;
import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.BytesValue;
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.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.ledger.core.ContractAccountSet; import com.jd.blockchain.ledger.core.ContractAccountSet;
import com.jd.blockchain.ledger.core.DataAccount; import com.jd.blockchain.ledger.core.DataAccount;
import com.jd.blockchain.ledger.core.DataAccountSet; import com.jd.blockchain.ledger.core.DataAccountSet;
@@ -22,15 +39,12 @@ import com.jd.blockchain.transaction.BlockchainQueryService;
import com.jd.blockchain.utils.Bytes; import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.QueryUtil; import com.jd.blockchain.utils.QueryUtil;
import java.util.ArrayList;
import java.util.List;
@RestController @RestController
@RequestMapping(path = "/") @RequestMapping(path = "/")
public class LedgerQueryController implements BlockchainQueryService { public class LedgerQueryController implements BlockchainQueryService {
@Autowired
private LedgerService ledgerService;
@Autowired
private LedgerService ledgerService;
@RequestMapping(method = RequestMethod.GET, path = "ledgers") @RequestMapping(method = RequestMethod.GET, path = "ledgers")
@Override @Override
@@ -42,7 +56,8 @@ public class LedgerQueryController implements BlockchainQueryService {
@Override @Override
public LedgerInfo getLedger(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) { public LedgerInfo getLedger(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
//TODO: 需要配置返回值的 spring MsgQueueMessageDispatcher ,对返回对象仅仅序列化声明的返回值类型的属性,而不是整个对象本身;
// TODO: 需要配置返回值的 spring MsgQueueMessageDispatcher
// ,对返回对象仅仅序列化声明的返回值类型的属性,而不是整个对象本身;
LedgerInfo ledgerInfo = new LedgerInfo(); LedgerInfo ledgerInfo = new LedgerInfo();
ledgerInfo.setHash(ledgerHash); ledgerInfo.setHash(ledgerHash);
ledgerInfo.setLatestBlockHash(ledger.getLatestBlockHash()); ledgerInfo.setLatestBlockHash(ledger.getLatestBlockHash());
@@ -83,25 +98,27 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}") @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}")
@Override @Override
public LedgerBlock getBlock(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, public LedgerBlock getBlock(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "blockHeight") long blockHeight) {
@PathVariable(name = "blockHeight") long blockHeight) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
//TODO: 需要配置返回值的 spring MsgQueueMessageDispatcher ,对返回对象仅仅序列化声明的返回值类型的属性,而不是整个对象本身;
// TODO: 需要配置返回值的 spring MsgQueueMessageDispatcher
// ,对返回对象仅仅序列化声明的返回值类型的属性,而不是整个对象本身;
return ledger.getBlock(blockHeight); return ledger.getBlock(blockHeight);
} }
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}") @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}")
@Override @Override
public LedgerBlock getBlock(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, public LedgerBlock getBlock(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "blockHash") HashDigest blockHash) {
@PathVariable(name = "blockHash") HashDigest blockHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
//TODO: 需要配置返回值的 spring MsgQueueMessageDispatcher ,对返回对象仅仅序列化声明的返回值类型的属性,而不是整个对象本身;
// TODO: 需要配置返回值的 spring MsgQueueMessageDispatcher
// ,对返回对象仅仅序列化声明的返回值类型的属性,而不是整个对象本身;
return ledger.getBlock(blockHash); return ledger.getBlock(blockHash);
} }
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/txs/count") @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/txs/count")
@Override @Override
public long getTransactionCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, public long getTransactionCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "blockHeight") long blockHeight) {
@PathVariable(name = "blockHeight") long blockHeight) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getBlock(blockHeight); LedgerBlock block = ledger.getBlock(blockHeight);
TransactionSet txSet = ledger.getTransactionSet(block); TransactionSet txSet = ledger.getTransactionSet(block);
@@ -111,7 +128,7 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/txs/count") @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/txs/count")
@Override @Override
public long getTransactionCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, public long getTransactionCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "blockHash") HashDigest blockHash) {
@PathVariable(name = "blockHash") HashDigest blockHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getBlock(blockHash); LedgerBlock block = ledger.getBlock(blockHash);
TransactionSet txSet = ledger.getTransactionSet(block); TransactionSet txSet = ledger.getTransactionSet(block);
@@ -130,7 +147,7 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/accounts/count") @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/accounts/count")
@Override @Override
public long getDataAccountCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, public long getDataAccountCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "blockHeight") long height) {
@PathVariable(name = "blockHeight") long height) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getBlock(height); LedgerBlock block = ledger.getBlock(height);
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
@@ -140,7 +157,7 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/accounts/count") @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/accounts/count")
@Override @Override
public long getDataAccountCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, public long getDataAccountCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "blockHash") HashDigest blockHash) {
@PathVariable(name = "blockHash") HashDigest blockHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getBlock(blockHash); LedgerBlock block = ledger.getBlock(blockHash);
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
@@ -159,7 +176,7 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/users/count") @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/users/count")
@Override @Override
public long getUserCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, public long getUserCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "blockHeight") long height) {
@PathVariable(name = "blockHeight") long height) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getBlock(height); LedgerBlock block = ledger.getBlock(height);
UserAccountSet userAccountSet = ledger.getUserAccountSet(block); UserAccountSet userAccountSet = ledger.getUserAccountSet(block);
@@ -169,7 +186,7 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/users/count") @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/users/count")
@Override @Override
public long getUserCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, public long getUserCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "blockHash") HashDigest blockHash) {
@PathVariable(name = "blockHash") HashDigest blockHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getBlock(blockHash); LedgerBlock block = ledger.getBlock(blockHash);
UserAccountSet userAccountSet = ledger.getUserAccountSet(block); UserAccountSet userAccountSet = ledger.getUserAccountSet(block);
@@ -188,7 +205,7 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/contracts/count") @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/contracts/count")
@Override @Override
public long getContractCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, public long getContractCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "blockHeight") long height) {
@PathVariable(name = "blockHeight") long height) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getBlock(height); LedgerBlock block = ledger.getBlock(height);
ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block);
@@ -198,7 +215,7 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/contracts/count") @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/contracts/count")
@Override @Override
public long getContractCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, public long getContractCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "blockHash") HashDigest blockHash) {
@PathVariable(name = "blockHash") HashDigest blockHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getBlock(blockHash); LedgerBlock block = ledger.getBlock(blockHash);
ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block);
@@ -217,9 +234,9 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/txs") @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/txs")
@Override @Override
public LedgerTransaction[] getTransactions(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, public LedgerTransaction[] getTransactions(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "blockHeight") long blockHeight,
@RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
@RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
@PathVariable(name = "blockHeight") long blockHeight,
@RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
@RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock ledgerBlock = ledger.getBlock(blockHeight); LedgerBlock ledgerBlock = ledger.getBlock(blockHeight);
@@ -230,8 +247,8 @@ public class LedgerQueryController implements BlockchainQueryService {
lastHeightTxTotalNums = (int) ledger.getTransactionSet(ledger.getBlock(blockHeight - 1)).getTotalCount(); lastHeightTxTotalNums = (int) ledger.getTransactionSet(ledger.getBlock(blockHeight - 1)).getTotalCount();
} }
int currentHeightTxTotalNums = (int)ledger.getTransactionSet(ledger.getBlock(blockHeight)).getTotalCount();
//取当前高度的增量交易数,在增量交易里进行查找
int currentHeightTxTotalNums = (int) ledger.getTransactionSet(ledger.getBlock(blockHeight)).getTotalCount();
// 取当前高度的增量交易数,在增量交易里进行查找
int currentHeightTxNums = currentHeightTxTotalNums - lastHeightTxTotalNums; int currentHeightTxNums = currentHeightTxTotalNums - lastHeightTxTotalNums;
// if (fromIndex < 0 || fromIndex >= currentHeightTxNums) { // if (fromIndex < 0 || fromIndex >= currentHeightTxNums) {
@@ -245,15 +262,15 @@ public class LedgerQueryController implements BlockchainQueryService {
// count = currentHeightTxNums - fromIndex; // count = currentHeightTxNums - fromIndex;
// } // }
int indexAndCount[] = QueryUtil.calFromIndexAndCount(fromIndex, count, currentHeightTxNums); int indexAndCount[] = QueryUtil.calFromIndexAndCount(fromIndex, count, currentHeightTxNums);
return transactionSet.getTxs(lastHeightTxTotalNums + indexAndCount[0] , indexAndCount[1]);
return transactionSet.getTxs(lastHeightTxTotalNums + indexAndCount[0], indexAndCount[1]);
} }
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/txs") @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}/txs")
@Override @Override
public LedgerTransaction[] getTransactions(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, public LedgerTransaction[] getTransactions(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "blockHash") HashDigest blockHash,
@RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
@RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
@PathVariable(name = "blockHash") HashDigest blockHash,
@RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
@RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock ledgerBlock = ledger.getBlock(blockHash); LedgerBlock ledgerBlock = ledger.getBlock(blockHash);
long height = ledgerBlock.getHeight(); long height = ledgerBlock.getHeight();
@@ -264,8 +281,8 @@ public class LedgerQueryController implements BlockchainQueryService {
lastHeightTxTotalNums = (int) ledger.getTransactionSet(ledger.getBlock(height - 1)).getTotalCount(); lastHeightTxTotalNums = (int) ledger.getTransactionSet(ledger.getBlock(height - 1)).getTotalCount();
} }
int currentHeightTxTotalNums = (int)ledger.getTransactionSet(ledger.getBlock(height)).getTotalCount();
//取当前块hash的增量交易数,在增量交易里进行查找
int currentHeightTxTotalNums = (int) ledger.getTransactionSet(ledger.getBlock(height)).getTotalCount();
// 取当前块hash的增量交易数,在增量交易里进行查找
int currentHeightTxNums = currentHeightTxTotalNums - lastHeightTxTotalNums; int currentHeightTxNums = currentHeightTxTotalNums - lastHeightTxTotalNums;
// if (fromIndex < 0 || fromIndex >= currentHeightTxNums) { // if (fromIndex < 0 || fromIndex >= currentHeightTxNums) {
@@ -279,13 +296,13 @@ public class LedgerQueryController implements BlockchainQueryService {
// count = currentHeightTxNums - fromIndex; // count = currentHeightTxNums - fromIndex;
// } // }
int indexAndCount[] = QueryUtil.calFromIndexAndCount(fromIndex, count, currentHeightTxNums); int indexAndCount[] = QueryUtil.calFromIndexAndCount(fromIndex, count, currentHeightTxNums);
return transactionSet.getTxs(lastHeightTxTotalNums + indexAndCount[0] , indexAndCount[1]);
return transactionSet.getTxs(lastHeightTxTotalNums + indexAndCount[0], indexAndCount[1]);
} }
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/txs/{contentHash}") @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/txs/{contentHash}")
@Override @Override
public LedgerTransaction getTransactionByContentHash(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, public LedgerTransaction getTransactionByContentHash(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "contentHash")HashDigest contentHash) {
@PathVariable(name = "contentHash") HashDigest contentHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock(); LedgerBlock block = ledger.getLatestBlock();
TransactionSet txset = ledger.getTransactionSet(block); TransactionSet txset = ledger.getTransactionSet(block);
@@ -295,7 +312,7 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/txs/state/{contentHash}") @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/txs/state/{contentHash}")
@Override @Override
public TransactionState getTransactionStateByContentHash(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, public TransactionState getTransactionStateByContentHash(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "contentHash") HashDigest contentHash) {
@PathVariable(name = "contentHash") HashDigest contentHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock(); LedgerBlock block = ledger.getLatestBlock();
TransactionSet txset = ledger.getTransactionSet(block); TransactionSet txset = ledger.getTransactionSet(block);
@@ -305,7 +322,7 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/users/address/{address}") @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/users/address/{address}")
@Override @Override
public UserInfo getUser(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, public UserInfo getUser(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "address") String address) {
@PathVariable(name = "address") String address) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock(); LedgerBlock block = ledger.getLatestBlock();
UserAccountSet userAccountSet = ledger.getUserAccountSet(block); UserAccountSet userAccountSet = ledger.getUserAccountSet(block);
@@ -315,18 +332,18 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts/address/{address}") @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts/address/{address}")
@Override @Override
public AccountHeader getDataAccount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, public AccountHeader getDataAccount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "address") String address) {
@PathVariable(name = "address") String address) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock(); LedgerBlock block = ledger.getLatestBlock();
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
return dataAccountSet.getDataAccount(Bytes.fromBase58(address)); return dataAccountSet.getDataAccount(Bytes.fromBase58(address));
} }
@RequestMapping(method = {RequestMethod.GET, RequestMethod.POST}, path = "ledgers/{ledgerHash}/accounts/{address}/entries")
@RequestMapping(method = { RequestMethod.GET,
RequestMethod.POST }, path = "ledgers/{ledgerHash}/accounts/{address}/entries")
@Override @Override
public KVDataEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, public KVDataEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "address") String address,
@RequestParam("keys") String... keys) {
@PathVariable(name = "address") String address, @RequestParam("keys") String... keys) {
if (keys == null || keys.length == 0) { if (keys == null || keys.length == 0) {
return null; return null;
} }
@@ -334,51 +351,50 @@ public class LedgerQueryController implements BlockchainQueryService {
LedgerBlock block = ledger.getLatestBlock(); LedgerBlock block = ledger.getLatestBlock();
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address)); DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address));
KVDataEntry[] entries = new KVDataEntry[keys.length]; KVDataEntry[] entries = new KVDataEntry[keys.length];
long ver; long ver;
for (int i = 0; i < entries.length; i++) { for (int i = 0; i < entries.length; i++) {
ver = dataAccount.getDataVersion(Bytes.fromString(keys[i])); ver = dataAccount.getDataVersion(Bytes.fromString(keys[i]));
if (ver < 0) { if (ver < 0) {
entries[i] = new KVDataObject(keys[i], -1, PrimitiveType.NIL, null);
}else {
byte[] value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver);
BytesValue decodeData = BinaryProtocol.decode(value);
entries[i] = new KVDataObject(keys[i], ver, PrimitiveType.valueOf(decodeData.getType().CODE), decodeData.getValue().toBytes());
entries[i] = new KVDataObject(keys[i], -1, null);
} else {
BytesValue value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver);
entries[i] = new KVDataObject(keys[i], ver, value);
} }
} }
return entries; return entries;
} }
@RequestMapping(method = {RequestMethod.GET, RequestMethod.POST}, path = "ledgers/{ledgerHash}/accounts/{address}/entries-version")
@RequestMapping(method = { RequestMethod.GET,
RequestMethod.POST }, path = "ledgers/{ledgerHash}/accounts/{address}/entries-version")
@Override @Override
public KVDataEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, public KVDataEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "address") String address,
@RequestBody KVInfoVO kvInfoVO) {
//parse kvInfoVO;
List<String> keyList = new ArrayList<>();
List<Long> versionList = new ArrayList<>();
if(kvInfoVO != null){
for(KVDataVO kvDataVO : kvInfoVO.getData()){
for(Long version : kvDataVO.getVersion()){
keyList.add(kvDataVO.getKey());
versionList.add(version);
}
}
}
String[] keys = keyList.toArray(new String[keyList.size()]);
Long[] versions = versionList.toArray(new Long[versionList.size()]);
@PathVariable(name = "address") String address, @RequestBody KVInfoVO kvInfoVO) {
// parse kvInfoVO;
List<String> keyList = new ArrayList<>();
List<Long> versionList = new ArrayList<>();
if (kvInfoVO != null) {
for (KVDataVO kvDataVO : kvInfoVO.getData()) {
for (Long version : kvDataVO.getVersion()) {
keyList.add(kvDataVO.getKey());
versionList.add(version);
}
}
}
String[] keys = keyList.toArray(new String[keyList.size()]);
Long[] versions = versionList.toArray(new Long[versionList.size()]);
if (keys == null || keys.length == 0) { if (keys == null || keys.length == 0) {
return null;
return null;
} }
if (versions == null || versions.length == 0) { if (versions == null || versions.length == 0) {
return null; return null;
} }
if(keys.length != versions.length){
throw new ContractException("keys.length!=versions.length!");
}
if (keys.length != versions.length) {
throw new ContractException("keys.length!=versions.length!");
}
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock(); LedgerBlock block = ledger.getLatestBlock();
@@ -389,18 +405,17 @@ public class LedgerQueryController implements BlockchainQueryService {
long ver = -1; long ver = -1;
for (int i = 0; i < entries.length; i++) { for (int i = 0; i < entries.length; i++) {
// ver = dataAccount.getDataVersion(Bytes.fromString(keys[i])); // ver = dataAccount.getDataVersion(Bytes.fromString(keys[i]));
ver = versions[i];
ver = versions[i];
if (ver < 0) { if (ver < 0) {
entries[i] = new KVDataObject(keys[i], -1, PrimitiveType.NIL, null);
}else {
if(dataAccount.getDataEntriesTotalCount()==0 ||
dataAccount.getBytes(Bytes.fromString(keys[i]), ver) == null){
//is the address is not exist; the result is null;
entries[i] = new KVDataObject(keys[i], -1, PrimitiveType.NIL, null);
entries[i] = new KVDataObject(keys[i], -1, null);
} else {
if (dataAccount.getDataEntriesTotalCount() == 0
|| dataAccount.getBytes(Bytes.fromString(keys[i]), ver) == null) {
// is the address is not exist; the result is null;
entries[i] = new KVDataObject(keys[i], -1, null);
} else { } else {
byte[] value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver);
BytesValue decodeData = BinaryProtocol.decode(value);
entries[i] = new KVDataObject(keys[i], ver, PrimitiveType.valueOf(decodeData.getType().CODE), decodeData.getValue().toBytes());
BytesValue value = dataAccount.getBytes(Bytes.fromString(keys[i]), ver);
entries[i] = new KVDataObject(keys[i], ver, value);
} }
} }
} }
@@ -408,12 +423,13 @@ public class LedgerQueryController implements BlockchainQueryService {
return entries; return entries;
} }
@RequestMapping(method = {RequestMethod.GET, RequestMethod.POST}, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries")
@RequestMapping(method = { RequestMethod.GET,
RequestMethod.POST }, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries")
@Override @Override
public KVDataEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, public KVDataEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "address") String address,
@RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
@RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
@PathVariable(name = "address") String address,
@RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
@RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock(); LedgerBlock block = ledger.getLatestBlock();
@@ -426,7 +442,7 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries/count") @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries/count")
@Override @Override
public long getDataEntriesTotalCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, public long getDataEntriesTotalCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "address") String address) {
@PathVariable(name = "address") String address) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock(); LedgerBlock block = ledger.getLatestBlock();
@@ -439,7 +455,7 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts/address/{address}") @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts/address/{address}")
@Override @Override
public AccountHeader getContract(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, public AccountHeader getContract(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "address") String address) {
@PathVariable(name = "address") String address) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock(); LedgerBlock block = ledger.getLatestBlock();
ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block);
@@ -448,6 +464,7 @@ public class LedgerQueryController implements BlockchainQueryService {
/** /**
* get more users by fromIndex and count; * get more users by fromIndex and count;
*
* @param ledgerHash * @param ledgerHash
* @param fromIndex * @param fromIndex
* @param count * @param count
@@ -456,44 +473,45 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/users") @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/users")
@Override @Override
public AccountHeader[] getUsers(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, public AccountHeader[] getUsers(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
@RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
@RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
@RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock(); LedgerBlock block = ledger.getLatestBlock();
UserAccountSet userAccountSet = ledger.getUserAccountSet(block); UserAccountSet userAccountSet = ledger.getUserAccountSet(block);
int pages[] = QueryUtil.calFromIndexAndCount(fromIndex,count,(int)userAccountSet.getTotalCount());
return userAccountSet.getAccounts(pages[0],pages[1]);
int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) userAccountSet.getTotalCount());
return userAccountSet.getAccounts(pages[0], pages[1]);
} }
/** /**
* get more dataAccounts by fromIndex and count; * get more dataAccounts by fromIndex and count;
*
* @param ledgerHash * @param ledgerHash
* @param fromIndex * @param fromIndex
* @param count * @param count
* @return * @return
*/ */
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts") @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts")
@Override
@Override
public AccountHeader[] getDataAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, public AccountHeader[] getDataAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
@RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
@RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
@RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock(); LedgerBlock block = ledger.getLatestBlock();
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
int pages[] = QueryUtil.calFromIndexAndCount(fromIndex,count,(int)dataAccountSet.getTotalCount());
return dataAccountSet.getAccounts(pages[0],pages[1]);
}
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts")
@Override
public AccountHeader[] getContractAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
@RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block);
int pages[] = QueryUtil.calFromIndexAndCount(fromIndex,count,(int)contractAccountSet.getTotalCount());
return contractAccountSet.getAccounts(pages[0],pages[1]);
}
int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccountSet.getTotalCount());
return dataAccountSet.getAccounts(pages[0], pages[1]);
}
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts")
@Override
public AccountHeader[] getContractAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
@RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block);
int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) contractAccountSet.getTotalCount());
return contractAccountSet.getAccounts(pages[0], pages[1]);
}
} }

+ 2
- 2
source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/PrivilegeSetting.java View File

@@ -1,6 +1,6 @@
package com.jd.blockchain.sdk; package com.jd.blockchain.sdk;
import com.jd.blockchain.ledger.PrivilegeType;
import com.jd.blockchain.ledger.PermissionType;
/** /**
* 权限设置;<br> * 权限设置;<br>
@@ -16,6 +16,6 @@ public interface PrivilegeSetting {
long getMask(String address); long getMask(String address);
boolean isEnable(String address, PrivilegeType privilege);
boolean isEnable(String address, PermissionType privilege);
} }

+ 3
- 4
source/sdk/sdk-samples/src/main/java/com/jd/blockchain/contract/samples/AssetContractImpl.java View File

@@ -11,7 +11,6 @@ import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.BlockchainIdentity; import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.KVDataEntry; import com.jd.blockchain.ledger.KVDataEntry;
import com.jd.blockchain.ledger.KVDataObject; import com.jd.blockchain.ledger.KVDataObject;
import com.jd.blockchain.utils.io.BytesUtils;


/** /**
* 示例:一个“资产管理”智能合约的实现; * 示例:一个“资产管理”智能合约的实现;
@@ -53,14 +52,14 @@ public class AssetContractImpl implements EventProcessingAwire, AssetContract {
// 计算资产的发行总数; // 计算资产的发行总数;
KVDataObject currTotal = (KVDataObject) kvEntries[0]; KVDataObject currTotal = (KVDataObject) kvEntries[0];
long newTotal = currTotal.longValue() + amount; long newTotal = currTotal.longValue() + amount;
eventContext.getLedger().dataAccount(ASSET_ADDRESS).set(KEY_TOTAL, BytesUtils.toBytes(newTotal),
eventContext.getLedger().dataAccount(ASSET_ADDRESS).setInt64(KEY_TOTAL, newTotal,
currTotal.getVersion()); currTotal.getVersion());


// 分配到持有者账户; // 分配到持有者账户;
KVDataObject holderAmount = (KVDataObject) kvEntries[1]; KVDataObject holderAmount = (KVDataObject) kvEntries[1];
long newHodlerAmount = holderAmount.longValue() + amount; long newHodlerAmount = holderAmount.longValue() + amount;
eventContext.getLedger().dataAccount(ASSET_ADDRESS).set(assetHolderAddress, BytesUtils.toBytes(newHodlerAmount),
holderAmount.getVersion()).set("K2", (byte[])null, -1).set("k3", (byte[])null, 3);
eventContext.getLedger().dataAccount(ASSET_ADDRESS).setInt64(assetHolderAddress, newHodlerAmount,
holderAmount.getVersion()).setText("K2", "info2", -1).setText("k3", "info3", 3);
} }




+ 1
- 1
source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_InsertData.java View File

@@ -59,7 +59,7 @@ public class SDKDemo_InsertData {
// 对象将被序列化为 JSON 形式存储,并基于 JSON 结构建立查询索引; // 对象将被序列化为 JSON 形式存储,并基于 JSON 结构建立查询索引;
String commodityDataAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf=="; String commodityDataAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf==";
Commodity commodity1 = new Commodity(); Commodity commodity1 = new Commodity();
txTemp.dataAccount(commodityDataAccount).set("ASSET_CODE", commodity1.getCode().getBytes(), -1);
txTemp.dataAccount(commodityDataAccount).setText("ASSET_CODE", commodity1.getCode(), -1);


// TX 准备就绪; // TX 准备就绪;
PreparedTransaction prepTx = txTemp.prepare(); PreparedTransaction prepTx = txTemp.prepare();


+ 4
- 4
source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_BatchInsertData_Test_.java View File

@@ -87,13 +87,13 @@ public class SDK_GateWay_BatchInsertData_Test_ {
String dataAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf=="; String dataAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf==";


String key1 = "jd_key1"; String key1 = "jd_key1";
byte[] val1 = "www.jd.com".getBytes();
String val1 = "www.jd.com";


String key2 = "jd_key2"; String key2 = "jd_key2";
byte[] val2 = "www.jd.com".getBytes();
String val2 = "www.jd.com";


txTemp.dataAccount(dataAccount).set(key1, val1, -1);
txTemp.dataAccount(dataAccount).set(key2, val2, -1);
txTemp.dataAccount(dataAccount).setText(key1, val1, -1);
txTemp.dataAccount(dataAccount).setText(key2, val2, -1);


// TX 准备就绪; // TX 准备就绪;
PreparedTransaction prepTx = txTemp.prepare(); PreparedTransaction prepTx = txTemp.prepare();


+ 2
- 2
source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_InsertData_Test_.java View File

@@ -84,9 +84,9 @@ public class SDK_GateWay_InsertData_Test_ {
String dataAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf=="; String dataAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf==";


String dataKey = "jd_code"; String dataKey = "jd_code";
byte[] dataVal = "www.jd.com".getBytes();
String dataVal = "www.jd.com";


txTemp.dataAccount(dataAccount).set(dataKey, dataVal, -1);
txTemp.dataAccount(dataAccount).setText(dataKey, dataVal, -1);


// TX 准备就绪; // TX 准备就绪;
PreparedTransaction prepTx = txTemp.prepare(); PreparedTransaction prepTx = txTemp.prepare();


+ 117
- 99
source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/IntegrationTest.java View File

@@ -1,13 +1,39 @@
package test.com.jd.blockchain.intgr; package test.com.jd.blockchain.intgr;


import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.Random;
import java.util.concurrent.CountDownLatch;

import org.springframework.core.io.ClassPathResource;

import com.jd.blockchain.consensus.ConsensusProvider; import com.jd.blockchain.consensus.ConsensusProvider;
import com.jd.blockchain.consensus.ConsensusProviders; import com.jd.blockchain.consensus.ConsensusProviders;
import com.jd.blockchain.consensus.ConsensusSettings; import com.jd.blockchain.consensus.ConsensusSettings;
import com.jd.blockchain.crypto.AddressEncoding;
import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.AsymmetricKeypair;
import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PrivKey;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig; import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig;
import com.jd.blockchain.ledger.*;
import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.BlockchainKeyGenerator;
import com.jd.blockchain.ledger.BlockchainKeypair;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.DataAccountKVSetOperation;
import com.jd.blockchain.ledger.KVDataEntry;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerInfo;
import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.ledger.PreparedTransaction;
import com.jd.blockchain.ledger.TransactionResponse;
import com.jd.blockchain.ledger.TransactionTemplate;
import com.jd.blockchain.ledger.UserInfo;
import com.jd.blockchain.ledger.core.DataAccountSet;
import com.jd.blockchain.ledger.core.LedgerManage; import com.jd.blockchain.ledger.core.LedgerManage;
import com.jd.blockchain.ledger.core.LedgerRepository; import com.jd.blockchain.ledger.core.LedgerRepository;
import com.jd.blockchain.ledger.core.impl.LedgerManager; import com.jd.blockchain.ledger.core.impl.LedgerManager;
@@ -23,18 +49,10 @@ import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.codec.HexUtils; import com.jd.blockchain.utils.codec.HexUtils;
import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback; import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback;
import com.jd.blockchain.utils.net.NetworkAddress; import com.jd.blockchain.utils.net.NetworkAddress;
import org.springframework.core.io.ClassPathResource;
import test.com.jd.blockchain.intgr.IntegratedContext.Node; import test.com.jd.blockchain.intgr.IntegratedContext.Node;
import test.com.jd.blockchain.intgr.perf.LedgerInitializeWebTest; import test.com.jd.blockchain.intgr.perf.LedgerInitializeWebTest;


import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.Random;
import java.util.concurrent.CountDownLatch;

public class IntegrationTest { public class IntegrationTest {
// 合约测试使用的初始化数据; // 合约测试使用的初始化数据;
BlockchainKeypair contractDataKey = BlockchainKeyGenerator.getInstance().generate(); BlockchainKeypair contractDataKey = BlockchainKeyGenerator.getInstance().generate();
@@ -179,9 +197,9 @@ public class IntegrationTest {
String dataAccount = dataAccountAddress; String dataAccount = dataAccountAddress;


String dataKey = "jingdong" + new Random().nextInt(100000); String dataKey = "jingdong" + new Random().nextInt(100000);
byte[] dataVal = "www.jd.com".getBytes();
String dataVal = "www.jd.com";


txTemp.dataAccount(dataAccount).set(dataKey, dataVal, -1);
txTemp.dataAccount(dataAccount).setText(dataKey, dataVal, -1);


// TX 准备就绪; // TX 准备就绪;
PreparedTransaction prepTx = txTemp.prepare(); PreparedTransaction prepTx = txTemp.prepare();
@@ -530,87 +548,87 @@ public class IntegrationTest {
} }
} }


// private LedgerBlock testSDK_Contract(AsymmetricKeypair adminKey, HashDigest ledgerHash,
// BlockchainService blockchainService, IntegratedContext context) {
// // valid the basic data in contract;
// prepareContractData(adminKey, ledgerHash, blockchainService, context);
//
// BlockchainKeypair userKey = BlockchainKeyGenerator.getInstance().generate();
//
// // 定义交易;
// TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash);
// byte[] contractCode = getChainCodeBytes();
//
// txTpl.users().register(userKey.getIdentity());
//
// txTpl.contracts().deploy(contractDeployKey.getIdentity(), contractCode);
//
// // 签名;
// PreparedTransaction ptx = txTpl.prepare();
// ptx.sign(adminKey);
//
// // 提交并等待共识返回;
// TransactionResponse txResp = ptx.commit();
//
// // 验证结果;
// txResp.getContentHash();
//
// Node node0 = context.getNode(0);
// LedgerRepository ledgerOfNode0 = node0.getLedgerManager().getLedger(ledgerHash);
// LedgerBlock block = ledgerOfNode0.getBlock(txResp.getBlockHeight());
// byte[] contractCodeInDb = ledgerOfNode0.getContractAccountSet(block).getContract(contractDeployKey.getAddress())
// .getChainCode();
// txContentHash = ptx.getHash();
//
// // execute the contract;
// testContractExe(adminKey, ledgerHash, userKey, blockchainService, context);
//
// return block;
// }
// private void testContractExe(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainKeypair userKey,
// BlockchainService blockchainService, IntegratedContext context) {
// LedgerInfo ledgerInfo = blockchainService.getLedger(ledgerHash);
// LedgerBlock previousBlock = blockchainService.getBlock(ledgerHash, ledgerInfo.getLatestBlockHeight() - 1);
//
// // 定义交易;
// TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash);
//
// txTpl.contractEvents().send(contractDeployKey.getAddress(), eventName,
// ("888##abc##" + contractDataKey.getAddress() + "##" + previousBlock.getHash().toBase58() + "##"
// + userKey.getAddress() + "##" + contractDeployKey.getAddress() + "##" + txContentHash.toBase58()
// + "##SOME-VALUE").getBytes());
//
// // 签名;
// PreparedTransaction ptx = txTpl.prepare();
// ptx.sign(adminKey);
//
// // 提交并等待共识返回;
// TransactionResponse txResp = ptx.commit();
//
// // 验证结果;
// txResp.getContentHash();
//
// LedgerInfo latestLedgerInfo = blockchainService.getLedger(ledgerHash);
//
// Node node0 = context.getNode(0);
// LedgerRepository ledgerOfNode0 = node0.getLedgerManager().getLedger(ledgerHash);
// LedgerBlock backgroundLedgerBlock = ledgerOfNode0.retrieveLatestBlock();
//
// // 验证合约中的赋值,外部可以获得;
// DataAccountSet dataAccountSet = ledgerOfNode0.getDataAccountSet(backgroundLedgerBlock);
// AsymmetricKeypair key = Crypto.getSignatureFunction("ED25519").generateKeypair();
// PubKey pubKey = key.getPubKey();
// Bytes dataAddress = AddressEncoding.generateAddress(pubKey);
//
// // 验证userAccount,从合约内部赋值,然后外部验证;由于目前不允许输入重复的key,所以在内部合约中构建的key,不便于在外展示,屏蔽之;
// // UserAccountSet userAccountSet =
// // ledgerOfNode0.getUserAccountSet(backgroundLedgerBlock);
// // PubKey userPubKey = new PubKey(CryptoAlgorithm.ED25519,
// // userPubKeyVal.getBytes());
// // String userAddress = AddressEncoding.generateAddress(userPubKey);
// // assertEquals(userAddress, userAccountSet.getUser(userAddress).getAddress());
// }
private LedgerBlock testSDK_Contract(AsymmetricKeypair adminKey, HashDigest ledgerHash,
BlockchainService blockchainService, IntegratedContext context) {
// valid the basic data in contract;
prepareContractData(adminKey, ledgerHash, blockchainService, context);
BlockchainKeypair userKey = BlockchainKeyGenerator.getInstance().generate();
// 定义交易;
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash);
byte[] contractCode = getChainCodeBytes();
txTpl.users().register(userKey.getIdentity());
txTpl.contracts().deploy(contractDeployKey.getIdentity(), contractCode);
// 签名;
PreparedTransaction ptx = txTpl.prepare();
ptx.sign(adminKey);
// 提交并等待共识返回;
TransactionResponse txResp = ptx.commit();
// 验证结果;
txResp.getContentHash();
Node node0 = context.getNode(0);
LedgerRepository ledgerOfNode0 = node0.getLedgerManager().getLedger(ledgerHash);
LedgerBlock block = ledgerOfNode0.getBlock(txResp.getBlockHeight());
byte[] contractCodeInDb = ledgerOfNode0.getContractAccountSet(block).getContract(contractDeployKey.getAddress())
.getChainCode();
txContentHash = ptx.getHash();
// execute the contract;
testContractExe(adminKey, ledgerHash, userKey, blockchainService, context);
return block;
}
private void testContractExe(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainKeypair userKey,
BlockchainService blockchainService, IntegratedContext context) {
LedgerInfo ledgerInfo = blockchainService.getLedger(ledgerHash);
LedgerBlock previousBlock = blockchainService.getBlock(ledgerHash, ledgerInfo.getLatestBlockHeight() - 1);
// 定义交易;
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash);
txTpl.contractEvents().send(contractDeployKey.getAddress(), eventName,
("888##abc##" + contractDataKey.getAddress() + "##" + previousBlock.getHash().toBase58() + "##"
+ userKey.getAddress() + "##" + contractDeployKey.getAddress() + "##" + txContentHash.toBase58()
+ "##SOME-VALUE").getBytes());
// 签名;
PreparedTransaction ptx = txTpl.prepare();
ptx.sign(adminKey);
// 提交并等待共识返回;
TransactionResponse txResp = ptx.commit();
// 验证结果;
txResp.getContentHash();
LedgerInfo latestLedgerInfo = blockchainService.getLedger(ledgerHash);
Node node0 = context.getNode(0);
LedgerRepository ledgerOfNode0 = node0.getLedgerManager().getLedger(ledgerHash);
LedgerBlock backgroundLedgerBlock = ledgerOfNode0.retrieveLatestBlock();
// 验证合约中的赋值,外部可以获得;
DataAccountSet dataAccountSet = ledgerOfNode0.getDataAccountSet(backgroundLedgerBlock);
AsymmetricKeypair key = Crypto.getSignatureFunction("ED25519").generateKeypair();
PubKey pubKey = key.getPubKey();
Bytes dataAddress = AddressEncoding.generateAddress(pubKey);
// 验证userAccount,从合约内部赋值,然后外部验证;由于目前不允许输入重复的key,所以在内部合约中构建的key,不便于在外展示,屏蔽之;
// UserAccountSet userAccountSet =
// ledgerOfNode0.getUserAccountSet(backgroundLedgerBlock);
// PubKey userPubKey = new PubKey(CryptoAlgorithm.ED25519,
// userPubKeyVal.getBytes());
// String userAddress = AddressEncoding.generateAddress(userPubKey);
// assertEquals(userAddress, userAccountSet.getUser(userAddress).getAddress());
}


private void prepareContractData(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainService blockchainService, private void prepareContractData(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainService blockchainService,
IntegratedContext context) { IntegratedContext context) {
@@ -620,11 +638,11 @@ public class IntegrationTest {
// 注册数据账户,并验证最终写入; // 注册数据账户,并验证最终写入;
txTpl.dataAccounts().register(contractDataKey.getIdentity()); txTpl.dataAccounts().register(contractDataKey.getIdentity());
DataAccountKVSetOperation kvsetOP = txTpl.dataAccount(contractDataKey.getAddress()) DataAccountKVSetOperation kvsetOP = txTpl.dataAccount(contractDataKey.getAddress())
.set("A", "Value_A_0".getBytes(), -1).set("B", "Value_B_0".getBytes(), -1)
.set(KEY_TOTAL, "total value,dataAccount".getBytes(), -1)
.set(KEY_ABC, "abc value,dataAccount".getBytes(), -1)
.setText("A", "Value_A_0", -1).setText("B", "Value_B_0", -1)
.setText(KEY_TOTAL, "total value,dataAccount", -1)
.setText(KEY_ABC, "abc value,dataAccount", -1)
// 所有的模拟数据都在这个dataAccount中填充; // 所有的模拟数据都在这个dataAccount中填充;
.set("ledgerHash", ledgerHash.getRawDigest(), -1).getOperation();
.setBytes("ledgerHash", ledgerHash.getRawDigest(), -1).getOperation();


// 签名; // 签名;
PreparedTransaction ptx = txTpl.prepare(); PreparedTransaction ptx = txTpl.prepare();
@@ -638,9 +656,9 @@ public class IntegrationTest {


LedgerRepository ledgerOfNode0 = node0.getLedgerManager().getLedger(ledgerHash); LedgerRepository ledgerOfNode0 = node0.getLedgerManager().getLedger(ledgerHash);
LedgerBlock block = ledgerOfNode0.getBlock(txResp.getBlockHeight()); LedgerBlock block = ledgerOfNode0.getBlock(txResp.getBlockHeight());
byte[] val1InDb = ledgerOfNode0.getDataAccountSet(block).getDataAccount(contractDataKey.getAddress())
BytesValue val1InDb = ledgerOfNode0.getDataAccountSet(block).getDataAccount(contractDataKey.getAddress())
.getBytes("A"); .getBytes("A");
byte[] val2InDb = ledgerOfNode0.getDataAccountSet(block).getDataAccount(contractDataKey.getAddress())
BytesValue val2InDb = ledgerOfNode0.getDataAccountSet(block).getDataAccount(contractDataKey.getAddress())
.getBytes(KEY_TOTAL); .getBytes(KEY_TOTAL);
} }




+ 3
- 4
source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerPerformanceTest.java View File

@@ -16,9 +16,9 @@ import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.consensus.ConsensusProvider; import com.jd.blockchain.consensus.ConsensusProvider;
import com.jd.blockchain.consensus.ConsensusProviders; import com.jd.blockchain.consensus.ConsensusProviders;
import com.jd.blockchain.consensus.ConsensusSettings; import com.jd.blockchain.consensus.ConsensusSettings;
import com.jd.blockchain.crypto.CryptoAlgorithm;
import com.jd.blockchain.crypto.AsymmetricKeypair; import com.jd.blockchain.crypto.AsymmetricKeypair;
import com.jd.blockchain.crypto.Crypto; import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.CryptoAlgorithm;
import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PrivKey;
import com.jd.blockchain.ledger.BlockchainIdentity; import com.jd.blockchain.ledger.BlockchainIdentity;
@@ -54,7 +54,6 @@ import com.jd.blockchain.transaction.TxBuilder;
import com.jd.blockchain.utils.ArgumentSet; import com.jd.blockchain.utils.ArgumentSet;
import com.jd.blockchain.utils.ConsoleUtils; import com.jd.blockchain.utils.ConsoleUtils;
import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback; import com.jd.blockchain.utils.concurrent.ThreadInvoker.AsyncCallback;
import com.jd.blockchain.utils.io.BytesUtils;
import com.jd.blockchain.utils.io.FileUtils; import com.jd.blockchain.utils.io.FileUtils;
import com.jd.blockchain.utils.net.NetworkAddress; import com.jd.blockchain.utils.net.NetworkAddress;


@@ -408,8 +407,8 @@ public class LedgerPerformanceTest {
// BlockchainKeyPair dataAccountKey = // BlockchainKeyPair dataAccountKey =
// BlockchainKeyGenerator.getInstance().generate(); // BlockchainKeyGenerator.getInstance().generate();
BlockchainIdentity targetAccount = dataAccounts[count % dataAccounts.length]; BlockchainIdentity targetAccount = dataAccounts[count % dataAccounts.length];
txbuilder.dataAccount(targetAccount.getAddress()).set("key-" + startTs + "-" + i,
BytesUtils.toBytes("value-" + i), -1L);
txbuilder.dataAccount(targetAccount.getAddress()).setText("key-" + startTs + "-" + i,
"value-" + i, -1L);
TransactionRequestBuilder reqBuilder = txbuilder.prepareRequest(); TransactionRequestBuilder reqBuilder = txbuilder.prepareRequest();
reqBuilder.signAsEndpoint(adminKey); reqBuilder.signAsEndpoint(adminKey);
txList.add(reqBuilder.buildRequest()); txList.add(reqBuilder.buildRequest());


+ 435
- 432
source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java View File

@@ -46,7 +46,6 @@ import java.util.concurrent.atomic.AtomicLong;


import static org.junit.Assert.*; import static org.junit.Assert.*;



/** /**
* *
* @author shaozhuguang * @author shaozhuguang
@@ -57,436 +56,440 @@ import static org.junit.Assert.*;
public class IntegrationBase { public class IntegrationBase {
public static String KEY_TOTAL = "total"; public static String KEY_TOTAL = "total";


static {
DataContractRegistry.register(LedgerInitOperation.class);
DataContractRegistry.register(UserRegisterOperation.class);
}
static {
DataContractRegistry.register(LedgerInitOperation.class);
DataContractRegistry.register(UserRegisterOperation.class);
}


public static final String PASSWORD = "abc";
public static final String PASSWORD = "abc";


public static final String[] PUB_KEYS = { "3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9",
"3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX",
"3snPdw7i7PZi6TStiyc6mzjprnNhgs2atSGNS8wPYzhbKaUWGFJt7x",
"3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk" };
public static final String[] PUB_KEYS = { "3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9",
"3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX",
"3snPdw7i7PZi6TStiyc6mzjprnNhgs2atSGNS8wPYzhbKaUWGFJt7x",
"3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk" };


public static final String[] PRIV_KEYS = {
"177gjzHTznYdPgWqZrH43W3yp37onm74wYXT4v9FukpCHBrhRysBBZh7Pzdo5AMRyQGJD7x",
"177gju9p5zrNdHJVEQnEEKF4ZjDDYmAXyfG84V5RPGVc5xFfmtwnHA7j51nyNLUFffzz5UT",
"177gjtwLgmSx5v1hFb46ijh7L9kdbKUpJYqdKVf9afiEmAuLgo8Rck9yu5UuUcHknWJuWaF",
"177gk1pudweTq5zgJTh8y3ENCTwtSFsKyX7YnpuKPo7rKgCkCBXVXh5z2syaTCPEMbuWRns" };
public static final String[] PRIV_KEYS = {
"177gjzHTznYdPgWqZrH43W3yp37onm74wYXT4v9FukpCHBrhRysBBZh7Pzdo5AMRyQGJD7x",
"177gju9p5zrNdHJVEQnEEKF4ZjDDYmAXyfG84V5RPGVc5xFfmtwnHA7j51nyNLUFffzz5UT",
"177gjtwLgmSx5v1hFb46ijh7L9kdbKUpJYqdKVf9afiEmAuLgo8Rck9yu5UuUcHknWJuWaF",
"177gk1pudweTq5zgJTh8y3ENCTwtSFsKyX7YnpuKPo7rKgCkCBXVXh5z2syaTCPEMbuWRns" };


public static final AtomicLong validLong = new AtomicLong();
public static final AtomicLong validLong = new AtomicLong();


public static KeyPairResponse testSDK_RegisterUser(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainService blockchainService) {
// 注册用户,并验证最终写入;
BlockchainKeypair user = BlockchainKeyGenerator.getInstance().generate();
public static KeyPairResponse testSDK_RegisterUser(AsymmetricKeypair adminKey, HashDigest ledgerHash,
BlockchainService blockchainService) {
// 注册用户,并验证最终写入;
BlockchainKeypair user = BlockchainKeyGenerator.getInstance().generate();


// 定义交易;
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash);
txTpl.users().register(user.getIdentity());
// 定义交易;
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash);
txTpl.users().register(user.getIdentity());


// 签名;
PreparedTransaction ptx = txTpl.prepare();
// 签名;
PreparedTransaction ptx = txTpl.prepare();


HashDigest transactionHash = ptx.getHash();
HashDigest transactionHash = ptx.getHash();


ptx.sign(adminKey);
ptx.sign(adminKey);


// 提交并等待共识返回;
TransactionResponse txResp = ptx.commit();
// 提交并等待共识返回;
TransactionResponse txResp = ptx.commit();


KeyPairResponse keyPairResponse = new KeyPairResponse();
keyPairResponse.keyPair = user;
keyPairResponse.txResp = txResp;
keyPairResponse.txHash = transactionHash;
return keyPairResponse;
}
KeyPairResponse keyPairResponse = new KeyPairResponse();
keyPairResponse.keyPair = user;
keyPairResponse.txResp = txResp;
keyPairResponse.txHash = transactionHash;
return keyPairResponse;
}


public static KeyPairResponse testSDK_RegisterDataAccount(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainService blockchainService) {
// 注册数据账户,并验证最终写入;
BlockchainKeypair dataAccount = BlockchainKeyGenerator.getInstance().generate();
public static KeyPairResponse testSDK_RegisterDataAccount(AsymmetricKeypair adminKey, HashDigest ledgerHash,
BlockchainService blockchainService) {
// 注册数据账户,并验证最终写入;
BlockchainKeypair dataAccount = BlockchainKeyGenerator.getInstance().generate();


// 定义交易;
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash);
txTpl.dataAccounts().register(dataAccount.getIdentity());
// 定义交易;
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash);
txTpl.dataAccounts().register(dataAccount.getIdentity());
txTpl.dataAccount(dataAccount.getAddress()).set("total", 200, -1); txTpl.dataAccount(dataAccount.getAddress()).set("total", 200, -1);
// txTpl.dataAccount(dataAccount.getAddress()).set("param1", "v", -1); // txTpl.dataAccount(dataAccount.getAddress()).set("param1", "v", -1);
// txTpl.dataAccount(dataAccount.getAddress()).set("param2", 200, -1); // txTpl.dataAccount(dataAccount.getAddress()).set("param2", 200, -1);


// 签名;
PreparedTransaction ptx = txTpl.prepare();

HashDigest transactionHash = ptx.getHash();

ptx.sign(adminKey);

// 提交并等待共识返回;
TransactionResponse txResp = ptx.commit();

KeyPairResponse keyPairResponse = new KeyPairResponse();
keyPairResponse.keyPair = dataAccount;
keyPairResponse.txResp = txResp;
keyPairResponse.txHash = transactionHash;
return keyPairResponse;
}

public static KvResponse testSDK_InsertData(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainService blockchainService,
Bytes dataAccount) {

// 在本地定义注册账号的 TX;
TransactionTemplate txTemp = blockchainService.newTransaction(ledgerHash);

// --------------------------------------
// 将商品信息写入到指定的账户中;
// 对象将被序列化为 JSON 形式存储,并基于 JSON 结构建立查询索引;
String dataKey = "jingdong" + System.currentTimeMillis() + new Random().nextInt(100000);
byte[] dataVal = "www.jd.com".getBytes();

txTemp.dataAccount(dataAccount).set(dataKey, dataVal, -1);

// TX 准备就绪;
PreparedTransaction prepTx = txTemp.prepare();

HashDigest transactionHash = prepTx.getHash();

// 使用私钥进行签名;
prepTx.sign(adminKey);

// 提交交易;
TransactionResponse txResp = prepTx.commit();

KvResponse kvResponse = new KvResponse();
kvResponse.ledgerHash = ledgerHash;
kvResponse.dataAccount = dataAccount;
kvResponse.txResp = txResp;
kvResponse.txHash = transactionHash;
kvResponse.key = dataKey;
kvResponse.value = dataVal;
return kvResponse;
}



public static void validKeyPair(IntegrationBase.KeyPairResponse keyPairResponse, LedgerRepository ledgerRepository, KeyPairType keyPairType) {
TransactionResponse txResp = keyPairResponse.txResp;
HashDigest transactionHash = keyPairResponse.txHash;
BlockchainKeypair keyPair = keyPairResponse.keyPair;
long index = validLong.incrementAndGet();
System.out.printf("validKeyPair start %s \r\n", index);
ledgerRepository.retrieveLatestBlock();

assertEquals(txResp.getExecutionState(), TransactionState.SUCCESS);
assertEquals(txResp.getBlockHeight(), ledgerRepository.getLatestBlockHeight());
assertEquals(txResp.getContentHash(), transactionHash);
assertEquals(txResp.getBlockHash(), ledgerRepository.getLatestBlockHash());
if (keyPairType == KeyPairType.USER) {
assertTrue(ledgerRepository.getUserAccountSet(ledgerRepository.getLatestBlock()).contains(keyPair.getAddress()));
}

if (keyPairType == KeyPairType.DATAACCOUNT) {
assertNotNull(ledgerRepository.getDataAccountSet(ledgerRepository.getLatestBlock())
.getDataAccount(keyPair.getAddress()));
}
System.out.printf("validKeyPair end %s \r\n", index);
}

public static void validKeyPair(IntegrationBase.KeyPairResponse keyPairResponse, LedgerRepository ledgerRepository, KeyPairType keyPairType, CountDownLatch countDownLatch) {

TransactionResponse txResp = keyPairResponse.txResp;
HashDigest transactionHash = keyPairResponse.txHash;
BlockchainKeypair keyPair = keyPairResponse.keyPair;
ledgerRepository.retrieveLatestBlock();

assertEquals(txResp.getExecutionState(), TransactionState.SUCCESS);
assertEquals(txResp.getBlockHeight(), ledgerRepository.getLatestBlockHeight());
assertEquals(txResp.getContentHash(), transactionHash);
assertEquals(txResp.getBlockHash(), ledgerRepository.getLatestBlockHash());
if (keyPairType == KeyPairType.USER) {
assertTrue(ledgerRepository.getUserAccountSet(ledgerRepository.getLatestBlock()).contains(keyPair.getAddress()));
}

if (keyPairType == KeyPairType.DATAACCOUNT) {
assertNotNull(ledgerRepository.getDataAccountSet(ledgerRepository.getLatestBlock())
.getDataAccount(keyPair.getAddress()));
}
countDownLatch.countDown();
}

public static void validKvWrite(IntegrationBase.KvResponse kvResponse, LedgerRepository ledgerRepository, BlockchainService blockchainService) {
// 先验证应答
TransactionResponse txResp = kvResponse.getTxResp();
HashDigest transactionHash = kvResponse.getTxHash();
HashDigest ledgerHash = kvResponse.getLedgerHash();
String daAddress = kvResponse.getDataAccount().toBase58();
String dataKey = kvResponse.getKey();
byte[] dataVal = kvResponse.getValue();

ledgerRepository.retrieveLatestBlock();

assertEquals(TransactionState.SUCCESS, txResp.getExecutionState());
assertEquals(txResp.getBlockHeight(), ledgerRepository.getLatestBlockHeight());
assertEquals(txResp.getContentHash(), transactionHash);
assertEquals(txResp.getBlockHash(), ledgerRepository.getLatestBlockHash());

KVDataEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, daAddress, dataKey);
for (KVDataEntry kvDataEntry : kvDataEntries) {
assertEquals(dataKey, kvDataEntry.getKey());
String valHexText = (String) kvDataEntry.getValue();
byte[] valBytes = HexUtils.decode(valHexText);
boolean isEqual = Arrays.equals(dataVal, valBytes);
assertTrue(isEqual);
}
}


public static LedgerRepository[] buildLedgers(LedgerBindingConfig[] bindingConfigs, DbConnectionFactory[] dbConnectionFactories){
int[] ids = {0, 1, 2, 3};
LedgerRepository[] ledgers = new LedgerRepository[ids.length];
LedgerManager[] ledgerManagers = new LedgerManager[ids.length];
for (int i = 0; i < ids.length; i++) {
ledgerManagers[i] = new LedgerManager();
HashDigest ledgerHash = bindingConfigs[0].getLedgerHashs()[0];
DbConnection conn = dbConnectionFactories[i].connect(bindingConfigs[i].getLedger(ledgerHash).getDbConnection().getUri());
ledgers[i] = ledgerManagers[i].register(ledgerHash, conn.getStorageService());
}
return ledgers;
}

public static void testConsistencyAmongNodes(LedgerRepository[] ledgers) {
LedgerRepository ledger0 = ledgers[0];
LedgerBlock latestBlock0 = ledger0.retrieveLatestBlock();
for (int i = 1; i < ledgers.length; i++) {
LedgerRepository otherLedger = ledgers[i];
LedgerBlock otherLatestBlock = otherLedger.retrieveLatestBlock();
assertEquals(ledger0.getHash(), otherLedger.getHash());
assertEquals(ledger0.getLatestBlockHeight(), otherLedger.getLatestBlockHeight());
assertEquals(ledger0.getLatestBlockHash(), otherLedger.getLatestBlockHash());

assertEquals(latestBlock0.getHeight(), otherLatestBlock.getHeight());
assertEquals(latestBlock0.getHash(), otherLatestBlock.getHash());
assertEquals(latestBlock0.getAdminAccountHash(), otherLatestBlock.getAdminAccountHash());
assertEquals(latestBlock0.getTransactionSetHash(), otherLatestBlock.getTransactionSetHash());
assertEquals(latestBlock0.getUserAccountSetHash(), otherLatestBlock.getUserAccountSetHash());
assertEquals(latestBlock0.getDataAccountSetHash(), otherLatestBlock.getDataAccountSetHash());
assertEquals(latestBlock0.getContractAccountSetHash(), otherLatestBlock.getContractAccountSetHash());
assertEquals(latestBlock0.getPreviousHash(), otherLatestBlock.getPreviousHash());
}
}

public static PeerTestRunner[] peerNodeStart(HashDigest ledgerHash, String dbType) {
NetworkAddress peerSrvAddr0 = new NetworkAddress("127.0.0.1", 12000);
LedgerBindingConfig bindingConfig0 = loadBindingConfig(0, ledgerHash, dbType);
PeerTestRunner peer0 = new PeerTestRunner(peerSrvAddr0, bindingConfig0);

NetworkAddress peerSrvAddr1 = new NetworkAddress("127.0.0.1", 12010);
LedgerBindingConfig bindingConfig1 = loadBindingConfig(1, ledgerHash, dbType);
PeerTestRunner peer1 = new PeerTestRunner(peerSrvAddr1, bindingConfig1);

NetworkAddress peerSrvAddr2 = new NetworkAddress("127.0.0.1", 12020);
LedgerBindingConfig bindingConfig2 = loadBindingConfig(2, ledgerHash, dbType);
PeerTestRunner peer2 = new PeerTestRunner(peerSrvAddr2, bindingConfig2);

NetworkAddress peerSrvAddr3 = new NetworkAddress("127.0.0.1", 12030);
LedgerBindingConfig bindingConfig3 = loadBindingConfig(3, ledgerHash, dbType);
PeerTestRunner peer3 = new PeerTestRunner(peerSrvAddr3, bindingConfig3);

ThreadInvoker.AsyncCallback<Object> peerStarting0 = peer0.start();
ThreadInvoker.AsyncCallback<Object> peerStarting1 = peer1.start();
ThreadInvoker.AsyncCallback<Object> peerStarting2 = peer2.start();
ThreadInvoker.AsyncCallback<Object> peerStarting3 = peer3.start();

peerStarting0.waitReturn();
peerStarting1.waitReturn();
peerStarting2.waitReturn();
peerStarting3.waitReturn();

return new PeerTestRunner[]{peer0, peer1, peer2, peer3};
}

public static LedgerBindingConfig loadBindingConfig(int id, HashDigest ledgerHash, String dbType) {
LedgerBindingConfig ledgerBindingConfig;
String newLedger = ledgerHash.toBase58();
String resourceClassPath = "ledger-binding-" + dbType + "-" + id + ".conf";
String ledgerBindingUrl = IntegrationBase.class.getResource("/") + resourceClassPath;

try {
URL url = new URL(ledgerBindingUrl);
File ledgerBindingConf = new File(url.getPath());
System.out.printf("URL-ledgerBindingConf = %s \r\n", url.getPath());
if (ledgerBindingConf.exists()) {
List<String> readLines = FileUtils.readLines(ledgerBindingConf);

List<String> writeLines = new ArrayList<>();

if (readLines != null && !readLines.isEmpty()) {
String oldLedgerLine = null;
for (String readLine : readLines) {
if (readLine.startsWith("ledger")) {
oldLedgerLine = readLine;
break;
}
}
String[] oldLedgerArray = oldLedgerLine.split("=");

String oldLedger = oldLedgerArray[1];
if (!oldLedger.equalsIgnoreCase(newLedger)) {
for (String readLine : readLines) {
String newLine = readLine.replace(oldLedger, newLedger);
if (dbType.equalsIgnoreCase("rocksdb")) {
if (newLine.contains("db.uri")) {
String[] propArray = newLine.split("=");
String dbKey = propArray[0];
String dbValue = LedgerInitConsensusConfig.rocksdbConnectionStrings[id];
newLine = dbKey + "=" + dbValue;
}
}
writeLines.add(newLine);
}
} else if(dbType.equalsIgnoreCase("rocksdb")) {
for (String readLine : readLines) {
String newLine = readLine;
if (readLine.contains("db.uri")) {
String[] propArray = readLine.split("=");
String dbKey = propArray[0];
String dbValue = LedgerInitConsensusConfig.rocksdbConnectionStrings[id];
newLine = dbKey + "=" + dbValue;
}
writeLines.add(newLine);
}
}
if (!writeLines.isEmpty()) {
FileUtils.writeLines(ledgerBindingConf, writeLines);
}
}
}
} catch (Exception e) {

}

ClassPathResource res = new ClassPathResource(resourceClassPath);
try(InputStream in = res.getInputStream()){
ledgerBindingConfig = LedgerBindingConfig.resolve(in);
} catch (IOException e) {
throw new IllegalStateException(e.getMessage(), e);
}
return ledgerBindingConfig;
}

public static class KeyPairResponse {
HashDigest txHash;

BlockchainKeypair keyPair;

TransactionResponse txResp;

public BlockchainKeypair getKeyPair() {
return keyPair;
}

public TransactionResponse getTxResp() {
return txResp;
}

public HashDigest getTxHash() {
return txHash;
}
}

public static class KvResponse {

Bytes dataAccount;

HashDigest ledgerHash;

HashDigest txHash;

TransactionResponse txResp;

String key;

byte[] value;

public HashDigest getTxHash() {
return txHash;
}

public TransactionResponse getTxResp() {
return txResp;
}

public String getKey() {
return key;
}

public byte[] getValue() {
return value;
}

public HashDigest getLedgerHash() {
return ledgerHash;
}

public Bytes getDataAccount() {
return dataAccount;
}
}

public enum KeyPairType {
USER,
DATAACCOUNT
}

// 合约测试使用的初始化数据;
// 签名;
PreparedTransaction ptx = txTpl.prepare();

HashDigest transactionHash = ptx.getHash();

ptx.sign(adminKey);

// 提交并等待共识返回;
TransactionResponse txResp = ptx.commit();

KeyPairResponse keyPairResponse = new KeyPairResponse();
keyPairResponse.keyPair = dataAccount;
keyPairResponse.txResp = txResp;
keyPairResponse.txHash = transactionHash;
return keyPairResponse;
}

public static KvResponse testSDK_InsertData(AsymmetricKeypair adminKey, HashDigest ledgerHash,
BlockchainService blockchainService, Bytes dataAccount) {

// 在本地定义注册账号的 TX;
TransactionTemplate txTemp = blockchainService.newTransaction(ledgerHash);

// --------------------------------------
// 将商品信息写入到指定的账户中;
// 对象将被序列化为 JSON 形式存储,并基于 JSON 结构建立查询索引;
String dataKey = "jingdong" + System.currentTimeMillis() + new Random().nextInt(100000);
String dataVal = "www.jd.com";

txTemp.dataAccount(dataAccount).setText(dataKey, dataVal, -1);

// TX 准备就绪;
PreparedTransaction prepTx = txTemp.prepare();

HashDigest transactionHash = prepTx.getHash();

// 使用私钥进行签名;
prepTx.sign(adminKey);

// 提交交易;
TransactionResponse txResp = prepTx.commit();

KvResponse kvResponse = new KvResponse();
kvResponse.ledgerHash = ledgerHash;
kvResponse.dataAccount = dataAccount;
kvResponse.txResp = txResp;
kvResponse.txHash = transactionHash;
kvResponse.key = dataKey;
kvResponse.value = dataVal;
return kvResponse;
}

public static void validKeyPair(IntegrationBase.KeyPairResponse keyPairResponse, LedgerRepository ledgerRepository,
KeyPairType keyPairType) {
TransactionResponse txResp = keyPairResponse.txResp;
HashDigest transactionHash = keyPairResponse.txHash;
BlockchainKeypair keyPair = keyPairResponse.keyPair;
long index = validLong.incrementAndGet();
System.out.printf("validKeyPair start %s \r\n", index);
ledgerRepository.retrieveLatestBlock();

assertEquals(txResp.getExecutionState(), TransactionState.SUCCESS);
assertEquals(txResp.getBlockHeight(), ledgerRepository.getLatestBlockHeight());
assertEquals(txResp.getContentHash(), transactionHash);
assertEquals(txResp.getBlockHash(), ledgerRepository.getLatestBlockHash());
if (keyPairType == KeyPairType.USER) {
assertTrue(ledgerRepository.getUserAccountSet(ledgerRepository.getLatestBlock())
.contains(keyPair.getAddress()));
}

if (keyPairType == KeyPairType.DATAACCOUNT) {
assertNotNull(ledgerRepository.getDataAccountSet(ledgerRepository.getLatestBlock())
.getDataAccount(keyPair.getAddress()));
}
System.out.printf("validKeyPair end %s \r\n", index);
}

public static void validKeyPair(IntegrationBase.KeyPairResponse keyPairResponse, LedgerRepository ledgerRepository,
KeyPairType keyPairType, CountDownLatch countDownLatch) {

TransactionResponse txResp = keyPairResponse.txResp;
HashDigest transactionHash = keyPairResponse.txHash;
BlockchainKeypair keyPair = keyPairResponse.keyPair;
ledgerRepository.retrieveLatestBlock();

assertEquals(txResp.getExecutionState(), TransactionState.SUCCESS);
assertEquals(txResp.getBlockHeight(), ledgerRepository.getLatestBlockHeight());
assertEquals(txResp.getContentHash(), transactionHash);
assertEquals(txResp.getBlockHash(), ledgerRepository.getLatestBlockHash());
if (keyPairType == KeyPairType.USER) {
assertTrue(ledgerRepository.getUserAccountSet(ledgerRepository.getLatestBlock())
.contains(keyPair.getAddress()));
}

if (keyPairType == KeyPairType.DATAACCOUNT) {
assertNotNull(ledgerRepository.getDataAccountSet(ledgerRepository.getLatestBlock())
.getDataAccount(keyPair.getAddress()));
}
countDownLatch.countDown();
}

public static void validKvWrite(IntegrationBase.KvResponse kvResponse, LedgerRepository ledgerRepository,
BlockchainService blockchainService) {
// 先验证应答
TransactionResponse txResp = kvResponse.getTxResp();
HashDigest transactionHash = kvResponse.getTxHash();
HashDigest ledgerHash = kvResponse.getLedgerHash();
String daAddress = kvResponse.getDataAccount().toBase58();
String dataKey = kvResponse.getKey();
String dataVal = kvResponse.getValue();

ledgerRepository.retrieveLatestBlock();

assertEquals(TransactionState.SUCCESS, txResp.getExecutionState());
assertEquals(txResp.getBlockHeight(), ledgerRepository.getLatestBlockHeight());
assertEquals(txResp.getContentHash(), transactionHash);
assertEquals(txResp.getBlockHash(), ledgerRepository.getLatestBlockHash());

KVDataEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, daAddress, dataKey);
for (KVDataEntry kvDataEntry : kvDataEntries) {
assertEquals(dataKey, kvDataEntry.getKey());
String valHexText = (String) kvDataEntry.getValue();
assertEquals(dataVal, valHexText);
}
}

public static LedgerRepository[] buildLedgers(LedgerBindingConfig[] bindingConfigs,
DbConnectionFactory[] dbConnectionFactories) {
int[] ids = { 0, 1, 2, 3 };
LedgerRepository[] ledgers = new LedgerRepository[ids.length];
LedgerManager[] ledgerManagers = new LedgerManager[ids.length];
for (int i = 0; i < ids.length; i++) {
ledgerManagers[i] = new LedgerManager();
HashDigest ledgerHash = bindingConfigs[0].getLedgerHashs()[0];
DbConnection conn = dbConnectionFactories[i]
.connect(bindingConfigs[i].getLedger(ledgerHash).getDbConnection().getUri());
ledgers[i] = ledgerManagers[i].register(ledgerHash, conn.getStorageService());
}
return ledgers;
}

public static void testConsistencyAmongNodes(LedgerRepository[] ledgers) {
LedgerRepository ledger0 = ledgers[0];
LedgerBlock latestBlock0 = ledger0.retrieveLatestBlock();
for (int i = 1; i < ledgers.length; i++) {
LedgerRepository otherLedger = ledgers[i];
LedgerBlock otherLatestBlock = otherLedger.retrieveLatestBlock();
assertEquals(ledger0.getHash(), otherLedger.getHash());
assertEquals(ledger0.getLatestBlockHeight(), otherLedger.getLatestBlockHeight());
assertEquals(ledger0.getLatestBlockHash(), otherLedger.getLatestBlockHash());

assertEquals(latestBlock0.getHeight(), otherLatestBlock.getHeight());
assertEquals(latestBlock0.getHash(), otherLatestBlock.getHash());
assertEquals(latestBlock0.getAdminAccountHash(), otherLatestBlock.getAdminAccountHash());
assertEquals(latestBlock0.getTransactionSetHash(), otherLatestBlock.getTransactionSetHash());
assertEquals(latestBlock0.getUserAccountSetHash(), otherLatestBlock.getUserAccountSetHash());
assertEquals(latestBlock0.getDataAccountSetHash(), otherLatestBlock.getDataAccountSetHash());
assertEquals(latestBlock0.getContractAccountSetHash(), otherLatestBlock.getContractAccountSetHash());
assertEquals(latestBlock0.getPreviousHash(), otherLatestBlock.getPreviousHash());
}
}

public static PeerTestRunner[] peerNodeStart(HashDigest ledgerHash, String dbType) {
NetworkAddress peerSrvAddr0 = new NetworkAddress("127.0.0.1", 12000);
LedgerBindingConfig bindingConfig0 = loadBindingConfig(0, ledgerHash, dbType);
PeerTestRunner peer0 = new PeerTestRunner(peerSrvAddr0, bindingConfig0);

NetworkAddress peerSrvAddr1 = new NetworkAddress("127.0.0.1", 12010);
LedgerBindingConfig bindingConfig1 = loadBindingConfig(1, ledgerHash, dbType);
PeerTestRunner peer1 = new PeerTestRunner(peerSrvAddr1, bindingConfig1);

NetworkAddress peerSrvAddr2 = new NetworkAddress("127.0.0.1", 12020);
LedgerBindingConfig bindingConfig2 = loadBindingConfig(2, ledgerHash, dbType);
PeerTestRunner peer2 = new PeerTestRunner(peerSrvAddr2, bindingConfig2);

NetworkAddress peerSrvAddr3 = new NetworkAddress("127.0.0.1", 12030);
LedgerBindingConfig bindingConfig3 = loadBindingConfig(3, ledgerHash, dbType);
PeerTestRunner peer3 = new PeerTestRunner(peerSrvAddr3, bindingConfig3);

ThreadInvoker.AsyncCallback<Object> peerStarting0 = peer0.start();
ThreadInvoker.AsyncCallback<Object> peerStarting1 = peer1.start();
ThreadInvoker.AsyncCallback<Object> peerStarting2 = peer2.start();
ThreadInvoker.AsyncCallback<Object> peerStarting3 = peer3.start();

peerStarting0.waitReturn();
peerStarting1.waitReturn();
peerStarting2.waitReturn();
peerStarting3.waitReturn();

return new PeerTestRunner[] { peer0, peer1, peer2, peer3 };
}

public static LedgerBindingConfig loadBindingConfig(int id, HashDigest ledgerHash, String dbType) {
LedgerBindingConfig ledgerBindingConfig;
String newLedger = ledgerHash.toBase58();
String resourceClassPath = "ledger-binding-" + dbType + "-" + id + ".conf";
String ledgerBindingUrl = IntegrationBase.class.getResource("/") + resourceClassPath;

try {
URL url = new URL(ledgerBindingUrl);
File ledgerBindingConf = new File(url.getPath());
System.out.printf("URL-ledgerBindingConf = %s \r\n", url.getPath());
if (ledgerBindingConf.exists()) {
List<String> readLines = FileUtils.readLines(ledgerBindingConf);

List<String> writeLines = new ArrayList<>();

if (readLines != null && !readLines.isEmpty()) {
String oldLedgerLine = null;
for (String readLine : readLines) {
if (readLine.startsWith("ledger")) {
oldLedgerLine = readLine;
break;
}
}
String[] oldLedgerArray = oldLedgerLine.split("=");

String oldLedger = oldLedgerArray[1];
if (!oldLedger.equalsIgnoreCase(newLedger)) {
for (String readLine : readLines) {
String newLine = readLine.replace(oldLedger, newLedger);
if (dbType.equalsIgnoreCase("rocksdb")) {
if (newLine.contains("db.uri")) {
String[] propArray = newLine.split("=");
String dbKey = propArray[0];
String dbValue = LedgerInitConsensusConfig.rocksdbConnectionStrings[id];
newLine = dbKey + "=" + dbValue;
}
}
writeLines.add(newLine);
}
} else if (dbType.equalsIgnoreCase("rocksdb")) {
for (String readLine : readLines) {
String newLine = readLine;
if (readLine.contains("db.uri")) {
String[] propArray = readLine.split("=");
String dbKey = propArray[0];
String dbValue = LedgerInitConsensusConfig.rocksdbConnectionStrings[id];
newLine = dbKey + "=" + dbValue;
}
writeLines.add(newLine);
}
}
if (!writeLines.isEmpty()) {
FileUtils.writeLines(ledgerBindingConf, writeLines);
}
}
}
} catch (Exception e) {

}

ClassPathResource res = new ClassPathResource(resourceClassPath);
try (InputStream in = res.getInputStream()) {
ledgerBindingConfig = LedgerBindingConfig.resolve(in);
} catch (IOException e) {
throw new IllegalStateException(e.getMessage(), e);
}
return ledgerBindingConfig;
}

public static class KeyPairResponse {
HashDigest txHash;

BlockchainKeypair keyPair;

TransactionResponse txResp;

public BlockchainKeypair getKeyPair() {
return keyPair;
}

public TransactionResponse getTxResp() {
return txResp;
}

public HashDigest getTxHash() {
return txHash;
}
}

public static class KvResponse {

Bytes dataAccount;

HashDigest ledgerHash;

HashDigest txHash;

TransactionResponse txResp;

String key;

String value;

public HashDigest getTxHash() {
return txHash;
}

public TransactionResponse getTxResp() {
return txResp;
}

public String getKey() {
return key;
}

public String getValue() {
return value;
}

public HashDigest getLedgerHash() {
return ledgerHash;
}

public Bytes getDataAccount() {
return dataAccount;
}
}

public enum KeyPairType {
USER, DATAACCOUNT
}

// 合约测试使用的初始化数据;
static BlockchainKeypair contractDataKey = BlockchainKeyGenerator.getInstance().generate(); static BlockchainKeypair contractDataKey = BlockchainKeyGenerator.getInstance().generate();
static BlockchainKeypair contractDeployKey = BlockchainKeyGenerator.getInstance().generate(); static BlockchainKeypair contractDeployKey = BlockchainKeyGenerator.getInstance().generate();
// 保存资产总数的键;
// 第二个参数;
// 保存资产总数的键;
// 第二个参数;
private static String contractZipName = "contract.jar"; private static String contractZipName = "contract.jar";
static HashDigest txContentHash; static HashDigest txContentHash;

public static LedgerBlock testSDK_Contract(AsymmetricKeypair adminKey, HashDigest ledgerHash, public static LedgerBlock testSDK_Contract(AsymmetricKeypair adminKey, HashDigest ledgerHash,
BlockchainService blockchainService,LedgerRepository ledgerRepository) {
BlockchainService blockchainService, LedgerRepository ledgerRepository) {
KeyPairResponse keyPairResponse = testSDK_RegisterDataAccount(adminKey,ledgerHash,blockchainService); KeyPairResponse keyPairResponse = testSDK_RegisterDataAccount(adminKey,ledgerHash,blockchainService);


System.out.println("adminKey="+ AddressEncoding.generateAddress(adminKey.getPubKey()));
BlockchainKeypair userKey = BlockchainKeyGenerator.getInstance().generate();
System.out.println("userKey="+userKey.getAddress());
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash);
txTpl.users().register(userKey.getIdentity());
System.out.println("adminKey=" + AddressEncoding.generateAddress(adminKey.getPubKey()));
BlockchainKeypair userKey = BlockchainKeyGenerator.getInstance().generate();
System.out.println("userKey=" + userKey.getAddress());
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash);
txTpl.users().register(userKey.getIdentity());


// 定义交易;
byte[] contractCode = getChainCodeBytes();
txTpl.contracts().deploy(contractDeployKey.getIdentity(), contractCode);
// 定义交易;
byte[] contractCode = getChainCodeBytes();
txTpl.contracts().deploy(contractDeployKey.getIdentity(), contractCode);


// 签名;
PreparedTransaction ptx = txTpl.prepare();
ptx.sign(adminKey);
// 签名;
PreparedTransaction ptx = txTpl.prepare();
ptx.sign(adminKey);


// 提交并等待共识返回;
TransactionResponse txResp = ptx.commit();
assertTrue(txResp.isSuccess());
// 提交并等待共识返回;
TransactionResponse txResp = ptx.commit();
assertTrue(txResp.isSuccess());


// 验证结果hash请求的hash=相应的内容hash;
// 验证结果;
assertEquals(ptx.getHash(),txResp.getContentHash()); assertEquals(ptx.getHash(),txResp.getContentHash());


LedgerBlock block = ledgerRepository.getBlock(txResp.getBlockHeight());
byte[] contractCodeInDb = ledgerRepository.getContractAccountSet(block).getContract(contractDeployKey.getAddress())
.getChainCode();
assertArrayEquals(contractCode, contractCodeInDb);
LedgerBlock block = ledgerRepository.getBlock(txResp.getBlockHeight());
byte[] contractCodeInDb = ledgerRepository.getContractAccountSet(block)
.getContract(contractDeployKey.getAddress()).getChainCode();
assertArrayEquals(contractCode, contractCodeInDb);


// execute the contract;
// execute the contract;
testContractExe(adminKey, ledgerHash, keyPairResponse.keyPair, blockchainService, ledgerRepository); testContractExe(adminKey, ledgerHash, keyPairResponse.keyPair, blockchainService, ledgerRepository);
testContractExe1(adminKey, ledgerHash, keyPairResponse.keyPair, blockchainService, ledgerRepository); testContractExe1(adminKey, ledgerHash, keyPairResponse.keyPair, blockchainService, ledgerRepository);


return block;
}
return block;
}


private static <T> void testContractExe(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainKeypair dataKey, private static <T> void testContractExe(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainKeypair dataKey,
BlockchainService blockchainService,LedgerRepository ledgerRepository) {
LedgerInfo ledgerInfo = blockchainService.getLedger(ledgerHash);
LedgerBlock previousBlock = blockchainService.getBlock(ledgerHash, ledgerInfo.getLatestBlockHeight() - 1);
BlockchainService blockchainService, LedgerRepository ledgerRepository) {
LedgerInfo ledgerInfo = blockchainService.getLedger(ledgerHash);
LedgerBlock previousBlock = blockchainService.getBlock(ledgerHash, ledgerInfo.getLatestBlockHeight() - 1);


// 定义交易;
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash);
// 定义交易;
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash);


Byte byteObj = Byte.parseByte("123"); Byte byteObj = Byte.parseByte("123");
// txTpl.contract(contractDeployKey.getAddress(),AssetContract2.class).issue(byteObj, // txTpl.contract(contractDeployKey.getAddress(),AssetContract2.class).issue(byteObj,
@@ -494,14 +497,14 @@ public class IntegrationBase {
txTpl.contract(contractDeployKey.getAddress(),AssetContract2.class).issue(byteObj, txTpl.contract(contractDeployKey.getAddress(),AssetContract2.class).issue(byteObj,
dataKey.getAddress().toBase58(),Bytes.fromString("123321")); dataKey.getAddress().toBase58(),Bytes.fromString("123321"));


// 签名;
PreparedTransaction ptx = txTpl.prepare();
ptx.sign(adminKey);
// 签名;
PreparedTransaction ptx = txTpl.prepare();
ptx.sign(adminKey);


// 提交并等待共识返回;
TransactionResponse txResp = ptx.commit();
// 提交并等待共识返回;
TransactionResponse txResp = ptx.commit();


// 验证结果;
// 验证结果;
Assert.assertTrue(txResp.isSuccess()); Assert.assertTrue(txResp.isSuccess());
assertEquals(ptx.getHash(),txResp.getContentHash()); assertEquals(ptx.getHash(),txResp.getContentHash());
LedgerBlock block = ledgerRepository.getBlock(txResp.getBlockHeight()); LedgerBlock block = ledgerRepository.getBlock(txResp.getBlockHeight());
@@ -529,43 +532,43 @@ public class IntegrationBase {
TransactionResponse txResp = ptx.commit(); TransactionResponse txResp = ptx.commit();


// 验证结果; // 验证结果;
Assert.assertTrue(txResp.isSuccess());
Assert.assertTrue(txResp.isSuccess());
assertEquals(ptx.getHash(),txResp.getContentHash()); assertEquals(ptx.getHash(),txResp.getContentHash());
LedgerBlock block = ledgerRepository.getBlock(txResp.getBlockHeight()); LedgerBlock block = ledgerRepository.getBlock(txResp.getBlockHeight());
KVDataEntry[] kvDataEntries = ledgerRepository.getDataAccountSet(block).getDataAccount(dataKey.getAddress()).getDataEntries(1,2); KVDataEntry[] kvDataEntries = ledgerRepository.getDataAccountSet(block).getDataAccount(dataKey.getAddress()).getDataEntries(1,2);
assertEquals("value1",kvDataEntries[0].getValue().toString()); assertEquals("value1",kvDataEntries[0].getValue().toString());
assertEquals(888L,kvDataEntries[1].getValue()); assertEquals(888L,kvDataEntries[1].getValue());
}
}


/**
* 根据合约构建字节数组;
*
* @return
*/
/**
* 根据合约构建字节数组;
*
* @return
*/
private static byte[] getChainCodeBytes() { private static byte[] getChainCodeBytes() {
// 构建合约的字节数组;
byte[] contractCode = null;
File file = null;
InputStream input = null;
try {
ClassPathResource contractPath = new ClassPathResource(contractZipName);
file = new File(contractPath.getURI());
assertTrue("contract zip file is not exist.", file.exists() == true);
input = new FileInputStream(file);
// 这种暴力的读取压缩包,在class解析时有问题,所有需要改进;
contractCode = new byte[input.available()];
input.read(contractCode);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (input != null) {
input.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return contractCode;
}
// 构建合约的字节数组;
byte[] contractCode = null;
File file = null;
InputStream input = null;
try {
ClassPathResource contractPath = new ClassPathResource(contractZipName);
file = new File(contractPath.getURI());
assertTrue("contract zip file is not exist.", file.exists() == true);
input = new FileInputStream(file);
// 这种暴力的读取压缩包,在class解析时有问题,所有需要改进;
contractCode = new byte[input.available()];
input.read(contractCode);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (input != null) {
input.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return contractCode;
}
} }

+ 27
- 30
source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestAll4Redis.java View File

@@ -2,6 +2,7 @@ package test.com.jd.blockchain.intgr;


import com.jd.blockchain.crypto.*; import com.jd.blockchain.crypto.*;
import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig; import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.*; import com.jd.blockchain.ledger.*;
import com.jd.blockchain.ledger.core.DataAccount; import com.jd.blockchain.ledger.core.DataAccount;
import com.jd.blockchain.ledger.core.DataAccountSet; import com.jd.blockchain.ledger.core.DataAccountSet;
@@ -201,9 +202,9 @@ public class IntegrationTestAll4Redis {
txTpl.dataAccounts().register(dataKey.getIdentity()); txTpl.dataAccounts().register(dataKey.getIdentity());


// add kv ops for data account // add kv ops for data account
DataAccountKVSetOperation dataKvsetOP = txTpl.dataAccount(dataKey.getAddress())
.set("A", "Value_A_0".getBytes(), -1).set("B", "Value_B_0".getBytes(), -1)
.set("C", "Value_C_0".getBytes(), -1).set("D", "Value_D_0".getBytes(), -1).getOperation();
DataAccountKVSetOperation dataKvsetOP = txTpl.dataAccount(dataKey.getAddress()).setText("A", "Value_A_0", -1)
.setText("B", "Value_B_0", -1).setText("C", "Value_C_0", -1).setText("D", "Value_D_0", -1)
.getOperation();


// 签名; // 签名;
PreparedTransaction ptx = txTpl.prepare(); PreparedTransaction ptx = txTpl.prepare();
@@ -215,18 +216,14 @@ public class IntegrationTestAll4Redis {
assertTrue(txResp.isSuccess()); assertTrue(txResp.isSuccess());
assertEquals(ledgerRepository.retrieveLatestBlockHeight(), txResp.getBlockHeight()); assertEquals(ledgerRepository.retrieveLatestBlockHeight(), txResp.getBlockHeight());


assertArrayEquals("Value_A_0".getBytes(),
ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock())
.getDataAccount(dataKey.getAddress()).getBytes("A"));
assertArrayEquals("Value_B_0".getBytes(),
ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock())
.getDataAccount(dataKey.getAddress()).getBytes("B"));
assertArrayEquals("Value_C_0".getBytes(),
ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock())
.getDataAccount(dataKey.getAddress()).getBytes("C"));
assertArrayEquals("Value_D_0".getBytes(),
ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock())
.getDataAccount(dataKey.getAddress()).getBytes("D"));
assertEquals("Value_A_0", ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock())
.getDataAccount(dataKey.getAddress()).getBytes("A").getValue().toUTF8String());
assertEquals("Value_B_0", ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock())
.getDataAccount(dataKey.getAddress()).getBytes("B").getValue().toUTF8String());
assertEquals("Value_C_0", ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock())
.getDataAccount(dataKey.getAddress()).getBytes("C").getValue().toUTF8String());
assertEquals("Value_D_0", ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock())
.getDataAccount(dataKey.getAddress()).getBytes("D").getValue().toUTF8String());
assertEquals(0, ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock()) assertEquals(0, ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock())
.getDataAccount(dataKey.getAddress()).getDataVersion("A")); .getDataAccount(dataKey.getAddress()).getDataVersion("A"));
assertEquals(0, ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock()) assertEquals(0, ledgerRepository.getDataAccountSet(ledgerRepository.retrieveLatestBlock())
@@ -253,8 +250,8 @@ public class IntegrationTestAll4Redis {


} }


private void testSDK_InsertData(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainService blockchainService,
Bytes dataAccountAddress, LedgerRepository ledgerRepository) {
private void testSDK_InsertData(AsymmetricKeypair adminKey, HashDigest ledgerHash,
BlockchainService blockchainService, Bytes dataAccountAddress, LedgerRepository ledgerRepository) {


// 在本地定义注册账号的 TX; // 在本地定义注册账号的 TX;
TransactionTemplate txTemp = blockchainService.newTransaction(ledgerHash); TransactionTemplate txTemp = blockchainService.newTransaction(ledgerHash);
@@ -265,9 +262,9 @@ public class IntegrationTestAll4Redis {
Bytes dataAccount = dataAccountAddress; Bytes dataAccount = dataAccountAddress;


String dataKey = "jingdong" + new Random().nextInt(100000); String dataKey = "jingdong" + new Random().nextInt(100000);
byte[] dataVal = "www.jd.com".getBytes();
String dataVal = "www.jd.com";


txTemp.dataAccount(dataAccount).set(dataKey, dataVal, -1);
txTemp.dataAccount(dataAccount).setText(dataKey, dataVal, -1);


// TX 准备就绪; // TX 准备就绪;
PreparedTransaction prepTx = txTemp.prepare(); PreparedTransaction prepTx = txTemp.prepare();
@@ -392,11 +389,10 @@ public class IntegrationTestAll4Redis {
.getDataAccount(contractDataKey.getAddress()); .getDataAccount(contractDataKey.getAddress());


DataAccountKVSetOperation kvsetOP = txTpl.dataAccount(contractDataKey.getAddress()) DataAccountKVSetOperation kvsetOP = txTpl.dataAccount(contractDataKey.getAddress())
.set("A", "Value_A_0".getBytes(), -1).set("B", "Value_B_0".getBytes(), -1)
.set(KEY_TOTAL, "total value,dataAccount".getBytes(), -1)
.set(KEY_ABC, "abc value,dataAccount".getBytes(), -1)
.setText("A", "Value_A_0", -1).setText("B", "Value_B_0", -1)
.setText(KEY_TOTAL, "total value,dataAccount", -1).setText(KEY_ABC, "abc value,dataAccount", -1)
// 所有的模拟数据都在这个dataAccount中填充; // 所有的模拟数据都在这个dataAccount中填充;
.set("ledgerHash", ledgerHash.getRawDigest(), -1).getOperation();
.setBytes("ledgerHash", ledgerHash.getRawDigest(), -1).getOperation();


byte[] contractCode = getChainCodeBytes(); byte[] contractCode = getChainCodeBytes();
txTpl.contracts().deploy(contractDeployKey.getIdentity(), contractCode); txTpl.contracts().deploy(contractDeployKey.getIdentity(), contractCode);
@@ -457,7 +453,8 @@ public class IntegrationTestAll4Redis {
PubKey pubKey = key.getPubKey(); PubKey pubKey = key.getPubKey();
Bytes dataAddress = AddressEncoding.generateAddress(pubKey); Bytes dataAddress = AddressEncoding.generateAddress(pubKey);
assertEquals(dataAddress, dataAccountSet.getDataAccount(dataAddress).getAddress()); assertEquals(dataAddress, dataAccountSet.getDataAccount(dataAddress).getAddress());
assertEquals("hello", new String(dataAccountSet.getDataAccount(dataAddress).getBytes(KEY_TOTAL, -1)));
assertEquals("hello",
dataAccountSet.getDataAccount(dataAddress).getBytes(KEY_TOTAL, -1).getValue().toUTF8String());


// 验证userAccount,从合约内部赋值,然后外部验证;内部定义动态key,外部不便于得到,临时屏蔽; // 验证userAccount,从合约内部赋值,然后外部验证;内部定义动态key,外部不便于得到,临时屏蔽;
// UserAccountSet userAccountSet = // UserAccountSet userAccountSet =
@@ -468,8 +465,8 @@ public class IntegrationTestAll4Redis {
// assertEquals(userAddress, userAccountSet.getUser(userAddress).getAddress()); // assertEquals(userAddress, userAccountSet.getUser(userAddress).getAddress());
} }


private void prepareContractData(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainService blockchainService,
LedgerRepository ledgerRepository) {
private void prepareContractData(AsymmetricKeypair adminKey, HashDigest ledgerHash,
BlockchainService blockchainService, LedgerRepository ledgerRepository) {


// 定义交易; // 定义交易;
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash);
@@ -484,12 +481,12 @@ public class IntegrationTestAll4Redis {


// 验证结果; // 验证结果;
LedgerBlock block = ledgerRepository.getBlock(txResp.getBlockHeight()); LedgerBlock block = ledgerRepository.getBlock(txResp.getBlockHeight());
byte[] val1InDb = ledgerRepository.getDataAccountSet(block).getDataAccount(contractDataKey.getAddress())
BytesValue val1InDb = ledgerRepository.getDataAccountSet(block).getDataAccount(contractDataKey.getAddress())
.getBytes("A"); .getBytes("A");
byte[] val2InDb = ledgerRepository.getDataAccountSet(block).getDataAccount(contractDataKey.getAddress())
BytesValue val2InDb = ledgerRepository.getDataAccountSet(block).getDataAccount(contractDataKey.getAddress())
.getBytes(KEY_TOTAL); .getBytes(KEY_TOTAL);
assertArrayEquals("Value_A_0".getBytes(), val1InDb);
assertArrayEquals("total value,dataAccount".getBytes(), val2InDb);
assertEquals("Value_A_0", val1InDb.getValue().toUTF8String());
assertEquals("total value,dataAccount", val2InDb.getValue().toUTF8String());
} }


/** /**


+ 2
- 2
source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestDataAccount.java View File

@@ -196,8 +196,8 @@ public class IntegrationTestDataAccount {
JsonTest jsonTest = new JsonTest("Jack"); JsonTest jsonTest = new JsonTest("Jack");
// //
// //add kv ops for data account: Bytes, string, long, json string // //add kv ops for data account: Bytes, string, long, json string
DataAccountKVSetOperation dataKvsetOP = txTpl.dataAccount(dataAddr).set("A", "Value_A_0".getBytes(), -1)
.set("B", "Value_B_0", -1).set("C", currentTime, -1).set("D", JSON.toJSONString(jsonTest), -1)
DataAccountKVSetOperation dataKvsetOP = txTpl.dataAccount(dataAddr).setText("A", "Value_A_0", -1)
.setText("B", "Value_B_0", -1).setInt64("C", currentTime, -1).setText("D", JSON.toJSONString(jsonTest), -1)
.getOperation(); .getOperation();


// 签名; // 签名;


+ 319
- 317
source/tools/tools-capability/src/main/java/com/jd/blockchain/capability/service/RemoteTransactionService.java View File

@@ -42,321 +42,323 @@ import com.jd.blockchain.utils.io.BytesUtils;


public class RemoteTransactionService { public class RemoteTransactionService {


private MsgQueueProducer txProducer;

private final ExecutorService instanceFactory = Executors.newSingleThreadExecutor();

private final ArrayBlockingQueue<List<byte[]>> txBlockingQueue = new ArrayBlockingQueue(1);

private final LinkedList<Bytes> dataAccountAddress = new LinkedList<>();

private Bytes defaultDataAccount;

private static final AtomicLong keyPrefix = new AtomicLong();

public void userRegister(int count) throws Exception {
initTxProducer();
int loop = 0;
if (count <= 0) {
userCreate();
} else {
loop = count / CapabilitySettings.TX_SIZE_PER_SEND;
userCreate(loop);
}
// 从队列中获取数据
if (count <= 0) {
for (;;) {
txRequestSend();
}
} else {
for (int i = 0; i < loop; i++) {
txRequestSend();
}
}
closeTxProducer();
}

public void dataAccountRegister(int count) throws Exception {
initTxProducer();
int loop = 0;
if (count <= 0) {
dataAccountCreate();
} else {
loop = count / CapabilitySettings.TX_SIZE_PER_SEND;
dataAccountCreate(loop);
}
// 从队列中获取数据
if (count <= 0) {
for (;;) {
txRequestSend();
}
} else {
for (int i = 0; i < loop; i++) {
txRequestSend();
}
}
closeTxProducer();
}

public void userAndDataAccountRegister(int userCount, int dataAccountCount) throws Exception {
if (userCount <= 0 || dataAccountCount <= 0) {
throw new IllegalArgumentException("userCount and dataAccountCount can not be 0!!!");
}
initTxProducer();
int userLoop = userCount / CapabilitySettings.TX_SIZE_PER_SEND;
int dataAccountLoop = dataAccountCount / CapabilitySettings.TX_SIZE_PER_SEND;
userCreate(userLoop);
dataAccountCreate(dataAccountLoop);
for (int i = 0, totalLoop = userLoop + dataAccountCount; i < totalLoop; i++) {
txRequestSend();
}
closeTxProducer();
}

public void dataAccountRegisterAndKvStorage(int dataAccountCount, int kvCount) throws Exception {
if (kvCount <= 0 || dataAccountCount <= 0) {
throw new IllegalArgumentException("userCount and dataAccountCount can not be 0!!!");
}
initTxProducer();
int dataAccountLoop = dataAccountCount / CapabilitySettings.TX_SIZE_PER_SEND;
dataAccountCreate(dataAccountLoop);
// 首先将数据账户写入
for (int i = 0; i < dataAccountLoop; i++) {
txRequestSend();
}
int kvLoop = kvCount / CapabilitySettings.TX_SIZE_PER_SEND;
// 然后将每个数据账户都写入指定数量的kv
Iterator<Bytes> iterator = dataAccountAddress.iterator();
while(iterator.hasNext()){
Bytes address = iterator.next();
kvStorageCreate(kvCount, address);
}
for (int i = 0, loop = kvLoop * dataAccountCount; i < loop; i++) {
txRequestSend();
}

closeTxProducer();
}

public void kvStorage(int kvCount) throws Exception {
initTxProducer();

dataAccountDefaultCreate();
try {
txRequestSend();
// 确认结块成功
Thread.sleep(10000);
} catch (Exception e) {
throw e;
}
int kvLoop = kvCount / CapabilitySettings.TX_SIZE_PER_SEND;
// 然后将每个数据账户都写入指定数量的kv
Bytes address = defaultDataAccount;
kvStorageCreate(kvLoop, address);
for (int i = 0; i < kvLoop; i++) {
txRequestSend();
}

closeTxProducer();
}



private void txRequestSend() throws Exception {
List<byte[]> txRequests = txBlockingQueue.take();
if (txRequests != null && !txRequests.isEmpty()) {
Iterator<byte[]> iterator = txRequests.iterator();
while(iterator.hasNext()){
byte[] txRequest = iterator.next();
try {
txProducer.publish(txRequest);
} catch (Exception e) {
e.printStackTrace();
}
}
ConsoleUtils.info("[*] Transaction Request send success!!!");
}
}

private void initTxProducer() throws Exception {
txProducer = MsgQueueFactory.newProducer(CapabilitySettings.MSG_QUEUE_URL, CapabilitySettings.TX_TOPIC);
txProducer.connect();
ConsoleUtils.info("[*] Transaction Producer start success!!!");
}

private void closeTxProducer() throws Exception{
txProducer.close();
}

private void userCreate(int loop) {
instanceFactory.execute(() -> {
for (int index = 0; index < loop; index++) {
// 每次生产10000个,然后放入队列中
try {
LinkedList<byte[]> txSerializeBytes = userActiveCreate();
txBlockingQueue.put(txSerializeBytes);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
}

private void userCreate() {
// 一直在生产用户
instanceFactory.execute(() -> {
for (;;) {
// 每次生产10000个,然后放入队列中
try {
LinkedList<byte[]> txSerializeBytes = userActiveCreate();
txBlockingQueue.put(txSerializeBytes);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
}


private void dataAccountCreate(int loop) {
dataAccountCreate(loop, false);
}

private void dataAccountCreate(int loop, final boolean isSave) {
instanceFactory.execute(() -> {
for (int index = 0; index < loop; index++) {
// 每次生产10000个,然后放入队列中
try {
LinkedList<byte[]> txSerializeBytes = dataAccountActiveCreate(isSave);
txBlockingQueue.put(txSerializeBytes);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
}

private void dataAccountDefaultCreate() {
instanceFactory.execute(() -> {
List<byte[]> currentBytes = new ArrayList<>();
TransactionRequest txRequest = dataAccountRegisterRequest(CapabilitySettings.ledgerHash, CapabilitySettings.adminKey);
byte[] serializeBytes = BinaryProtocol.encode(txRequest, TransactionRequest.class);
currentBytes.add(serializeBytes);
try {
txBlockingQueue.put(currentBytes);
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}

private void dataAccountCreate() {
// 一直在生产用户
instanceFactory.execute(() -> {
for (;;) {
// 每次生产10000个,然后放入队列中
try {
LinkedList<byte[]> txSerializeBytes = dataAccountActiveCreate();
txBlockingQueue.put(txSerializeBytes);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
}

private void kvStorageCreate(int loop, Bytes address) {
// 一直在生产用户
instanceFactory.execute(() -> {
for (int index = 0; index < loop; index++) {
// 每次生产10000个,然后放入队列中
try {
LinkedList<byte[]> txSerializeBytes = kvActiveCreate(address);
txBlockingQueue.put(txSerializeBytes);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
}

private LinkedList<byte[]> userActiveCreate() {
// 每次生产10000个,然后放入队列中
LinkedList<byte[]> txSerializeBytes = new LinkedList<>();
for (int i = 0; i < CapabilitySettings.TX_SIZE_PER_SEND; i++) {
TransactionRequest txRequest = userRegisterRequest(CapabilitySettings.ledgerHash, CapabilitySettings.adminKey);
byte[] serializeBytes = BinaryProtocol.encode(txRequest, TransactionRequest.class);
txSerializeBytes.addFirst(serializeBytes);
}
return txSerializeBytes;
}

private LinkedList<byte[]> dataAccountActiveCreate() {
return dataAccountActiveCreate(false);
}

private LinkedList<byte[]> dataAccountActiveCreate(boolean isSave) {
// 每次生产10000个,然后放入队列中
LinkedList<byte[]> txSerializeBytes = new LinkedList<>();
for (int i = 0; i < CapabilitySettings.TX_SIZE_PER_SEND; i++) {
TransactionRequest txRequest = dataAccountRegisterRequest(CapabilitySettings.ledgerHash, CapabilitySettings.adminKey, isSave);
byte[] serializeBytes = BinaryProtocol.encode(txRequest, TransactionRequest.class);
txSerializeBytes.addFirst(serializeBytes);
}
return txSerializeBytes;
}

private LinkedList<byte[]> kvActiveCreate(Bytes address) {
// 每次生产10000个,然后放入队列中
LinkedList<byte[]> txSerializeBytes = new LinkedList<>();
for (int i = 0; i < CapabilitySettings.TX_SIZE_PER_SEND; i++) {
TransactionRequest txRequest = kvStorageRequest(address, CapabilitySettings.ledgerHash, CapabilitySettings.adminKey);
byte[] serializeBytes = BinaryProtocol.encode(txRequest, TransactionRequest.class);
txSerializeBytes.addFirst(serializeBytes);
}
return txSerializeBytes;
}

private TransactionRequest userRegisterRequest(HashDigest ledgerHash, AsymmetricKeypair adminKey) {
TxBuilder txbuilder = new TxBuilder(ledgerHash);
BlockchainKeypair userKey = BlockchainKeyGenerator.getInstance().generate();
txbuilder.users().register(userKey.getIdentity());
TransactionRequestBuilder reqBuilder = txbuilder.prepareRequest();
reqBuilder.signAsEndpoint(adminKey);
return reqBuilder.buildRequest();
}

private TransactionRequest dataAccountRegisterRequest(HashDigest ledgerHash, AsymmetricKeypair adminKey, boolean isSave) {
TxBuilder txbuilder = new TxBuilder(ledgerHash);
BlockchainKeypair dataAccountKey = BlockchainKeyGenerator.getInstance().generate();
BlockchainIdentity identity = dataAccountKey.getIdentity();
txbuilder.dataAccounts().register(identity);
TransactionRequestBuilder reqBuilder = txbuilder.prepareRequest();
reqBuilder.signAsEndpoint(adminKey);
if (isSave) {
dataAccountAddress.addFirst(identity.getAddress());
}
return reqBuilder.buildRequest();
}

private TransactionRequest dataAccountRegisterRequest(HashDigest ledgerHash, AsymmetricKeypair adminKey) {
TxBuilder txbuilder = new TxBuilder(ledgerHash);
BlockchainKeypair dataAccountKey = BlockchainKeyGenerator.getInstance().generate();
BlockchainIdentity identity = dataAccountKey.getIdentity();
txbuilder.dataAccounts().register(identity);
TransactionRequestBuilder reqBuilder = txbuilder.prepareRequest();
reqBuilder.signAsEndpoint(adminKey);
defaultDataAccount = identity.getAddress();
return reqBuilder.buildRequest();
}

private TransactionRequest kvStorageRequest(Bytes address, HashDigest ledgerHash, AsymmetricKeypair adminKey) {
TxBuilder txbuilder = new TxBuilder(ledgerHash);
long currValue = keyPrefix.getAndIncrement();
txbuilder.dataAccount(address).set("key-" + currValue + "-" + System.currentTimeMillis(),
BytesUtils.toBytes("value-" + currValue), -1L);
TransactionRequestBuilder reqBuilder = txbuilder.prepareRequest();
reqBuilder.signAsEndpoint(adminKey);
return reqBuilder.buildRequest();
}
private MsgQueueProducer txProducer;

private final ExecutorService instanceFactory = Executors.newSingleThreadExecutor();

private final ArrayBlockingQueue<List<byte[]>> txBlockingQueue = new ArrayBlockingQueue(1);

private final LinkedList<Bytes> dataAccountAddress = new LinkedList<>();

private Bytes defaultDataAccount;

private static final AtomicLong keyPrefix = new AtomicLong();

public void userRegister(int count) throws Exception {
initTxProducer();
int loop = 0;
if (count <= 0) {
userCreate();
} else {
loop = count / CapabilitySettings.TX_SIZE_PER_SEND;
userCreate(loop);
}
// 从队列中获取数据
if (count <= 0) {
for (;;) {
txRequestSend();
}
} else {
for (int i = 0; i < loop; i++) {
txRequestSend();
}
}
closeTxProducer();
}

public void dataAccountRegister(int count) throws Exception {
initTxProducer();
int loop = 0;
if (count <= 0) {
dataAccountCreate();
} else {
loop = count / CapabilitySettings.TX_SIZE_PER_SEND;
dataAccountCreate(loop);
}
// 从队列中获取数据
if (count <= 0) {
for (;;) {
txRequestSend();
}
} else {
for (int i = 0; i < loop; i++) {
txRequestSend();
}
}
closeTxProducer();
}

public void userAndDataAccountRegister(int userCount, int dataAccountCount) throws Exception {
if (userCount <= 0 || dataAccountCount <= 0) {
throw new IllegalArgumentException("userCount and dataAccountCount can not be 0!!!");
}
initTxProducer();
int userLoop = userCount / CapabilitySettings.TX_SIZE_PER_SEND;
int dataAccountLoop = dataAccountCount / CapabilitySettings.TX_SIZE_PER_SEND;
userCreate(userLoop);
dataAccountCreate(dataAccountLoop);
for (int i = 0, totalLoop = userLoop + dataAccountCount; i < totalLoop; i++) {
txRequestSend();
}
closeTxProducer();
}

public void dataAccountRegisterAndKvStorage(int dataAccountCount, int kvCount) throws Exception {
if (kvCount <= 0 || dataAccountCount <= 0) {
throw new IllegalArgumentException("userCount and dataAccountCount can not be 0!!!");
}
initTxProducer();
int dataAccountLoop = dataAccountCount / CapabilitySettings.TX_SIZE_PER_SEND;
dataAccountCreate(dataAccountLoop);
// 首先将数据账户写入
for (int i = 0; i < dataAccountLoop; i++) {
txRequestSend();
}
int kvLoop = kvCount / CapabilitySettings.TX_SIZE_PER_SEND;
// 然后将每个数据账户都写入指定数量的kv
Iterator<Bytes> iterator = dataAccountAddress.iterator();
while (iterator.hasNext()) {
Bytes address = iterator.next();
kvStorageCreate(kvCount, address);
}
for (int i = 0, loop = kvLoop * dataAccountCount; i < loop; i++) {
txRequestSend();
}

closeTxProducer();
}

public void kvStorage(int kvCount) throws Exception {
initTxProducer();

dataAccountDefaultCreate();
try {
txRequestSend();
// 确认结块成功
Thread.sleep(10000);
} catch (Exception e) {
throw e;
}
int kvLoop = kvCount / CapabilitySettings.TX_SIZE_PER_SEND;
// 然后将每个数据账户都写入指定数量的kv
Bytes address = defaultDataAccount;
kvStorageCreate(kvLoop, address);
for (int i = 0; i < kvLoop; i++) {
txRequestSend();
}

closeTxProducer();
}

private void txRequestSend() throws Exception {
List<byte[]> txRequests = txBlockingQueue.take();
if (txRequests != null && !txRequests.isEmpty()) {
Iterator<byte[]> iterator = txRequests.iterator();
while (iterator.hasNext()) {
byte[] txRequest = iterator.next();
try {
txProducer.publish(txRequest);
} catch (Exception e) {
e.printStackTrace();
}
}
ConsoleUtils.info("[*] Transaction Request send success!!!");
}
}

private void initTxProducer() throws Exception {
txProducer = MsgQueueFactory.newProducer(CapabilitySettings.MSG_QUEUE_URL, CapabilitySettings.TX_TOPIC);
txProducer.connect();
ConsoleUtils.info("[*] Transaction Producer start success!!!");
}

private void closeTxProducer() throws Exception {
txProducer.close();
}

private void userCreate(int loop) {
instanceFactory.execute(() -> {
for (int index = 0; index < loop; index++) {
// 每次生产10000个,然后放入队列中
try {
LinkedList<byte[]> txSerializeBytes = userActiveCreate();
txBlockingQueue.put(txSerializeBytes);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
}

private void userCreate() {
// 一直在生产用户
instanceFactory.execute(() -> {
for (;;) {
// 每次生产10000个,然后放入队列中
try {
LinkedList<byte[]> txSerializeBytes = userActiveCreate();
txBlockingQueue.put(txSerializeBytes);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
}

private void dataAccountCreate(int loop) {
dataAccountCreate(loop, false);
}

private void dataAccountCreate(int loop, final boolean isSave) {
instanceFactory.execute(() -> {
for (int index = 0; index < loop; index++) {
// 每次生产10000个,然后放入队列中
try {
LinkedList<byte[]> txSerializeBytes = dataAccountActiveCreate(isSave);
txBlockingQueue.put(txSerializeBytes);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
}

private void dataAccountDefaultCreate() {
instanceFactory.execute(() -> {
List<byte[]> currentBytes = new ArrayList<>();
TransactionRequest txRequest = dataAccountRegisterRequest(CapabilitySettings.ledgerHash,
CapabilitySettings.adminKey);
byte[] serializeBytes = BinaryProtocol.encode(txRequest, TransactionRequest.class);
currentBytes.add(serializeBytes);
try {
txBlockingQueue.put(currentBytes);
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}

private void dataAccountCreate() {
// 一直在生产用户
instanceFactory.execute(() -> {
for (;;) {
// 每次生产10000个,然后放入队列中
try {
LinkedList<byte[]> txSerializeBytes = dataAccountActiveCreate();
txBlockingQueue.put(txSerializeBytes);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
}

private void kvStorageCreate(int loop, Bytes address) {
// 一直在生产用户
instanceFactory.execute(() -> {
for (int index = 0; index < loop; index++) {
// 每次生产10000个,然后放入队列中
try {
LinkedList<byte[]> txSerializeBytes = kvActiveCreate(address);
txBlockingQueue.put(txSerializeBytes);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
}

private LinkedList<byte[]> userActiveCreate() {
// 每次生产10000个,然后放入队列中
LinkedList<byte[]> txSerializeBytes = new LinkedList<>();
for (int i = 0; i < CapabilitySettings.TX_SIZE_PER_SEND; i++) {
TransactionRequest txRequest = userRegisterRequest(CapabilitySettings.ledgerHash,
CapabilitySettings.adminKey);
byte[] serializeBytes = BinaryProtocol.encode(txRequest, TransactionRequest.class);
txSerializeBytes.addFirst(serializeBytes);
}
return txSerializeBytes;
}

private LinkedList<byte[]> dataAccountActiveCreate() {
return dataAccountActiveCreate(false);
}

private LinkedList<byte[]> dataAccountActiveCreate(boolean isSave) {
// 每次生产10000个,然后放入队列中
LinkedList<byte[]> txSerializeBytes = new LinkedList<>();
for (int i = 0; i < CapabilitySettings.TX_SIZE_PER_SEND; i++) {
TransactionRequest txRequest = dataAccountRegisterRequest(CapabilitySettings.ledgerHash,
CapabilitySettings.adminKey, isSave);
byte[] serializeBytes = BinaryProtocol.encode(txRequest, TransactionRequest.class);
txSerializeBytes.addFirst(serializeBytes);
}
return txSerializeBytes;
}

private LinkedList<byte[]> kvActiveCreate(Bytes address) {
// 每次生产10000个,然后放入队列中
LinkedList<byte[]> txSerializeBytes = new LinkedList<>();
for (int i = 0; i < CapabilitySettings.TX_SIZE_PER_SEND; i++) {
TransactionRequest txRequest = kvStorageRequest(address, CapabilitySettings.ledgerHash,
CapabilitySettings.adminKey);
byte[] serializeBytes = BinaryProtocol.encode(txRequest, TransactionRequest.class);
txSerializeBytes.addFirst(serializeBytes);
}
return txSerializeBytes;
}

private TransactionRequest userRegisterRequest(HashDigest ledgerHash, AsymmetricKeypair adminKey) {
TxBuilder txbuilder = new TxBuilder(ledgerHash);
BlockchainKeypair userKey = BlockchainKeyGenerator.getInstance().generate();
txbuilder.users().register(userKey.getIdentity());
TransactionRequestBuilder reqBuilder = txbuilder.prepareRequest();
reqBuilder.signAsEndpoint(adminKey);
return reqBuilder.buildRequest();
}

private TransactionRequest dataAccountRegisterRequest(HashDigest ledgerHash, AsymmetricKeypair adminKey,
boolean isSave) {
TxBuilder txbuilder = new TxBuilder(ledgerHash);
BlockchainKeypair dataAccountKey = BlockchainKeyGenerator.getInstance().generate();
BlockchainIdentity identity = dataAccountKey.getIdentity();
txbuilder.dataAccounts().register(identity);
TransactionRequestBuilder reqBuilder = txbuilder.prepareRequest();
reqBuilder.signAsEndpoint(adminKey);
if (isSave) {
dataAccountAddress.addFirst(identity.getAddress());
}
return reqBuilder.buildRequest();
}

private TransactionRequest dataAccountRegisterRequest(HashDigest ledgerHash, AsymmetricKeypair adminKey) {
TxBuilder txbuilder = new TxBuilder(ledgerHash);
BlockchainKeypair dataAccountKey = BlockchainKeyGenerator.getInstance().generate();
BlockchainIdentity identity = dataAccountKey.getIdentity();
txbuilder.dataAccounts().register(identity);
TransactionRequestBuilder reqBuilder = txbuilder.prepareRequest();
reqBuilder.signAsEndpoint(adminKey);
defaultDataAccount = identity.getAddress();
return reqBuilder.buildRequest();
}

private TransactionRequest kvStorageRequest(Bytes address, HashDigest ledgerHash, AsymmetricKeypair adminKey) {
TxBuilder txbuilder = new TxBuilder(ledgerHash);
long currValue = keyPrefix.getAndIncrement();
txbuilder.dataAccount(address).setText("key-" + currValue + "-" + System.currentTimeMillis(),
"value-" + currValue, -1L);
TransactionRequestBuilder reqBuilder = txbuilder.prepareRequest();
reqBuilder.signAsEndpoint(adminKey);
return reqBuilder.buildRequest();
}
} }

+ 1
- 1
source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitException.java View File

@@ -1,6 +1,6 @@
package com.jd.blockchain.tools.initializer; package com.jd.blockchain.tools.initializer;


import com.jd.blockchain.ledger.core.LedgerException;
import com.jd.blockchain.ledger.LedgerException;


public class LedgerInitException extends LedgerException{ public class LedgerInitException extends LedgerException{


+ 4
- 0
source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Bytes.java View File

@@ -235,6 +235,10 @@ public class Bytes implements BytesSerializable {
} }
return new Bytes(BytesUtils.toBytes(value)); return new Bytes(BytesUtils.toBytes(value));
} }
public String toUTF8String() {
return BytesUtils.toString(toBytes());
}


public static Bytes fromLong(long value) { public static Bytes fromLong(long value) {
if (value > -1 && value < MAX_CACHE) { if (value > -1 && value < MAX_CACHE) {


+ 68
- 91
source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesUtils.java View File

@@ -1,6 +1,11 @@
package com.jd.blockchain.utils.io; package com.jd.blockchain.utils.io;
import java.io.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import com.jd.blockchain.utils.IllegalDataException; import com.jd.blockchain.utils.IllegalDataException;
@@ -19,6 +24,10 @@ public class BytesUtils {
public static final int MAX_BUFFER_SIZE = 1024 * 1024 * 1024; public static final int MAX_BUFFER_SIZE = 1024 * 1024 * 1024;
public static final int BUFFER_SIZE = 64; public static final int BUFFER_SIZE = 64;
public static final byte TRUE_BYTE = 1;
public static final byte FALSE_BYTE = 0;
private BytesUtils() { private BytesUtils() {
} }
@@ -28,10 +37,8 @@ public class BytesUtils {
* *
* 此方法不处理两者其中之一为 null 的情形,因为无法定义相等性,所以将引发 {@link NullPointerException} 异常; * 此方法不处理两者其中之一为 null 的情形,因为无法定义相等性,所以将引发 {@link NullPointerException} 异常;
* *
* @param bytes1
* bytes1
* @param bytes2
* bytes2
* @param bytes1 bytes1
* @param bytes2 bytes2
* @return boolean * @return boolean
*/ */
public static boolean equals(byte[] bytes1, byte[] bytes2) { public static boolean equals(byte[] bytes1, byte[] bytes2) {
@@ -64,8 +71,7 @@ public class BytesUtils {
* 将输入流的所有内容都读入到字节数组返回; 如果输入流的长度超出 MAX_BUFFER_SIZE 定义的值,则抛出 * 将输入流的所有内容都读入到字节数组返回; 如果输入流的长度超出 MAX_BUFFER_SIZE 定义的值,则抛出
* IllegalArgumentException ; * IllegalArgumentException ;
* *
* @param in
* in
* @param in in
* @return byte[] * @return byte[]
*/ */
public static byte[] copyToBytes(InputStream in) { public static byte[] copyToBytes(InputStream in) {
@@ -95,15 +101,11 @@ public class BytesUtils {
/** /**
* 将输入流复制到输出流; * 将输入流复制到输出流;
* *
* @param in
* 输入流;
* @param out
* 输出流;
* @param maxSize
* 最大字节大小;
* @param in 输入流;
* @param out 输出流;
* @param maxSize 最大字节大小;
* @return 返回实际复制的字节数; * @return 返回实际复制的字节数;
* @throws IOException
* exception
* @throws IOException exception
*/ */
public static int copy(InputStream in, OutputStream out, int maxSize) throws IOException { public static int copy(InputStream in, OutputStream out, int maxSize) throws IOException {
byte[] buffer = new byte[BUFFER_SIZE]; byte[] buffer = new byte[BUFFER_SIZE];
@@ -126,8 +128,7 @@ public class BytesUtils {
/** /**
* 将 int 值转为4字节的二进制数组; * 将 int 值转为4字节的二进制数组;
* *
* @param value
* value
* @param value value
* @return 转换后的二进制数组,高位在前,低位在后; * @return 转换后的二进制数组,高位在前,低位在后;
*/ */
public static byte[] toBytes(int value) { public static byte[] toBytes(int value) {
@@ -142,11 +143,14 @@ public class BytesUtils {
return bytes; return bytes;
} }
public static byte[] toBytes(boolean value) {
return new byte[] { value ? TRUE_BYTE : FALSE_BYTE };
}
/** /**
* 将 long 值转为8字节的二进制数组; * 将 long 值转为8字节的二进制数组;
* *
* @param value
* value
* @param value value
* @return 转换后的二进制数组,高位在前,低位在后; * @return 转换后的二进制数组,高位在前,低位在后;
*/ */
public static byte[] toBytes(long value) { public static byte[] toBytes(long value) {
@@ -158,10 +162,8 @@ public class BytesUtils {
/** /**
* 将 int 值转为4字节的二进制数组; * 将 int 值转为4字节的二进制数组;
* *
* @param value
* 要转换的int整数;
* @param bytes
* 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 0 开始的4个元素;
* @param value 要转换的int整数;
* @param bytes 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 0 开始的4个元素;
*/ */
public static void toBytes(short value, byte[] bytes) { public static void toBytes(short value, byte[] bytes) {
toBytes(value, bytes, 0); toBytes(value, bytes, 0);
@@ -176,12 +178,9 @@ public class BytesUtils {
* <p> * <p>
* 以“高位在前”的方式转换,即:数值的高位保存在数组地址的低位; * 以“高位在前”的方式转换,即:数值的高位保存在数组地址的低位;
* *
* @param value
* 要转换的int整数;
* @param bytes
* 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 offset 指定位置开始的4个元素;
* @param offset
* 写入转换结果的起始位置;
* @param value 要转换的int整数;
* @param bytes 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 offset 指定位置开始的4个元素;
* @param offset 写入转换结果的起始位置;
* @return 返回写入的长度; * @return 返回写入的长度;
*/ */
public static int toBytes(int value, byte[] bytes, int offset) { public static int toBytes(int value, byte[] bytes, int offset) {
@@ -197,12 +196,9 @@ public class BytesUtils {
* <p> * <p>
* 以“高位在后”的方式转换,即:数值的高位保存在数组地址的高位; * 以“高位在后”的方式转换,即:数值的高位保存在数组地址的高位;
* *
* @param value
* 要转换的int整数;
* @param bytes
* 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 offset 指定位置开始的4个元素;
* @param offset
* 写入转换结果的起始位置;
* @param value 要转换的int整数;
* @param bytes 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 offset 指定位置开始的4个元素;
* @param offset 写入转换结果的起始位置;
* @return 返回写入的长度; * @return 返回写入的长度;
*/ */
public static int toBytesInReverse(int value, byte[] bytes, int offset) { public static int toBytesInReverse(int value, byte[] bytes, int offset) {
@@ -218,14 +214,10 @@ public class BytesUtils {
* <p> * <p>
* 以“高位在后”的方式转换,即:数值的高位保存在数组地址的高位; * 以“高位在后”的方式转换,即:数值的高位保存在数组地址的高位;
* *
* @param value
* 要转换的int整数;
* @param bytes
* 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 offset 指定位置开始的4个元素;
* @param offset
* 写入转换结果的起始位置;
* @param len
* 写入长度;必须大于 0 ,小于等于 4;
* @param value 要转换的int整数;
* @param bytes 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 offset 指定位置开始的4个元素;
* @param offset 写入转换结果的起始位置;
* @param len 写入长度;必须大于 0 ,小于等于 4;
* @return 返回写入的长度; * @return 返回写入的长度;
*/ */
public static int toBytesInReverse(int value, byte[] bytes, int offset, int len) { public static int toBytesInReverse(int value, byte[] bytes, int offset, int len) {
@@ -263,12 +255,9 @@ public class BytesUtils {
/** /**
* 将 long 值转为8字节的二进制数组; * 将 long 值转为8字节的二进制数组;
* *
* @param value
* 要转换的long整数;
* @param bytes
* 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 offset 指定位置开始的8个元素;
* @param offset
* 写入转换结果的起始位置;
* @param value 要转换的long整数;
* @param bytes 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 offset 指定位置开始的8个元素;
* @param offset 写入转换结果的起始位置;
* @return 返回写入的长度; * @return 返回写入的长度;
*/ */
public static int toBytes(long value, byte[] bytes, int offset) { public static int toBytes(long value, byte[] bytes, int offset) {
@@ -312,6 +301,10 @@ public class BytesUtils {
} }
} }
/**
* @param bytes
* @return
*/
public static String toString(byte[] bytes) { public static String toString(byte[] bytes) {
return toString(bytes, DEFAULT_CHARSET); return toString(bytes, DEFAULT_CHARSET);
} }
@@ -342,11 +335,14 @@ public class BytesUtils {
} }
} }
public static boolean toBoolean(byte value) {
return value != FALSE_BYTE;
}
/** /**
* 按从高位到低位的顺序将指定二进制数组从位置 0 开始的 4 个字节转换为 int 整数; * 按从高位到低位的顺序将指定二进制数组从位置 0 开始的 4 个字节转换为 int 整数;
* *
* @param bytes
* 要转换的二进制数组;
* @param bytes 要转换的二进制数组;
* @return 转换后的 int 整数; * @return 转换后的 int 整数;
*/ */
public static int toInt(byte[] bytes) { public static int toInt(byte[] bytes) {
@@ -362,10 +358,8 @@ public class BytesUtils {
/** /**
* 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 2 个字节转换为 short 整数; * 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 2 个字节转换为 short 整数;
* *
* @param bytes
* 要转换的二进制数组;
* @param offset
* 要读取数据的开始位置
* @param bytes 要转换的二进制数组;
* @param offset 要读取数据的开始位置
* @return 转换后的 short 整数; * @return 转换后的 short 整数;
*/ */
public static short toShort(byte[] bytes, int offset) { public static short toShort(byte[] bytes, int offset) {
@@ -387,10 +381,8 @@ public class BytesUtils {
/** /**
* 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 4 个字节转换为 int 整数; * 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 4 个字节转换为 int 整数;
* *
* @param bytes
* 要转换的二进制数组;
* @param offset
* 要读取数据的开始位置
* @param bytes 要转换的二进制数组;
* @param offset 要读取数据的开始位置
* @return 转换后的 int 整数; * @return 转换后的 int 整数;
*/ */
public static int toInt(byte[] bytes, int offset) { public static int toInt(byte[] bytes, int offset) {
@@ -407,14 +399,11 @@ public class BytesUtils {
/** /**
* 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 4 个字节转换为 int 整数; * 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 4 个字节转换为 int 整数;
* *
* @param bytes
* 要转换的二进制数组;
* @param offset
* 要读取数据的开始位置
* @param bytes 要转换的二进制数组;
* @param offset 要读取数据的开始位置
* @return 转换后的 int 整数; * @return 转换后的 int 整数;
* *
* @param len
* 长度;len 必须满足: len 大于等于 1 且小于等于4;
* @param len 长度;len 必须满足: len 大于等于 1 且小于等于4;
* @return 转换后的 int 整数; * @return 转换后的 int 整数;
*/ */
public static int toInt(byte[] bytes, int offset, int len) { public static int toInt(byte[] bytes, int offset, int len) {
@@ -433,18 +422,14 @@ public class BytesUtils {
/** /**
* 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 4 个字节转换为 int 整数; * 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 4 个字节转换为 int 整数;
* *
* @param bytes
* 要转换的二进制数组;
* @param offset
* 要读取数据的开始位置
* @param bytes 要转换的二进制数组;
* @param offset 要读取数据的开始位置
* @return 转换后的 int 整数; * @return 转换后的 int 整数;
* *
* @param len
* 长度;len 必须满足: len 大于等于 1 且小于等于4;
* @param highAlign
* 是否高位对齐;<br>
* true 表示参数 bytes 的首个字节对应为整数的最高8位;<br>
* false 表示参数 bytes 的最后字节对应为整数的最低8位;
* @param len 长度;len 必须满足: len 大于等于 1 且小于等于4;
* @param highAlign 是否高位对齐;<br>
* true 表示参数 bytes 的首个字节对应为整数的最高8位;<br>
* false 表示参数 bytes 的最后字节对应为整数的最低8位;
* @return 转换后的 int 整数; * @return 转换后的 int 整数;
*/ */
public static int toInt(byte[] bytes, int offset, int len, boolean highAlign) { public static int toInt(byte[] bytes, int offset, int len, boolean highAlign) {
@@ -472,10 +457,8 @@ public class BytesUtils {
/** /**
* 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 8个字节转换为 long 整数; * 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 8个字节转换为 long 整数;
* *
* @param bytes
* 要转换的二进制数组;
* @param offset
* 要读取数据的开始位置
* @param bytes 要转换的二进制数组;
* @param offset 要读取数据的开始位置
* @return 转换后的 long 整数; * @return 转换后的 long 整数;
*/ */
public static long toLong(byte[] bytes, int offset) { public static long toLong(byte[] bytes, int offset) {
@@ -495,8 +478,7 @@ public class BytesUtils {
/** /**
* 从指定的输入流中读入2个字节,由前到后按由高位到低位的方式转为 short 整数; * 从指定的输入流中读入2个字节,由前到后按由高位到低位的方式转为 short 整数;
* *
* @param in
* in
* @param in in
* @return short * @return short
*/ */
public static short readShort(InputStream in) { public static short readShort(InputStream in) {
@@ -531,8 +513,7 @@ public class BytesUtils {
/** /**
* 从指定的输入流中读入4个字节,由前到后按由高位到低位的方式转为 int 整数; * 从指定的输入流中读入4个字节,由前到后按由高位到低位的方式转为 int 整数;
* *
* @param in
* in
* @param in in
* @return int * @return int
*/ */
public static int readInt(InputStream in) { public static int readInt(InputStream in) {
@@ -658,11 +639,9 @@ public class BytesUtils {
/** /**
* 从字节数组获取对象 * 从字节数组获取对象
* *
* @param objBytes
* objBytes
* @param objBytes objBytes
* @return object * @return object
* @throws Exception
* exception
* @throws Exception exception
*/ */
// public static Object getObjectFromBytes(byte[] objBytes) throws Exception { // public static Object getObjectFromBytes(byte[] objBytes) throws Exception {
// if (objBytes == null || objBytes.length == 0) { // if (objBytes == null || objBytes.length == 0) {
@@ -676,11 +655,9 @@ public class BytesUtils {
/** /**
* 从对象获取一个字节数组; * 从对象获取一个字节数组;
* *
* @param obj
* obj
* @param obj obj
* @return byte array * @return byte array
* @throws Exception
* exception
* @throws Exception exception
*/ */
public static byte[] getBytesFromObject(Object obj) throws Exception { public static byte[] getBytesFromObject(Object obj) throws Exception {
if (obj == null) { if (obj == null) {


Loading…
Cancel
Save