Search in sources :

Example 1 with MerkleHashSortTree

use of com.jd.blockchain.ledger.merkletree.MerkleHashSortTree in project jdchain-core by blockchain-jd-com.

the class MerkleHashSortTreeTest method testImmutability.

/**
 * 测试 Merkle 根哈希的不变性,即相同的数据集合得到相同的默克尔树根哈希,与数据加入的先后顺序无关;
 */
@Test
public void testImmutability() {
    // 长度为 0 的情况;
    int count = 0;
    // System.out.printf("\r\n\r\n================= %s 个节点 =================\r\n\r\n", count);
    List<VersioningKVData<String, byte[]>> dataList = generateDatas(count);
    VersioningKVData<String, byte[]>[] datas = toArray(dataList);
    HashDigest rootHash0_1 = buildMerkleRootHash(datas);
    HashDigest rootHash0_2 = buildMerkleRootHash(datas);
    assertNotNull(rootHash0_1);
    assertNotNull(rootHash0_2);
    assertEquals(rootHash0_1, rootHash0_2);
    // 长度为 1 的情况;
    count = 1;
    // System.out.printf("\r\n\r\n================= %s 个节点 =================\r\n\r\n", count);
    dataList = generateDatas(count);
    datas = toArray(dataList);
    HashDigest rootHash1_1 = buildMerkleRootHash(datas);
    HashDigest rootHash1_2 = buildMerkleRootHash(datas);
    assertNotNull(rootHash1_1);
    assertNotNull(rootHash1_2);
    assertEquals(rootHash1_1, rootHash1_2);
    // 长度为 2 的情况;
    count = 2;
    // System.out.printf("\r\n\r\n================= %s 个节点 =================\r\n\r\n", count);
    dataList = generateDatas(count);
    datas = toArray(dataList);
    VersioningKVData<String, byte[]>[] datas1 = toArray(dataList);
    datas1[0] = datas[1];
    datas1[1] = datas[0];
    HashDigest rootHash2_1 = buildMerkleRootHash(datas);
    HashDigest rootHash2_2 = buildMerkleRootHash(datas1);
    assertNotNull(rootHash2_1);
    assertNotNull(rootHash2_2);
    assertEquals(rootHash2_1, rootHash2_2);
    // 长度为 8 的情况;
    count = 8;
    // System.out.printf("\r\n\r\n================= %s 个节点 =================\r\n\r\n", count);
    dataList = generateDatas(count);
    datas = toArray(dataList);
    datas1 = getRandomSortingCopy(datas);
    HashDigest rootHash_N1 = buildMerkleRootHash(datas);
    HashDigest rootHash_N2 = buildMerkleRootHash(datas1);
    assertNotNull(rootHash_N1);
    assertNotNull(rootHash_N2);
    assertEquals(rootHash_N1, rootHash_N2);
    // 长度为 16 的情况;
    count = 16;
    // System.out.printf("\r\n\r\n================= %s 个节点 =================\r\n\r\n", count);
    dataList = generateDatas(count);
    datas = toArray(dataList);
    datas1 = getRandomSortingCopy(datas);
    rootHash_N1 = buildMerkleRootHash(datas);
    rootHash_N2 = buildMerkleRootHash(datas1);
    assertNotNull(rootHash_N1);
    assertNotNull(rootHash_N2);
    assertEquals(rootHash_N1, rootHash_N2);
    // 长度为 32 的情况;
    count = 32;
    // System.out.printf("\r\n\r\n================= %s 个节点 =================\r\n\r\n", count);
    dataList = generateDatas(count);
    datas = toArray(dataList);
    datas1 = getRandomSortingCopy(datas);
    rootHash_N1 = buildMerkleRootHash(datas);
    rootHash_N2 = buildMerkleRootHash(datas1);
    assertNotNull(rootHash_N1);
    assertNotNull(rootHash_N2);
    assertEquals(rootHash_N1, rootHash_N2);
    // 长度为 1025 的情况;
    count = 1025;
    // System.out.printf("\r\n\r\n================= %s 个节点 =================\r\n\r\n", count);
    dataList = generateDatas(count);
    datas = toArray(dataList);
    datas1 = getRandomSortingCopy(datas);
    MerkleHashSortTree merkleTree = newMerkleTree_with_committed(datas);
    MerkleHashSortTree merkleTree1 = newMerkleTree_with_committed(datas1);
    assertEquals(rootHash_N1, rootHash_N2);
    assertEqualsTrie(merkleTree, merkleTree1);
}
Also used : HashDigest(com.jd.blockchain.crypto.HashDigest) MerkleHashSortTree(com.jd.blockchain.ledger.merkletree.MerkleHashSortTree) VersioningKVData(com.jd.blockchain.storage.service.utils.VersioningKVData) Test(org.junit.Test)

