Browse Source

Fixed all compilation errors;

tags/1.1.2^2
huanghaiquan 5 years ago
parent
commit
a05f4e7895
37 changed files with 605 additions and 834 deletions
  1. +3
    -3
      source/contract/contract-samples/src/main/java/com/jd/blockchain/contract/ReadContractImpl.java
  2. +7
    -7
      source/contract/contract-samples/src/main/java/com/jd/blockchain/contract/TransferContractImpl.java
  3. +4
    -4
      source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java
  4. +2
    -2
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java
  5. +28
    -15
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerQueryService.java
  6. +6
    -1
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccountSet.java
  7. +154
    -3
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataSet.java
  8. +4
    -4
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ContractLedgerContext.java
  9. +3
    -3
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/TxTestContractImpl.java
  10. +2
    -1
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/AccountSetTest.java
  11. +2
    -1
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractInfo.java
  12. +0
    -616
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataObject.java
  13. +78
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedKVData.java
  14. +9
    -1
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedKVEntry.java
  15. +15
    -16
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedValue.java
  16. +4
    -4
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java
  17. +40
    -16
      source/peer/src/main/java/com/jd/blockchain/peer/web/LedgerQueryController.java
  18. +4
    -4
      source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/converters/ClientResolveUtil.java
  19. +7
    -7
      source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java
  20. +3
    -3
      source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java
  21. +8
    -8
      source/sdk/sdk-samples/src/main/java/com/jd/blockchain/contract/samples/AssetContractImpl.java
  22. +2
    -2
      source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_Query.java
  23. +3
    -3
      source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Contract_Demo.java
  24. +2
    -2
      source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Contract_Random_Demo.java
  25. +2
    -2
      source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_InsertData_Demo.java
  26. +3
    -3
      source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Query_Test_.java
  27. +3
    -3
      source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/IntegrationTest.java
  28. +2
    -2
      source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java
  29. +3
    -3
      source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestAll4Redis.java
  30. +2
    -2
      source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestDataAccount.java
  31. +52
    -17
      source/utils/utils-common/src/main/java/com/jd/blockchain/utils/ArrayUtils.java
  32. +0
    -2
      source/utils/utils-common/src/main/java/com/jd/blockchain/utils/BaseConstant.java
  33. +1
    -1
      source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DataEntry.java
  34. +21
    -0
      source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DataIterator.java
  35. +0
    -34
      source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DataTypeUtils.java
  36. +39
    -33
      source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Dataset.java
  37. +87
    -6
      source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DatasetHelper.java

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

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

import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.KVDataEntry;
import com.jd.blockchain.ledger.TypedKVEntry;

