use of com.jd.blockchain.storage.service.utils.VersioningKVData in project jdchain-core by blockchain-jd-com.
the class MerkleHashSortTreeTest method assertDataEquals.
private void assertDataEquals(VersioningKVData<String, byte[]>[] datas, SkippingIterator<KVEntry> kvIter) {
Map<String, VersioningKVData<String, byte[]>> dataMap = new HashMap<>();
for (VersioningKVData<String, byte[]> dt : datas) {
dataMap.put(dt.getKey(), dt);
}
assertEquals(datas.length, kvIter.getTotalCount());
Set<String> keyReadSet = new HashSet<String>();
while (kvIter.hasNext()) {
KVEntry kvEntry = (KVEntry) kvIter.next();
String strKey = kvEntry.getKey().toUTF8String();
assertFalse(keyReadSet.contains(strKey));
assertTrue(dataMap.containsKey(strKey));
VersioningKVData<String, byte[]> dt = dataMap.get(strKey);
assertEquals(dt.getVersion(), kvEntry.getVersion());
assertArrayEquals(dt.getValue(), kvEntry.getValue().toBytes());
keyReadSet.add(strKey);
}
}
use of com.jd.blockchain.storage.service.utils.VersioningKVData in project jdchain-core by blockchain-jd-com.
the class MerkleHashSortTreeTest method testDataIterator.
/**
* 测试浏览默克尔树的所有数据节点;
*/
@Test
public void testDataIterator() {
int count = 1024;
List<VersioningKVData<String, byte[]>> dataList = generateDatas(count);
VersioningKVData<String, byte[]>[] datas = toArray(dataList);
MerkleHashSortTree merkleTree = newMerkleTree_with_committed(datas);
HashDigest rootHash = merkleTree.getRootHash();
assertNotNull(rootHash);
assertEquals(count, merkleTree.getTotalKeys());
Map<String, VersioningKVData<String, byte[]>> dataMap = new HashMap<String, VersioningKVData<String, byte[]>>();
for (VersioningKVData<String, byte[]> data : datas) {
dataMap.put(data.getKey(), data);
}
Iterator<KVEntry> dataIterator = merkleTree.iterator();
String[] dataKeys = new String[count];
int index = 0;
while (dataIterator.hasNext()) {
KVEntry data = dataIterator.next();
assertNotNull(data);
String key = data.getKey().toUTF8String();
assertTrue(dataMap.containsKey(key));
dataMap.remove(key);
dataKeys[index] = key;
index++;
}
assertEquals(0, dataMap.size());
assertEquals(count, index);
SkippingIterator<KVEntry> skippingIterator = merkleTree.iterator();
testDataIteratorSkipping(dataKeys, skippingIterator, 0);
skippingIterator = merkleTree.iterator();
testDataIteratorSkipping(dataKeys, skippingIterator, 1);
skippingIterator = merkleTree.iterator();
testDataIteratorSkipping(dataKeys, skippingIterator, 2);
skippingIterator = merkleTree.iterator();
testDataIteratorSkipping(dataKeys, skippingIterator, 16);
skippingIterator = merkleTree.iterator();
testDataIteratorSkipping(dataKeys, skippingIterator, 128);
skippingIterator = merkleTree.iterator();
testDataIteratorSkipping(dataKeys, skippingIterator, 1023);
skippingIterator = merkleTree.iterator();
testDataIteratorSkipping(dataKeys, skippingIterator, 1024);
}
use of com.jd.blockchain.storage.service.utils.VersioningKVData in project jdchain-core by blockchain-jd-com.
the class MerkleHashSortTreeTest method testReloading.
/**
* 测试树的加载读取;
*/
@Test
public void testReloading() {
TreeOptions cryptoSetting = createTreeOptions();
MemoryKVStorage storage = new MemoryKVStorage();
// 数据集合长度为 100 时也能正常生成;
int count = 1024;
List<VersioningKVData<String, byte[]>> dataList = generateDatas(count);
VersioningKVData<String, byte[]>[] datas = toArray(dataList);
MerkleHashSortTree merkleTree = newMerkleTree_with_committed(datas, cryptoSetting, storage);
HashDigest rootHash0 = merkleTree.getRootHash();
assertNotNull(rootHash0);
assertEquals(count, merkleTree.getTotalKeys());
// TODO: 暂时注释掉默克尔证明相关的内容;
// for (VersioningKVData<String, byte[]> data : datas) {
// assertMerkleProof(data, merkleTree);
// }
// testMerkleProof1024(datas, merkleTree);
MerkleHashSortTree merkleTree_reload = new MerkleHashSortTree(rootHash0, cryptoSetting, KEY_PREFIX, storage);
assertEquals(count, merkleTree_reload.getTotalKeys());
// TODO: 暂时注释掉默克尔证明相关的内容;
// testMerkleProof1024(datas, merkleTree_reload);
VersioningKVData<String, byte[]> data28 = new VersioningKVData<String, byte[]>("KEY-28", 1, BytesUtils.toBytes("NEW-VALUE-VERSION-1"));
VersioningKVData<String, byte[]> data606 = new VersioningKVData<String, byte[]>("KEY-606", 1, BytesUtils.toBytes("NEW-VALUE-VERSION-1"));
VersioningKVData<String, byte[]> data770 = new VersioningKVData<String, byte[]>("KEY-770", 1, BytesUtils.toBytes("NEW-VALUE-VERSION-1"));
VersioningKVData<String, byte[]> data898 = new VersioningKVData<String, byte[]>("KEY-898", 1, BytesUtils.toBytes("NEW-VALUE-VERSION-1"));
VersioningKVData<String, byte[]> data69 = new VersioningKVData<String, byte[]>("KEY-69", 1, BytesUtils.toBytes("NEW-VALUE-VERSION-1"));
merkleTree_reload.setData(data28.getKey(), data28.getVersion(), data28.getValue());
merkleTree_reload.setData(data606.getKey(), data606.getVersion(), data606.getValue());
merkleTree_reload.setData(data770.getKey(), data770.getVersion(), data770.getValue());
merkleTree_reload.setData(data898.getKey(), data898.getVersion(), data898.getValue());
merkleTree_reload.setData(data69.getKey(), data69.getVersion(), data69.getValue());
merkleTree_reload.commit();
HashDigest rootHash1 = merkleTree_reload.getRootHash();
assertNotNull(rootHash1);
assertNotEquals(rootHash0, rootHash1);
// TODO: 暂时注释掉默克尔证明相关的内容;
// MerkleProof proof = merkleTree_reload.getProof(data28.getKey(), 1);
// assertNotNull(proof);
// MerkleProofLevel[] hashPaths = proof.getProofLevels();
// assertEquals(5, hashPaths.length);
// proof = merkleTree_reload.getProof(data28.getKey(), 0);
// assertNotNull(proof);
// hashPaths = proof.getProofLevels();
// assertEquals(6, hashPaths.length);
KVEntry data28_reload_0 = merkleTree_reload.getData(data28.getKey(), 0);
assertNotNull(data28_reload_0);
assertEquals(data28.getKey(), data28_reload_0.getKey().toUTF8String());
assertEquals(datas[28].getVersion(), data28_reload_0.getVersion());
assertArrayEquals(datas[28].getValue(), data28_reload_0.getValue().toBytes());
KVEntry data28_reload_1 = merkleTree_reload.getData(data28.getKey(), 1);
assertNotNull(data28_reload_1);
assertEquals(data28.getKey(), data28_reload_1.getKey().toUTF8String());
assertEquals(data28.getVersion(), data28_reload_1.getVersion());
assertArrayEquals(data28.getValue(), data28_reload_1.getValue().toBytes());
// merkleTree_reload.print();
// 测试不同根哈希加载的默克尔树能够检索的最新版本;
MerkleHashSortTree merkleTree_0 = new MerkleHashSortTree(rootHash0, cryptoSetting, KEY_PREFIX, storage);
MerkleHashSortTree merkleTree_1 = new MerkleHashSortTree(rootHash1, cryptoSetting, KEY_PREFIX, storage);
KVEntry data28_reload = merkleTree_0.getData(data28.getKey());
assertEquals(0, data28_reload.getVersion());
data28_reload = merkleTree_1.getData(data28.getKey());
assertEquals(1, data28_reload.getVersion());
// 测试在修改状态下检索默克尔证明的正确性;
VersioningKVData<String, byte[]> data28_2 = new VersioningKVData<String, byte[]>("KEY-28", 2, BytesUtils.toBytes("NEW-VALUE-VERSION-2"));
// TODO: 暂时注释掉默克尔证明相关的内容;
// MerkleProof proof28_1 = merkleTree_1.getProof("KEY-28", 1);
// MerkleProof proof606_1 = merkleTree_1.getProof("KEY-606", 1);
// assertNotNull(proof28_1);
// assertNotNull(proof606_1);
// 针对编号为 28 的数据加入一条新版本记录;
merkleTree_1.setData(data28_2.getKey(), data28_2.getVersion(), data28_2.getValue());
// TODO: 暂时注释掉默克尔证明相关的内容;
// 对于修改中的数据项,查询未提交的最新版本数据的默克尔证明为 null,但是其已提交版本的证明不受影响;
// 此外,其它未修改的数据项的默克尔证明也不受影响;
// MerkleProof proof28_1_1 = merkleTree_1.getProof("KEY-28", 1);
// MerkleProof proof28_2 = merkleTree_1.getProof("KEY-28", 2);
// MerkleProof proof606_1_1 = merkleTree_1.getProof("KEY-606", 1);
// assertNotNull(proof28_1_1);
// assertNotNull(proof606_1_1);
// assertNull(proof28_2);
// assertEquals(proof28_1, proof28_1_1);
// assertEquals(proof606_1, proof606_1_1);
// 当提交修改之后,可以获取到修改数据项的最新版本的证明,同时其旧版本的证明也刷新了中间路径(加入了新版本数据节点);
merkleTree_1.commit();
// TODO: 暂时注释掉默克尔证明相关的内容;
// MerkleProof proof28_1_2 = merkleTree_1.getProof("KEY-28", 1);
// MerkleProof proof28_2_1 = merkleTree_1.getProof("KEY-28", 2);
// MerkleProof proof606_1_2 = merkleTree_1.getProof("KEY-606", 1);
// assertNotNull(proof28_1_2);
// assertNotNull(proof28_2_1);
// assertNotNull(proof606_1_2);
// TODO: 暂时注释掉默克尔证明相关的内容;
// 由于默克尔树发生了修改,所有默克尔证明发生了改变;
// assertFalse(proof28_1.equals(proof28_1_2));
// assertFalse(proof606_1.equals(proof606_1_2));
// 同一个key的数据项的最新版本的默克尔证明路径节点中数据节点部分(倒数第2项),出现在其前一个版本的更新后的数据证明中倒数第3项;
// 验证默克尔证明的长度增长;
// MerkleProof proof28_5 = merkleTree_1.getProof("KEY-28", 0);
// assertNotNull(proof28_5);
// hashPaths = proof28_5.getProofLevels();
// assertEquals(7, hashPaths.length);
// TODO: 暂时注释掉默克尔证明相关的内容;
// 重新加载默克尔树,默克尔证明是一致的;
// MerkleHashSortTree merkleTree_1_1 = new MerkleHashSortTree(rootHash1, cryptoSetting, KEY_PREFIX, storage);
// MerkleProof proof28_4 = merkleTree_1_1.getProof("KEY-28", 1);
// assertNotNull(proof28_4);
// assertEquals(proof28_1, proof28_4);
// merkleTree_1.print();
}
use of com.jd.blockchain.storage.service.utils.VersioningKVData 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.storage.service.utils.VersioningKVData in project jdchain-core by blockchain-jd-com.
the class MerkleHashSortTreeTest method createNewVersion.
private VersioningKVData<String, byte[]> createNewVersion(VersioningKVData<String, byte[]>[] datas, int newIndex) {
Random rand = new Random();
byte[] bytes = new byte[16];
rand.nextBytes(bytes);
VersioningKVData<String, byte[]> newData = new VersioningKVData<String, byte[]>(datas[newIndex].getKey(), datas[newIndex].getVersion() + 1, bytes);
datas[newIndex] = newData;
return newData;
}
Aggregations