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)),
/**
* 日期时间;
* 时间
*/
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;

import com.jd.blockchain.ledger.BytesValue;
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.ContractEngine;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.runtime.Module;
import com.jd.blockchain.runtime.RuntimeContext;
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
* @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);



+ 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.PubKey;
import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage;
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
*/
public BaseAccount getAccount(Bytes address, long version) {
@@ -226,10 +226,8 @@ public class AccountSet implements Transactional, MerkleProvable {
*
* 如果指定的地址和公钥不匹配,则会引发 {@link LedgerException} 异常;
*
* @param address
* 区块链地址;
* @param pubKey
* 公钥;
* @param address 区块链地址;
* @param pubKey 公钥;
* @return 注册成功的账户对象;
*/
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,
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,
ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, long version) {
AccountHeader accInfo = BinaryProtocol.decode(bytes);
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) {
@@ -388,15 +385,14 @@ public class AccountSet implements Transactional, MerkleProvable {
public VersioningAccount(Bytes address, PubKey pubKey, HashDigest rootHash, CryptoSetting cryptoSetting,
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;
}
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;
}
@@ -426,7 +422,7 @@ public class AccountSet implements Transactional, MerkleProvable {
// }
@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);
if (v > -1) {
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;

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

protected MerkleDataSet dataset;

private AccountAccessPolicy accessPolicy;

/**
* Create a new Account with the specified address and pubkey; <br>
*
@@ -38,8 +38,8 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional
* @param pubKey
*/
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
*/
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 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 exStorage
* @param verStorage
@@ -79,18 +78,15 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional
* @param accessPolicy
*/
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,
readonly, accessPolicy);
readonly);
}

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.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 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>
* If the key is new created success, then return 0; <br>
* If the key is updated success, then return the new version;<br>
* If this operation fail by version checking or other reason, then
* return -1;
*/
public long setBytes(Bytes key, byte[] value, long version) {
// 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
* @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
* @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
@@ -207,10 +208,6 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional

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

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.PubKey;
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.io.BytesUtils;
public class ContractAccount implements AccountHeader {
@@ -42,15 +43,16 @@ public class ContractAccount implements AccountHeader {
}
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() {
return accBase.getBytes(CHAIN_CODE_KEY);
return accBase.getBytes(CHAIN_CODE_KEY).getValue().toBytes();
}
public byte[] getChainCode(long version) {
return accBase.getBytes(CHAIN_CODE_KEY, version);
return accBase.getBytes(CHAIN_CODE_KEY, version).getValue().toBytes();
}
public long getChaincodeVersion() {
@@ -58,15 +60,18 @@ public class ContractAccount implements AccountHeader {
}
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) {
return BytesUtils.toString(accBase.getBytes(encodePropertyKey(key)));
BytesValue bytesValue = accBase.getBytes(encodePropertyKey(key));
return BytesValueEntry.toText(bytesValue);
}
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) {


+ 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.CryptoProvider;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;

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.ledger.AccountHeader;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.BytesValueEntry;
import com.jd.blockchain.ledger.KVDataEntry;
import com.jd.blockchain.ledger.KVDataObject;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.serialize.binary.BinarySerializeUtils;
public class DataAccount implements AccountHeader, MerkleProvable {
@@ -41,10 +41,22 @@ public class DataAccount implements AccountHeader, MerkleProvable {
public MerkleProof getProof(Bytes 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);
}
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
@@ -74,7 +86,7 @@ public class DataAccount implements AccountHeader, MerkleProvable {
* @param key
* @return return null if not exist;
*/
public byte[] getBytes(String key) {
public BytesValue getBytes(String key) {
return baseAccount.getBytes(Bytes.fromString(key));
}
@@ -84,7 +96,7 @@ public class DataAccount implements AccountHeader, MerkleProvable {
* @param key
* @return return null if not exist;
*/
public byte[] getBytes(Bytes key) {
public BytesValue getBytes(Bytes key) {
return baseAccount.getBytes(key);
}
@@ -95,7 +107,7 @@ public class DataAccount implements AccountHeader, MerkleProvable {
* @param version
* @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);
}
@@ -106,7 +118,7 @@ public class DataAccount implements AccountHeader, MerkleProvable {
* @param version
* @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);
}
@@ -119,7 +131,6 @@ public class DataAccount implements AccountHeader, MerkleProvable {
*/
public KVDataEntry[] getDataEntries(int fromIndex, int count) {
if (getDataEntriesTotalCount() == 0 || count == 0) {
return null;
}
@@ -142,7 +153,7 @@ public class DataAccount implements AccountHeader, MerkleProvable {
key = baseAccount.dataset.getKeyAtIndex(fromIndex);
ver = baseAccount.dataset.getVersion(key);
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++;
}
@@ -162,5 +173,4 @@ public class DataAccount implements AccountHeader, MerkleProvable {
}
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.HashDigest;
import com.jd.blockchain.crypto.HashFunction;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.LedgerInitSetting;
import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;


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

import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.LedgerTransaction;
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;

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.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy;
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.HashFunction;
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.ExPolicy;
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.ledger.ParticipantNode;
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.VersioningKVStorage;
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();
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.crypto.HashDigest;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.LedgerTransaction;
import com.jd.blockchain.ledger.TransactionState;
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.PubKey;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.BytesValueEntry;
import com.jd.blockchain.ledger.UserInfo;
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() {
byte[] pkBytes = baseAccount.getBytes(DATA_PUB_KEY);
BytesValue pkBytes = baseAccount.getBytes(DATA_PUB_KEY);
if (pkBytes == null) {
return null;
}
return new PubKey(pkBytes);
return new PubKey(pkBytes.getValue().toBytes());
}
public long setDataPubKey(PubKey pubKey) {
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) {
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) {
@@ -62,15 +63,17 @@ public class UserAccount implements UserInfo {
}
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) {
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) {
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) {


+ 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.ledger.AccountHeader;
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.VersioningKVStorage;
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.stereotype.Component;

import com.jd.blockchain.ledger.LedgerException;
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.impl.handles.ContractCodeDeployOperationHandle;
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.HashDigest;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.LedgerInitSetting;
import com.jd.blockchain.ledger.core.LedgerConsts;
import com.jd.blockchain.ledger.core.LedgerEditor;
import com.jd.blockchain.ledger.core.LedgerException;
import com.jd.blockchain.ledger.core.LedgerManage;
import com.jd.blockchain.ledger.core.LedgerRepository;
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;
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.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.DataAccount;
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.utils.Bytes;
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 {
private LedgerService ledgerService;
public LedgerQueryService(LedgerService ledgerService) {
private LedgerService ledgerService;
public LedgerQueryService(LedgerService ledgerService) {
this.ledgerService = ledgerService;
}
@@ -37,7 +46,7 @@ public class LedgerQueryService implements BlockchainQueryService {
@Override
public LedgerInfo getLedger(HashDigest ledgerHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerInfo ledgerInfo =new LedgerInfo();
LedgerInfo ledgerInfo = new LedgerInfo();
ledgerInfo.setHash(ledger.getHash());
ledgerInfo.setLatestBlockHash(ledger.getLatestBlockHash());
ledgerInfo.setLatestBlockHeight(ledger.getLatestBlockHeight());
@@ -173,8 +182,8 @@ public class LedgerQueryService implements BlockchainQueryService {
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;
//
// if (fromIndex < 0 || fromIndex >= currentHeightTxNums) {
@@ -187,8 +196,8 @@ public class LedgerQueryService implements BlockchainQueryService {
// if (count > currentHeightTxNums) {
// 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
@@ -203,8 +212,8 @@ public class LedgerQueryService implements BlockchainQueryService {
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;
// if (fromIndex < 0 || fromIndex >= currentHeightTxNums) {
@@ -217,8 +226,8 @@ public class LedgerQueryService implements BlockchainQueryService {
// if (count > currentHeightTxNums) {
// 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
@@ -228,7 +237,7 @@ public class LedgerQueryService implements BlockchainQueryService {
TransactionSet txset = ledger.getTransactionSet(block);
return txset.get(contentHash);
}
@Override
public TransactionState getTransactionStateByContentHash(HashDigest ledgerHash, HashDigest contentHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
@@ -243,7 +252,7 @@ public class LedgerQueryService implements BlockchainQueryService {
LedgerBlock block = ledger.getLatestBlock();
UserAccountSet userAccountSet = ledger.getUserAccountSet(block);
return userAccountSet.getUser(address);
}
@Override
@@ -263,33 +272,32 @@ public class LedgerQueryService implements BlockchainQueryService {
LedgerBlock block = ledger.getLatestBlock();
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address));
KVDataEntry[] entries = new KVDataEntry[keys.length];
long ver;
for (int i = 0; i < entries.length; 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) {
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;
}
public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) {
//parse 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()){
if (kvInfoVO != null) {
for (KVDataVO kvDataVO : kvInfoVO.getData()) {
for (Long version : kvDataVO.getVersion()) {
keyList.add(kvDataVO.getKey());
versionList.add(version);
}
@@ -301,12 +309,12 @@ public class LedgerQueryService implements BlockchainQueryService {
if (keys == null || keys.length == 0) {
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);
LedgerBlock block = ledger.getLatestBlock();
@@ -314,22 +322,21 @@ public class LedgerQueryService implements BlockchainQueryService {
DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address));
KVDataEntry[] entries = new KVDataEntry[keys.length];
long ver = -1;
long ver = -1;
for (int i = 0; i < entries.length; i++) {
// ver = dataAccount.getDataVersion(Bytes.fromString(keys[i]));
// dataAccount.getBytes(Bytes.fromString(keys[i]),1);
ver = versions[i];
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 {
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);
LedgerBlock block = ledger.getLatestBlock();
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
int pages[] = QueryUtil.calFromIndexAndCount(fromIndex,count,(int)dataAccountSet.getTotalCount());
return dataAccountSet.getAccounts(pages[0],pages[1]);
int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccountSet.getTotalCount());
return dataAccountSet.getAccounts(pages[0], pages[1]);
}
@Override
@@ -390,8 +397,8 @@ public class LedgerQueryService implements BlockchainQueryService {
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) contractAccountSet.getTotalCount());
return contractAccountSet.getAccounts(pages[0], pages[1]);
}
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.LedgerDataSet;
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.LedgerTransactionContext;
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 {

@Override
public boolean checkCommitting(AccountHeader account) {
public boolean checkDataWriting(AccountHeader account) {
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.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.ledger.TransactionResponse;
import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.ledger.core.LedgerDataSet;
import com.jd.blockchain.ledger.core.LedgerEditor;
import com.jd.blockchain.ledger.core.LedgerException;
import com.jd.blockchain.ledger.core.LedgerService;
import com.jd.blockchain.ledger.core.LedgerTransactionContext;
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.ContractServiceProviders;
import com.jd.blockchain.ledger.ContractEventSendOperation;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.ledger.core.ContractAccount;
import com.jd.blockchain.ledger.core.ContractAccountSet;
import com.jd.blockchain.ledger.core.LedgerDataSet;
import com.jd.blockchain.ledger.core.LedgerException;
import com.jd.blockchain.ledger.core.LedgerService;
import com.jd.blockchain.ledger.core.OperationHandle;
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.List;

import com.alibaba.fastjson.JSON;
import com.jd.blockchain.contract.LedgerContext;
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.transaction.BlockchainQueryService;
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.UserRegisterOperationBuilderImpl;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.io.BytesUtils;

public class ContractLedgerContext implements LedgerContext {

@@ -250,60 +264,95 @@ public class ContractLedgerContext implements LedgerContext {
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
public DataAccountKVSetOperation getOperation() {
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
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);
generatedOpList.add(op);
opHandleContext.handle(op);
handle(op);
return this;
}

@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);
generatedOpList.add(op);
opHandleContext.handle(op);
handle(op);
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
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);
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;
}
@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);
handle(op);
return this;
}
private void handle(Operation op) {
generatedOpList.add(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());
KVWriteEntry[] writeset = kvWriteOp.getWriteSet();
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.ledger.BlockchainKeyGenerator;
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.CryptoConfig;
import com.jd.blockchain.ledger.core.impl.OpeningAccessPolicy;
import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.io.BytesUtils;

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

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

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

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

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

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,预期导致失败;
assertEquals(-1, v);

baseAccount.commit();
v = 0;
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();
// 预期成功;
assertEquals(v + 1, s);
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);



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

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

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

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.sm.SMCryptoService;
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.LedgerInitSetting;
import com.jd.blockchain.ledger.LedgerTransaction;
@@ -37,67 +39,99 @@ import com.jd.blockchain.utils.io.BytesUtils;
import com.jd.blockchain.utils.net.NetworkAddress;

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


static {
DataContractRegistry.register(com.jd.blockchain.ledger.TransactionContent.class);
DataContractRegistry.register(com.jd.blockchain.ledger.UserRegisterOperation.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")
@Test
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());

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();
// 提交数据,写入存储;
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
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());
UserAccount userAccount = ldgDS.getUserAccountSet().register(userKP.getAddress(), userKP.getPubKey());
userAccount.setProperty("Name", "孙悟空", -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(0, tx.getBlockHeight());

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

private LedgerInitSetting createLedgerInitSetting() {
SignatureFunction signFunc = Crypto.getSignatureFunction("ED25519");
CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length];
for (int i = 0; i < SUPPORTED_PROVIDERS.length; 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.setSequenceNumber(1);
DataAccountKVSetOperation kvsetOP = opFactory.dataAccount(id.getAddress())
.set("Name", ByteArray.fromString("AAA", "UTF-8"), -1).getOperation();
.setText("Name", "AAA", -1).getOperation();
contentBlob.addOperation(kvsetOP);
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());

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];
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.PrimitiveType;
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;
@@ -29,6 +29,6 @@ public interface BytesValue {
* @return
*/
@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;

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),
/**
* 日期时间;
* 时间
*/
DATETIME(PrimitiveType.DATETIME.CODE),
TIMESTAMP(PrimitiveType.TIMESTAMP.CODE),
/**
* 文本数据;
@@ -81,7 +81,6 @@ public enum BytesValueType {
*/
LOCATION(PrimitiveType.LOCATION.CODE);
@EnumField(type = PrimitiveType.INT8)
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;

import com.jd.blockchain.binaryproto.PrimitiveType;

public interface KVDataEntry {

/**
@@ -27,11 +25,12 @@ public interface KVDataEntry {
*
* @return
*/
PrimitiveType getType();
BytesValueType getType();
/**
* 值;
* @return
*/
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;

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

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.BytesUtils;

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

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.type = type;
this.version = version < 0 ? -1 : version;
this.bytesValue = bytesValue;
}
@@ -62,8 +58,8 @@ public class KVDataObject implements KVDataEntry {
* @see com.jd.blockchain.ledger.KVDataEntry#getType()
*/
@Override
public PrimitiveType getType() {
return type;
public BytesValueType getType() {
return bytesValue == null ? BytesValueType.NIL : bytesValue.getType();
}

@Override
@@ -72,24 +68,20 @@ public class KVDataObject implements KVDataEntry {
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
*/
public boolean isNil() {
return PrimitiveType.NIL == type;
return bytesValue == null || BytesValueType.NIL == bytesValue.getType();
}

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

/**
@@ -127,10 +119,10 @@ public class KVDataObject implements KVDataEntry {
* @return
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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>
*
* 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#DATETIME} 有效;
* 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#TIMESTAMP} 有效;
* <p>
*
* 无效类型将引发 {@link IllegalStateException} 异常;
@@ -236,19 +230,20 @@ public class KVDataObject implements KVDataEntry {
* @return
*/
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);
}
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>
*
* 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#TEXT} / {@link PrimitiveType#JSON} /
* {@link PrimitiveType#XML} 有效;
* 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#TEXT} /
* {@link PrimitiveType#JSON} / {@link PrimitiveType#XML} 有效;
* <p>
*
* 无效类型将引发 {@link IllegalStateException} 异常;
@@ -256,15 +251,12 @@ public class KVDataObject implements KVDataEntry {
* @return
*/
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 {


+ 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();
}
@Override
public DataAccountKVSetOperationBuilder set(String key, byte[] value, long expVersion) {
innerBuilder.set(key, value, expVersion);
private void addOperation() {
if (op == null) {
op = innerBuilder.getOperation();
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;
}
@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;
}
@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;
}
@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;
}


+ 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.utils.Bytes;
/**
* @author huanghaiquan
*
*/
public interface DataAccountKVSetOperationBuilder {
/**
@@ -12,8 +16,22 @@ public interface DataAccountKVSetOperationBuilder {
*/
DataAccountKVSetOperation getOperation();
// /**
// * 写入字节数组;
// *
// * @param key
// * 键;
// * @param value
// * 值;byte[]格式
// * @param expVersion
// * 预期的当前版本;如果版本不匹配,则写入失败;
// * @return
// */
// @Deprecated
// DataAccountKVSetOperationBuilder set(String key, byte[] value, long expVersion);
/**
* 写入键值;
* 写入字节数组
*
* @param key
* 键;
@@ -23,7 +41,21 @@ public interface DataAccountKVSetOperationBuilder {
* 预期的当前版本;如果版本不匹配,则写入失败;
* @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
*/
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 value
* 值;Bytes格式
* 值;String格式
* @param expVersion
* 预期的当前版本;如果版本不匹配,则写入失败;
* @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
* 键;
@@ -59,6 +146,6 @@ public interface DataAccountKVSetOperationBuilder {
* 预期的当前版本;如果版本不匹配,则写入失败;
* @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.BytesValueEntry;
import com.jd.blockchain.ledger.DataAccountKVSetOperation;
import com.jd.blockchain.ledger.BytesValueType;
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;
public DataAccountKVSetOperationBuilderImpl(Bytes accountAddress) {
operation = new DataAccountKVSetOpTemplate(accountAddress);
}
@@ -21,35 +18,69 @@ public class DataAccountKVSetOperationBuilderImpl implements DataAccountKVSetOpe
return operation;
}
// @Deprecated
// @Override
// public DataAccountKVSetOperationBuilder set(String key, byte[] value, long expVersion) {
// return setBytes(key, value, expVersion);
// }
@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);
return this;
}
@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);
return this;
}
// @Override
// public DataAccountKVSetOperationBuilder set(String key, String value, long expVersion) {
// return setText(key, value, expVersion);
// }
@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);
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
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);
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();

/**
* 写入数据;
* 写入数据; <br>
*
* @param accountAddress
* @return
*/
DataAccountKVSetOperationBuilder dataAccount(String accountAddress);
/**
* 写入数据;
*
* @param accountAddress
* @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;
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 {
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;

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.DataContractRegistry;
import com.jd.blockchain.ledger.BytesValueEntry;
import com.jd.blockchain.ledger.DataAccountKVSetOperation;
import com.jd.blockchain.ledger.BytesValueType;
import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate;
import com.jd.blockchain.transaction.KVData;
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
@@ -43,11 +42,11 @@ public class DataAccountKVSetOpTemplateTest {
String accountAddress = "zhangsandhakhdkah";
data = new DataAccountKVSetOpTemplate(Bytes.fromString(accountAddress));
KVData kvData1 =
new KVData("test1", new BytesValueEntry(BytesValueType.TEXT, "zhangsan".getBytes()), 9999L);
new KVData("test1", BytesValueEntry.fromText("zhangsan"), 9999L);
KVData kvData2 =
new KVData("test2", new BytesValueEntry(BytesValueType.TEXT, "lisi".getBytes()), 9990L);
new KVData("test2", BytesValueEntry.fromText("lisi"), 9990L);
KVData kvData3 =
new KVData("test3", new BytesValueEntry(BytesValueType.TEXT, "wangwu".getBytes()), 1990L);
new KVData("test3", BytesValueEntry.fromText("wangwu"), 1990L);
data.set(kvData1);
data.set(kvData2);
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;

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.DataContractRegistry;
import com.jd.blockchain.ledger.BytesValueEntry;
import com.jd.blockchain.ledger.DataAccountKVSetOperation;
import com.jd.blockchain.ledger.BytesValueType;
import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate;
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
@@ -30,26 +29,26 @@ import static org.junit.Assert.assertEquals;
*/

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.transaction.BlockchainOperationFactory;
import com.jd.blockchain.transaction.TxContentBlob;
import com.jd.blockchain.utils.io.ByteArray;
public class TxContentBlobTest {
@@ -48,7 +47,7 @@ public class TxContentBlobTest {
contentBlob.setHash(contentHash);
DataAccountKVSetOperation kvsetOP = opFactory.dataAccount(id.getAddress())
.set("Name", ByteArray.fromString("AAA", "UTF-8"), -1).getOperation();
.setText("Name", "AAA", -1).getOperation();
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.TxContentBlob;
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.setSequenceNumber(1);
DataAccountKVSetOperation kvsetOP = opFactory.dataAccount(id.getAddress())
.set("Name", ByteArray.fromString("AAA", "UTF-8"), -1).getOperation();
.setText("Name","AAA", -1).getOperation();
contentBlob.addOperation(kvsetOP);
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;
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.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.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.DataAccount;
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.QueryUtil;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping(path = "/")
public class LedgerQueryController implements BlockchainQueryService {
@Autowired
private LedgerService ledgerService;
@Autowired
private LedgerService ledgerService;
@RequestMapping(method = RequestMethod.GET, path = "ledgers")
@Override
@@ -42,7 +56,8 @@ public class LedgerQueryController implements BlockchainQueryService {
@Override
public LedgerInfo getLedger(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
//TODO: 需要配置返回值的 spring MsgQueueMessageDispatcher ,对返回对象仅仅序列化声明的返回值类型的属性,而不是整个对象本身;
// TODO: 需要配置返回值的 spring MsgQueueMessageDispatcher
// ,对返回对象仅仅序列化声明的返回值类型的属性,而不是整个对象本身;
LedgerInfo ledgerInfo = new LedgerInfo();
ledgerInfo.setHash(ledgerHash);
ledgerInfo.setLatestBlockHash(ledger.getLatestBlockHash());
@@ -83,25 +98,27 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}")
@Override
public LedgerBlock getBlock(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "blockHeight") long blockHeight) {
@PathVariable(name = "blockHeight") long blockHeight) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
//TODO: 需要配置返回值的 spring MsgQueueMessageDispatcher ,对返回对象仅仅序列化声明的返回值类型的属性,而不是整个对象本身;
// TODO: 需要配置返回值的 spring MsgQueueMessageDispatcher
// ,对返回对象仅仅序列化声明的返回值类型的属性,而不是整个对象本身;
return ledger.getBlock(blockHeight);
}
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/hash/{blockHash}")
@Override
public LedgerBlock getBlock(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "blockHash") HashDigest blockHash) {
@PathVariable(name = "blockHash") HashDigest blockHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
//TODO: 需要配置返回值的 spring MsgQueueMessageDispatcher ,对返回对象仅仅序列化声明的返回值类型的属性,而不是整个对象本身;
// TODO: 需要配置返回值的 spring MsgQueueMessageDispatcher
// ,对返回对象仅仅序列化声明的返回值类型的属性,而不是整个对象本身;
return ledger.getBlock(blockHash);
}
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/height/{blockHeight}/txs/count")
@Override
public long getTransactionCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "blockHeight") long blockHeight) {
@PathVariable(name = "blockHeight") long blockHeight) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getBlock(blockHeight);
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")
@Override
public long getTransactionCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "blockHash") HashDigest blockHash) {
@PathVariable(name = "blockHash") HashDigest blockHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getBlock(blockHash);
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")
@Override
public long getDataAccountCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "blockHeight") long height) {
@PathVariable(name = "blockHeight") long height) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getBlock(height);
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")
@Override
public long getDataAccountCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "blockHash") HashDigest blockHash) {
@PathVariable(name = "blockHash") HashDigest blockHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getBlock(blockHash);
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")
@Override
public long getUserCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "blockHeight") long height) {
@PathVariable(name = "blockHeight") long height) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getBlock(height);
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")
@Override
public long getUserCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "blockHash") HashDigest blockHash) {
@PathVariable(name = "blockHash") HashDigest blockHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getBlock(blockHash);
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")
@Override
public long getContractCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "blockHeight") long height) {
@PathVariable(name = "blockHeight") long height) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getBlock(height);
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")
@Override
public long getContractCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "blockHash") HashDigest blockHash) {
@PathVariable(name = "blockHash") HashDigest blockHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getBlock(blockHash);
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")
@Override
public LedgerTransaction[] getTransactions(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "blockHeight") long blockHeight,
@RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
@RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
@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);
LedgerBlock ledgerBlock = ledger.getBlock(blockHeight);
@@ -230,8 +247,8 @@ public class LedgerQueryController implements BlockchainQueryService {
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;
// if (fromIndex < 0 || fromIndex >= currentHeightTxNums) {
@@ -245,15 +262,15 @@ public class LedgerQueryController implements BlockchainQueryService {
// count = currentHeightTxNums - fromIndex;
// }
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")
@Override
public LedgerTransaction[] getTransactions(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "blockHash") HashDigest blockHash,
@RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
@RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
@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);
LedgerBlock ledgerBlock = ledger.getBlock(blockHash);
long height = ledgerBlock.getHeight();
@@ -264,8 +281,8 @@ public class LedgerQueryController implements BlockchainQueryService {
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;
// if (fromIndex < 0 || fromIndex >= currentHeightTxNums) {
@@ -279,13 +296,13 @@ public class LedgerQueryController implements BlockchainQueryService {
// count = currentHeightTxNums - fromIndex;
// }
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}")
@Override
public LedgerTransaction getTransactionByContentHash(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "contentHash")HashDigest contentHash) {
@PathVariable(name = "contentHash") HashDigest contentHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
TransactionSet txset = ledger.getTransactionSet(block);
@@ -295,7 +312,7 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/txs/state/{contentHash}")
@Override
public TransactionState getTransactionStateByContentHash(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "contentHash") HashDigest contentHash) {
@PathVariable(name = "contentHash") HashDigest contentHash) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
TransactionSet txset = ledger.getTransactionSet(block);
@@ -305,7 +322,7 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/users/address/{address}")
@Override
public UserInfo getUser(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "address") String address) {
@PathVariable(name = "address") String address) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
UserAccountSet userAccountSet = ledger.getUserAccountSet(block);
@@ -315,18 +332,18 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts/address/{address}")
@Override
public AccountHeader getDataAccount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "address") String address) {
@PathVariable(name = "address") String address) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
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
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) {
return null;
}
@@ -334,51 +351,50 @@ public class LedgerQueryController implements BlockchainQueryService {
LedgerBlock block = ledger.getLatestBlock();
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block);
DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address));
KVDataEntry[] entries = new KVDataEntry[keys.length];
long ver;
for (int i = 0; i < entries.length; i++) {
ver = dataAccount.getDataVersion(Bytes.fromString(keys[i]));
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;
}
@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
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) {
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 (keys.length != versions.length) {
throw new ContractException("keys.length!=versions.length!");
}
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
@@ -389,18 +405,17 @@ public class LedgerQueryController implements BlockchainQueryService {
long ver = -1;
for (int i = 0; i < entries.length; i++) {
// ver = dataAccount.getDataVersion(Bytes.fromString(keys[i]));
ver = versions[i];
ver = versions[i];
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 {
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;
}
@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
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);
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")
@Override
public long getDataEntriesTotalCount(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "address") String address) {
@PathVariable(name = "address") String address) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
@@ -439,7 +455,7 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts/address/{address}")
@Override
public AccountHeader getContract(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "address") String address) {
@PathVariable(name = "address") String address) {
LedgerRepository ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block);
@@ -448,6 +464,7 @@ public class LedgerQueryController implements BlockchainQueryService {
/**
* get more users by fromIndex and count;
*
* @param ledgerHash
* @param fromIndex
* @param count
@@ -456,44 +473,45 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/users")
@Override
public AccountHeader[] getUsers(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
@RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
@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();
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;
*
* @param ledgerHash
* @param fromIndex
* @param count
* @return
*/
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/accounts")
@Override
@Override
public AccountHeader[] getDataAccounts(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
@RequestParam(name = "count", required = false, defaultValue = "-1") int count) {
@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();
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;
import com.jd.blockchain.ledger.PrivilegeType;
import com.jd.blockchain.ledger.PermissionType;
/**
* 权限设置;<br>
@@ -16,6 +16,6 @@ public interface PrivilegeSetting {
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.KVDataEntry;
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];
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());

// 分配到持有者账户;
KVDataObject holderAmount = (KVDataObject) kvEntries[1];
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 结构建立查询索引;
String commodityDataAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf==";
Commodity commodity1 = new Commodity();
txTemp.dataAccount(commodityDataAccount).set("ASSET_CODE", commodity1.getCode().getBytes(), -1);
txTemp.dataAccount(commodityDataAccount).setText("ASSET_CODE", commodity1.getCode(), -1);

// TX 准备就绪;
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 key1 = "jd_key1";
byte[] val1 = "www.jd.com".getBytes();
String val1 = "www.jd.com";

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 准备就绪;
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 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 准备就绪;
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;

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.ConsensusProviders;
import com.jd.blockchain.consensus.ConsensusSettings;
import com.jd.blockchain.crypto.AddressEncoding;
import com.jd.blockchain.crypto.AsymmetricKeypair;
import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PrivKey;
import com.jd.blockchain.crypto.PubKey;
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.LedgerRepository;
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.concurrent.ThreadInvoker.AsyncCallback;
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.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 {
// 合约测试使用的初始化数据;
BlockchainKeypair contractDataKey = BlockchainKeyGenerator.getInstance().generate();
@@ -179,9 +197,9 @@ public class IntegrationTest {
String dataAccount = dataAccountAddress;

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 准备就绪;
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,
IntegratedContext context) {
@@ -620,11 +638,11 @@ public class IntegrationTest {
// 注册数据账户,并验证最终写入;
txTpl.dataAccounts().register(contractDataKey.getIdentity());
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中填充;
.set("ledgerHash", ledgerHash.getRawDigest(), -1).getOperation();
.setBytes("ledgerHash", ledgerHash.getRawDigest(), -1).getOperation();

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

LedgerRepository ledgerOfNode0 = node0.getLedgerManager().getLedger(ledgerHash);
LedgerBlock block = ledgerOfNode0.getBlock(txResp.getBlockHeight());
byte[] val1InDb = ledgerOfNode0.getDataAccountSet(block).getDataAccount(contractDataKey.getAddress())
BytesValue val1InDb = ledgerOfNode0.getDataAccountSet(block).getDataAccount(contractDataKey.getAddress())
.getBytes("A");
byte[] val2InDb = ledgerOfNode0.getDataAccountSet(block).getDataAccount(contractDataKey.getAddress())
BytesValue val2InDb = ledgerOfNode0.getDataAccountSet(block).getDataAccount(contractDataKey.getAddress())
.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.ConsensusProviders;
import com.jd.blockchain.consensus.ConsensusSettings;
import com.jd.blockchain.crypto.CryptoAlgorithm;
import com.jd.blockchain.crypto.AsymmetricKeypair;
import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.CryptoAlgorithm;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PrivKey;
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.ConsoleUtils;
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.net.NetworkAddress;

@@ -408,8 +407,8 @@ public class LedgerPerformanceTest {
// BlockchainKeyPair dataAccountKey =
// BlockchainKeyGenerator.getInstance().generate();
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();
reqBuilder.signAsEndpoint(adminKey);
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.*;


/**
*
* @author shaozhuguang
@@ -57,436 +56,440 @@ import static org.junit.Assert.*;
public class IntegrationBase {
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("param1", "v", -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 contractDeployKey = BlockchainKeyGenerator.getInstance().generate();
// 保存资产总数的键;
// 第二个参数;
// 保存资产总数的键;
// 第二个参数;
private static String contractZipName = "contract.jar";
static HashDigest txContentHash;

public static LedgerBlock testSDK_Contract(AsymmetricKeypair adminKey, HashDigest ledgerHash,
BlockchainService blockchainService,LedgerRepository ledgerRepository) {
BlockchainService blockchainService, LedgerRepository ledgerRepository) {
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());

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);
testContractExe1(adminKey, ledgerHash, keyPairResponse.keyPair, blockchainService, ledgerRepository);

return block;
}
return block;
}

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");
// txTpl.contract(contractDeployKey.getAddress(),AssetContract2.class).issue(byteObj,
@@ -494,14 +497,14 @@ public class IntegrationBase {
txTpl.contract(contractDeployKey.getAddress(),AssetContract2.class).issue(byteObj,
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());
assertEquals(ptx.getHash(),txResp.getContentHash());
LedgerBlock block = ledgerRepository.getBlock(txResp.getBlockHeight());
@@ -529,43 +532,43 @@ public class IntegrationBase {
TransactionResponse txResp = ptx.commit();

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

/**
* 根据合约构建字节数组;
*
* @return
*/
/**
* 根据合约构建字节数组;
*
* @return
*/
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.gateway.GatewayConfigProperties.KeyPairConfig;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.*;
import com.jd.blockchain.ledger.core.DataAccount;
import com.jd.blockchain.ledger.core.DataAccountSet;
@@ -201,9 +202,9 @@ public class IntegrationTestAll4Redis {
txTpl.dataAccounts().register(dataKey.getIdentity());

// 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();
@@ -215,18 +216,14 @@ public class IntegrationTestAll4Redis {
assertTrue(txResp.isSuccess());
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())
.getDataAccount(dataKey.getAddress()).getDataVersion("A"));
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;
TransactionTemplate txTemp = blockchainService.newTransaction(ledgerHash);
@@ -265,9 +262,9 @@ public class IntegrationTestAll4Redis {
Bytes dataAccount = dataAccountAddress;

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 准备就绪;
PreparedTransaction prepTx = txTemp.prepare();
@@ -392,11 +389,10 @@ public class IntegrationTestAll4Redis {
.getDataAccount(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中填充;
.set("ledgerHash", ledgerHash.getRawDigest(), -1).getOperation();
.setBytes("ledgerHash", ledgerHash.getRawDigest(), -1).getOperation();

byte[] contractCode = getChainCodeBytes();
txTpl.contracts().deploy(contractDeployKey.getIdentity(), contractCode);
@@ -457,7 +453,8 @@ public class IntegrationTestAll4Redis {
PubKey pubKey = key.getPubKey();
Bytes dataAddress = AddressEncoding.generateAddress(pubKey);
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,外部不便于得到,临时屏蔽;
// UserAccountSet userAccountSet =
@@ -468,8 +465,8 @@ public class IntegrationTestAll4Redis {
// 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);
@@ -484,12 +481,12 @@ public class IntegrationTestAll4Redis {

// 验证结果;
LedgerBlock block = ledgerRepository.getBlock(txResp.getBlockHeight());
byte[] val1InDb = ledgerRepository.getDataAccountSet(block).getDataAccount(contractDataKey.getAddress())
BytesValue val1InDb = ledgerRepository.getDataAccountSet(block).getDataAccount(contractDataKey.getAddress())
.getBytes("A");
byte[] val2InDb = ledgerRepository.getDataAccountSet(block).getDataAccount(contractDataKey.getAddress())
BytesValue val2InDb = ledgerRepository.getDataAccountSet(block).getDataAccount(contractDataKey.getAddress())
.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");
//
// //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();

// 签名;


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

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;

import com.jd.blockchain.ledger.core.LedgerException;
import com.jd.blockchain.ledger.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));
}
public String toUTF8String() {
return BytesUtils.toString(toBytes());
}

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


Loading…
Cancel
Save