Search in sources :

Example 11 with TreeOptions

use of com.jd.blockchain.ledger.merkletree.TreeOptions 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());
}
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)

Example 12 with TreeOptions

use of com.jd.blockchain.ledger.merkletree.TreeOptions 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();
}
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)

Example 13 with TreeOptions

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

the class MerkleHashSortTreeTest method testHashBucket.

/**
 */
@Test
public void testHashBucket() {
    byte[][] keys = new byte[4][];
    byte[][] values = new byte[4][];
    for (int i = 0; i < keys.length; i++) {
        keys[i] = BytesUtils.toBytes("KEY-" + i);
        values[i] = RandomUtils.generateRandomBytes(16);
    }
    TreeOptions treeOptions = TreeOptions.build().setDefaultHashAlgorithm(ClassicAlgorithm.SHA256.code());
    Bytes bucketPrefix = Bytes.fromString("BUCKET");
    MemoryKVStorage kvStorage = new MemoryKVStorage();
    MerkleHashBucket hashBucket = new MerkleHashBucket(100, keys[0], values[0], TreeDegree.D3, treeOptions, bucketPrefix, kvStorage);
    // 验证初始化之后的数据是否正确;
    assertEquals(1, hashBucket.getKeysCount());
    MerkleValue<byte[]> value = hashBucket.getValue(keys[0]);
    assertNotNull(value);
    assertEquals(0, value.getId());
    assertArrayEquals(values[0], value.getValue());
    assertEquals(0, hashBucket.getVersion(keys[0]));
    MerkleValue<byte[]> value_v1 = hashBucket.getValue(keys[0], 1);
    assertNull(value_v1);
    MerkleValue<byte[]> value1_v1 = hashBucket.getValue(keys[1], 0);
    assertNull(value1_v1);
    // 提交数据;
    hashBucket.commit();
    // 模拟对默尔克哈希桶的存储;
    byte[] bucketBytes = BinaryProtocol.encode(hashBucket, HashBucketEntry.class);
    HashBucketEntry bucketEntry = BinaryProtocol.decode(bucketBytes);
    // 重新加载;
    hashBucket = new MerkleHashBucket(100, bucketEntry.getKeySet(), TreeDegree.D3, treeOptions, bucketPrefix, kvStorage);
    // 验证重新加载之后的数据正确性;
    value = hashBucket.getValue(keys[0]);
    assertNotNull(value);
    assertEquals(0, value.getId());
    assertArrayEquals(values[0], value.getValue());
    assertEquals(0, hashBucket.getVersion(keys[0]));
    assertEquals(1, hashBucket.getKeysCount());
    SkippingIterator<MerkleValue<HashEntry>> keysIterator = hashBucket.iterator();
    assertEquals(1, keysIterator.getTotalCount());
    assertTrue(keysIterator.hasNext());
    MerkleValue<HashEntry> entry = keysIterator.next();
    assertNotNull(entry);
    assertTrue(entry.getValue() instanceof BytesKeyValue);
    BytesKeyValue kv = (BytesKeyValue) entry.getValue();
    assertArrayEquals(keys[0], kv.getKey().toBytes());
    assertArrayEquals(values[0], kv.getValue().toBytes());
    // 验证加入新的键;
    for (int i = 1; i < keys.length; i++) {
        hashBucket.setValue(keys[i], 0, values[i]);
    }
    assertEquals(keys.length, hashBucket.getKeysCount());
    for (int i = 0; i < keys.length; i++) {
        value = hashBucket.getValue(keys[i]);
        assertNotNull(value);
        // id 即版本;
        assertEquals(0, value.getId());
        assertArrayEquals(values[i], value.getValue());
        assertEquals(0, hashBucket.getVersion(keys[i]));
    }
    hashBucket.commit();
    // 重新加载并验证数据;
    bucketBytes = BinaryProtocol.encode(hashBucket, HashBucketEntry.class);
    bucketEntry = BinaryProtocol.decode(bucketBytes);
    hashBucket = new MerkleHashBucket(100, bucketEntry.getKeySet(), TreeDegree.D3, treeOptions, bucketPrefix, kvStorage);
    assertEquals(keys.length, hashBucket.getKeysCount());
    for (int i = 0; i < keys.length; i++) {
        value = hashBucket.getValue(keys[i]);
        assertNotNull(value);
        // id 即版本;
        assertEquals(0, value.getId());
        assertArrayEquals(values[i], value.getValue());
        assertEquals(0, hashBucket.getVersion(keys[i]));
    }
}
Also used : MerkleHashBucket(com.jd.blockchain.ledger.merkletree.MerkleHashBucket) Bytes(utils.Bytes) HashEntry(com.jd.blockchain.ledger.merkletree.HashEntry) HashBucketEntry(com.jd.blockchain.ledger.merkletree.HashBucketEntry) TreeOptions(com.jd.blockchain.ledger.merkletree.TreeOptions) BytesKeyValue(com.jd.blockchain.ledger.merkletree.BytesKeyValue) MemoryKVStorage(com.jd.blockchain.storage.service.utils.MemoryKVStorage) MerkleValue(com.jd.blockchain.ledger.merkletree.MerkleValue) Test(org.junit.Test)

Example 14 with TreeOptions

use of com.jd.blockchain.ledger.merkletree.TreeOptions 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);
}
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)

Example 15 with TreeOptions

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

the class MerkleHashSortTreeTest method newMerkleTree_with_committed.

private MerkleHashSortTree newMerkleTree_with_committed(VersioningKVData<String, byte[]>[] datas) {
    TreeOptions treeOption = createTreeOptions();
    MemoryKVStorage storage = new MemoryKVStorage();
    return newMerkleTree(datas, treeOption, storage, true);
}
Also used : TreeOptions(com.jd.blockchain.ledger.merkletree.TreeOptions) MemoryKVStorage(com.jd.blockchain.storage.service.utils.MemoryKVStorage)

Aggregations

TreeOptions (com.jd.blockchain.ledger.merkletree.TreeOptions)21 MemoryKVStorage (com.jd.blockchain.storage.service.utils.MemoryKVStorage)21 Test (org.junit.Test)15 HashDigest (com.jd.blockchain.crypto.HashDigest)10 MerkleHashSortTree (com.jd.blockchain.ledger.merkletree.MerkleHashSortTree)8 KVEntry (com.jd.blockchain.ledger.merkletree.KVEntry)7 VersioningKVData (com.jd.blockchain.storage.service.utils.VersioningKVData)6 MerkleValue (com.jd.blockchain.ledger.merkletree.MerkleValue)5 Random (java.util.Random)4 Bytes (utils.Bytes)4 SecureRandom (java.security.SecureRandom)3 HashMap (java.util.HashMap)2 MerkleProofException (com.jd.blockchain.ledger.core.MerkleProofException)1 BytesConverter (com.jd.blockchain.ledger.merkletree.BytesConverter)1 BytesKeyValue (com.jd.blockchain.ledger.merkletree.BytesKeyValue)1 DefaultDataPolicy (com.jd.blockchain.ledger.merkletree.DefaultDataPolicy)1 HashBucketEntry (com.jd.blockchain.ledger.merkletree.HashBucketEntry)1 HashEntry (com.jd.blockchain.ledger.merkletree.HashEntry)1 MerkleHashBucket (com.jd.blockchain.ledger.merkletree.MerkleHashBucket)1 MerkleTree (com.jd.blockchain.ledger.merkletree.MerkleTree)1