Browse Source

Refactored the Value structure of BaseAccount;

tags/1.0.0
huanghaiquan 6 years ago
parent
commit
f550c6d518
52 changed files with 1424 additions and 1291 deletions
  1. +1
    -0
      source/contract/contract-framework/src/main/java/com/jd/blockchain/contract/engine/ContractEngine.java
  2. +1
    -0
      source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/JVMContractEngine.java
  3. +3
    -1
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountSet.java
  4. +17
    -6
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/BaseAccount.java
  5. +12
    -7
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java
  6. +1
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/CryptoConfig.java
  7. +10
    -11
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java
  8. +1
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminAccount.java
  9. +1
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerEditor.java
  10. +1
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerService.java
  11. +1
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataSet.java
  12. +1
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleTree.java
  13. +1
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantDataSet.java
  14. +1
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionSet.java
  15. +11
    -8
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccount.java
  16. +1
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccountSet.java
  17. +1
    -1
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/DefaultOperationHandleRegisteration.java
  18. +1
    -1
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerManager.java
  19. +60
    -53
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerQueryService.java
  20. +0
    -1
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerRepositoryImpl.java
  21. +1
    -1
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionBatchProcessor.java
  22. +1
    -1
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractEventSendOperationHandle.java
  23. +15
    -15
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractLedgerContext.java
  24. +7
    -7
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/BaseAccountTest.java
  25. +57
    -23
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerEditerTest.java
  26. +1
    -1
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerTransactionDataTest.java
  27. +3
    -5
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TransactionSetTest.java
  28. +102
    -80
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValueEntry.java
  29. +2
    -3
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataEntry.java
  30. +52
    -60
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataObject.java
  31. +1
    -1
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerException.java
  32. +1
    -1
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerPermissionException.java
  33. +17
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ValueTypeCastException.java
  34. +12
    -12
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainOperationFactory.java
  35. +26
    -26
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilder.java
  36. +9
    -9
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilderImpl.java
  37. +1
    -2
      source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/TxContentBlobTest.java
  38. +1
    -2
      source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/TxRequestMessageTest.java
  39. +127
    -109
      source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java
  40. +3
    -4
      source/sdk/sdk-samples/src/main/java/com/jd/blockchain/contract/samples/AssetContractImpl.java
  41. +1
    -1
      source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_InsertData.java
  42. +4
    -4
      source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_BatchInsertData_Test_.java
  43. +2
    -2
      source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_InsertData_Test_.java
  44. +9
    -8
      source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/IntegrationTest.java
  45. +3
    -4
      source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerPerformanceTest.java
  46. +474
    -471
      source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java
  47. +27
    -30
      source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestAll4Redis.java
  48. +1
    -1
      source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestDataAccount.java
  49. +319
    -317
      source/tools/tools-capability/src/main/java/com/jd/blockchain/capability/service/RemoteTransactionService.java
  50. +1
    -1
      source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitException.java
  51. +4
    -0
      source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Bytes.java
  52. +14
    -1
      source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesUtils.java

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


+ 3
- 1
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;
@@ -420,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;


+ 17
- 6
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;
@@ -154,8 +156,9 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional
* If this operation fail by version checking or other reason, then
* return -1;
*/
public long setBytes(Bytes key, byte[] value, long version) {
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);
}

/**
@@ -175,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);
}

/**
@@ -186,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


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



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

@@ -44,19 +44,18 @@ public class DataAccount implements AccountHeader, MerkleProvable {
public long setBytes(Bytes key, BytesValue value, long version) {
byte[] bytesValue = BinaryProtocol.encode(value, BytesValue.class);
return baseAccount.setBytes(key, bytesValue, version);
return baseAccount.setBytes(key, value, version);
}
public long setBytes(Bytes key, String value, long version) {
BytesValue bv = BytesValueEntry.fromText(value);
return setBytes(key, bv, version);
BytesValue bytesValue = BytesValueEntry.fromText(value);
return baseAccount.setBytes(key, bytesValue, version);
}
public long setBytes(Bytes key, byte[] value, long version) {
BytesValue bv = BytesValueEntry.fromBytes(value);
return setBytes(key, bv, version);
BytesValue bytesValue = BytesValueEntry.fromBytes(value);
return baseAccount.setBytes(key, bytesValue, version);
}
/**
@@ -87,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));
}
@@ -97,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);
}
@@ -108,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);
}
@@ -119,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);
}
@@ -154,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++;
}


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


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


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

@@ -269,13 +269,13 @@ public class ContractLedgerContext implements LedgerContext {
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 = BytesValueEntry.fromBytes(value);
// this.op = new SingleKVSetOpTemplate(key, bytesValue, expVersion);
// handle(op);
// return this;
// }

@Override
public DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion) {
@@ -301,14 +301,14 @@ public class ContractLedgerContext implements LedgerContext {
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;
}
// @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 setJSON(String key, String value, long expVersion) {


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

@@ -12,11 +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.storage.service.utils.MemoryKVStorage;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.io.BytesUtils;

/**
*
@@ -53,33 +53,33 @@ public class BaseAccountTest {
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;
}

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

@@ -6,14 +6,12 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.security.KeyFactory;
import java.util.Random;

import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.HashDigest;

import org.junit.Test;

import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.BlockchainKeyGenerator;
import com.jd.blockchain.ledger.BlockchainKeypair;
import com.jd.blockchain.ledger.ContractCodeDeployOperation;
@@ -71,7 +69,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);


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

@@ -8,85 +8,107 @@ import com.jd.blockchain.utils.io.BytesUtils;
* @author huanghaiquan
*
*/
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);
}
public static BytesValue fromText(String value) {
return new BytesValueEntry(BytesValueType.TEXT, BytesUtils.toBytes(value));
}
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;
}
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/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();
}

