use of com.jd.blockchain.ledger.LedgerBlock in project jdchain-core by blockchain-jd-com.
the class TransactionBatchProcessorTest method testSingleTxProcess.
@Test
public void testSingleTxProcess() {
final MemoryKVStorage STORAGE = new MemoryKVStorage();
// 初始化账本到指定的存储库;
HashDigest ledgerHash = LedgerTestUtils.initLedger(STORAGE, parti0, parti1, parti2, parti3);
// 加载账本;
LedgerManager ledgerManager = new LedgerManager();
LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, STORAGE, LedgerDataStructure.MERKLE_TREE);
// 验证交易总数;创始区块的交易数预期为 1 ——只有一笔账本初始化的交易;
long totalCount = ledgerRepo.getTransactionSet().getTotalCount();
assertEquals(1, totalCount);
// 验证参与方账户的存在;
LedgerDataSet previousBlockDataset = ledgerRepo.getLedgerDataSet(ledgerRepo.getLatestBlock());
UserAccount user0 = previousBlockDataset.getUserAccountSet().getAccount(parti0.getAddress());
assertNotNull(user0);
boolean partiRegistered = previousBlockDataset.getUserAccountSet().contains(parti0.getAddress());
assertTrue(partiRegistered);
// 生成新区块;
LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();
OperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration();
LedgerSecurityManager securityManager = getSecurityManager();
TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor, ledgerRepo, opReg);
// 注册新用户;
BlockchainKeypair userKeypair = BlockchainKeyGenerator.getInstance().generate();
TransactionRequest transactionRequest = LedgerTestUtils.createTxRequest_UserReg(userKeypair, ledgerHash, parti0, parti0);
TransactionResponse txResp = txbatchProcessor.schedule(transactionRequest);
LedgerBlock newBlock = newBlockEditor.prepare();
newBlockEditor.commit();
// 验证正确性;
ledgerManager = new LedgerManager();
ledgerRepo = ledgerManager.register(ledgerHash, STORAGE, LedgerDataStructure.MERKLE_TREE);
LedgerBlock latestBlock = ledgerRepo.getLatestBlock();
assertEquals(newBlock.getHash(), latestBlock.getHash());
assertEquals(1, newBlock.getHeight());
// 再次验证交易数;在新增一笔交易之后,交易数预期为 2 ;
totalCount = ledgerRepo.getTransactionSet().getTotalCount();
assertEquals(2, totalCount);
assertEquals(TransactionState.SUCCESS, txResp.getExecutionState());
}
use of com.jd.blockchain.ledger.LedgerBlock in project jdchain-core by blockchain-jd-com.
the class TransactionBatchProcessorTest method testTxRollbackByVersionsConflict.
@Test
public void testTxRollbackByVersionsConflict() {
final MemoryKVStorage STORAGE = new MemoryKVStorage();
// 初始化账本到指定的存储库;
HashDigest ledgerHash = LedgerTestUtils.initLedger(STORAGE, parti0, parti1, parti2, parti3);
// 加载账本;
LedgerManager ledgerManager = new LedgerManager();
LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, STORAGE, LedgerDataStructure.MERKLE_TREE);
// 验证参与方账户的存在;
LedgerDataSet previousBlockDataset = ledgerRepo.getLedgerDataSet(ledgerRepo.getLatestBlock());
UserAccount user0 = previousBlockDataset.getUserAccountSet().getAccount(parti0.getAddress());
assertNotNull(user0);
boolean partiRegistered = previousBlockDataset.getUserAccountSet().contains(parti0.getAddress());
assertTrue(partiRegistered);
// 注册数据账户;
// 生成新区块;
LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();
OperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration();
LedgerSecurityManager securityManager = getSecurityManager();
TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor, ledgerRepo, opReg);
BlockchainKeypair dataAccountKeypair = BlockchainKeyGenerator.getInstance().generate();
TransactionRequest transactionRequest1 = LedgerTestUtils.createTxRequest_DataAccountReg_SHA256(dataAccountKeypair, ledgerHash, parti0, parti0);
TransactionResponse txResp1 = txbatchProcessor.schedule(transactionRequest1);
LedgerBlock newBlock = newBlockEditor.prepare();
newBlockEditor.commit();
assertEquals(TransactionState.SUCCESS, txResp1.getExecutionState());
DataAccount dataAccount = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress());
assertNotNull(dataAccount);
// 正确写入 KV 数据;
TransactionRequest txreq1 = LedgerTestUtils.createTxRequest_DataAccountWrite_SHA256(dataAccountKeypair.getAddress(), "K1", "V-1-1", -1, ledgerHash, parti0, parti0);
TransactionRequest txreq2 = LedgerTestUtils.createTxRequest_DataAccountWrite_SHA256(dataAccountKeypair.getAddress(), "K2", "V-2-1", -1, ledgerHash, parti0, parti0);
TransactionRequest txreq3 = LedgerTestUtils.createTxRequest_DataAccountWrite_SHA256(dataAccountKeypair.getAddress(), "K3", "V-3-1", -1, ledgerHash, parti0, parti0);
// 连续写 K1,K1的版本将变为1;
TransactionRequest txreq4 = LedgerTestUtils.createTxRequest_DataAccountWrite_SHA256(dataAccountKeypair.getAddress(), "K1", "V-1-2", 0, ledgerHash, parti0, parti0);
newBlockEditor = ledgerRepo.createNextBlock();
previousBlockDataset = ledgerRepo.getLedgerDataSet(ledgerRepo.getLatestBlock());
txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor, ledgerRepo, opReg);
txbatchProcessor.schedule(txreq1);
txbatchProcessor.schedule(txreq2);
txbatchProcessor.schedule(txreq3);
txbatchProcessor.schedule(txreq4);
newBlock = newBlockEditor.prepare();
newBlockEditor.commit();
BytesValue v1_0 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getDataset().getValue("K1", 0);
BytesValue v1_1 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getDataset().getValue("K1", 1);
BytesValue v2 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getDataset().getValue("K2", 0);
BytesValue v3 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getDataset().getValue("K3", 0);
assertNotNull(v1_0);
assertNotNull(v1_1);
assertNotNull(v2);
assertNotNull(v3);
assertEquals("V-1-1", v1_0.getBytes().toUTF8String());
assertEquals("V-1-2", v1_1.getBytes().toUTF8String());
assertEquals("V-2-1", v2.getBytes().toUTF8String());
assertEquals("V-3-1", v3.getBytes().toUTF8String());
// 提交多笔数据写入的交易,包含存在数据版本冲突的交易,验证交易是否正确回滚;
// 先写一笔正确的交易; k3 的版本将变为 1 ;
TransactionRequest txreq5 = LedgerTestUtils.createTxRequest_DataAccountWrite_SHA256(dataAccountKeypair.getAddress(), "K3", "V-3-2", 0, ledgerHash, parti0, parti0);
// 指定冲突的版本号,正确的应该是版本1;
TransactionRequest txreq6 = LedgerTestUtils.createTxRequest_DataAccountWrite_SHA256(dataAccountKeypair.getAddress(), "K1", "V-1-3", 0, ledgerHash, parti0, parti0);
newBlockEditor = ledgerRepo.createNextBlock();
previousBlockDataset = ledgerRepo.getLedgerDataSet(ledgerRepo.getLatestBlock());
txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor, ledgerRepo, opReg);
txbatchProcessor.schedule(txreq5);
// 预期会产生版本冲突异常; DataVersionConflictionException;
DataVersionConflictException versionConflictionException = null;
try {
txbatchProcessor.schedule(txreq6);
} catch (DataVersionConflictException e) {
versionConflictionException = e;
}
// assertNotNull(versionConflictionException);
newBlock = newBlockEditor.prepare();
newBlockEditor.commit();
BytesValue v1 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getDataset().getValue("K1");
v3 = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getDataset().getValue("K3");
// k1 的版本仍然为1,没有更新;
long k1_version = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getDataset().getVersion("K1");
assertEquals(1, k1_version);
long k3_version = ledgerRepo.getDataAccountSet().getAccount(dataAccountKeypair.getAddress()).getDataset().getVersion("K3");
assertEquals(1, k3_version);
assertNotNull(v1);
assertNotNull(v3);
assertEquals("V-1-2", v1.getBytes().toUTF8String());
assertEquals("V-3-2", v3.getBytes().toUTF8String());
// // 验证正确性;
// ledgerManager = new LedgerManager();
// ledgerRepo = ledgerManager.register(ledgerHash, STORAGE);
//
// LedgerBlock latestBlock = ledgerRepo.getLatestBlock();
// assertEquals(newBlock.getHash(), latestBlock.getHash());
// assertEquals(1, newBlock.getHeight());
//
// LedgerTransaction tx1 = ledgerRepo.getTransactionSet()
// .get(transactionRequest1.getTransactionHash());
//
// assertNotNull(tx1);
// assertEquals(TransactionState.SUCCESS, tx1.getExecutionState());
}
use of com.jd.blockchain.ledger.LedgerBlock in project jdchain-core by blockchain-jd-com.
the class LedgerEditorTest method testRollback.
@Test
public void testRollback() {
BlockchainKeypair parti0 = LedgerTestUtils.createKeyPair("7VeRLBwqTAz8oRazEazeaEfqei46sk2FzvBgyHMUBJvrUEGT", "7VeRUm27GbrsX9HbQSZguChLp24HZYub6s5FJ7FjBht8BmbA");
BlockchainKeypair parti1 = LedgerTestUtils.createKeyPair("7VeRNJasZp76ThmUkoAajJEduotS4JC6T9wzhz9TDPvjLCRk", "7VeRcBcPkTZ4hFwfcKRgFJWdDesHyysQWkKYC6xfPApbfvwQ");
BlockchainKeypair parti2 = LedgerTestUtils.createKeyPair("7VeR7uSd7sqxkMp73936MoK7eUSmGPVrsmrwdekiR9fmvdYN", "7VeRUkgMXRegHHWhezv4LdJV6oQuSXo6Ezp2sjC2M5NTUWkz");
BlockchainKeypair parti3 = LedgerTestUtils.createKeyPair("7VeR8X8fa9th42XSXvnuBLfR4v3dxjXq6jPfvF7nDPB2MTo1", "7VeRdreAev1E8ySsLWX7rRMArh5wHBTmZXKwNUuoVo7cBn6o");
BlockchainKeypair[] participants = new BlockchainKeypair[] { parti0, parti1, parti2, parti3 };
final MemoryKVStorage STORAGE = new MemoryKVStorage();
// 初始化账本到指定的存储库;
HashDigest ledgerHash = LedgerTestUtils.initLedger(STORAGE, parti0, parti1, parti2, parti3);
System.out.printf("\r\n------------ LEDGER [%s] -----------\r\n", ledgerHash.toBase58());
// 验证重新加载的正确性;
LedgerManager manager = new LedgerManager();
LedgerRepository repo = manager.register(ledgerHash, STORAGE, LedgerDataStructure.MERKLE_TREE);
LedgerBlock block = repo.getBlock(ledgerHash);
assertNotNull(block);
assertNotNull(block.getHash());
assertEquals(0, block.getHeight());
// 创建交易连续交易,验证中间的交易回滚是否影响前后的交易;
BlockchainKeypair user1 = LedgerTestUtils.createKeyPair("7VeRKf3GFLFcBfzvtzmtyMXEoX2HYGEJ4j7CmHcnRV99W5Dp", "7VeRYQjeAaQY5Po8MMtmGNHA2SniqLXmJaZwBS5K8zTtMAU1");
TransactionRequest req1 = LedgerTestUtils.createTxRequest_UserReg_SHA256(user1, ledgerHash, 1580315317127L, parti0, parti0);
// 引发错误的参数:ts=1580315317127;
// txhash=j5wPGKT5CUzwi8j6VfCWaP2p9YZ6WVWtMANp9HbHWzvhgG
System.out.printf("\r\n ===||=== transactionRequest1.getTransactionContent().getHash()=[%s]\r\n", req1.getTransactionHash().toBase58());
BlockchainKeypair user2 = LedgerTestUtils.createKeyPair("7VeRKSnDFveTfLLMsLZDmmhGmgf7i142XHgBFjnrKuS95tY3", "7VeRTiJ2TpQD9aBi29ajnqdntgoVBANmC3oCbHThKb5tzfTJ");
TransactionRequest req2 = LedgerTestUtils.createTxRequest_MultiOPs_WithNotExistedDataAccount_SHA256(user2, ledgerHash, 202001202020L, parti0, parti0);
System.out.printf("\r\n ===||=== transactionRequest2.getTransactionContent().getHash()=[%s]\r\n", req2.getTransactionHash().toBase58());
BlockchainKeypair user3 = LedgerTestUtils.createKeyPair("7VeRDoaSexqLWKkaZyrQwdwSuE9n5nszduMrYBfYRfEkREQV", "7VeRdFtTuLfrzCYJzQ6enQUkGTc83ATgjr8WbmfjBQuTFpHt");
TransactionRequest req3 = LedgerTestUtils.createTxRequest_UserReg_SHA256(user3, ledgerHash, 202001202020L, parti0, parti0);
System.out.printf("\r\n ===||=== transactionRequest3.getTransactionContent().getHash()=[%s]\r\n", req3.getTransactionHash().toBase58());
System.out.println("\r\n--------------- Start new Block 1 --------------\r\n");
// 创建交易;
LedgerEditor editor = repo.createNextBlock();
System.out.println("\r\n--------------- Start new tx1 --------------\r\n");
LedgerTransactionContext txctx1 = editor.newTransaction(req1);
((UserAccountSetEditor) (txctx1.getDataset().getUserAccountSet())).register(user1.getAddress(), user1.getPubKey());
TransactionResult tx1 = txctx1.commit(TransactionState.SUCCESS);
HashDigest txHash1 = tx1.getTransactionHash();
System.out.println("\r\n--------------- Start new tx2 --------------\r\n");
LedgerTransactionContext txctx2 = editor.newTransaction(req2);
((UserAccountSetEditor) (txctx2.getDataset().getUserAccountSet())).register(user2.getAddress(), user2.getPubKey());
TransactionResult tx2 = txctx2.discardAndCommit(TransactionState.DATA_ACCOUNT_DOES_NOT_EXIST);
HashDigest txHash2 = tx2.getTransactionHash();
System.out.println("\r\n--------------- Start new tx3 --------------\r\n");
LedgerTransactionContext txctx3 = editor.newTransaction(req3);
((UserAccountSetEditor) (txctx3.getDataset().getUserAccountSet())).register(user3.getAddress(), user3.getPubKey());
TransactionResult tx3 = txctx3.commit(TransactionState.SUCCESS);
HashDigest txHash3 = tx3.getTransactionHash();
System.out.println("\r\n--------------- Start preparing new block 1 --------------\r\n");
LedgerBlock block1 = editor.prepare();
System.out.println("\r\n--------------- Start commiting new block 1 --------------\r\n");
editor.commit();
System.out.printf("\r\n--------------- End commiting new block 1 [Storage.Count=%s]--------------\r\n\r\n", STORAGE.getStorageCount());
assertEquals(1, block1.getHeight());
// 重新加载和验证;
manager = new LedgerManager();
repo = manager.register(ledgerHash, STORAGE, LedgerDataStructure.MERKLE_TREE);
LedgerTransaction act_tx1 = repo.getTransactionSet().getTransaction(txHash1);
LedgerTransaction act_tx2 = repo.getTransactionSet().getTransaction(txHash2);
LedgerTransaction act_tx3 = repo.getTransactionSet().getTransaction(txHash3);
assertNotNull(act_tx3);
assertNotNull(act_tx2);
assertNotNull(act_tx1);
}
use of com.jd.blockchain.ledger.LedgerBlock in project jdchain-core by blockchain-jd-com.
the class BlockFullRollBackTest method testBlockFullkRollBack.
@Test
public void testBlockFullkRollBack() {
final MemoryKVStorage STORAGE = new MemoryKVStorage();
final MemoryKVStorage STORAGE_Mock = Mockito.spy(STORAGE);
// 初始化账本到指定的存储库;
ledgerHash = initLedger(STORAGE_Mock, parti0, parti1, parti2, parti3);
System.out.println("---------- Ledger init OK !!! ----------");
// 加载账本;
LedgerManager ledgerManager = new LedgerManager();
LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, STORAGE_Mock, LedgerDataStructure.MERKLE_TREE);
// 构造存储错误,并产生区块回滚
doThrow(BlockRollbackException.class).when(STORAGE_Mock).set(any(), any(), anyLong());
LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();
OperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration();
LedgerSecurityManager securityManager = getSecurityManager();
TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor, ledgerRepo, opReg);
// 注册新用户;
BlockchainKeypair userKeypair = BlockchainKeyGenerator.getInstance().generate();
TransactionRequest transactionRequest = LedgerTestUtils.createTxRequest_UserReg(userKeypair, ledgerHash, parti0, parti0);
TransactionResponse txResp = txbatchProcessor.schedule(transactionRequest);
LedgerBlock newBlock = newBlockEditor.prepare();
try {
newBlockEditor.commit();
} catch (BlockRollbackException e) {
newBlockEditor.cancel();
}
// 验证正确性;
ledgerManager = new LedgerManager();
ledgerRepo = ledgerManager.register(ledgerHash, STORAGE_Mock, LedgerDataStructure.MERKLE_TREE);
LedgerBlock latestBlock = ledgerRepo.getLatestBlock();
assertEquals(ledgerRepo.getBlockHash(0), latestBlock.getHash());
assertEquals(0, latestBlock.getHeight());
LedgerDataSet ledgerDS = ledgerRepo.getLedgerDataSet(latestBlock);
boolean existUser = ledgerDS.getUserAccountSet().contains(userKeypair.getAddress());
assertFalse(existUser);
doCallRealMethod().when(STORAGE_Mock).set(any(), any(), anyLong());
// 区块正常提交
// 生成新区块;
LedgerEditor newBlockEditor1 = ledgerRepo.createNextBlock();
OperationHandleRegisteration opReg1 = new DefaultOperationHandleRegisteration();
LedgerSecurityManager securityManager1 = getSecurityManager();
TransactionBatchProcessor txbatchProcessor1 = new TransactionBatchProcessor(securityManager1, newBlockEditor1, ledgerRepo, opReg1);
// 注册新用户;
BlockchainKeypair userKeypair1 = BlockchainKeyGenerator.getInstance().generate();
TransactionRequest transactionRequest1 = LedgerTestUtils.createTxRequest_UserReg(userKeypair1, ledgerHash, parti0, parti0);
TransactionResponse txResp1 = txbatchProcessor1.schedule(transactionRequest1);
LedgerBlock newBlock1 = newBlockEditor1.prepare();
try {
newBlockEditor1.commit();
} catch (BlockRollbackException e) {
newBlockEditor1.cancel();
}
ledgerManager = new LedgerManager();
ledgerRepo = ledgerManager.register(ledgerHash, STORAGE_Mock, LedgerDataStructure.MERKLE_TREE);
LedgerBlock latestBlock1 = ledgerRepo.getLatestBlock();
assertEquals(newBlock1.getHash(), latestBlock1.getHash());
assertEquals(1, latestBlock1.getHeight());
LedgerDataSet ledgerDS1 = ledgerRepo.getLedgerDataSet(latestBlock1);
boolean existUser1 = ledgerDS1.getUserAccountSet().contains(userKeypair1.getAddress());
assertTrue(existUser1);
}
use of com.jd.blockchain.ledger.LedgerBlock in project jdchain-core by blockchain-jd-com.
the class DataSearchServiceHandler method searchAll.
@Override
public Map<String, Object> searchAll(HashDigest ledgerHash, String keyword) {
Map<String, Object> data = new HashMap<>();
data.put("combine", true);
// 区块
LedgerBlock block = searchBlock(ledgerHash, keyword);
if (null != block) {
data.put("blocks", new LedgerBlock[] { block });
}
// 交易
Transaction tx = searchTransaction(ledgerHash, keyword);
if (null != tx) {
data.put("txs", new Transaction[] { tx });
}
// 数据账户
DataAccountInfo dataAccount = searchDataAccount(ledgerHash, keyword);
if (null != dataAccount) {
data.put("accounts", new DataAccountInfo[] { dataAccount });
}
// 事件账户
BlockchainIdentity eventAccount = searchEventAccount(ledgerHash, keyword);
if (null != eventAccount) {
data.put("event_accounts", new BlockchainIdentity[] { eventAccount });
}
// 合约
ContractInfo contract = searchContractAccount(ledgerHash, keyword);
if (null != contract) {
data.put("contracts", new ContractInfo[] { contract });
}
// 用户
UserInfo user = searchUser(ledgerHash, keyword);
if (null != user) {
data.put("users", new UserInfo[] { user });
}
return data;
}
Aggregations