@Contract
public class ReadContractImpl implements EventProcessingAware, ReadContract {
@@ -24,7 +24,7 @@ public class ReadContractImpl implements EventProcessingAware, ReadContract {
@Override
@ContractEvent(name = "read-key")
public String read(String address, String key) {
KVDataEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, key);
TypedKVEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, key);

if (kvDataEntries != null && kvDataEntries.length == 1) {
return kvDataEntries[0].getValue().toString();
@@ -35,7 +35,7 @@ public class ReadContractImpl implements EventProcessingAware, ReadContract {
@Override
@ContractEvent(name = "version-key")
public Long readVersion(String address, String key) {
KVDataEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, key);
TypedKVEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, key);

if (kvDataEntries != null && kvDataEntries.length == 1) {
return kvDataEntries[0].getVersion();


+ 7
- 7
source/contract/contract-samples/src/main/java/com/jd/blockchain/contract/TransferContractImpl.java View File

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

import com.alibaba.fastjson.JSON;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.KVDataEntry;
import com.jd.blockchain.ledger.TypedKVEntry;
import com.jd.blockchain.ledger.KVDataVO;
import com.jd.blockchain.ledger.KVInfoVO;

@@ -14,7 +14,7 @@ public class TransferContractImpl implements EventProcessingAware, TransferContr

@Override
public String create(String address, String account, long money) {
KVDataEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, account);
TypedKVEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, account);
// 肯定有返回值,但若不存在则返回version=-1
if (kvDataEntries != null && kvDataEntries.length > 0) {
long currVersion = kvDataEntries[0].getVersion();
@@ -32,13 +32,13 @@ public class TransferContractImpl implements EventProcessingAware, TransferContr
@Override
public String transfer(String address, String from, String to, long money) {
// 首先查询余额
KVDataEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, from, to);
TypedKVEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, from, to);
if (kvDataEntries == null || kvDataEntries.length != 2) {
throw new IllegalStateException(String.format("%s -> %s - %s may be not created !!!", address, from, to));
} else {
// 判断from账号中钱数量是否足够
long fromMoney = 0L, toMoney = 0L, fromVersion = 0L, toVersion = 0L;
for (KVDataEntry kvDataEntry : kvDataEntries) {
for (TypedKVEntry kvDataEntry : kvDataEntries) {
if (kvDataEntry.getKey().equals(from)) {
fromMoney = (long) kvDataEntry.getValue();
fromVersion = kvDataEntry.getVersion();
@@ -62,7 +62,7 @@ public class TransferContractImpl implements EventProcessingAware, TransferContr

@Override
public long read(String address, String account) {
KVDataEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, account);
TypedKVEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, account);
if (kvDataEntries == null || kvDataEntries.length == 0) {
return -1;
}
@@ -71,7 +71,7 @@ public class TransferContractImpl implements EventProcessingAware, TransferContr

@Override
public String readAll(String address, String account) {
KVDataEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, account);
TypedKVEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, account);
// 获取最新的版本号
if (kvDataEntries == null || kvDataEntries.length == 0) {
return "";
@@ -91,7 +91,7 @@ public class TransferContractImpl implements EventProcessingAware, TransferContr

KVInfoVO kvInfoVO = new KVInfoVO(kvDataVOS);

KVDataEntry[] allEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, kvInfoVO);
TypedKVEntry[] allEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, kvInfoVO);

return JSON.toJSONString(allEntries);
}


+ 4
- 4
source/gateway/src/main/java/com/jd/blockchain/gateway/web/BlockBrowserController.java View File

@@ -25,7 +25,7 @@ import com.jd.blockchain.gateway.PeerService;
import com.jd.blockchain.gateway.service.DataRetrievalService;
import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.ContractInfo;
import com.jd.blockchain.ledger.KVDataEntry;
import com.jd.blockchain.ledger.TypedKVEntry;
import com.jd.blockchain.ledger.KVInfoVO;
import com.jd.blockchain.ledger.LedgerAdminInfo;
import com.jd.blockchain.ledger.LedgerBlock;
@@ -261,7 +261,7 @@ public class BlockBrowserController implements BlockchainExtendQueryService {
@RequestMapping(method = { RequestMethod.GET,
RequestMethod.POST }, path = "ledgers/{ledgerHash}/accounts/{address}/entries")
@Override
public KVDataEntry[] getDataEntries(@PathVariable("ledgerHash") HashDigest ledgerHash,
public TypedKVEntry[] getDataEntries(@PathVariable("ledgerHash") HashDigest ledgerHash,
@PathVariable("address") String address, @RequestParam("keys") String... keys) {
return peerService.getQueryService().getDataEntries(ledgerHash, address, keys);
}
@@ -269,7 +269,7 @@ public class BlockBrowserController implements BlockchainExtendQueryService {
@RequestMapping(method = { RequestMethod.GET,
RequestMethod.POST }, path = "ledgers/{ledgerHash}/accounts/{address}/entries-version")
@Override
public KVDataEntry[] getDataEntries(@PathVariable("ledgerHash") HashDigest ledgerHash,
public TypedKVEntry[] getDataEntries(@PathVariable("ledgerHash") HashDigest ledgerHash,
@PathVariable("address") String address, @RequestBody KVInfoVO kvInfoVO) {
return peerService.getQueryService().getDataEntries(ledgerHash, address, kvInfoVO);
}
@@ -277,7 +277,7 @@ public class BlockBrowserController implements BlockchainExtendQueryService {
@RequestMapping(method = { RequestMethod.GET,
RequestMethod.POST }, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries")
@Override
public KVDataEntry[] getDataEntries(@PathVariable("ledgerHash") HashDigest ledgerHash,
public TypedKVEntry[] getDataEntries(@PathVariable("ledgerHash") HashDigest ledgerHash,
@PathVariable("address") String address,
@RequestParam(name = "fromIndex", required = false, defaultValue = "0") int fromIndex,
@RequestParam(name = "count", required = false, defaultValue = "-1") int count) {


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

@@ -2,8 +2,8 @@ package com.jd.blockchain.ledger.core;
import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.KVDataEntry;
import com.jd.blockchain.ledger.KVDataObject;
import com.jd.blockchain.ledger.TypedKVEntry;
import com.jd.blockchain.ledger.TypedKVData;
import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.ledger.TypedValue;
import com.jd.blockchain.utils.Bytes;


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

@@ -8,8 +8,9 @@ import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.ContractInfo;
import com.jd.blockchain.ledger.KVDataEntry;
import com.jd.blockchain.ledger.KVDataObject;
import com.jd.blockchain.ledger.TypedKVEntry;
import com.jd.blockchain.ledger.TypedValue;
import com.jd.blockchain.ledger.TypedKVData;
import com.jd.blockchain.ledger.KVDataVO;
import com.jd.blockchain.ledger.KVInfoVO;
import com.jd.blockchain.ledger.LedgerAdminInfo;
@@ -22,12 +23,15 @@ import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.ledger.UserInfo;
import com.jd.blockchain.transaction.BlockchainQueryService;
import com.jd.blockchain.utils.ArrayUtils;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.DataEntry;
import com.jd.blockchain.utils.DataIterator;
import com.jd.blockchain.utils.QueryUtil;

public class LedgerQueryService implements BlockchainQueryService {

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

private HashDigest[] ledgerHashs;

@@ -278,7 +282,7 @@ public class LedgerQueryService implements BlockchainQueryService {
}

@Override
public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys) {
public TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys) {
if (keys == null || keys.length == 0) {
return EMPTY_ENTRIES;
}
@@ -287,7 +291,8 @@ public class LedgerQueryService implements BlockchainQueryService {
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address));

KVDataEntry[] entries = new KVDataEntry[keys.length];
TypedKVEntry[] entries = new TypedKVEntry[keys.length];
long ver;
for (int i = 0; i < entries.length; i++) {
final String currKey = keys[i];
@@ -295,17 +300,17 @@ public class LedgerQueryService implements BlockchainQueryService {
ver = dataAccount == null ? -1 : dataAccount.getDataset().getVersion(currKey);

if (ver < 0) {
entries[i] = new KVDataObject(currKey, -1, null);
entries[i] = new TypedKVData(currKey, -1, null);
} else {
BytesValue value = dataAccount.getDataset().getValue(currKey, ver);
entries[i] = new KVDataObject(currKey, ver, value);
entries[i] = new TypedKVData(currKey, ver, value);
}
}

return entries;
}

public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) {
public TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) {
// parse kvInfoVO;
List<String> keyList = new ArrayList<>();
List<Long> versionList = new ArrayList<>();
@@ -335,22 +340,22 @@ public class LedgerQueryService implements BlockchainQueryService {
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address));

KVDataEntry[] entries = new KVDataEntry[keys.length];
TypedKVEntry[] entries = new TypedKVEntry[keys.length];
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, null);
entries[i] = new TypedKVData(keys[i], -1, null);
} else {
if (dataAccount.getDataset().getDataCount() == 0
|| dataAccount.getDataset().getValue(keys[i], ver) == null) {
// is the address is not exist; the result is null;
entries[i] = new KVDataObject(keys[i], -1, null);
entries[i] = new TypedKVData(keys[i], -1, null);
} else {
BytesValue value = dataAccount.getDataset().getValue(keys[i], ver);
entries[i] = new KVDataObject(keys[i], ver, value);
entries[i] = new TypedKVData(keys[i], ver, value);
}
}
}
@@ -359,14 +364,22 @@ public class LedgerQueryService implements BlockchainQueryService {
}

@Override
public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count) {
public TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count) {
checkLedgerHash(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address));

int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccount.getDataset().getDataCount());
return dataAccount.getDataset()..getDataEntries(pages[0], pages[1]);
// int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccount.getDataset().getDataCount());
// return dataAccount.getDataset().getDataEntry(key, version).getDataEntries(pages[0], pages[1]);
DataIterator<String, TypedValue> iterator = dataAccount.getDataset().iterator();
iterator.skip(fromIndex);
DataEntry<String, TypedValue>[] dataEntries = iterator.next(count);
TypedKVEntry[] typedKVEntries = ArrayUtils.castTo(dataEntries, TypedKVEntry.class,
e -> e == null ? null : new TypedKVData(e.getKey(), e.getVersion(), e.getValue()));
return typedKVEntries;
}

@Override


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

@@ -136,7 +136,12 @@ public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQ
* @return
*/
public boolean contains(Bytes address) {
long latestVersion = getVersion(address);
InnerMerkleAccount acc = latestAccountsCache.get(address);
if (acc != null) {
// 无论是新注册未提交的,还是缓存已提交的账户实例,都认为是存在;
return true;
}
long latestVersion = merkleDataset.getVersion(address);
return latestVersion > -1;
}


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

@@ -10,10 +10,12 @@ import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.storage.service.utils.BufferedKVStorage;
import com.jd.blockchain.storage.service.utils.VersioningKVData;
import com.jd.blockchain.utils.ArrayUtils;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.Transactional;
import com.jd.blockchain.utils.DataEntry;
import com.jd.blockchain.utils.DataIterator;
import com.jd.blockchain.utils.Dataset;
import com.jd.blockchain.utils.Transactional;
import com.jd.blockchain.utils.io.BytesUtils;
/**
@@ -39,6 +41,9 @@ public class MerkleDataSet implements Transactional, MerkleProvable, Dataset<Byt
private final Bytes dataKeyPrefix;
private final Bytes merkleKeyPrefix;
@SuppressWarnings("unchecked")
private static final DataEntry<Bytes, byte[]>[] EMPTY_ENTRIES = new DataEntry[0];
private BufferedKVStorage bufferedStorage;
private VersioningKVStorage valueStorage;
@@ -162,11 +167,16 @@ public class MerkleDataSet implements Transactional, MerkleProvable, Dataset<Byt
return merkleTree.getDataCount();
}
/**
* 返回理论上允许的最大数据索引;
*
* @return
*/
public long getMaxIndex() {
return merkleTree.getMaxSn();
}
public byte[][] getLatestValues(int fromIndex, int count) {
public byte[][] getLatestValues(long fromIndex, int count) {
if (count > LedgerConsts.MAX_LIST_COUNT) {
throw new IllegalArgumentException("Count exceed the upper limit[" + LedgerConsts.MAX_LIST_COUNT + "]!");
}
@@ -182,13 +192,16 @@ public class MerkleDataSet implements Transactional, MerkleProvable, Dataset<Byt
return values;
}
public DataEntry<Bytes, byte[]>[] getLatestDataEntries(int fromIndex, int count) {
public DataEntry<Bytes, byte[]>[] getLatestDataEntries(long fromIndex, int count) {
if (count > LedgerConsts.MAX_LIST_COUNT) {
throw new IllegalArgumentException("Count exceed the upper limit[" + LedgerConsts.MAX_LIST_COUNT + "]!");
}
if (fromIndex < 0 || (fromIndex + count) > merkleTree.getDataCount()) {
throw new IllegalArgumentException("Index out of bound!");
}
if (count == 0) {
return EMPTY_ENTRIES;
}
@SuppressWarnings("unchecked")
DataEntry<Bytes, byte[]>[] values = new DataEntry[count];
byte[] bytesValue;
@@ -201,6 +214,19 @@ public class MerkleDataSet implements Transactional, MerkleProvable, Dataset<Byt
return values;
}
public DataEntry<Bytes, byte[]> getLatestDataEntry(long index) {
if (index < 0 || index + 1 > merkleTree.getDataCount()) {
throw new IllegalArgumentException("Index out of bound!");
}
byte[] bytesValue;
MerkleDataNode dataNode = merkleTree.getData(index);
Bytes dataKey = encodeDataKey(dataNode.getKey());
bytesValue = valueStorage.get(dataKey, dataNode.getVersion());
DataEntry<Bytes, byte[]> entry = new VersioningKVData<Bytes, byte[]>(dataNode.getKey(), dataNode.getVersion(),
bytesValue);
return entry;
}
/**
* get the data at the specific index;
*
@@ -505,6 +531,16 @@ public class MerkleDataSet implements Transactional, MerkleProvable, Dataset<Byt
return new VersioningKVData<Bytes, byte[]>(key, version, value);
}
@Override
public DataIterator<Bytes, byte[]> iterator() {
return new AscDataInterator(getDataCount());
}
@Override
public DataIterator<Bytes, byte[]> iteratorDesc() {
return new DescDataInterator(getDataCount());
}
public MerkleDataEntry getMerkleEntry(Bytes key, long version) {
DataEntry<Bytes, byte[]> dataEntry = getDataEntry(key, version);
if (dataEntry == null) {
@@ -586,4 +622,119 @@ public class MerkleDataSet implements Transactional, MerkleProvable, Dataset<Byt
merkleTree.cancel();
snGenerator = new MerkleSequenceSNGenerator(merkleTree);
}
// ----------------------------------------------------------
private class AscDataInterator implements DataIterator<Bytes, byte[]> {
private final long total;
private long cursor = 0;
public AscDataInterator(long total) {
this.total = total;
}
@Override
public void skip(long count) {
cursor = nextCursor(count);
}
private long nextCursor(long skippingCount) {
long c = cursor + skippingCount;
return c > total ? total : c;
}
@Override
public DataEntry<Bytes, byte[]> next() {
if (hasNext()) {
DataEntry<Bytes, byte[]> entry = getLatestDataEntry(cursor);
cursor = nextCursor(1);
return entry;
}
return null;
}
@Override
public DataEntry<Bytes, byte[]>[] next(int count) {
if (hasNext()) {
long from = cursor;
long nextCursor = nextCursor(count);
long c = nextCursor - cursor;
if (c > LedgerConsts.MAX_LIST_COUNT) {
throw new IllegalArgumentException(
"Count exceed the upper limit[" + LedgerConsts.MAX_LIST_COUNT + "]!");
}
DataEntry<Bytes, byte[]>[] entries = getLatestDataEntries(from, (int) c);
cursor = nextCursor;
return entries;
}
return EMPTY_ENTRIES;
}
@Override
public boolean hasNext() {
return cursor < total;
}
}
private class DescDataInterator implements DataIterator<Bytes, byte[]> {
private final long total;
private long cursor;
public DescDataInterator(long total) {
this.total = total;
this.cursor = total - 1;
}
@Override
public void skip(long count) {
cursor = nextCursor(count);
}
private long nextCursor(long skippingCount) {
long c = cursor - skippingCount;
return c < 0 ? -1 : c;
}
@Override
public DataEntry<Bytes, byte[]> next() {
if (hasNext()) {
DataEntry<Bytes, byte[]> entry = getLatestDataEntry(cursor);
cursor = nextCursor(1);
return entry;
}
return null;
}
@Override
public DataEntry<Bytes, byte[]>[] next(int count) {
if (hasNext()) {
long nextCursor = nextCursor(count);
long from = nextCursor + 1;
long c = cursor - nextCursor;
if (c > LedgerConsts.MAX_LIST_COUNT) {
throw new IllegalArgumentException(
"Count exceed the upper limit[" + LedgerConsts.MAX_LIST_COUNT + "]!");
}
DataEntry<Bytes, byte[]>[] entries = getLatestDataEntries(from, (int) c);
// reverse;
ArrayUtils.reverse(entries);
cursor = nextCursor;
return entries;
}
return EMPTY_ENTRIES;
}
@Override
public boolean hasNext() {
return cursor < total;
}
}
}

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

@@ -10,7 +10,7 @@ import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.ContractInfo;
import com.jd.blockchain.ledger.DataAccountKVSetOperation;
import com.jd.blockchain.ledger.DataAccountRegisterOperation;
import com.jd.blockchain.ledger.KVDataEntry;
import com.jd.blockchain.ledger.TypedKVEntry;
import com.jd.blockchain.ledger.KVInfoVO;
import com.jd.blockchain.ledger.LedgerAdminInfo;
import com.jd.blockchain.ledger.LedgerBlock;
@@ -172,17 +172,17 @@ public class ContractLedgerContext implements LedgerContext {
}

@Override
public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys) {
public TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys) {
return innerQueryService.getDataEntries(ledgerHash, address, keys);
}

@Override
public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) {
public TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) {
return innerQueryService.getDataEntries(ledgerHash, address, kvInfoVO);
}

@Override
public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count) {
public TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count) {
return innerQueryService.getDataEntries(ledgerHash, address, fromIndex, count);
}



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

@@ -3,7 +3,7 @@ package test.com.jd.blockchain.ledger;
import com.jd.blockchain.contract.ContractEventContext;
import com.jd.blockchain.contract.ContractLifecycleAware;
import com.jd.blockchain.contract.EventProcessingAware;
import com.jd.blockchain.ledger.KVDataEntry;
import com.jd.blockchain.ledger.TypedKVEntry;
import com.jd.blockchain.utils.Bytes;

public class TxTestContractImpl implements TxTestContract, ContractLifecycleAware, EventProcessingAware {
@@ -16,7 +16,7 @@ public class TxTestContractImpl implements TxTestContract, ContractLifecycleAwar

@Override
public boolean testReadable() {
KVDataEntry v1 = eventContext.getLedger().getDataEntries(eventContext.getCurrentLedgerHash(),
TypedKVEntry v1 = eventContext.getLedger().getDataEntries(eventContext.getCurrentLedgerHash(),
dataAddress.toBase58(), KEY)[0];
String text1 = (String) v1.getValue();
System.out.printf("k1=%s, version=%s \r\n", text1, v1.getVersion());
@@ -26,7 +26,7 @@ public class TxTestContractImpl implements TxTestContract, ContractLifecycleAwar
System.out.printf("new value = %s\r\n", newValue);
eventContext.getLedger().dataAccount(dataAddress).setText(KEY, newValue, v1.getVersion());

KVDataEntry v2 = eventContext.getLedger().getDataEntries(eventContext.getCurrentLedgerHash(),
TypedKVEntry v2 = eventContext.getLedger().getDataEntries(eventContext.getCurrentLedgerHash(),
dataAddress.toBase58(), KEY)[0];
System.out.printf("---- read new value ----\r\nk1=%s, version=%s \r\n", v2.getValue(), v2.getVersion());



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

@@ -48,7 +48,8 @@ public class AccountSetTest {

BlockchainKeypair userKey = BlockchainKeyGenerator.getInstance().generate();
accset.register(userKey.getAddress(), userKey.getPubKey());

//尚未提交之前,可以检索到账户的存在,但版本仍然标记为 -1;
MerkleAccount userAcc = accset.getAccount(userKey.getAddress());
assertNotNull(userAcc);
assertTrue(accset.contains(userKey.getAddress()));


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

@@ -6,8 +6,9 @@ import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.consts.DataCodes;

@DataContract(code= DataCodes.CONTRACT_ACCOUNT_HEADER)
public interface ContractInfo extends BlockchainIdentity {
public interface ContractInfo extends BlockchainIdentity, MerkleSnapshot {

@DataField(order=4, primitiveType= PrimitiveType.BYTES)
byte[] getChainCode();

}

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

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

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;

/**
* KV数据项;
*
* <p>
*
* {@link KVDataObject} 被设计为只读对象;
*
* @author huanghaiquan
*
*/
public class KVDataObject implements KVDataEntry {

private String key;

private long version;

private BytesValue bytesValue;

public KVDataObject(String key, long version, BytesValue bytesValue) {
this.key = key;
this.version = version < 0 ? -1 : version;
this.bytesValue = bytesValue;
}

/*
* (non-Javadoc)
*
* @see com.jd.blockchain.ledger.KVDataEntry#getKey()
*/
@Override
public String getKey() {
return key;
}

/*
* (non-Javadoc)
*
* @see com.jd.blockchain.ledger.KVDataEntry#getVersion()
*/
@Override
public long getVersion() {
return version;
}

/*
* (non-Javadoc)
*
* @see com.jd.blockchain.ledger.KVDataEntry#getType()
*/
@Override
public DataType getType() {
return bytesValue == null ? DataType.NIL : bytesValue.getType();
}

@Override
public Object getValue() {
if (bytesValue == null) {
return null;
}

switch (getType()) {
case NIL:
return null;
case TEXT:
return bytesValue.getBytes().toUTF8String();
case BYTES:
return ByteArray.toHex(bytesValue.getBytes().toBytes());
case INT64:
return BytesUtils.toLong(bytesValue.getBytes().toBytes());
case JSON:
return bytesValue.getBytes().toUTF8String();
case XML:
return bytesValue.getBytes().toUTF8String();

default:
throw new IllegalStateException("Unsupported value type[" + getType() + "] to resolve!");
}
}

/**
* 是否为空值;
* <p>
*
* 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#NIL} 时返回 true,其它情况返回 false;
* <p>
*
* @return
*/
public boolean isNil() {
return bytesValue == null || DataType.NIL == bytesValue.getType();
}

/**
* 字节数组形式的原始内容;
*
* @return
*/
Bytes bytesArray() {
return bytesValue.getBytes();
}

/**
* 返回 8 位整数值;
* <p>
*
* 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#INT8} 有效;
* <p>
*
* 无效类型将引发 {@link IllegalStateException} 异常;
*
* @return
*/
public byte tinyValue() {
if (DataType.INT8 == getType()) {
return bytesValue.getBytes().toBytes()[0];
}
throw new IllegalStateException(String.format("Expected type [%s], but [%s]", DataType.INT8, getType()));
}

/**
* 返回 16 位整数值;
* <p>
*
* 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#INT16} 有效;
* <p>
*
* 无效类型将引发 {@link IllegalStateException} 异常;
*
* @return
*/
public short shortValue() {
if (DataType.INT16 == getType()) {
return BytesUtils.toShort(bytesValue.getBytes().toBytes(), 0);
}
throw new IllegalStateException(String.format("Expected type [%s], but [%s]", DataType.INT16, getType()));
}

/**
* 返回 32 位整数值;
* <p>
*
* 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#INT32} 有效;
* <p>
*
* 无效类型将引发 {@link IllegalStateException} 异常;
*
* @return
*/
public int intValue() {
if (DataType.INT32 == getType()) {
return BytesUtils.toInt(bytesValue.getBytes().toBytes(), 0);
}
throw new IllegalStateException(String.format("Expected type [%s], but [%s]", DataType.INT32, getType()));
}

/**
* 返回 64 位整数值;
* <p>
*
* 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#INT64} 有效;
* <p>
*
* 无效类型将引发 {@link IllegalStateException} 异常;
*
* @return
*/
public long longValue() {
if (DataType.INT64 == getType()) {
return BytesUtils.toLong(bytesValue.getBytes().toBytes(), 0);
}
throw new IllegalStateException(String.format("Expected type [%s], but [%s]", DataType.INT64, getType()));

}

/**
* 返回大整数值;
* <p>
*
* 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#BIG_INT} 有效;
* <p>
*
* 无效类型将引发 {@link IllegalStateException} 异常;
*
* @return
*/
public BigInteger bigIntValue() {
if (DataType.BIG_INT == getType()) {
return new BigInteger(bytesValue.getBytes().toBytes());
}
throw new IllegalStateException(
String.format("Expected type [%s], but [%s]", DataType.BIG_INT, getType()));
}

/**
* 返回布尔值;
* <p>
*
* 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#BIG_INT} 有效;
* <p>
*
* 无效类型将引发 {@link IllegalStateException} 异常;
*
* @return
*/
public boolean boolValue() {
if (DataType.BOOLEAN == getType()) {
return BytesUtils.toBoolean(bytesValue.getBytes().toBytes()[0]);
}
throw new IllegalStateException(
String.format("Expected type [%s], but [%s]", DataType.BOOLEAN, getType()));
}

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

/**
* 返回大整数值;
* <p>
*
* 仅当数据类型 {@link #getType()} 为 {@link PrimitiveType#TEXT} /
* {@link PrimitiveType#JSON} / {@link PrimitiveType#XML} 有效;
* <p>
*
* 无效类型将引发 {@link IllegalStateException} 异常;
*
* @return
*/
public String stringValue() {
DataType type = getType();
if (DataType.TEXT == type || DataType.JSON == type || DataType.XML == type) {
return bytesValue.getBytes().toUTF8String();
}
throw new IllegalStateException(String.format("Expected type [%s] or [%s] or [%s] , but [%s]",
PrimitiveType.TEXT, DataType.JSON, DataType.XML, type));
}

// // ----------------
// public KVDataEntry nextVersionNil() {
// return nilState(key, version + 1);
// }
//
// public KVDataEntry nextVersionBoolean(boolean value) {
// return booleanState(key, version + 1, value);
// }
//
// public KVDataEntry nextVersionTiny(byte value) {
// return tinyState(key, version + 1, value);
// }
//
// public KVDataEntry nextVersionShort(short value) {
// return shortState(key, version + 1, value);
// }
//
// public KVDataEntry nextVersionInt(int value) {
// return intState(key, version + 1, value);
// }
//
// public KVDataEntry nextVersionLong(long value) {
// return longState(key, version + 1, value);
// }
//
// public KVDataEntry nextVersionDatetime(Date value) {
// return datetimeState(key, version + 1, value);
// }
//
// public KVDataEntry nextVersionJson(String value) {
// return jsonState(key, version + 1, value);
// }
//
// public KVDataEntry nextVersionXml(String value) {
// return xmlState(key, version + 1, value);
// }
//
// public KVDataEntry nextVersionBigInt(BigInteger value) {
// return bigIntState(key, version + 1, value);
// }
//
// public KVDataEntry nextVersionText(boolean encrypted, String value) {
// return textState(key, version + 1, encrypted, value);
// }
//
// public KVDataEntry nextVersionBytes(boolean encrypted, byte[] value) {
// return bytesState(key, version + 1, encrypted, value);
// }
//
// public KVDataEntry nextVersionImage(boolean encrypted, byte[] value) {
// return imageState(key, version + 1, encrypted, value);
// }
//
// public KVDataEntry nextVersionVideo(boolean encrypted, byte[] value) {
// return videoState(key, version + 1, encrypted, value);
// }
//
// public KVDataEntry nextVersionLocation(boolean encrypted, byte[] value) {
// return locationState(key, version + 1, encrypted, value);
// }
// // ----------------
//
// public KVDataEntry newNil() {
// return nilState(key, version);
// }
//
// public KVDataEntry newBoolean(boolean value) {
// return booleanState(key, version, value);
// }
//
// public KVDataEntry newTiny(byte value) {
// return tinyState(key, version, value);
// }
//
// public KVDataEntry newShort(short value) {
// return shortState(key, version, value);
// }
//
// public KVDataEntry newInt(int value) {
// return intState(key, version, value);
// }
//
// public KVDataObject newLong(long value) {
// return longState(key, version, value);
// }
//
// public KVDataEntry newDatetime(Date value) {
// return datetimeState(key, version, value);
// }
//
// public KVDataEntry newJson(String value) {
// return jsonState(key, version, value);
// }
//
// public KVDataEntry newXml(String value) {
// return xmlState(key, version, value);
// }
//
// public KVDataEntry newBigInt(BigInteger value) {
// return bigIntState(key, version, value);
// }
//
// public KVDataEntry newText(boolean encrypted, String value) {
// return textState(key, version, encrypted, value);
// }
//
// public KVDataEntry newBytes(boolean encrypted, byte[] value) {
// return bytesState(key, version, encrypted, value);
// }
//
// public KVDataEntry newImage(boolean encrypted, byte[] value) {
// return imageState(key, version, encrypted, value);
// }
//
// public KVDataEntry newVideo(boolean encrypted, byte[] value) {
// return videoState(key, version, encrypted, value);
// }
//
// public KVDataEntry newLocation(boolean encrypted, byte[] value) {
// return locationState(key, version, encrypted, value);
// }
//
// // ----------------
//
// public KVDataEntry newNil(long version) {
// return nilState(key, version);
// }
//
// public KVDataEntry newBoolean(long version, boolean value) {
// return booleanState(key, version, value);
// }
//
// public KVDataEntry newTiny(long version, byte value) {
// return tinyState(key, version, value);
// }
//
// public KVDataEntry newShort(long version, short value) {
// return shortState(key, version, value);
// }
//
// public KVDataEntry newInt(long version, int value) {
// return intState(key, version, value);
// }
//
// public KVDataEntry newLong(long version, long value) {
// return longState(key, version, value);
// }
//
// public KVDataEntry newDatetime(long version, Date value) {
// return datetimeState(key, version, value);
// }
//
// public KVDataEntry newJson(long version, String value) {
// return jsonState(key, version, value);
// }
//
// public KVDataEntry newXml(long version, String value) {
// return xmlState(key, version, value);
// }
//
// public KVDataEntry newBigInt(long version, BigInteger value) {
// return bigIntState(key, version, value);
// }
//
// public KVDataEntry newText(long version, boolean encrypted, String value) {
// return textState(key, version, encrypted, value);
// }
//
// public KVDataEntry newBytes(long version, boolean encrypted, byte[] value) {
// return bytesState(key, version, encrypted, value);
// }
//
// public KVDataEntry newImage(long version, boolean encrypted, byte[] value) {
// return imageState(key, version, encrypted, value);
// }
//
// public KVDataEntry newVideo(long version, boolean encrypted, byte[] value) {
// return videoState(key, version, encrypted, value);
// }
//
// public KVDataEntry newLocation(long version, boolean encrypted, byte[] value) {
// return locationState(key, version, encrypted, value);
// }
//
// // ----------------
//
// public static KVDataEntry booleanState(String key, boolean value) {
// return booleanState(key, -1, value);
// }
//
// public static KVDataEntry tinyState(String key, byte value) {
// return tinyState(key, -1, value);
// }
//
// public static KVDataEntry shortState(String key, short value) {
// return shortState(key, -1, value);
// }
//
// public static KVDataEntry intState(String key, int value) {
// return intState(key, -1, value);
// }
//
// public static KVDataEntry longState(String key, long value) {
// return longState(key, -1, value);
// }
//
// public static KVDataEntry datetimeState(String key, Date value) {
// return datetimeState(key, -1, value);
// }
//
// public static KVDataEntry jsonState(String key, String value) {
// return jsonState(key, -1, value);
// }
//
// public static KVDataEntry xmlState(String key, String value) {
// return xmlState(key, -1, value);
// }
//
// public static KVDataEntry bigIntState(String key, BigInteger value) {
// return bigIntState(key, -1, value);
// }
//
// public static KVDataObject textState(String key, String value) {
// return textState(key, -1, false, value);
// }
//
// public static KVDataEntry bytesState(String key, byte[] value) {
// return bytesState(key, -1, false, value);
// }
//
// public static KVDataEntry imageState(String key, byte[] value) {
// return imageState(key, -1, false, value);
// }
//
// public static KVDataEntry videoState(String key, byte[] value) {
// return videoState(key, -1, false, value);
// }
//
// public static KVDataEntry locationState(String key, byte[] value) {
// return locationState(key, -1, false, value);
// }
//
// // ----------------
//
// public static KVDataEntry textState(String key, boolean encrypted, String value) {
// return textState(key, -1, encrypted, value);
// }
//
// public static KVDataEntry bytesState(String key, boolean encrypted, byte[] value) {
// return bytesState(key, -1, encrypted, value);
// }
//
// public static KVDataEntry imageState(String key, boolean encrypted, byte[] value) {
// return imageState(key, -1, encrypted, value);
// }
//
// public static KVDataEntry videoState(String key, boolean encrypted, byte[] value) {
// return videoState(key, -1, encrypted, value);
// }
//
// public static KVDataEntry locationState(String key, boolean encrypted, byte[] value) {
// return locationState(key, -1, encrypted, value);
// }
//
// // ----------------------
//
// public static KVDataEntry nilState(String key) {
// return new KVDataObject(key, ValueType.NIL, -1, false, BytesUtils.EMPTY_BYTES);
// }
//
// public static KVDataEntry nilState(String key, long version) {
// return new KVDataObject(key, ValueType.NIL, version, false, BytesUtils.EMPTY_BYTES);
// }
//
// public static KVDataEntry booleanState(String key, long version, boolean value) {
// byte[] v = { value ? (byte) 1 : (byte) 0 };
// return new KVDataObject(key, ValueType.BOOLEAN, version, false, v);
// }
//
// public static KVDataEntry tinyState(String key, long version, byte value) {
// byte[] v = { value };
// return new KVDataObject(key, ValueType.INT8, version, false, v);
// }
//
// public static KVDataEntry shortState(String key, long version, short value) {
// byte[] v = BytesUtils.toBytes(value);
// return new KVDataObject(key, ValueType.INT16, version, false, v);
// }
//
// public static KVDataEntry intState(String key, long version, int value) {
// byte[] v = BytesUtils.toBytes(value);
// return new KVDataObject(key, ValueType.INT32, version, false, v);
// }
//
// public static KVDataObject longState(String key, long version, long value) {
// byte[] v = BytesUtils.toBytes(value);
// return new KVDataObject(key, ValueType.INT64, version, false, v);
// }
//
// public static KVDataEntry datetimeState(String key, long version, Date value) {
// byte[] v = BytesUtils.toBytes(value.getTime());
// return new KVDataObject(key, ValueType.DATETIME, version, false, v);
// }
//
// public static KVDataObject textState(String key, long version, boolean encrypted, String value) {
// try {
// byte[] v = value.getBytes("UTF-8");
// return new KVDataObject(key, ValueType.TEXT, version, encrypted, v);
// } catch (UnsupportedEncodingException e) {
// throw new IllegalStateException(e.getMessage(), e);
// }
// }
//
// public static KVDataEntry jsonState(String key, long version, String value) {
// try {
// byte[] v = value.getBytes("UTF-8");
// return new KVDataObject(key, ValueType.JSON, version, false, v);
// } catch (UnsupportedEncodingException e) {
// throw new IllegalStateException(e.getMessage(), e);
// }
// }
//
// public static KVDataEntry xmlState(String key, long version, String value) {
// try {
// byte[] v = value.getBytes("UTF-8");
// return new KVDataObject(key, ValueType.XML, version, false, v);
// } catch (UnsupportedEncodingException e) {
// throw new IllegalStateException(e.getMessage(), e);
// }
// }
//
// public static KVDataEntry bigIntState(String key, long version, BigInteger value) {
// byte[] v = value.toByteArray();
// return new KVDataObject(key, ValueType.BIG_INT, version, false, v);
// }
//
// public static KVDataEntry bytesState(String key, long version, boolean encrypted, byte[] value) {
// return new KVDataObject(key, ValueType.BYTES, version, encrypted, value);
// }
//
// public static KVDataEntry imageState(String key, long version, boolean encrypted, byte[] value) {
// return new KVDataObject(key, ValueType.IMG, version, encrypted, value);
// }
//
// public static KVDataEntry videoState(String key, long version, boolean encrypted, byte[] value) {
// return new KVDataObject(key, ValueType.VIDEO, version, encrypted, value);
// }
//
// public static KVDataEntry locationState(String key, long version, boolean encrypted, byte[] value) {
// return new KVDataObject(key, ValueType.LOCATION, version, encrypted, value);
// }

}

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

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

/**
* 强类型的“键-值”数据对象;
*
* <p>
*
* {@link TypedKVData} 被设计为只读对象;
*
* @author huanghaiquan
*
*/
public class TypedKVData implements TypedKVEntry {

private String key;

private long version;

private DataType type;

private Object value;

public TypedKVData(String key, long version, DataType type, Object value) {
this.key = key;
this.version = version;
this.type = type;
this.value = value;
}

public TypedKVData(String key, long version, BytesValue bytesValue) {
this.key = key;
this.version = version;
TypedValue typedValue;
if (bytesValue != null && bytesValue instanceof TypedValue) {
typedValue = (TypedValue) bytesValue;
} else {
typedValue = TypedValue.wrap(bytesValue);
}
this.type = typedValue.getType();
this.value = typedValue.getValue();
}

/*
* (non-Javadoc)
*
* @see com.jd.blockchain.ledger.KVDataEntry#getKey()
*/
@Override
public String getKey() {
return key;
}

/*
* (non-Javadoc)
*
* @see com.jd.blockchain.ledger.KVDataEntry#getVersion()
*/
@Override
public long getVersion() {
return version;
}

/*
* (non-Javadoc)
*
* @see com.jd.blockchain.ledger.KVDataEntry#getType()
*/
@Override
public DataType getType() {
return type;
}

@Override
public Object getValue() {
return value;
}

}

source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/KVDataEntry.java → source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TypedKVEntry.java View File

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

public interface KVDataEntry {
public interface TypedKVEntry {

/**
* 键名;
@@ -33,4 +33,12 @@ public interface KVDataEntry {
*/
Object getValue();
default long longValue() {
if (getType() == DataType.INT64) {
Object value = getValue();
return value == null ? 0 : (long) value;
}
throw new IllegalStateException(String.format("Expected type [%s], but [%s]", DataType.INT64, getType()));
}
}

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

@@ -16,9 +16,9 @@ import com.jd.blockchain.utils.io.BytesUtils;
*
*/
public class TypedValue implements BytesValue {
public static final BytesValue NIL = new TypedValue();
private DataType type;
private Bytes value;

@@ -31,16 +31,19 @@ public class TypedValue implements BytesValue {
this.type = type;
this.value = bytes;
}
private TypedValue(BytesValue bytesValue) {
this.type = bytesValue.getType();
this.value = bytesValue.getBytes();
if (bytesValue == null) {
this.type = DataType.NIL;
} else {
this.type = bytesValue.getType();
this.value = bytesValue.getBytes();
}
}
private TypedValue() {
this.type = DataType.NIL;
}

@Override
public DataType getType() {
@@ -229,8 +232,7 @@ public class TypedValue implements BytesValue {
if (DataType.BIG_INT == type) {
return toBigInteger();
}
throw new IllegalStateException(
String.format("Type [%s] cannot be convert to BigInteger!", type));
throw new IllegalStateException(String.format("Type [%s] cannot be convert to BigInteger!", type));
}

private BigInteger toBigInteger() {
@@ -280,8 +282,7 @@ public class TypedValue implements BytesValue {
if (DataType.TIMESTAMP == type) {
return toDatetime();
}
throw new IllegalStateException(
String.format("Type [%s] cannot be convert to datetime!", type));
throw new IllegalStateException(String.format("Type [%s] cannot be convert to datetime!", type));
}

private Date toDatetime() {
@@ -346,8 +347,7 @@ public class TypedValue implements BytesValue {
if (DataType.HASH_DIGEST == type) {
return toHashDegist();
}
throw new IllegalStateException(
String.format("Type [%s] cannot be convert to hash digest!", type));
throw new IllegalStateException(String.format("Type [%s] cannot be convert to hash digest!", type));
}

private HashDigest toHashDegist() {
@@ -375,14 +375,13 @@ public class TypedValue implements BytesValue {
if (DataType.SIGNATURE_DIGEST == type) {
return toSignatureDigest();
}
throw new IllegalStateException(
String.format("Type [%s] cannot be convert to signature digest!", type));
throw new IllegalStateException(String.format("Type [%s] cannot be convert to signature digest!", type));
}

private SignatureDigest toSignatureDigest() {
return new SignatureDigest(toBytesArray());
}
public static TypedValue wrap(BytesValue value) {
return new TypedValue(value);
}


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

@@ -5,7 +5,7 @@ import org.springframework.cglib.core.Block;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.ContractInfo;
import com.jd.blockchain.ledger.KVDataEntry;
import com.jd.blockchain.ledger.TypedKVEntry;
import com.jd.blockchain.ledger.KVInfoVO;
import com.jd.blockchain.ledger.LedgerAdminInfo;
import com.jd.blockchain.ledger.LedgerBlock;
@@ -264,9 +264,9 @@ public interface BlockchainQueryService {
* @param keys
* @return
*/
KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys);
TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys);
KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO);
TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO);
/**
* 返回指定数据账户中KV数据的总数; <br>
@@ -287,7 +287,7 @@ public interface BlockchainQueryService {
* 如果参数值为 -1,则返回全部的记录;<br>
* @return
*/
KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count);
TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count);
/**
* 返回合约账户信息;


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

@@ -3,7 +3,6 @@ package com.jd.blockchain.peer.web;
import java.util.ArrayList;
import java.util.List;

import com.jd.blockchain.ledger.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
@@ -14,6 +13,22 @@ import org.springframework.web.bind.annotation.RestController;

import com.jd.blockchain.contract.ContractException;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.ContractInfo;
import com.jd.blockchain.ledger.KVDataVO;
import com.jd.blockchain.ledger.KVInfoVO;
import com.jd.blockchain.ledger.LedgerAdminInfo;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerInfo;
import com.jd.blockchain.ledger.LedgerMetadata;
import com.jd.blockchain.ledger.LedgerTransaction;
import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.ledger.TypedKVData;
import com.jd.blockchain.ledger.TypedKVEntry;
import com.jd.blockchain.ledger.TypedValue;
import com.jd.blockchain.ledger.UserInfo;
import com.jd.blockchain.ledger.core.ContractAccountQuery;
import com.jd.blockchain.ledger.core.DataAccount;
import com.jd.blockchain.ledger.core.DataAccountQuery;
@@ -23,7 +38,10 @@ import com.jd.blockchain.ledger.core.ParticipantCertData;
import com.jd.blockchain.ledger.core.TransactionQuery;
import com.jd.blockchain.ledger.core.UserAccountQuery;
import com.jd.blockchain.transaction.BlockchainQueryService;
import com.jd.blockchain.utils.ArrayUtils;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.DataEntry;
import com.jd.blockchain.utils.DataIterator;
import com.jd.blockchain.utils.QueryUtil;

@RestController
@@ -72,7 +90,7 @@ public class LedgerQueryController implements BlockchainQueryService {
}
return null;
}
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/admininfo")
@Override
public LedgerAdminInfo getLedgerAdminInfo(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) {
@@ -337,7 +355,7 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = { RequestMethod.GET,
RequestMethod.POST }, path = "ledgers/{ledgerHash}/accounts/{address}/entries")
@Override
public KVDataEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
public TypedKVEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "address") String address, @RequestParam("keys") String... keys) {
if (keys == null || keys.length == 0) {
return null;
@@ -347,15 +365,15 @@ public class LedgerQueryController implements BlockchainQueryService {
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address));

KVDataEntry[] entries = new KVDataEntry[keys.length];
TypedKVEntry[] entries = new TypedKVEntry[keys.length];
long ver;
for (int i = 0; i < entries.length; i++) {
ver = dataAccount.getDataset().getVersion(keys[i]);
if (ver < 0) {
entries[i] = new KVDataObject(keys[i], -1, null);
entries[i] = new TypedKVData(keys[i], -1, null);
} else {
BytesValue value = dataAccount.getDataset().getValue(keys[i], ver);
entries[i] = new KVDataObject(keys[i], ver, value);
entries[i] = new TypedKVData(keys[i], ver, value);
}
}

@@ -365,7 +383,7 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = { RequestMethod.GET,
RequestMethod.POST }, path = "ledgers/{ledgerHash}/accounts/{address}/entries-version")
@Override
public KVDataEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
public TypedKVEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "address") String address, @RequestBody KVInfoVO kvInfoVO) {
// parse kvInfoVO;
List<String> keyList = new ArrayList<>();
@@ -396,21 +414,21 @@ public class LedgerQueryController implements BlockchainQueryService {
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address));

KVDataEntry[] entries = new KVDataEntry[keys.length];
TypedKVEntry[] entries = new TypedKVEntry[keys.length];
long ver = -1;
for (int i = 0; i < entries.length; i++) {
// ver = dataAccount.getDataVersion(Bytes.fromString(keys[i]));
ver = versions[i];
if (ver < 0) {
entries[i] = new KVDataObject(keys[i], -1, null);
entries[i] = new TypedKVData(keys[i], -1, null);
} else {
if (dataAccount.getDataset().getDataCount() == 0
|| dataAccount.getDataset().getValue(keys[i], ver) == null) {
// is the address is not exist; the result is null;
entries[i] = new KVDataObject(keys[i], -1, null);
entries[i] = new TypedKVData(keys[i], -1, null);
} else {
BytesValue value = dataAccount.getDataset().getValue(keys[i], ver);
entries[i] = new KVDataObject(keys[i], ver, value);
entries[i] = new TypedKVData(keys[i], ver, value);
}
}
}
@@ -421,7 +439,7 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = { RequestMethod.GET,
RequestMethod.POST }, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries")
@Override
public KVDataEntry[] getDataEntries(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
public TypedKVEntry[] 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) {
@@ -431,15 +449,21 @@ public class LedgerQueryController implements BlockchainQueryService {
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
DataAccount dataAccount = dataAccountSet.getAccount(Bytes.fromBase58(address));

int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccount.getDataset().getDataCount());
return dataAccount.getDataEntries(pages[0], pages[1]);
// int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccount.getDataset().getDataCount());
// return dataAccount.getDataEntries(pages[0], pages[1]);

DataIterator<String, TypedValue> iterator = dataAccount.getDataset().iterator();
iterator.skip(fromIndex);
DataEntry<String, TypedValue>[] dataEntries = iterator.next(count);
TypedKVEntry[] typedKVEntries = ArrayUtils.castTo(dataEntries, TypedKVEntry.class,
e -> e == null ? null : new TypedKVData(e.getKey(), e.getVersion(), e.getValue()));
return typedKVEntries;
}

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

LedgerQuery ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block);
@@ -451,7 +475,7 @@ public class LedgerQueryController implements BlockchainQueryService {
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts/address/{address}")
@Override
public ContractInfo getContract(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,
@PathVariable(name = "address") String address) {
@PathVariable(name = "address") String address) {
LedgerQuery ledger = ledgerService.getLedger(ledgerHash);
LedgerBlock block = ledger.getLatestBlock();
ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block);


+ 4
- 4
source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/converters/ClientResolveUtil.java View File

@@ -39,14 +39,14 @@ import com.jd.blockchain.utils.io.BytesUtils;

public class ClientResolveUtil {

public static KVDataEntry[] read(KVDataEntry[] kvDataEntries) {
public static TypedKVEntry[] read(TypedKVEntry[] kvDataEntries) {
if (kvDataEntries == null || kvDataEntries.length == 0) {
return kvDataEntries;
}
KVDataEntry[] resolveKvDataEntries = new KVDataEntry[kvDataEntries.length];
TypedKVEntry[] resolveKvDataEntries = new TypedKVEntry[kvDataEntries.length];
// kvDataEntries是代理对象,需要处理
for (int i = 0; i < kvDataEntries.length; i++) {
KVDataEntry kvDataEntry = kvDataEntries[i];
TypedKVEntry kvDataEntry = kvDataEntries[i];
String key = kvDataEntry.getKey();
long version = kvDataEntry.getVersion();
DataType dataType = kvDataEntry.getType();
@@ -330,7 +330,7 @@ public class ClientResolveUtil {

}

public static class KvData implements KVDataEntry {
public static class KvData implements TypedKVEntry {

private String key;



+ 7
- 7
source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java View File

@@ -3,7 +3,7 @@ package com.jd.blockchain.sdk.proxy;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.ContractInfo;
import com.jd.blockchain.ledger.KVDataEntry;
import com.jd.blockchain.ledger.TypedKVEntry;
import com.jd.blockchain.ledger.KVInfoVO;
import com.jd.blockchain.ledger.LedgerAdminInfo;
import com.jd.blockchain.ledger.LedgerBlock;
@@ -161,20 +161,20 @@ public abstract class BlockchainServiceProxy implements BlockchainService {
}

@Override
public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys) {
KVDataEntry[] kvDataEntries = getQueryService(ledgerHash).getDataEntries(ledgerHash, address, keys);
public TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys) {
TypedKVEntry[] kvDataEntries = getQueryService(ledgerHash).getDataEntries(ledgerHash, address, keys);
return ClientResolveUtil.read(kvDataEntries);
}

@Override
public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) {
KVDataEntry[] kvDataEntries = getQueryService(ledgerHash).getDataEntries(ledgerHash, address, kvInfoVO);
public TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) {
TypedKVEntry[] kvDataEntries = getQueryService(ledgerHash).getDataEntries(ledgerHash, address, kvInfoVO);
return ClientResolveUtil.read(kvDataEntries);
}

@Override
public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count) {
KVDataEntry[] kvDataEntries = getQueryService(ledgerHash).getDataEntries(ledgerHash, address, fromIndex, count);
public TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count) {
TypedKVEntry[] kvDataEntries = getQueryService(ledgerHash).getDataEntries(ledgerHash, address, fromIndex, count);
return ClientResolveUtil.read(kvDataEntries);
}



+ 3
- 3
source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpBlockchainQueryService.java View File

@@ -504,13 +504,13 @@ public interface HttpBlockchainQueryService extends BlockchainExtendQueryService
*/
@HttpAction(method=HttpMethod.POST, path="ledgers/{ledgerHash}/accounts/{address}/entries")
@Override
KVDataEntry[] getDataEntries(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash,
TypedKVEntry[] getDataEntries(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash,
@PathParam(name="address") String address,
@RequestParam(name="keys", array = true) String... keys);

@HttpAction(method=HttpMethod.POST, path="ledgers/{ledgerHash}/accounts/{address}/entries-version")
@Override
KVDataEntry[] getDataEntries(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash,
TypedKVEntry[] getDataEntries(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash,
@PathParam(name="address") String address,
@RequestBody KVInfoVO kvInfoVO);

@@ -531,7 +531,7 @@ public interface HttpBlockchainQueryService extends BlockchainExtendQueryService
*/
@HttpAction(method = HttpMethod.POST, path = "ledgers/{ledgerHash}/accounts/address/{address}/entries")
@Override
KVDataEntry[] getDataEntries(@PathParam(name = "ledgerHash") HashDigest ledgerHash,
TypedKVEntry[] getDataEntries(@PathParam(name = "ledgerHash") HashDigest ledgerHash,
@PathParam(name = "address") String address,
@RequestParam(name = "fromIndex", required = false) int fromIndex,
@RequestParam(name = "count", required = false) int count);


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

@@ -9,8 +9,8 @@ import com.jd.blockchain.contract.ContractException;
import com.jd.blockchain.contract.EventProcessingAware;
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.ledger.TypedKVEntry;
import com.jd.blockchain.ledger.TypedKVData;
import com.jd.blockchain.utils.Bytes;

/**
@@ -47,16 +47,16 @@ public class AssetContractImpl implements EventProcessingAware, AssetContract {
}

// 查询当前值;
KVDataEntry[] kvEntries = eventContext.getLedger().getDataEntries(currentLedgerHash(), ASSET_ADDRESS, KEY_TOTAL,
TypedKVEntry[] kvEntries = eventContext.getLedger().getDataEntries(currentLedgerHash(), ASSET_ADDRESS, KEY_TOTAL,
assetHolderAddress);

// 计算资产的发行总数;
KVDataObject currTotal = (KVDataObject) kvEntries[0];
TypedKVData currTotal = (TypedKVData) kvEntries[0];
long newTotal = currTotal.longValue() + amount;
eventContext.getLedger().dataAccount(ASSET_ADDRESS).setInt64(KEY_TOTAL, newTotal, currTotal.getVersion());
// 分配到持有者账户;
KVDataObject holderAmount = (KVDataObject) kvEntries[1];
TypedKVData holderAmount = (TypedKVData) kvEntries[1];
long newHodlerAmount = holderAmount.longValue() + amount;
eventContext.getLedger().dataAccount(ASSET_ADDRESS)
.setInt64(assetHolderAddress, newHodlerAmount, holderAmount.getVersion()).setText("K2", "info2", -1)
@@ -77,10 +77,10 @@ public class AssetContractImpl implements EventProcessingAware, AssetContract {
checkSignerPermission(fromAddress);

// 查询现有的余额;
KVDataEntry[] origBalances = eventContext.getLedger().getDataEntries(currentLedgerHash(), ASSET_ADDRESS,
TypedKVEntry[] origBalances = eventContext.getLedger().getDataEntries(currentLedgerHash(), ASSET_ADDRESS,
fromAddress, toAddress);
KVDataEntry fromBalanceKV = origBalances[0];
KVDataEntry toBalanceKV = origBalances[1];
TypedKVEntry fromBalanceKV = origBalances[0];
TypedKVEntry toBalanceKV = origBalances[1];
long fromBalance = fromBalanceKV.getVersion() == -1 ? 0 : (long) fromBalanceKV.getValue();
long toBalance = toBalanceKV.getVersion() == -1 ? 0 : (long) toBalanceKV.getValue();



+ 2
- 2
source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_Query.java View File

@@ -4,7 +4,7 @@ import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.BlockchainKeyGenerator;
import com.jd.blockchain.ledger.BlockchainKeypair;
import com.jd.blockchain.ledger.KVDataEntry;
import com.jd.blockchain.ledger.TypedKVEntry;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerTransaction;
import com.jd.blockchain.ledger.Transaction;
@@ -67,7 +67,7 @@ public class SDKDemo_Query {
// 获取数据;
String commerceAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf==";
String[] objKeys = new String[] { "x001", "x002" };
KVDataEntry[] kvData = service.getDataEntries(LEDGER_HASH, commerceAccount, objKeys);
TypedKVEntry[] kvData = service.getDataEntries(LEDGER_HASH, commerceAccount, objKeys);
long payloadVersion = kvData[0].getVersion();


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

@@ -6,7 +6,7 @@ import static com.jd.blockchain.transaction.ContractReturnValue.decode;
import com.jd.blockchain.contract.TransferContract;
import com.jd.blockchain.ledger.BlockchainKeyGenerator;
import com.jd.blockchain.ledger.BlockchainKeypair;
import com.jd.blockchain.ledger.KVDataEntry;
import com.jd.blockchain.ledger.TypedKVEntry;
import com.jd.blockchain.ledger.PreparedTransaction;
import com.jd.blockchain.ledger.TransactionResponse;
import com.jd.blockchain.ledger.TransactionTemplate;
@@ -106,11 +106,11 @@ public class SDK_Contract_Demo extends SDK_Base_Demo {
}

private long readByKvOperation(String address, String account) {
KVDataEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, address, account);
TypedKVEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, address, account);
if (kvDataEntries == null || kvDataEntries.length == 0) {
throw new IllegalStateException(String.format("Ledger %s Service inner Error !!!", ledgerHash.toBase58()));
}
KVDataEntry kvDataEntry = kvDataEntries[0];
TypedKVEntry kvDataEntry = kvDataEntries[0];
if (kvDataEntry.getVersion() == -1) {
return 0L;
}


+ 2
- 2
source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Contract_Random_Demo.java View File

@@ -79,11 +79,11 @@ public class SDK_Contract_Random_Demo extends SDK_Base_Demo {
}

private long readByKvOperation(String address, String account) {
KVDataEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, address, account);
TypedKVEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, address, account);
if (kvDataEntries == null || kvDataEntries.length == 0) {
throw new IllegalStateException(String.format("Ledger %s Service inner Error !!!", ledgerHash.toBase58()));
}
KVDataEntry kvDataEntry = kvDataEntries[0];
TypedKVEntry kvDataEntry = kvDataEntries[0];
if (kvDataEntry.getVersion() == -1) {
return 0L;
}


+ 2
- 2
source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_InsertData_Demo.java View File

@@ -107,9 +107,9 @@ public class SDK_InsertData_Demo extends SDK_Base_Demo {
// KVDataEntry[] kvData = blockchainService.getDataEntries(ledgerHash, commerceAccount, objKeys);

// 获取数据账户下所有的KV列表
KVDataEntry[] kvData = blockchainService.getDataEntries(ledgerHash, commerceAccount, 0, 100);
TypedKVEntry[] kvData = blockchainService.getDataEntries(ledgerHash, commerceAccount, 0, 100);
if (kvData != null && kvData.length > 0) {
for (KVDataEntry kvDatum : kvData) {
for (TypedKVEntry kvDatum : kvData) {
System.out.println("kvData.key=" + kvDatum.getKey());
System.out.println("kvData.version=" + kvDatum.getVersion());
System.out.println("kvData.type=" + kvDatum.getType());


+ 3
- 3
source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_GateWay_Query_Test_.java View File

@@ -24,7 +24,7 @@ import com.jd.blockchain.ledger.BlockchainKeyGenerator;
import com.jd.blockchain.ledger.BlockchainKeypair;
import com.jd.blockchain.ledger.DigitalSignature;
import com.jd.blockchain.ledger.EndpointRequest;
import com.jd.blockchain.ledger.KVDataEntry;
import com.jd.blockchain.ledger.TypedKVEntry;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerInfo;
import com.jd.blockchain.ledger.LedgerTransaction;
@@ -149,8 +149,8 @@ public class SDK_GateWay_Query_Test_ {

String commerceAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf==";
String[] objKeys = new String[] { "x001", "x002" };
KVDataEntry[] kvData = service.getDataEntries(ledgerHash, commerceAccount, objKeys);
for (KVDataEntry kvDatum : kvData) {
TypedKVEntry[] kvData = service.getDataEntries(ledgerHash, commerceAccount, objKeys);
for (TypedKVEntry kvDatum : kvData) {
System.out.println("kvData.key=" + kvDatum.getKey());
System.out.println("kvData.version=" + kvDatum.getVersion());
System.out.println("kvData.value=" + kvDatum.getValue());


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

@@ -26,7 +26,7 @@ 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.TypedKVEntry;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerInfo;
import com.jd.blockchain.ledger.LedgerInitProperties;
@@ -216,8 +216,8 @@ public class IntegrationTest {
ledgerOfNode0.retrieveLatestBlock(); // 更新内存

// 先验证应答
KVDataEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, dataAccountAddress, dataKey);
for (KVDataEntry kvDataEntry : kvDataEntries) {
TypedKVEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, dataAccountAddress, dataKey);
for (TypedKVEntry kvDataEntry : kvDataEntries) {
String valHexText = (String) kvDataEntry.getValue();
byte[] valBytes = HexUtils.decode(valHexText);
String valText = new String(valBytes);


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

@@ -286,8 +286,8 @@ public class IntegrationBase {
assertEquals(txResp.getContentHash(), transactionHash);
assertEquals(txResp.getBlockHash(), ledgerRepository.getLatestBlockHash());

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


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

@@ -26,7 +26,7 @@ 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.TypedKVEntry;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerInfo;
import com.jd.blockchain.ledger.LedgerInitProperties;
@@ -302,9 +302,9 @@ public class IntegrationTestAll4Redis {
assertEquals(txResp.getContentHash(), prepTx.getHash());
assertEquals(txResp.getBlockHash(), ledgerRepository.getLatestBlockHash());

KVDataEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, dataAccountAddress.toString(),
TypedKVEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, dataAccountAddress.toString(),
dataKey);
for (KVDataEntry kvDataEntry : kvDataEntries) {
for (TypedKVEntry kvDataEntry : kvDataEntries) {
assertEquals(dataKey, kvDataEntry.getKey());
String valHexText = (String) kvDataEntry.getValue();
byte[] valBytes = HexUtils.decode(valHexText);


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

@@ -23,7 +23,7 @@ import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig;
import com.jd.blockchain.ledger.BlockchainKeyGenerator;
import com.jd.blockchain.ledger.BlockchainKeypair;
import com.jd.blockchain.ledger.DataAccountKVSetOperation;
import com.jd.blockchain.ledger.KVDataEntry;
import com.jd.blockchain.ledger.TypedKVEntry;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerInitProperties;
import com.jd.blockchain.ledger.PreparedTransaction;
@@ -214,7 +214,7 @@ public class IntegrationTestDataAccount {
e.printStackTrace();
}

KVDataEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHashs[0], dataAddr.toBase58(), "A", "B",
TypedKVEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHashs[0], dataAddr.toBase58(), "A", "B",
"C", "D");
for (int i = 0; i < kvDataEntries.length; i++) {
Object result = kvDataEntries[i].getValue();


+ 52
- 17
source/utils/utils-common/src/main/java/com/jd/blockchain/utils/ArrayUtils.java View File

@@ -9,17 +9,29 @@ import java.util.*;
*/
public abstract class ArrayUtils {
private ArrayUtils() {
}
public static <T, R> R[] castTo(T[] objs, Class<R> clazz, CastFunction<T, R> cf) {
if (objs == null) {
return null;
}
@SuppressWarnings("unchecked")
R[] array = (R[]) Array.newInstance(clazz, objs.length);
for (int i = 0; i < objs.length; i++) {
array[i] = cf.cast(objs[i]);
}
return array;
}
public static <T> T[] singleton(T obj, Class<T> clazz) {
@SuppressWarnings("unchecked")
T[] array = (T[]) Array.newInstance(clazz, 1);
array[0] = obj;
return array;
}
public static <T> T[] toArray(Iterator<T> itr, Class<T> clazz){
public static <T> T[] toArray(Iterator<T> itr, Class<T> clazz) {
List<T> lst = new LinkedList<T>();
while (itr.hasNext()) {
T t = (T) itr.next();
@@ -30,19 +42,19 @@ public abstract class ArrayUtils {
lst.toArray(array);
return array;
}
public static <T> T[] toArray(Collection<T> collection, Class<T> clazz){
public static <T> T[] toArray(Collection<T> collection, Class<T> clazz) {
@SuppressWarnings("unchecked")
T[] array = (T[]) Array.newInstance(clazz, collection.size());
collection.toArray(array);
return array;
}
public static <T> List<T> asList(T[] array){
public static <T> List<T> asList(T[] array) {
return asList(array, 0, array.length);
}
public static <T> Set<T> asSet(T[] array){
public static <T> Set<T> asSet(T[] array) {
if (array == null || array.length == 0) {
return Collections.emptySet();
}
@@ -52,8 +64,8 @@ public abstract class ArrayUtils {
}
return set;
}
public static <T> SortedSet<T> asSortedSet(T[] array){
public static <T> SortedSet<T> asSortedSet(T[] array) {
if (array == null || array.length == 0) {
return Collections.emptySortedSet();
}
@@ -63,12 +75,12 @@ public abstract class ArrayUtils {
}
return set;
}
public static <T> List<T> asList(T[] array, int fromIndex){
public static <T> List<T> asList(T[] array, int fromIndex) {
return asList(array, fromIndex, array.length);
}
public static <T> List<T> asList(T[] array, int fromIndex, int toIndex){
public static <T> List<T> asList(T[] array, int fromIndex, int toIndex) {
if (toIndex < fromIndex) {
throw new IllegalArgumentException("The toIndex less than fromIndex!");
}
@@ -78,10 +90,33 @@ public abstract class ArrayUtils {
if (toIndex > array.length) {
throw new IllegalArgumentException("The toIndex great than the length of array!");
}
if (fromIndex == toIndex) {
return Collections.emptyList();
}
return new ReadonlyArrayListWrapper<T>(array, fromIndex, toIndex);
}
public static interface CastFunction<T, R> {
public R cast(T data);
}
/**
* Reverse all elements of the specified array; <br>
*
* @param <T>
* @param array
*/
public static <T> void reverse(T[] array) {
if (array == null || array.length < 2) {
return;
}
T t;
for (int i = 0, j = array.length - 1; i < j; i++, j--) {
t = array[i];
array[i] = array[j];
array[j] = t;
}
}
}

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

@@ -1,7 +1,5 @@
package com.jd.blockchain.utils;
import java.io.File;
/**
*
* @author zhaogw


+ 1
- 1
source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DataEntry.java View File

@@ -1,7 +1,7 @@
package com.jd.blockchain.utils;
/**
* 版本化的键值数据项
* Versioning Key-Value data entry
*
* @author huanghaiquan
*


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

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

/**
* 数据迭代器;
*
* @author huanghaiquan
*
* @param <K>
* @param <V>
*/
public interface DataIterator<K, V> {

void skip(long count);
DataEntry<K, V> next();

DataEntry<K, V>[] next(int count);
boolean hasNext();
}

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

@@ -1,34 +0,0 @@
package com.jd.blockchain.utils;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import org.springframework.util.TypeUtils;
public abstract class DataTypeUtils {
private static Map<Class<?>, Class<?>> wrapperTypes = new HashMap<Class<?>, Class<?>>();
static{
wrapperTypes.put(long.class, Long.class);
wrapperTypes.put(int.class, Integer.class);
wrapperTypes.put(char.class, Character.class);
wrapperTypes.put(byte.class, Byte.class);
wrapperTypes.put(boolean.class, Boolean.class);
}
public static boolean isAssignable(Type lhsType, Type rhsType) {
boolean assignable = TypeUtils.isAssignable(lhsType, rhsType);
if (assignable) {
return true;
}
if (lhsType instanceof Class) {
Class<?> lhsClass = (Class<?>) lhsType;
}
return false;
}
}

+ 39
- 33
source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Dataset.java View File

@@ -1,7 +1,20 @@
package com.jd.blockchain.utils;

/**
* Key-Value data set;
*
* @author huanghaiquan
*
* @param <K>
* @param <V>
*/
public interface Dataset<K, V> {

/**
* Total count of data entries;
*
* @return
*/
long getDataCount();

/**
@@ -26,17 +39,6 @@ public interface Dataset<K, V> {
*/
long setValue(K key, V value, long version);

// /**
// * Return the specified version's value;<br>
// *
// * If the key with the specified version doesn't exist, then return null;<br>
// * If the version is specified to -1, then return the latest version's value;
// *
// * @param key
// * @param version
// */
// byte[] getValue(String key, long version);

/**
* Return the specified version's value;<br>
*
@@ -48,47 +50,51 @@ public interface Dataset<K, V> {
*/
V getValue(K key, long version);

// /**
// * Return the latest version's value;
// *
// * @param key
// * @return return null if not exist;
// */
// byte[] getValue(String key);

/**
* Return the latest version's value;
* Return the value of the latest version;
*
* @param key
* @return return null if not exist;
*/
V getValue(K key);

// /**
// * Return the latest version entry associated the specified key; If the key
// * doesn't exist, then return -1;
// *
// * @param key
// * @return
// */
// long getVersion(String key);

/**
* Return the latest version entry associated the specified key; If the key
* doesn't exist, then return -1;
* Return the latest version number of the specified key;
*
* @param key
* @return
* @return The version number of the specified key; If the key doesn't exist,
* then return -1;
*/
long getVersion(K key);

/**
* Return data entry
*
* @param key
* @return Null if the key doesn't exist!
*/
DataEntry<K, V> getDataEntry(K key);

/**
*
* @param key
* @param version
* @return
*/
DataEntry<K, V> getDataEntry(K key, long version);

/**
* Ascending iterator;
*
* @return
*/
DataIterator<K, V> iterator();

/**
* Descending iterator;
*
* @return
*/
DataIterator<K, V> iteratorDesc();

}

+ 87
- 6
source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DatasetHelper.java View File

@@ -1,8 +1,12 @@
package com.jd.blockchain.utils;

/**
* Helper for {@link Dataset};
*
* @author huanghaiquan
*
*/
public class DatasetHelper {

public static final TypeMapper<Bytes, String> UTF8_STRING_BYTES_MAPPER = new TypeMapper<Bytes, String>() {

@@ -29,7 +33,7 @@ public class DatasetHelper {
return Bytes.fromString(t2);
}
};
/**
* 适配两个不同类型参数的数据集;
*
@@ -121,8 +125,8 @@ public class DatasetHelper {
T2 decode(T1 t1);

}
private static class EmptyMapper<T> implements TypeMapper<T, T>{
private static class EmptyMapper<T> implements TypeMapper<T, T> {

@Override
public T encode(T t) {
@@ -133,7 +137,7 @@ public class DatasetHelper {
public T decode(T t) {
return t;
}
}

private static class DatasetUpdatingMonitor<K, V> implements Dataset<K, V> {
@@ -186,6 +190,16 @@ public class DatasetHelper {
return dataset.getDataEntry(key, version);
}

@Override
public DataIterator<K, V> iterator() {
return dataset.iterator();
}

@Override
public DataIterator<K, V> iteratorDesc() {
return dataset.iteratorDesc();
}

}

/**
@@ -269,6 +283,73 @@ public class DatasetHelper {
return new KeyValueEntry<K2, V2>(key, v, entry.getVersion());
}

@Override
public DataIterator<K2, V2> iterator() {
DataIterator<K1, V1> it = dataset.iterator();
return new DataIteratorAdapter<K1, K2, V1, V2>(it, keyMapper, valueMapper);
}

@Override
public DataIterator<K2, V2> iteratorDesc() {
DataIterator<K1, V1> it = dataset.iteratorDesc();
return new DataIteratorAdapter<K1, K2, V1, V2>(it, keyMapper, valueMapper);
}

}

private static class DataIteratorAdapter<K1, K2, V1, V2> implements DataIterator<K2, V2> {

private DataIterator<K1, V1> iterator;

private TypeMapper<K1, K2> keyMapper;
private TypeMapper<V1, V2> valueMapper;

public DataIteratorAdapter(DataIterator<K1, V1> iterator, TypeMapper<K1, K2> keyMapper,
TypeMapper<V1, V2> valueMapper) {
this.iterator = iterator;
this.keyMapper = keyMapper;
this.valueMapper = valueMapper;
}

@Override
public void skip(long count) {
iterator.skip(count);
}

@Override
public DataEntry<K2, V2> next() {
DataEntry<K1, V1> entry = iterator.next();
return cast(entry);
}

private DataEntry<K2, V2> cast(DataEntry<K1, V1> entry) {
if (entry == null) {
return null;
}

K2 k = keyMapper.decode(entry.getKey());
V2 v = valueMapper.decode(entry.getValue());
return new KeyValueEntry<K2, V2>(k, v, entry.getVersion());
}

@SuppressWarnings("unchecked")
@Override
public DataEntry<K2, V2>[] next(int count) {
DataEntry<K1, V1>[] entries = iterator.next(count);
if (entries == null) {
return null;
}
if (entries.length == 0) {
return (DataEntry<K2, V2>[]) entries;
}
return ArrayUtils.castTo(entries, DataEntry.class, e -> cast(e));
}

@Override
public boolean hasNext() {
return iterator.hasNext();
}

}

private static class KeyValueEntry<K, V> implements DataEntry<K, V> {


Loading…
Cancel
Save