Example 2 with MerkleHashSortTree

use of com.jd.blockchain.ledger.merkletree.MerkleHashSortTree in project jdchain-core by blockchain-jd-com.

the class MerkleHashSortTreeTest method newMerkleTree.

private MerkleHashSortTree newMerkleTree(VersioningKVData<String, byte[]>[] datas, TreeOptions treeOption, ExPolicyKVStorage storage, boolean commit) {
    MerkleHashSortTree merkleTree = new MerkleHashSortTree(treeOption, KEY_PREFIX, storage);
    assertTrue(merkleTree.isUpdated());
    setDatas(merkleTree, datas);
    if (commit) {
        merkleTree.commit();
        assertFalse(merkleTree.isUpdated());
    }
    return merkleTree;
}
Also used : MerkleHashSortTree(com.jd.blockchain.ledger.merkletree.MerkleHashSortTree)

Example 3 with MerkleHashSortTree

use of com.jd.blockchain.ledger.merkletree.MerkleHashSortTree 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());
}
Also used : VersioningKVData(com.jd.blockchain.storage.service.utils.VersioningKVData) KVEntry(com.jd.blockchain.ledger.merkletree.KVEntry) Random(java.util.Random) SecureRandom(java.security.SecureRandom) TreeOptions(com.jd.blockchain.ledger.merkletree.TreeOptions) HashDigest(com.jd.blockchain.crypto.HashDigest) MemoryKVStorage(com.jd.blockchain.storage.service.utils.MemoryKVStorage) MerkleHashSortTree(com.jd.blockchain.ledger.merkletree.MerkleHashSortTree) Test(org.junit.Test)

Example 4 with MerkleHashSortTree

use of com.jd.blockchain.ledger.merkletree.MerkleHashSortTree 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);
    }
}
Also used : Bytes(utils.Bytes) KVEntry(com.jd.blockchain.ledger.merkletree.KVEntry) TreeOptions(com.jd.blockchain.ledger.merkletree.TreeOptions) HashDigest(com.jd.blockchain.crypto.HashDigest) MemoryKVStorage(com.jd.blockchain.storage.service.utils.MemoryKVStorage) MerkleHashSortTree(com.jd.blockchain.ledger.merkletree.MerkleHashSortTree) VersioningKVData(com.jd.blockchain.storage.service.utils.VersioningKVData) Test(org.junit.Test)

Example 5 with MerkleHashSortTree

use of com.jd.blockchain.ledger.merkletree.MerkleHashSortTree 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);
    }
}
Also used : KVEntry(com.jd.blockchain.ledger.merkletree.KVEntry) TreeOptions(com.jd.blockchain.ledger.merkletree.TreeOptions) HashDigest(com.jd.blockchain.crypto.HashDigest) MemoryKVStorage(com.jd.blockchain.storage.service.utils.MemoryKVStorage) MerkleHashSortTree(com.jd.blockchain.ledger.merkletree.MerkleHashSortTree) VersioningKVData(com.jd.blockchain.storage.service.utils.VersioningKVData) Test(org.junit.Test)

Aggregations

MerkleHashSortTree (com.jd.blockchain.ledger.merkletree.MerkleHashSortTree)14 HashDigest (com.jd.blockchain.crypto.HashDigest)11 VersioningKVData (com.jd.blockchain.storage.service.utils.VersioningKVData)11 Test (org.junit.Test)11 KVEntry (com.jd.blockchain.ledger.merkletree.KVEntry)9 TreeOptions (com.jd.blockchain.ledger.merkletree.TreeOptions)8 MemoryKVStorage (com.jd.blockchain.storage.service.utils.MemoryKVStorage)8 Random (java.util.Random)2 Bytes (utils.Bytes)2 MerkleProof (com.jd.blockchain.ledger.MerkleProof)1 MerkleTree (com.jd.blockchain.ledger.merkletree.MerkleTree)1 SecureRandom (java.security.SecureRandom)1 HashMap (java.util.HashMap)1