+ 52
- 60
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,10 +211,11 @@ 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()));
}

/**
@@ -236,19 +230,20 @@ public class KVDataObject implements KVDataEntry {
* @return
*/
public Date datetimeValue() {
if (PrimitiveType.TIMESTAMP == 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.TIMESTAMP, 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));
}

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


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



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

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

public class LedgerPermissionException extends LedgerException {



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

}

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

@@ -150,12 +150,12 @@ public class BlockchainOperationFactory implements ClientOperator, LedgerInitOpe
}
}
@Override
public DataAccountKVSetOperationBuilder set(String key, byte[] value, long expVersion) {
innerBuilder.set(key, value, expVersion);
addOperation();
return this;
}
// @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) {
@@ -192,12 +192,12 @@ public class BlockchainOperationFactory implements ClientOperator, LedgerInitOpe
return this;
}
@Override
public DataAccountKVSetOperationBuilder set(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.setText(key, value, expVersion);
// addOperation();
// return this;
// }
@Override
public DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion) {


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

@@ -16,19 +16,19 @@ public interface DataAccountKVSetOperationBuilder {
*/
DataAccountKVSetOperation getOperation();
/**
* 写入字节数组;
*
* @param key
* 键;
* @param value
* 值;byte[]格式
* @param expVersion
* 预期的当前版本;如果版本不匹配,则写入失败;
* @return
*/
@Deprecated
DataAccountKVSetOperationBuilder set(String key, byte[] value, long expVersion);
// /**
// * 写入字节数组;
// *
// * @param key
// * 键;
// * @param value
// * 值;byte[]格式
// * @param expVersion
// * 预期的当前版本;如果版本不匹配,则写入失败;
// * @return
// */
// @Deprecated
// DataAccountKVSetOperationBuilder set(String key, byte[] value, long expVersion);
/**
* 写入字节数组;
@@ -69,19 +69,19 @@ public interface DataAccountKVSetOperationBuilder {
*/
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
// * 值;String格式
// * @param expVersion
// * 预期的当前版本;如果版本不匹配,则写入失败;
// * @return
// */
// @Deprecated
// DataAccountKVSetOperationBuilder set(String key, String value, long expVersion);
/**
* 写入文本键值;


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

@@ -18,11 +18,11 @@ public class DataAccountKVSetOperationBuilderImpl implements DataAccountKVSetOpe
return operation;
}
@Deprecated
@Override
public DataAccountKVSetOperationBuilder set(String key, byte[] value, long expVersion) {
return setBytes(key, value, expVersion);
}
// @Deprecated
// @Override
// public DataAccountKVSetOperationBuilder set(String key, byte[] value, long expVersion) {
// return setBytes(key, value, expVersion);
// }
@Override
public DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion) {
@@ -38,10 +38,10 @@ public class DataAccountKVSetOperationBuilderImpl implements DataAccountKVSetOpe
return this;
}
@Override
public DataAccountKVSetOperationBuilder set(String key, String value, long expVersion) {
return setText(key, value, expVersion);
}
// @Override
// public DataAccountKVSetOperationBuilder set(String key, String value, long expVersion) {
// return setText(key, value, expVersion);
// }
@Override
public DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion) {


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

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


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

@@ -23,6 +23,7 @@ import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig;
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;
@@ -196,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();
@@ -637,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();
@@ -655,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());


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

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

import static org.junit.Assert.*;


/**
*
* @author shaozhuguang
@@ -53,480 +52,484 @@ import static org.junit.Assert.*;

public class IntegrationBase {

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

public static final String PASSWORD = "abc";

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

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

public static final AtomicLong validLong = new AtomicLong();

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

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

HashDigest transactionHash = ptx.getHash();
static {
DataContractRegistry.register(LedgerInitOperation.class);
DataContractRegistry.register(UserRegisterOperation.class);
}

ptx.sign(adminKey);
public static final String PASSWORD = "abc";

// 提交并等待共识返回;
TransactionResponse txResp = ptx.commit();
public static final String[] PUB_KEYS = { "3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9",
"3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX",
"3snPdw7i7PZi6TStiyc6mzjprnNhgs2atSGNS8wPYzhbKaUWGFJt7x",
"3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk" };

KeyPairResponse keyPairResponse = new KeyPairResponse();
keyPairResponse.keyPair = user;
keyPairResponse.txResp = txResp;
keyPairResponse.txHash = transactionHash;
return keyPairResponse;
}
public static final String[] PRIV_KEYS = {
"177gjzHTznYdPgWqZrH43W3yp37onm74wYXT4v9FukpCHBrhRysBBZh7Pzdo5AMRyQGJD7x",
"177gju9p5zrNdHJVEQnEEKF4ZjDDYmAXyfG84V5RPGVc5xFfmtwnHA7j51nyNLUFffzz5UT",
"177gjtwLgmSx5v1hFb46ijh7L9kdbKUpJYqdKVf9afiEmAuLgo8Rck9yu5UuUcHknWJuWaF",
"177gk1pudweTq5zgJTh8y3ENCTwtSFsKyX7YnpuKPo7rKgCkCBXVXh5z2syaTCPEMbuWRns" };

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

// 定义交易;
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash);
txTpl.dataAccounts().register(dataAccount.getIdentity());
public static KeyPairResponse testSDK_RegisterUser(AsymmetricKeypair adminKey, HashDigest ledgerHash,
BlockchainService blockchainService) {
// 注册用户,并验证最终写入;
BlockchainKeypair user = BlockchainKeyGenerator.getInstance().generate();

// 签名;
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
}

// 合约测试使用的初始化数据;
BlockchainKeypair contractDataKey = BlockchainKeyGenerator.getInstance().generate();
BlockchainKeypair contractDeployKey = BlockchainKeyGenerator.getInstance().generate();
// 保存资产总数的键;
private static final String KEY_TOTAL = "TOTAL";
// 第二个参数;
private static final String KEY_ABC = "abc";
private String contractZipName = "Example1.jar";
HashDigest txContentHash;
String pubKeyVal = "jd.com"+System.currentTimeMillis();
private String eventName = "issue-asset";
public LedgerBlock testSDK_Contract(AsymmetricKeypair adminKey, HashDigest ledgerHash,
BlockchainService blockchainService,LedgerRepository ledgerRepository) {
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);

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

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

// 验证结果;
txResp.getContentHash();

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

// execute the contract;
testContractExe(adminKey, ledgerHash, userKey, blockchainService, ledgerRepository);

return block;
}

private void testContractExe(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainKeypair userKey,
BlockchainService blockchainService,LedgerRepository ledgerRepository) {
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##123##" + contractDataKey.getAddress()).getBytes());

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

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

// 验证结果;
txResp.getContentHash();
Assert.assertTrue(txResp.isSuccess());
}

/**
* 根据合约构建字节数组;
*
* @return
*/
private 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;
}
// 定义交易;
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash);
txTpl.users().register(user.getIdentity());

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

