use of com.jd.blockchain.ledger.merkletree.KVEntry in project jdchain-core by blockchain-jd-com.
the class MerkleHashSortTreeTest method testReadUncommitting.
/**
* 验证 HashSortingMerkleTree 在未提交之前的总数和根哈希维持不变的特性,新增的数据记录可读,但是具有临时性,一旦回滚则被清除;
*/
@Test
public void testReadUncommitting() {
// 数据集合长度为 1024 时也能正常生成;
int count = 100;
List<VersioningKVData<String, byte[]>> dataList = generateDatas(count);
VersioningKVData<String, byte[]>[] datas = toArray(dataList);
TreeOptions treeOption = createTreeOptions();
MemoryKVStorage storage = new MemoryKVStorage();
MerkleHashSortTree merkleTree = new MerkleHashSortTree(treeOption, KEY_PREFIX, storage);
setDatas(merkleTree, datas);
assertDataExist(merkleTree, datas);
// 未提交之前查不到信息;
assertNull(merkleTree.getRootHash());
assertEquals(0, merkleTree.getTotalKeys());
KVEntry dt = merkleTree.getData("KEY-69");
assertNotNull(dt);
assertEquals(0, dt.getVersion());
dt = merkleTree.getData("KEY-69", 0);
assertNotNull(dt);
assertEquals(0, dt.getVersion());
dt = merkleTree.getData("KEY-69", 1);
assertNull(dt);
// 提交;
merkleTree.commit();
// 重新加载;
HashDigest rootHash = merkleTree.getRootHash();
assertNotNull(rootHash);
merkleTree = new MerkleHashSortTree(rootHash, treeOption, KEY_PREFIX, storage);
// 测试写入数据的多版本;
VersioningKVData<String, byte[]> data69 = new VersioningKVData<String, byte[]>("KEY-69", 1, BytesUtils.toBytes("NEW-VALUE-VERSION-1"));
merkleTree.setData(data69.getKey(), data69.getVersion(), data69.getValue());
dt = merkleTree.getData("KEY-69", 1);
assertNotNull(dt);
assertEquals(1, dt.getVersion());
merkleTree.commit();
rootHash = merkleTree.getRootHash();
assertNotNull(rootHash);
// 预期键的总数不变;
assertEquals(count, merkleTree.getTotalKeys());
dt = merkleTree.getData("KEY-69");
assertNotNull(dt);
assertEquals(1, dt.getVersion());
dt = merkleTree.getData("KEY-69", 0);
assertNotNull(dt);
assertEquals(0, dt.getVersion());
dt = merkleTree.getData("KEY-69", 1);
assertNotNull(dt);
assertEquals(1, dt.getVersion());
// 整体地验证数据的存在性;
datas[69] = data69;
assertDataExist(merkleTree, datas);
}
use of com.jd.blockchain.ledger.merkletree.KVEntry in project jdchain-core by blockchain-jd-com.
the class MerkleHashTrieTest method testMerkleTreeDiffNewLeafType.
@Test
public void testMerkleTreeDiffNewLeafType() {
CryptoSetting cryptoSetting = createCryptoSetting();
MemoryKVStorage storage = new MemoryKVStorage();
List<String> newdataListString = new ArrayList<String>();
List<String> dataListString = new ArrayList<String>();
List<VersioningKVData<String, byte[]>> dataList = new ArrayList<VersioningKVData<String, byte[]>>();
List<VersioningKVData<String, byte[]>> newdataList = new ArrayList<VersioningKVData<String, byte[]>>();
int count = 1;
int newAddCount = 1;
VersioningKVData<String, byte[]> orginData0 = new VersioningKVData<String, byte[]>("KEY-0", 0L, BytesUtils.concat(BytesUtils.toBytes(0), BytesUtils.toBytes("VALUE")));
dataList.add(orginData0);
dataListString.add(orginData0.getKey());
VersioningKVData<String, byte[]>[] datas = toArray(dataList);
MerkleHashTrie merkleTree = newMerkleTree_with_committed(datas, cryptoSetting, storage);
HashDigest rootHash0 = merkleTree.getRootHash();
assertNotNull(rootHash0);
assertEquals(count, merkleTree.getTotalKeys());
assertEquals(count, merkleTree.getTotalRecords());
// reload and add random key data item;
MerkleHashTrie merkleTree_reload = new MerkleHashTrie(rootHash0, cryptoSetting, KEY_PREFIX, storage, false);
assertEquals(count, merkleTree_reload.getTotalKeys());
assertEquals(count, merkleTree_reload.getTotalRecords());
assertEquals(rootHash0, merkleTree_reload.getRootHash());
VersioningKVData<String, byte[]> data0 = new VersioningKVData<String, byte[]>("KEY-1741789838495252", 0L, BytesUtils.concat(BytesUtils.toBytes(0), BytesUtils.toBytes("VALUE")));
newdataList.add(data0);
for (int i = 0; i < newdataList.size(); i++) {
merkleTree_reload.setData(newdataList.get(i).getKey(), newdataList.get(i).getVersion(), newdataList.get(i).getValue());
newdataListString.add(newdataList.get(i).getKey());
}
merkleTree_reload.commit();
HashDigest rootHash1 = merkleTree_reload.getRootHash();
assertNotNull(rootHash1);
assertNotEquals(rootHash0, rootHash1);
assertEquals(count + newAddCount, merkleTree_reload.getTotalKeys());
assertEquals(count + newAddCount, merkleTree_reload.getTotalRecords());
SkippingIterator<KVEntry> diffIterator = merkleTree_reload.getKeyDiffIterator(merkleTree);
// max boundary skip test
assertEquals(newAddCount, diffIterator.getTotalCount());
assertEquals(-1, diffIterator.getCursor());
assertTrue(diffIterator.hasNext());
long skipped = diffIterator.skip(newAddCount);
assertEquals(newAddCount, skipped);
assertFalse(diffIterator.hasNext());
// re-interator and random skip test
int skipNum = 0;
diffIterator = merkleTree_reload.getKeyDiffIterator(merkleTree);
assertEquals(newAddCount, diffIterator.getTotalCount());
assertEquals(-1, diffIterator.getCursor());
assertTrue(diffIterator.hasNext());
long skipped1 = diffIterator.skip(skipNum);
assertEquals(skipNum, skipped1);
int diffNum = 0;
// TODO: 无效的验证逻辑; by huanghaiquan at 2020-07-15;
// while (diffIterator.hasNext()) {
// MerkleData data = diffIterator.next();
// assertNotNull(data);
// assertFalse(dataList.contains(new String(data.getKey())));
// assertTrue(newdataListString.contains(new String(data.getKey())));
// diffNum++;
// }
// assertEquals(diffNum, diffIterator.getCount() - skipNum);
// re-interator and next test
diffIterator = merkleTree_reload.getKeyDiffIterator(merkleTree);
int diffNum1 = 0;
assertEquals(newAddCount, diffIterator.getTotalCount());
while (diffIterator.hasNext()) {
KVEntry data = diffIterator.next();
assertNotNull(data);
diffNum1++;
}
assertFalse(diffIterator.hasNext());
assertEquals(newAddCount - 1, diffIterator.getCursor());
assertEquals(newAddCount, diffIterator.getTotalCount());
assertEquals(diffNum1, diffIterator.getTotalCount());
// re-interator and test next key consistency
diffIterator = merkleTree_reload.getKeyDiffIterator(merkleTree);
// TODO: 无效的验证逻辑; by huanghaiquan at 2020-07-15;
// while (diffIterator.hasNext()) {
// MerkleData data = diffIterator.next();
// assertNotNull(data);
// assertFalse(dataList.contains(new String(data.getKey())));
// assertTrue(newdataListString.contains(new String(data.getKey())));
// }
}
use of com.jd.blockchain.ledger.merkletree.KVEntry in project jdchain-core by blockchain-jd-com.
the class MerkleHashDataset method getDataEntries.
@Override
public DataEntry<Bytes, byte[]>[] getDataEntries(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.getTotalKeys()) {
throw new IllegalArgumentException("Index out of bound!");
}
if (count == 0) {
return EMPTY_ENTRIES;
}
@SuppressWarnings("unchecked") DataEntry<Bytes, byte[]>[] values = new DataEntry[count];
byte[] bytesValue;
SkippingIterator<KVEntry> iterator = merkleTree.iterator();
iterator.skip(fromIndex);
for (int i = 0; i < count && iterator.hasNext(); i++) {
KVEntry dataNode = iterator.next();
Bytes dataKey = encodeDataKey(dataNode.getKey());
bytesValue = valueStorage.get(dataKey, dataNode.getVersion());
values[i] = new VersioningKVData<Bytes, byte[]>(dataNode.getKey(), dataNode.getVersion(), bytesValue);
}
return values;
}
use of com.jd.blockchain.ledger.merkletree.KVEntry in project jdchain-core by blockchain-jd-com.
the class MerkleHashDataset method getDataEntryAt.
public DataEntry<Bytes, byte[]> getDataEntryAt(long index) {
if (index < 0 || index + 1 > merkleTree.getTotalKeys()) {
throw new IllegalArgumentException("Index out of bound!");
}
byte[] bytesValue;
SkippingIterator<KVEntry> iterator = merkleTree.iterator();
iterator.skip(index);
if (iterator.hasNext()) {
KVEntry dataNode = iterator.next();
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;
}
return null;
}
use of com.jd.blockchain.ledger.merkletree.KVEntry in project jdchain-core by blockchain-jd-com.
the class MerkleHashDataset method getValues.
public byte[][] getValues(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.getTotalKeys()) {
throw new IllegalArgumentException("The specified from-index and count are out of bound!");
}
byte[][] values = new byte[count][];
SkippingIterator<KVEntry> iterator = merkleTree.iterator();
iterator.skip(fromIndex);
for (int i = 0; i < count && iterator.hasNext(); i++) {
KVEntry dataNode = iterator.next();
Bytes dataKey = encodeDataKey(dataNode.getKey());
values[i] = valueStorage.get(dataKey, dataNode.getVersion());
}
return values;
}
Aggregations