use of com.jd.blockchain.storage.service.utils.VersioningKVData in project jdchain-core by blockchain-jd-com.
the class MerkleHashSortTreeTest method testReloadTreeAddRandomNewDataNode.
/**
* 对已存在的树进行重载,增加新的数据节点,通过重载树验证新节点是否添加成功,total keys 与total records
* 是否符合预期,新添加的数据节点Key随机产生
*/
@Test
public void testReloadTreeAddRandomNewDataNode() {
Random random = new Random();
byte[] bytes = new byte[200];
random.nextBytes(bytes);
String newDataKey = bytes.toString();
TreeOptions treeOptions = createTreeOptions();
MemoryKVStorage storage = new MemoryKVStorage();
int count = 1024;
List<VersioningKVData<String, byte[]>> dataList = generateDatas(count);
VersioningKVData<String, byte[]>[] datas = toArray(dataList);
MerkleHashSortTree merkleTree = newMerkleTree_with_committed(datas, treeOptions, storage);
HashDigest rootHash0 = merkleTree.getRootHash();
assertNotNull(rootHash0);
assertEquals(count, merkleTree.getTotalKeys());
// reload and add one data item;
MerkleHashSortTree merkleTree_reload = new MerkleHashSortTree(rootHash0, treeOptions, KEY_PREFIX, storage);
assertEquals(count, merkleTree_reload.getTotalKeys());
assertEquals(rootHash0, merkleTree_reload.getRootHash());
VersioningKVData<String, byte[]> data1025 = new VersioningKVData<String, byte[]>(newDataKey, 0, BytesUtils.toBytes("NEW-VALUE-1025-VERSION-0"));
merkleTree_reload.setData(data1025.getKey(), data1025.getVersion(), data1025.getValue());
merkleTree_reload.commit();
HashDigest rootHash1 = merkleTree_reload.getRootHash();
assertNotNull(rootHash1);
assertNotEquals(rootHash0, rootHash1);
KVEntry data1025_reload_0 = merkleTree_reload.getData(data1025.getKey(), 0);
assertNotNull(data1025_reload_0);
KVEntry data0_reload_0 = merkleTree_reload.getData("KEY-0", 0);
assertNotNull(data0_reload_0);
System.out.println("mkl reload total keys = " + merkleTree_reload.getTotalKeys());
assertEquals(count + 1, merkleTree_reload.getTotalKeys());
MerkleHashSortTree merkleTree_reload_1 = new MerkleHashSortTree(rootHash1, treeOptions, KEY_PREFIX, storage);
assertEquals(count + 1, merkleTree_reload_1.getTotalKeys());
assertEquals(rootHash1, merkleTree_reload_1.getRootHash());
HashDigest rootHash2 = merkleTree_reload_1.getRootHash();
assertNotNull(rootHash2);
assertNotEquals(rootHash0, rootHash2);
KVEntry data1025_reload_1 = merkleTree_reload_1.getData(data1025.getKey(), 0);
assertNotNull(data1025_reload_1);
KVEntry data0_reload_1 = merkleTree_reload_1.getData("KEY-0", 0);
assertNotNull(data0_reload_1);
System.out.println("mkl reload total keys = " + merkleTree_reload_1.getTotalKeys());
assertEquals(count + 1, merkleTree_reload_1.getTotalKeys());
}
use of com.jd.blockchain.storage.service.utils.VersioningKVData in project jdchain-core by blockchain-jd-com.
the class MerkleHashSortTreeTest method testExtendPersistedPathNodes.
/**
* 测试在已经持久化的默克尔树上追加新节点时,扩展已有路径节点的正确性;
*/
@Test
public void testExtendPersistedPathNodes() {
int count = 10240;
List<VersioningKVData<String, byte[]>> dataList = generateDatas(count);
VersioningKVData<String, byte[]>[] datas = toArray(dataList);
TreeOptions treeOption = createTreeOptions();
MemoryKVStorage storage = new MemoryKVStorage();
Bytes prefix = Bytes.fromString(LedgerTestUtils.LEDGER_KEY_PREFIX);
MerkleHashSortTree merkleTree = new MerkleHashSortTree(treeOption, prefix, storage);
int firstBatch = 500;
for (int i = 0; i < firstBatch; i++) {
merkleTree.setData(datas[i].getKey(), datas[i].getVersion(), datas[i].getValue());
}
// 先提交;
merkleTree.commit();
// 加载默克尔树到新实例;
HashDigest rootHash = merkleTree.getRootHash();
MerkleHashSortTree merkleTree1 = new MerkleHashSortTree(rootHash, treeOption, prefix, storage);
for (int i = firstBatch; i < datas.length; i++) {
merkleTree1.setData(datas[i].getKey(), datas[i].getVersion(), datas[i].getValue());
}
merkleTree1.commit();
// 重新加载;未正确扩展路径节点时,部分已持久化的叶子节点有可能丢失,在重新加载默克尔树并进行检索时将发现此错误;
rootHash = merkleTree1.getRootHash();
MerkleHashSortTree merkleTree2 = new MerkleHashSortTree(rootHash, treeOption, prefix, storage);
for (int i = 0; i < datas.length; i++) {
KVEntry data = merkleTree2.getData(datas[i].getKey());
assertNotNull(data);
}
}
use of com.jd.blockchain.storage.service.utils.VersioningKVData in project jdchain-core by blockchain-jd-com.
the class MerkleHashSortTreeTest method testAddDataWithHashConfliction.
/**
* 测试加入存在哈希冲突(基于 {@link MerkleHashSortTree#MURMUR3_HASH_POLICY}
* 哈希策略)的数据时是否能够正确处理;<br>
*/
@Test
public void testAddDataWithHashConfliction() {
// 8 位哈希最多有 256 个值,设置数据的总数大于 256 必然产生哈希冲突,可以验证哈希桶处理多个 key 的情况;
int count = 300;
List<VersioningKVData<String, byte[]>> dataList = generateDatas(count);
VersioningKVData<String, byte[]>[] datas = toArray(dataList);
TreeOptions treeOption = createTreeOptions();
MemoryKVStorage storage = new MemoryKVStorage();
MerkleHashSortTree merkleTree = new HashTreeIn8Bits(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();
assertEquals(count, merkleTree.getTotalKeys());
// 重新加载;
HashDigest rootHash = merkleTree.getRootHash();
assertNotNull(rootHash);
merkleTree = new HashTreeIn8Bits(rootHash, treeOption, KEY_PREFIX, storage);
assertEquals(count, merkleTree.getTotalKeys());
assertDataExist(merkleTree, datas);
// 验证迭代器;
SkippingIterator<KVEntry> kvIter = merkleTree.iterator();
assertDataEquals(datas, kvIter);
// 验证增加不同版本;
{
VersioningKVData<String, byte[]> newData = createNewVersion(datas, 2);
VersioningKVData<String, byte[]> newData1 = createNewVersion(datas, 26);
VersioningKVData<String, byte[]> newData2 = createNewVersion(datas, 8);
VersioningKVData<String, byte[]> newData3 = createNewVersion(datas, 2);
merkleTree.setData(newData.getKey(), newData.getVersion(), newData.getValue());
merkleTree.setData(newData1.getKey(), newData1.getVersion(), newData1.getValue());
merkleTree.setData(newData2.getKey(), newData2.getVersion(), newData2.getValue());
merkleTree.setData(newData3.getKey(), newData3.getVersion(), newData3.getValue());
// 验证最新数据;
assertDataExist(merkleTree, datas);
// 迭代器返回不包含未提交的数据;
// kvIter = merkleTree.iterator();
// assertDataEquals(datas, kvIter);
merkleTree.commit();
// 验证提交之后的数据;
kvIter = merkleTree.iterator();
assertDataEquals(datas, kvIter);
}
}
use of com.jd.blockchain.storage.service.utils.VersioningKVData in project jdchain-core by blockchain-jd-com.
the class MerkleHashSortTreeTest method testCancel.
/**
* 验证 HashSortingMerkleTree 在未提交之前,新增的数据记录可读和可回滚特性;
*/
@Test
public void testCancel() {
// 数据集合长度为 1024 时也能正常生成;
int count = 1024;
List<VersioningKVData<String, byte[]>> dataList = generateDatas(count);
VersioningKVData<String, byte[]>[] datas = toArray(dataList);
MerkleHashSortTree merkleTree = newMerkleTree(datas);
assertTrue(merkleTree.isUpdated());
// 未提交之前查不到信息;
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);
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());
assertTrue(merkleTree.isUpdated());
// 回滚全部数据;
merkleTree.cancel();
HashDigest rootHash = merkleTree.getRootHash();
assertNull(rootHash);
assertEquals(0, merkleTree.getTotalKeys());
dt = merkleTree.getData("KEY-69");
assertNull(dt);
dt = merkleTree.getData("KEY-69", 0);
assertNull(dt);
dt = merkleTree.getData("KEY-69", 1);
assertNull(dt);
// 对于新创建的空的默克尔树的 updated 属性为 true,回滚之后仍然是空的,此时预期 updated 属性为 true;
assertTrue(merkleTree.isUpdated());
// 加入数据,提交后继续加入数据,验证能够正常回滚到上一次提交;
setDatas(merkleTree, datas);
merkleTree.commit();
assertDataExist(merkleTree, datas);
int count2 = 200;
List<VersioningKVData<String, byte[]>> dataList2 = generateDatasFrom(count, count2);
VersioningKVData<String, byte[]>[] datas2 = toArray(dataList2);
setDatas(merkleTree, datas2);
// 在回滚之前,验证全部的数据都存在;
assertDataExist(merkleTree, datas);
assertDataExist(merkleTree, datas2);
// 回滚未提交的第二批数据;
merkleTree.cancel();
// 验证仅剩第一批数据;
assertDataExist(merkleTree, datas);
assertDataNotExist(merkleTree, datas2);
}
use of com.jd.blockchain.storage.service.utils.VersioningKVData in project jdchain-core by blockchain-jd-com.
the class MerkleHashSortTreeTest method testReloadTreeAddNewDataNode.
/**
* 对已存在的树进行重载,增加新的数据节点,通过重载树验证新节点是否添加成功,total keys 与total records
* 是否符合预期,新添加的数据节点Key具有一定的规律
*/
@Test
public void testReloadTreeAddNewDataNode() {
TreeOptions cryptoSetting = createTreeOptions();
MemoryKVStorage storage = new MemoryKVStorage();
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());
// reload and add one data item;
MerkleHashSortTree merkleTree_reload = new MerkleHashSortTree(rootHash0, cryptoSetting, KEY_PREFIX, storage);
assertEquals(count, merkleTree_reload.getTotalKeys());
assertEquals(rootHash0, merkleTree_reload.getRootHash());
VersioningKVData<String, byte[]> data1025 = new VersioningKVData<String, byte[]>("KEY-1025", 0, BytesUtils.toBytes("NEW-VALUE-1025-VERSION-0"));
merkleTree_reload.setData(data1025.getKey(), data1025.getVersion(), data1025.getValue());
merkleTree_reload.commit();
HashDigest rootHash1 = merkleTree_reload.getRootHash();
assertNotNull(rootHash1);
assertNotEquals(rootHash0, rootHash1);
KVEntry data1025_reload_0 = merkleTree_reload.getData(data1025.getKey(), 0);
assertNotNull(data1025_reload_0);
KVEntry data0_reload_0 = merkleTree_reload.getData("KEY-0", 0);
assertNotNull(data0_reload_0);
System.out.println("mkl reload total keys = " + merkleTree_reload.getTotalKeys());
assertEquals(count + 1, merkleTree_reload.getTotalKeys());
MerkleHashSortTree merkleTree_reload_1 = new MerkleHashSortTree(rootHash1, cryptoSetting, KEY_PREFIX, storage);
assertEquals(count + 1, merkleTree_reload_1.getTotalKeys());
assertEquals(rootHash1, merkleTree_reload_1.getRootHash());
HashDigest rootHash2 = merkleTree_reload_1.getRootHash();
assertNotNull(rootHash2);
assertNotEquals(rootHash0, rootHash2);
KVEntry data1025_reload_1 = merkleTree_reload_1.getData(data1025.getKey(), 0);
assertNotNull(data1025_reload_1);
KVEntry data0_reload_1 = merkleTree_reload_1.getData("KEY-0", 0);
assertNotNull(data0_reload_1);
System.out.println("mkl reload total keys = " + merkleTree_reload_1.getTotalKeys());
assertEquals(count + 1, merkleTree_reload_1.getTotalKeys());
}
Aggregations