HashDigest transactionHash = ptx.getHash();

ptx.sign(adminKey);

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

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

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

// 签名;
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
}

// 合约测试使用的初始化数据;
BlockchainKeypair contractDataKey = BlockchainKeyGenerator.getInstance().generate();
BlockchainKeypair contractDeployKey = BlockchainKeyGenerator.getInstance().generate();
// 保存资产总数的键;
private static final String KEY_TOTAL = "TOTAL";
// 第二个参数;
private static final String KEY_ABC = "abc";
private String contractZipName = "Example1.jar";
HashDigest txContentHash;
String pubKeyVal = "jd.com" + System.currentTimeMillis();
private String eventName = "issue-asset";

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

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

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

// 验证结果;
txResp.getContentHash();

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

// execute the contract;
testContractExe(adminKey, ledgerHash, userKey, blockchainService, ledgerRepository);

return block;
}

private void testContractExe(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainKeypair userKey,
BlockchainService blockchainService, LedgerRepository ledgerRepository) {
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##123##" + contractDataKey.getAddress()).getBytes());

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

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

// 验证结果;
txResp.getContentHash();
Assert.assertTrue(txResp.isSuccess());
}

/**
* 根据合约构建字节数组;
*
* @return
*/
private 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;
}
}

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

@@ -23,6 +23,7 @@ import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig;
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;
@@ -219,9 +220,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();
@@ -233,18 +234,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())
@@ -271,8 +268,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);
@@ -283,9 +280,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();
@@ -410,11 +407,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);
@@ -478,7 +474,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 =
@@ -489,8 +486,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);
@@ -505,12 +502,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());
}

/**


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

@@ -196,7 +196,7 @@ 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)
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) {


+ 14
- 1
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;
@@ -296,6 +301,10 @@ public class BytesUtils {
}
}
/**
* @param bytes
* @return
*/
public static String toString(byte[] bytes) {
return toString(bytes, DEFAULT_CHARSET);
}
@@ -326,6 +335,10 @@ public class BytesUtils {
}
}
public static boolean toBoolean(byte value) {
return value != FALSE_BYTE;
}
/**
* 按从高位到低位的顺序将指定二进制数组从位置 0 开始的 4 个字节转换为 int 整数;
*


Loading…
Cancel
Save