use of com.jd.blockchain.storage.service.utils.MemoryKVStorage in project jdchain-core by blockchain-jd-com.
the class AccountSetTest method test.
@Test
public void test() {
OpeningAccessPolicy accessPolicy = new OpeningAccessPolicy();
MemoryKVStorage storage = new MemoryKVStorage();
CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length];
for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) {
supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]);
}
CryptoConfig cryptoConf = new CryptoConfig();
cryptoConf.setSupportedProviders(supportedProviders);
cryptoConf.setAutoVerifyHash(true);
cryptoConf.setHashAlgorithm(ClassicAlgorithm.SHA256);
String keyPrefix = "";
MerkleAccountSetEditor accset = new MerkleAccountSetEditor(cryptoConf, Bytes.fromString(keyPrefix), storage, storage, accessPolicy);
BlockchainKeypair userKey = BlockchainKeyGenerator.getInstance().generate();
accset.register(userKey.getAddress(), userKey.getPubKey());
// 尚未提交之前,可以检索到账户的存在,但版本仍然标记为 -1;
CompositeAccount userAcc = accset.getAccount(userKey.getAddress());
assertNotNull(userAcc);
assertTrue(accset.contains(userKey.getAddress()));
accset.commit();
HashDigest rootHash = accset.getRootHash();
assertNotNull(rootHash);
MerkleAccountSetEditor reloadAccSet = new MerkleAccountSetEditor(rootHash, cryptoConf, Bytes.fromString(keyPrefix), storage, storage, true, accessPolicy);
CompositeAccount reloadUserAcc = reloadAccSet.getAccount(userKey.getAddress());
assertNotNull(reloadUserAcc);
assertTrue(reloadAccSet.contains(userKey.getAddress()));
assertEquals(userAcc.getID().getAddress(), reloadUserAcc.getID().getAddress());
assertEquals(userAcc.getID().getPubKey(), reloadUserAcc.getID().getPubKey());
}
use of com.jd.blockchain.storage.service.utils.MemoryKVStorage in project jdchain-core by blockchain-jd-com.
the class BaseAccountTest method basicTest.
@Test
public void basicTest() {
String keyPrefix = "";
MemoryKVStorage testStorage = new MemoryKVStorage();
CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length];
for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) {
supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]);
}
CryptoConfig cryptoConf = new CryptoConfig();
cryptoConf.setSupportedProviders(supportedProviders);
cryptoConf.setAutoVerifyHash(true);
cryptoConf.setHashAlgorithm(ClassicAlgorithm.SHA256);
// OpeningAccessPolicy accPlc = new OpeningAccessPolicy();
BlockchainKeypair bck = BlockchainKeyGenerator.getInstance().generate();
// 新建账户;
MerkleComplecatedAccount baseAccount = new MerkleComplecatedAccount(bck.getIdentity(), cryptoConf, Bytes.fromString(keyPrefix), testStorage, testStorage);
// 初始化新账户时,先写入PubKey;
assertTrue(baseAccount.isUpdated());
assertFalse(baseAccount.isReadonly());
// 在空白状态下写入数据;
long v = baseAccount.getDataset().setValue("A", TypedValue.fromText("VALUE_A"), 0);
// 预期失败;
assertEquals(-1, v);
v = baseAccount.getDataset().setValue("A", TypedValue.fromText("VALUE_A"), 1);
// 预期失败;
assertEquals(-1, v);
v = baseAccount.getDataset().setValue("A", TypedValue.fromText("VALUE_A"), -1);
// 预期成功;
assertEquals(0, v);
v = baseAccount.getDataset().setValue("A", TypedValue.fromText("VALUE_A-1"), -1);
// 已经存在版本,指定版本号-1,预期导致失败;
assertEquals(-1, v);
baseAccount.commit();
v = 0;
for (int i = 0; i < 10; i++) {
long s = baseAccount.getDataset().setValue("A", TypedValue.fromText("VALUE_A_" + i), v);
baseAccount.commit();
// 预期成功;
assertEquals(v + 1, s);
v++;
}
v = baseAccount.getDataset().setValue("A", TypedValue.fromText("VALUE_A_" + v), v + 1);
// 预期成功;
assertEquals(-1, v);
System.out.println("============== commit ==============");
baseAccount.commit();
}
use of com.jd.blockchain.storage.service.utils.MemoryKVStorage in project jdchain-core by blockchain-jd-com.
the class MerkleHashTrieTest method testMerkleTreeDiffPathsType.
@Test
public void testMerkleTreeDiffPathsType() {
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 = 2;
int newAddCount = 5;
VersioningKVData<String, byte[]> orginData0 = new VersioningKVData<String, byte[]>("KEY-19745261600024463", 0L, BytesUtils.concat(BytesUtils.toBytes(0), BytesUtils.toBytes("VALUE")));
dataList.add(orginData0);
dataListString.add(orginData0.getKey());
VersioningKVData<String, byte[]> orginData1 = new VersioningKVData<String, byte[]>("KEY-155749221633494971", 0L, BytesUtils.concat(BytesUtils.toBytes(0), BytesUtils.toBytes("VALUE")));
dataList.add(orginData1);
dataListString.add(orginData1.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);
VersioningKVData<String, byte[]> data1 = new VersioningKVData<String, byte[]>("KEY-2741789838505562", 0L, BytesUtils.concat(BytesUtils.toBytes(0), BytesUtils.toBytes("VALUE")));
newdataList.add(data1);
VersioningKVData<String, byte[]> data2 = new VersioningKVData<String, byte[]>("KEY-0745023937104559", 0L, BytesUtils.concat(BytesUtils.toBytes(0), BytesUtils.toBytes("VALUE")));
newdataList.add(data2);
VersioningKVData<String, byte[]> data3 = new VersioningKVData<String, byte[]>("KEY-7745261599950097", 0L, BytesUtils.concat(BytesUtils.toBytes(0), BytesUtils.toBytes("VALUE")));
newdataList.add(data3);
VersioningKVData<String, byte[]> data4 = new VersioningKVData<String, byte[]>("KEY-9745261599963367", 0L, BytesUtils.concat(BytesUtils.toBytes(0), BytesUtils.toBytes("VALUE")));
newdataList.add(data4);
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 = 4;
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.storage.service.utils.MemoryKVStorage in project jdchain-core by blockchain-jd-com.
the class MerkleSortTreeTest method testIterator.
@Test
public void testIterator() {
TreeOptions options = createTreeOptions();
MemoryKVStorage storage = new MemoryKVStorage();
MerkleSortTree<byte[]> mst = MerkleSortTree.createBytesTree(options, DEFAULT_MKL_KEY_PREFIX, storage);
// 验证空的迭代器;
SkippingIterator<MerkleValue<byte[]>> iter = mst.bytesIterator();
assertEquals(0, iter.getTotalCount());
assertEquals(-1, iter.getCursor());
assertFalse(iter.hasNext());
assertNull(iter.next());
// 加入数据,验证顺序数据插入的生成的迭代器;
int count1 = 10;
byte[][] datas1 = generateRandomData(count1);
long[] ids1 = generateSeqenceIDs(0, count1);
HashMap<Long, byte[]> dataMap = new HashMap<Long, byte[]>();
mapIdValues(ids1, datas1, dataMap);
addDatasAndCommit(ids1, datas1, mst);
iter = mst.iterator();
assertIteratorSortedAndEquals(iter, count1, ids1, dataMap);
// 随机加入;验证迭代器返回有序的序列;
Set<Long> excludingIDs = createIdSet(ids1);
int count2 = (int) power(4, 8) + 1;
byte[][] datas2 = generateRandomData(count2);
long[] ids2 = generateRandomIDs(count2, excludingIDs, true);
mapIdValues(ids2, datas2, dataMap);
addDatasAndCommit(ids2, datas2, mst);
long[] totalIds = ArrayUtils.concat(ids1, ids2);
Arrays.sort(totalIds);
long totalCount = count1 + count2;
iter = mst.iterator();
assertIteratorSortedAndEquals(iter, totalCount, totalIds, dataMap);
// 验证有跳跃的情形;
iter = mst.iterator();
assertEquals(-1, iter.getCursor());
int index = -1;
long skipped = 1;
iter.skip(skipped);
index += skipped;
assertEquals(index, iter.getCursor());
MerkleValue<byte[]> merkleData = iter.next();
index++;
assertEquals(index, iter.getCursor());
assertNotNull(merkleData);
assertEquals(totalIds[index], merkleData.getId());
skipped = 2;
iter.skip(skipped);
index += skipped;
assertEquals(index, iter.getCursor());
merkleData = iter.next();
index++;
assertEquals(index, iter.getCursor());
assertNotNull(merkleData);
assertEquals(totalIds[index], merkleData.getId());
skipped = 3;
iter.skip(skipped);
index += skipped;
assertEquals(index, iter.getCursor());
merkleData = iter.next();
index++;
assertEquals(index, iter.getCursor());
assertNotNull(merkleData);
assertEquals(totalIds[index], merkleData.getId());
SecureRandom random = new SecureRandom();
for (int j = 0; j < 100; j++) {
skipped = random.nextInt(100);
iter.skip(skipped);
index += skipped;
assertEquals(index, iter.getCursor());
merkleData = iter.next();
index++;
assertEquals(index, iter.getCursor());
assertNotNull(merkleData);
assertEquals(totalIds[index], merkleData.getId());
}
// 验证直接跳跃到倒数第 1 条的情形;
long left = iter.getCount();
iter.skip(left - 1);
assertTrue(iter.hasNext());
assertEquals(1, iter.getCount());
merkleData = iter.next();
assertEquals(totalCount - 1, iter.getCursor());
assertNotNull(merkleData);
assertEquals(totalIds[(int) totalCount - 1], merkleData.getId());
assertFalse(iter.hasNext());
merkleData = iter.next();
assertNull(merkleData);
// 验证直接跳跃到末尾的情形;
iter = mst.iterator();
assertTrue(iter.hasNext());
long c = iter.skip(totalCount);
assertEquals(totalCount, c);
assertFalse(iter.hasNext());
merkleData = iter.next();
assertNull(merkleData);
}
use of com.jd.blockchain.storage.service.utils.MemoryKVStorage in project jdchain-core by blockchain-jd-com.
the class MerkleSortTreeTest method testMultiDataCountIterator.
/**
* 测试包含数据策略中计数大于 1 的数据迭代;
*/
@Test
public void testMultiDataCountIterator() {
TreeOptions options = createTreeOptions();
MemoryKVStorage storage = new MemoryKVStorage();
DataPolicy<byte[]> bytesDataPolicy = new DefaultDataPolicy<byte[]>() {
@Override
public byte[] updateData(long id, byte[] origData, byte[] newData) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
if (origData == null) {
BytesUtils.writeInt(1, out);
} else {
int count = BytesUtils.toInt(origData) + 1;
BytesUtils.writeInt(count, out);
out.write(origData, 4, origData.length - 4);
}
BytesEncoding.writeInNormal(newData, out);
return out.toByteArray();
}
@Override
public long count(long id, byte[] data) {
return BytesUtils.toInt(data);
}
@Override
public SkippingIterator<MerkleValue<byte[]>> iterator(long id, byte[] bytesData, long count, BytesConverter<byte[]> converter) {
byte[][] values = new byte[(int) count][];
ByteArrayInputStream in = new ByteArrayInputStream(bytesData, 4, bytesData.length - 4);
for (int i = 0; i < values.length; i++) {
values[i] = BytesEncoding.readInNormal(in);
}
return new BytesEntriesIterator(id, values);
}
};
MerkleSortTree<byte[]> mst = MerkleSortTree.createBytesTree(options, DEFAULT_MKL_KEY_PREFIX, storage, bytesDataPolicy);
int count = 16;
byte[][] datas = generateRandomData(count);
long[] ids = new long[count];
int startIndex = 10;
for (int i = 0; i < startIndex; i++) {
ids[i] = i;
}
// 从 10 开始,连续3条不同的记录使用相同的 编码;
int testId = startIndex + 2;
ids[startIndex] = testId;
ids[startIndex + 1] = testId;
ids[startIndex + 2] = testId;
for (int i = 0; i < ids.length - startIndex - 3; i++) {
ids[startIndex + i + 3] = startIndex + i + 5;
}
addDatas(ids, datas, mst);
mst.commit();
// 验证所有的数据都能够正常检索;
SkippingIterator<MerkleValue<byte[]>> iter = mst.iterator();
assertEquals(count, iter.getTotalCount());
assertIteratorEquals(count, datas, ids, 0, iter);
// 验证略过中间数据也能够正常检索:跳跃到连续 id 的前一条;
iter = mst.iterator();
iter.skip(startIndex - 1);
int i = startIndex - 1;
assertIteratorEquals(count - (startIndex - 1), datas, ids, startIndex - 1, iter);
// 验证略过中间数据也能够正常检索:跳跃到连续 id 的第1条;
iter = mst.iterator();
iter.skip(startIndex);
i = startIndex;
{
MerkleValue<byte[]> v = iter.next();
assertNotNull(v);
assertEquals(testId, v.getId());
assertArrayEquals(datas[i], v.getValue());
v = iter.next();
assertNotNull(v);
assertEquals(testId, v.getId());
assertArrayEquals(datas[i + 1], v.getValue());
v = iter.next();
assertNotNull(v);
assertEquals(testId, v.getId());
assertArrayEquals(datas[i + 2], v.getValue());
}
assertIteratorEquals(count - (i + 3), datas, ids, i + 3, iter);
// 验证略过中间数据也能够正常检索:跳跃到连续 id 的第2条;
iter = mst.iterator();
iter.skip(startIndex + 1);
i = startIndex;
{
MerkleValue<byte[]> v = iter.next();
assertNotNull(v);
assertEquals(testId, v.getId());
assertArrayEquals(datas[i + 1], v.getValue());
v = iter.next();
assertNotNull(v);
assertEquals(testId, v.getId());
assertArrayEquals(datas[i + 2], v.getValue());
}
assertIteratorEquals(count - (i + 3), datas, ids, i + 3, iter);
// 验证略过中间数据也能够正常检索:跳跃到连续 id 的第3条;
iter = mst.iterator();
iter.skip(startIndex + 2);
i = startIndex;
{
MerkleValue<byte[]> v = iter.next();
assertNotNull(v);
assertEquals(testId, v.getId());
assertArrayEquals(datas[i + 2], v.getValue());
}
assertIteratorEquals(count - (i + 3), datas, ids, i + 3, iter);
// 验证略过中间数据也能够正常检索:跳跃到连续 id 第3条;
iter = mst.iterator();
iter.skip(startIndex + 3);
assertIteratorEquals(count - (startIndex + 3), datas, ids, startIndex + 3, iter);
}
Aggregations