use of com.jd.blockchain.ledger.core.LedgerRepository in project jdchain-core by blockchain-jd-com.
the class ContractInvokingTest method testRollbackWhileVersionConfliction.
/**
* 验证在合约方法中写入数据账户时,如果版本校验失败是否会引发异常而导致回滚;<br>
* 期待正确的表现是引发异常而回滚当前交易;
*/
@Ignore("需要更新合约")
@Test
public void testRollbackWhileVersionConfliction() {
// 初始化账本到指定的存储库;
HashDigest ledgerHash = initLedger(storage, parti0, parti1, parti2, parti3);
// 重新加载账本;
LedgerManager ledgerManager = new LedgerManager();
LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, storage, LedgerDataStructure.MERKLE_TREE);
// 创建合约处理器;
ContractInvokingHandle contractInvokingHandle = new ContractInvokingHandle();
// 创建和加载合约实例;
BlockchainKeypair contractKey = BlockchainKeyGenerator.getInstance().generate();
Bytes contractAddress = contractKey.getAddress();
TxTestContractImpl contractInstance = new TxTestContractImpl();
contractInvokingHandle.setup(contractAddress, TxTestContract.class, contractInstance);
// 注册合约处理器;
DefaultOperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration();
opReg.registerHandle(contractInvokingHandle);
// 发布指定地址合约
deploy(ledgerRepo, ledgerManager, opReg, ledgerHash, contractKey);
// 注册数据账户;
BlockchainKeypair kpDataAccount = BlockchainKeyGenerator.getInstance().generate();
contractInstance.setDataAddress(kpDataAccount.getAddress());
registerDataAccount(ledgerRepo, ledgerManager, opReg, ledgerHash, kpDataAccount);
// 调用合约
// 构建基于接口调用合约的交易请求,用于测试合约调用;
buildBlock(ledgerRepo, ledgerManager, opReg, new TxDefinitor() {
@Override
public void buildTx(TxBuilder txBuilder) {
TxTestContract contractProxy = txBuilder.contract(contractAddress, TxTestContract.class);
contractProxy.testRollbackWhileVersionConfliction(kpDataAccount.getAddress().toBase58(), "K1", "V1-0", -1);
contractProxy.testRollbackWhileVersionConfliction(kpDataAccount.getAddress().toBase58(), "K2", "V2-0", -1);
}
});
// 预期数据都能够正常写入;
DataEntry<String, TypedValue> kv1 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataset().getDataEntry("K1", 0);
DataEntry<String, TypedValue> kv2 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataset().getDataEntry("K2", 0);
assertEquals(0, kv1.getVersion());
assertEquals(0, kv2.getVersion());
assertEquals("V1-0", kv1.getValue().stringValue());
assertEquals("V2-0", kv2.getValue().stringValue());
// 构建基于接口调用合约的交易请求,用于测试合约调用;
buildBlock(ledgerRepo, ledgerManager, opReg, new TxDefinitor() {
@Override
public void buildTx(TxBuilder txBuilder) {
TxTestContract contractProxy = txBuilder.contract(contractAddress, TxTestContract.class);
contractProxy.testRollbackWhileVersionConfliction(kpDataAccount.getAddress().toBase58(), "K1", "V1-1", 0);
contractProxy.testRollbackWhileVersionConfliction(kpDataAccount.getAddress().toBase58(), "K2", "V2-1", 0);
}
});
// 预期数据都能够正常写入;
kv1 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataset().getDataEntry("K1", 1);
kv2 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataset().getDataEntry("K2", 1);
assertEquals(1, kv1.getVersion());
assertEquals(1, kv2.getVersion());
assertEquals("V1-1", kv1.getValue().stringValue());
assertEquals("V2-1", kv2.getValue().stringValue());
// 构建基于接口调用合约的交易请求,用于测试合约调用;
buildBlock(ledgerRepo, ledgerManager, opReg, new TxDefinitor() {
@Override
public void buildTx(TxBuilder txBuilder) {
TxTestContract contractProxy = txBuilder.contract(contractAddress, TxTestContract.class);
contractProxy.testRollbackWhileVersionConfliction(kpDataAccount.getAddress().toBase58(), "K1", "V1-2", 1);
contractProxy.testRollbackWhileVersionConfliction(kpDataAccount.getAddress().toBase58(), "K2", "V2-2", // 预期会回滚;
0);
}
});
// 预期数据回滚,账本没有发生变更;
kv1 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataset().getDataEntry("K1", 1);
assertEquals(1, kv1.getVersion());
assertEquals("V1-1", kv1.getValue().stringValue());
kv1 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataset().getDataEntry("K1", 2);
assertNull(kv1);
kv2 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataset().getDataEntry("K2", 1);
assertEquals(1, kv2.getVersion());
}
use of com.jd.blockchain.ledger.core.LedgerRepository in project jdchain-core by blockchain-jd-com.
the class ContractInvokingTest method testNormal.
@Ignore("合约需要更新")
@Test
public void testNormal() {
// 初始化账本到指定的存储库;
HashDigest ledgerHash = initLedger(storage, parti0, parti1, parti2, parti3);
// 重新加载账本;
LedgerManager ledgerManager = new LedgerManager();
LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, storage, LedgerDataStructure.MERKLE_TREE);
// 创建合约处理器;
ContractInvokingHandle contractInvokingHandle = new ContractInvokingHandle();
// 创建和加载合约实例;
BlockchainKeypair contractKey = BlockchainKeyGenerator.getInstance().generate();
Bytes contractAddress = contractKey.getAddress();
TestContract contractInstance = Mockito.mock(TestContract.class);
final String asset = "AK";
final long issueAmount = new Random().nextLong();
when(contractInstance.issue(anyString(), anyLong())).thenReturn(issueAmount);
// 装载合约;
contractInvokingHandle.setup(contractAddress, TestContract.class, contractInstance);
// 注册合约处理器;
DefaultOperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration();
opReg.registerHandle(contractInvokingHandle);
// 发布指定地址合约
deploy(ledgerRepo, ledgerManager, opReg, ledgerHash, contractKey);
// 创建新区块的交易处理器;
LedgerBlock preBlock = ledgerRepo.getLatestBlock();
LedgerDataSet previousBlockDataset = ledgerRepo.getLedgerDataSet(preBlock);
// 加载合约
LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();
LedgerSecurityManager securityManager = getSecurityManager();
TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor, ledgerRepo, opReg);
// 构建基于接口调用合约的交易请求,用于测试合约调用;
CryptoSetting cryptoSetting = ledgerRepo.getAdminInfo().getSettings().getCryptoSetting();
TxBuilder txBuilder = new TxBuilder(ledgerHash, cryptoSetting.getHashAlgorithm());
TestContract contractProxy = txBuilder.contract(contractAddress, TestContract.class);
// 构造调用合约的交易;
contractProxy.issue(asset, issueAmount);
TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest();
txReqBuilder.signAsEndpoint(parti0);
txReqBuilder.signAsNode(parti0);
TransactionRequest txReq = txReqBuilder.buildRequest();
TransactionResponse resp = txbatchProcessor.schedule(txReq);
verify(contractInstance, times(1)).issue(asset, issueAmount);
OperationResult[] opResults = resp.getOperationResults();
assertEquals(1, opResults.length);
assertEquals(0, opResults[0].getIndex());
byte[] expectedRetnBytes = BinaryProtocol.encode(TypedValue.fromInt64(issueAmount), BytesValue.class);
byte[] reallyRetnBytes = BinaryProtocol.encode(opResults[0].getResult(), BytesValue.class);
assertArrayEquals(expectedRetnBytes, reallyRetnBytes);
// 提交区块;
TransactionBatchResultHandle txResultHandle = txbatchProcessor.prepare();
txResultHandle.commit();
LedgerBlock latestBlock = ledgerRepo.getLatestBlock();
assertEquals(preBlock.getHeight() + 1, latestBlock.getHeight());
assertEquals(resp.getBlockHeight(), latestBlock.getHeight());
assertEquals(resp.getBlockHash(), latestBlock.getHash());
// 再验证一次结果;
assertEquals(1, opResults.length);
assertEquals(0, opResults[0].getIndex());
reallyRetnBytes = BinaryProtocol.encode(opResults[0].getResult(), BytesValue.class);
assertArrayEquals(expectedRetnBytes, reallyRetnBytes);
}
use of com.jd.blockchain.ledger.core.LedgerRepository 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);
}
Aggregations