diff --git a/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServer.java b/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServer.java index 297ccebe..aa62da01 100644 --- a/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServer.java +++ b/source/consensus/consensus-bftsmart/src/main/java/com/jd/blockchain/consensus/bftsmart/service/BftsmartNodeServer.java @@ -354,126 +354,75 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer // }); } - /** - * - * Used by consensus write phase, pre compute new block hash - * - */ -// public BatchAppResultImpl preComputeAppHash(byte[][] commands) { -// String batchId = messageHandle.beginBatch(realmName); -// List> asyncFutureLinkedList = new ArrayList<>(commands.length); -// List responseLinkedList = new ArrayList<>(); -// try { -// int msgId = 0; -// for (byte[] txContent : commands) { -// AsyncFuture asyncFuture = messageHandle.processOrdered(msgId++, txContent, realmName, batchId); -// asyncFutureLinkedList.add(asyncFuture); -// } -// StateSnapshot stateSnapshot = messageHandle.completeBatch(realmName, batchId); -// byte[] blockHashBytes = stateSnapshot.getSnapshot(); -// -// for (int i = 0; i< asyncFutureLinkedList.size(); i++) { -// responseLinkedList.add(asyncFutureLinkedList.get(i).get()); -// } -// -// -// return new BatchAppResultImpl(responseLinkedList, blockHashBytes, batchId); -// -// } catch (Exception e) { -// // todo 需要处理应答码 404 -// LOGGER.error("Error occurred while processing ordered messages! --" + e.getMessage(), e); -// messageHandle.rollbackBatch(realmName, batchId, TransactionState.IGNORED_BY_CONSENSUS_PHASE_PRECOMPUTE_ROLLBACK.CODE); -// } -// -// return null; -// } - /** * Used by consensus write phase, pre compute new block hash */ public BatchAppResultImpl preComputeAppHash(byte[][] commands) { - String batchId = messageHandle.beginBatch(realmName); + List> asyncFutureLinkedList = new ArrayList<>(commands.length); List responseLinkedList = new ArrayList<>(); - BatchAppResultImpl result; + StateSnapshot newStateSnapshot = null; + StateSnapshot preStateSnapshot = null; + BatchAppResultImpl result = null; + String batchId = null; + int msgId = 0; + try { - int msgId = 0; - boolean isOK = true; - TransactionState transactionState = TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK; + batchId = messageHandle.beginBatch(realmName); + + preStateSnapshot = messageHandle.getStateSnapshot(realmName); + + if (preStateSnapshot == null) { + throw new IllegalStateException("Pre block state snapshot is null!"); + } for (int i = 0; i < commands.length; i++) { byte[] txContent = commands[i]; - try { - AsyncFuture asyncFuture = messageHandle.processOrdered(msgId++, txContent, realmName, batchId); - asyncFutureLinkedList.add(asyncFuture); - } catch (BlockRollbackException e) { - LOGGER.error("Error occurred while processing ordered messages! --" + e.getMessage(), e); - isOK = false; - // TODO: handle the BlockRollbackException in detail; - if (e instanceof DataVersionConflictException) { - transactionState = TransactionState.DATA_VERSION_CONFLICT; - } - break; - } + AsyncFuture asyncFuture = messageHandle.processOrdered(msgId++, txContent, realmName, batchId); + asyncFutureLinkedList.add(asyncFuture); } + newStateSnapshot = messageHandle.completeBatch(realmName, batchId); - if (isOK) { - StateSnapshot stateSnapshot = messageHandle.completeBatch(realmName, batchId); - byte[] blockHashBytes = stateSnapshot.getSnapshot(); - - for (int i = 0; i < asyncFutureLinkedList.size(); i++) { - responseLinkedList.add(asyncFutureLinkedList.get(i).get()); - } - - result = new BatchAppResultImpl(responseLinkedList, blockHashBytes, batchId); - result.setErrorCode((byte) 0); - - return result; - } else { - - for (int i = 0; i < commands.length; i++) { - responseLinkedList.add(createAppResponse(commands[i],transactionState)); - } - - Random random = new Random(); - byte[] rand = new byte[4]; - random.nextBytes(rand); + for (int i = 0; i < asyncFutureLinkedList.size(); i++) { + responseLinkedList.add(asyncFutureLinkedList.get(i).get()); + } - result = new BatchAppResultImpl(responseLinkedList, rand, batchId); - result.setErrorCode((byte) 1); + result = new BatchAppResultImpl(responseLinkedList, newStateSnapshot.getSnapshot(), batchId); + result.setErrorCode((byte) 0); - return result; + } catch (Exception e) { + LOGGER.error("Error occurred while pre compute app! --" + e.getMessage(), e); + for (int i = 0; i < commands.length; i++) { + responseLinkedList.add(createAppResponse(commands[i],TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK)); } - } catch (Exception e) { - LOGGER.error("Error occurred while genearte batch app result! --" + e.getMessage(), e); - throw e; + result = new BatchAppResultImpl(responseLinkedList,preStateSnapshot.getSnapshot(), batchId); + result.setErrorCode((byte) 1); } + + return result; } - public byte[] createAppResponse(byte[] command, TransactionState transactionState) { + // Block full rollback responses, generated in pre compute phase, due to tx exception + private byte[] createAppResponse(byte[] command, TransactionState transactionState) { TransactionRequest txRequest = BinaryProtocol.decode(command); TxResponseMessage resp = new TxResponseMessage(txRequest.getTransactionContent().getHash()); -// resp.setExecutionState(TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK); + resp.setExecutionState(transactionState); return BinaryProtocol.encode(resp, TransactionResponse.class); } - /** - * - * Consensus write phase will terminate, new block hash values are inconsistent, update batch messages execute state - * - */ + //update batch messages to block full rollback state public List updateAppResponses(List asyncResponseLinkedList) { List updatedResponses = new ArrayList<>(); for(int i = 0; i < asyncResponseLinkedList.size(); i++) { TransactionResponse txResponse = BinaryProtocol.decode(asyncResponseLinkedList.get(i)); TxResponseMessage resp = new TxResponseMessage(txResponse.getContentHash()); - resp.setExecutionState(TransactionState.IGNORED_BY_CONSENSUS_PHASE_PRECOMPUTE_ROLLBACK); + resp.setExecutionState(TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK); updatedResponses.add(BinaryProtocol.encode(resp, TransactionResponse.class)); } @@ -486,9 +435,12 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer * */ public void preComputeAppCommit(String batchId) { - - messageHandle.commitBatch(realmName, batchId); - + try { + messageHandle.commitBatch(realmName, batchId); + } catch (BlockRollbackException e) { + LOGGER.error("Error occurred while pre compute commit --" + e.getMessage(), e); + throw e; + } } /** @@ -497,7 +449,7 @@ public class BftsmartNodeServer extends DefaultRecoverable implements NodeServer * */ public void preComputeAppRollback(String batchId) { - messageHandle.rollbackBatch(realmName, batchId, TransactionState.IGNORED_BY_CONSENSUS_PHASE_PRECOMPUTE_ROLLBACK.CODE); + messageHandle.rollbackBatch(realmName, batchId, TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK.CODE); LOGGER.debug("Rollback of operations that cause inconsistencies in the ledger"); } diff --git a/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/ConsensusProviders.java b/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/ConsensusProviders.java index c1b8c58c..58853099 100644 --- a/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/ConsensusProviders.java +++ b/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/ConsensusProviders.java @@ -19,7 +19,8 @@ public class ConsensusProviders { provider = providers.get(className); if (provider == null) { provider = loadProvider(ConsensusProvider.class, className); - providers.put(className, provider); +// providers.put(className, provider); + registerProvider(provider); } } } diff --git a/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/service/MessageHandle.java b/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/service/MessageHandle.java index 4e0e1b89..1acb44c4 100644 --- a/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/service/MessageHandle.java +++ b/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/service/MessageHandle.java @@ -59,4 +59,12 @@ public interface MessageHandle { */ AsyncFuture processUnordered(byte[] message); + /** + * 获得当前最新区块的状态快照 + * + * @param realmName + * @return 最新区块的状态快照 + */ + StateSnapshot getStateSnapshot(String realmName); + } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerRepositoryImpl.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerRepositoryImpl.java index 9734f880..49e7ebba 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerRepositoryImpl.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerRepositoryImpl.java @@ -374,6 +374,10 @@ class LedgerRepositoryImpl implements LedgerRepository { return new LedgerDataset(adminDataset, userAccountSet, dataAccountSet, contractAccountSet, true); } + public synchronized void resetNextBlockEditor() { + this.nextBlockEditor = null; + } + @Override public synchronized LedgerEditor createNextBlock() { if (closed) { diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionalEditor.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionalEditor.java index ea7bb7ed..15954e4f 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionalEditor.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionalEditor.java @@ -355,7 +355,11 @@ public class LedgerTransactionalEditor implements LedgerEditor { throw new IllegalStateException("The current block is not ready yet!"); } - baseStorage.flush(); + try { + baseStorage.flush(); + } catch (Exception e) { + throw new BlockRollbackException(e.getMessage(), e); + } committed = true; } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionBatchProcessor.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionBatchProcessor.java index 3d2ebed9..be733dbf 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionBatchProcessor.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionBatchProcessor.java @@ -39,6 +39,14 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { private TransactionBatchResult batchResult; + public byte[] getPrevLatestBlockHash() { + return ledger.getLatestBlockHash().toBytes(); + } + + public long getPreLatestBlockHeight() { + return ledger.getLatestBlockHeight(); + } + public HashDigest getLedgerHash() { return ledger.getHash(); } @@ -273,9 +281,6 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { // rollback all the block; // TODO: handle the BlockRollbackException in detail; result = TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK; - if (e instanceof DataVersionConflictException) { - result = TransactionState.DATA_VERSION_CONFLICT; - } txCtx.rollback(); LOGGER.error( String.format("Transaction was rolled back! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s", @@ -295,6 +300,8 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { result = TransactionState.CONTRACT_DOES_NOT_EXIST; } else if (e instanceof ParticipantDoesNotExistException) { result = TransactionState.PARTICIPANT_DOES_NOT_EXIST; + } else if (e instanceof DataVersionConflictException) { + result = TransactionState.DATA_VERSION_CONFLICT; } txCtx.discardAndCommit(result, operationResults); LOGGER.error(String.format( diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionEngineImpl.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionEngineImpl.java index 2d0fb55a..e684ff4d 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionEngineImpl.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionEngineImpl.java @@ -48,6 +48,16 @@ public class TransactionEngineImpl implements TransactionEngine { return batchs.get(ledgerHash); } + public void freeBatch(HashDigest ledgerHash) { + finishBatch(ledgerHash); + } + + public void resetNewBlockEditor(HashDigest ledgerHash) { + + LedgerRepository ledgerRepo = ledgerService.getLedger(ledgerHash); + ((LedgerRepositoryImpl)ledgerRepo).resetNextBlockEditor(); + } + private void finishBatch(HashDigest ledgerHash) { batchs.remove(ledgerHash); } diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/BlockFullRollBackTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/BlockFullRollBackTest.java new file mode 100644 index 00000000..6c8009f9 --- /dev/null +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/BlockFullRollBackTest.java @@ -0,0 +1,188 @@ +package test.com.jd.blockchain.ledger.core; + +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.ledger.*; +import com.jd.blockchain.ledger.core.*; +import com.jd.blockchain.storage.service.utils.MemoryKVStorage; +import org.junit.Test; +import org.mockito.Mockito; + +import static org.junit.Assert.*; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Mockito.doCallRealMethod; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.when; + +public class BlockFullRollBackTest { + + static { + DataContractRegistry.register(TransactionContent.class); + DataContractRegistry.register(TransactionContentBody.class); + DataContractRegistry.register(TransactionRequest.class); + DataContractRegistry.register(NodeRequest.class); + DataContractRegistry.register(EndpointRequest.class); + DataContractRegistry.register(TransactionResponse.class); + DataContractRegistry.register(UserRegisterOperation.class); + DataContractRegistry.register(DataAccountRegisterOperation.class); + } + + private static final String LEDGER_KEY_PREFIX = "LDG://"; + + private HashDigest ledgerHash = null; + + private BlockchainKeypair parti0 = BlockchainKeyGenerator.getInstance().generate(); + private BlockchainKeypair parti1 = BlockchainKeyGenerator.getInstance().generate(); + private BlockchainKeypair parti2 = BlockchainKeyGenerator.getInstance().generate(); + private BlockchainKeypair parti3 = BlockchainKeyGenerator.getInstance().generate(); + + private BlockchainKeypair[] participants = { parti0, parti1, parti2, parti3 }; + + + @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); + + // 构造存储错误,并产生区块回滚 + 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); + LedgerBlock latestBlock = ledgerRepo.getLatestBlock(); + assertEquals(ledgerRepo.getBlockHash(0), latestBlock.getHash()); + assertEquals(0, latestBlock.getHeight()); + + LedgerDataQuery ledgerDS = ledgerRepo.getLedgerData(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); + LedgerBlock latestBlock1 = ledgerRepo.getLatestBlock(); + assertEquals(newBlock1.getHash(), latestBlock1.getHash()); + assertEquals(1, latestBlock1.getHeight()); + + LedgerDataQuery ledgerDS1 = ledgerRepo.getLedgerData(latestBlock1); + boolean existUser1 = ledgerDS1.getUserAccountSet().contains(userKeypair1.getAddress()); + + assertTrue(existUser1); + + } + + private static LedgerSecurityManager getSecurityManager() { + LedgerSecurityManager securityManager = Mockito.mock(LedgerSecurityManager.class); + + SecurityPolicy securityPolicy = Mockito.mock(SecurityPolicy.class); + when(securityPolicy.isEndpointEnable(any(LedgerPermission.class), any())).thenReturn(true); + when(securityPolicy.isEndpointEnable(any(TransactionPermission.class), any())).thenReturn(true); + when(securityPolicy.isNodeEnable(any(LedgerPermission.class), any())).thenReturn(true); + when(securityPolicy.isNodeEnable(any(TransactionPermission.class), any())).thenReturn(true); + + when(securityManager.createSecurityPolicy(any(), any())).thenReturn(securityPolicy); + + return securityManager; + } + + private HashDigest initLedger(MemoryKVStorage storage, BlockchainKeypair... partiKeys) { + // 创建初始化配置; + LedgerInitSetting initSetting = LedgerTestUtils.createLedgerInitSetting(partiKeys); + + // 创建账本; + LedgerEditor ldgEdt = LedgerTransactionalEditor.createEditor(initSetting, LEDGER_KEY_PREFIX, storage, storage); + + TransactionRequest genesisTxReq = LedgerTestUtils.createLedgerInitTxRequest(partiKeys); + LedgerTransactionContext genisisTxCtx = ldgEdt.newTransaction(genesisTxReq); + LedgerDataset ldgDS = genisisTxCtx.getDataset(); + + for (int i = 0; i < partiKeys.length; i++) { + UserAccount userAccount = ldgDS.getUserAccountSet().register(partiKeys[i].getAddress(), + partiKeys[i].getPubKey()); + userAccount.setProperty("Name", "参与方-" + i, -1); + userAccount.setProperty("Share", "" + (10 + i), -1); + } + + LedgerTransaction tx = genisisTxCtx.commit(TransactionState.SUCCESS); + + assertEquals(genesisTxReq.getTransactionContent().getHash(), tx.getTransactionContent().getHash()); + assertEquals(0, tx.getBlockHeight()); + + LedgerBlock block = ldgEdt.prepare(); + + assertEquals(0, block.getHeight()); + assertNotNull(block.getHash()); + assertNull(block.getPreviousHash()); + + // 创世区块的账本哈希为 null; + assertNull(block.getLedgerHash()); + assertNotNull(block.getHash()); + + // 提交数据,写入存储; + ldgEdt.commit(); + + HashDigest ledgerHash = block.getHash(); + return ledgerHash; + } +} diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionBatchProcessorTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionBatchProcessorTest.java index 3d7f179b..a0e554e1 100644 --- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionBatchProcessorTest.java +++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionBatchProcessorTest.java @@ -372,7 +372,7 @@ public class TransactionBatchProcessorTest { } catch (DataVersionConflictException e) { versionConflictionException = e; } - assertNotNull(versionConflictionException); +// assertNotNull(versionConflictionException); newBlock = newBlockEditor.prepare(); newBlockEditor.commit(); diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataVersionConflictException.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataVersionConflictException.java index 8af67d01..9831c0cc 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataVersionConflictException.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataVersionConflictException.java @@ -1,6 +1,6 @@ package com.jd.blockchain.ledger; -public class DataVersionConflictException extends BlockRollbackException { +public class DataVersionConflictException extends LedgerException { private static final long serialVersionUID = 3583192000738807503L; diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/PeerServerBooter.java b/source/peer/src/main/java/com/jd/blockchain/peer/PeerServerBooter.java index 056753fe..b7892879 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/PeerServerBooter.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/PeerServerBooter.java @@ -169,7 +169,9 @@ public class PeerServerBooter { app.addInitializers((ApplicationContextInitializer) applicationContext -> { ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory(); for (Object bean : externalBeans) { - beanFactory.registerSingleton(bean.toString(), bean); + if (bean != null) { + beanFactory.registerSingleton(bean.toString(), bean); + } } }); } diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/consensus/ConsensusMessageDispatcher.java b/source/peer/src/main/java/com/jd/blockchain/peer/consensus/ConsensusMessageDispatcher.java index 7a3ba62f..fb123b99 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/consensus/ConsensusMessageDispatcher.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/consensus/ConsensusMessageDispatcher.java @@ -6,6 +6,8 @@ import com.jd.blockchain.ledger.OperationResult; import com.jd.blockchain.ledger.TransactionRequest; import com.jd.blockchain.ledger.TransactionResponse; import com.jd.blockchain.ledger.TransactionState; +import com.jd.blockchain.ledger.core.TransactionBatchProcessor; +import com.jd.blockchain.ledger.core.TransactionEngineImpl; import com.jd.blockchain.service.TransactionBatchProcess; import com.jd.blockchain.service.TransactionBatchResultHandle; import com.jd.blockchain.service.TransactionEngine; @@ -19,6 +21,7 @@ import com.jd.blockchain.consensus.service.MessageHandle; import com.jd.blockchain.consensus.service.StateSnapshot; import com.jd.blockchain.crypto.HashDigest; +import javax.swing.plaf.nimbus.State; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -61,6 +64,17 @@ public class ConsensusMessageDispatcher implements MessageHandle { return realmProcessor.newBatchId(); } + @Override + public StateSnapshot getStateSnapshot(String realmName) { + RealmProcessor realmProcessor = realmProcessorMap.get(realmName); + if (realmProcessor == null) { + throw new IllegalArgumentException("RealmName is not init!"); + } + + return realmProcessor.getStateSnapshot(); + + } + @Override public AsyncFuture processOrdered(int messageId, byte[] message, String realmName, String batchId) { // TODO 要求messageId在同一个批次不重复,但目前暂不验证 @@ -191,6 +205,10 @@ public class ConsensusMessageDispatcher implements MessageHandle { return currBatchId; } + public StateSnapshot getStateSnapshot() { + return new BlockStateSnapshot(((TransactionBatchProcessor)getTxBatchProcess()).getPreLatestBlockHeight(), ((TransactionBatchProcessor)getTxBatchProcess()).getPrevLatestBlockHash()); + } + public AsyncFuture schedule(TransactionRequest txRequest) { CompletableAsyncFuture asyncTxResult = new CompletableAsyncFuture<>(); TransactionResponse resp = getTxBatchProcess().schedule(txRequest); @@ -236,6 +254,7 @@ public class ConsensusMessageDispatcher implements MessageHandle { currBatchId = null; txResponseMap = null; txBatchProcess = null; + batchResultHandle =null; } finally { realmLock.unlock(); } @@ -244,10 +263,15 @@ public class ConsensusMessageDispatcher implements MessageHandle { public void rollback(int reasonCode) { realmLock.lock(); try { - batchResultHandle.cancel(TransactionState.valueOf((byte)reasonCode)); + if (batchResultHandle != null) { + batchResultHandle.cancel(TransactionState.valueOf((byte)reasonCode)); + } currBatchId = null; txResponseMap = null; txBatchProcess = null; + batchResultHandle = null; + ((TransactionEngineImpl) (txEngine)).freeBatch(ledgerHash); + ((TransactionEngineImpl) (txEngine)).resetNewBlockEditor(ledgerHash); } finally { realmLock.unlock(); } diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/ledger/LedgerConfigurer.java b/source/peer/src/main/java/com/jd/blockchain/peer/ledger/LedgerConfigurer.java index f6c8bcb9..5c5c8b7e 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/ledger/LedgerConfigurer.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/ledger/LedgerConfigurer.java @@ -1,5 +1,6 @@ package com.jd.blockchain.peer.ledger; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -12,6 +13,7 @@ import com.jd.blockchain.service.TransactionEngine; @Configuration public class LedgerConfigurer { + @ConditionalOnMissingBean @Bean public LedgerManager ledgerManager() { return new LedgerManager(); diff --git a/source/pom.xml b/source/pom.xml index d2195de0..6b804e5d 100644 --- a/source/pom.xml +++ b/source/pom.xml @@ -35,7 +35,7 @@ - 0.3.0.RELEASE + 0.4.0.RELEASE 1.1.2.RELEASE 1.1.2.RELEASE 2.4 diff --git a/source/test/test-integration/pom.xml b/source/test/test-integration/pom.xml index 4f63af4d..3f0b7650 100644 --- a/source/test/test-integration/pom.xml +++ b/source/test/test-integration/pom.xml @@ -58,6 +58,11 @@ ${project.version} + + org.mockito + mockito-core + + diff --git a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/IntegratedContext.java b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/IntegratedContext.java index 7a3bed53..f77158bd 100644 --- a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/IntegratedContext.java +++ b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/IntegratedContext.java @@ -6,12 +6,16 @@ import java.util.Map; import com.jd.blockchain.consensus.ConsensusSettings; import com.jd.blockchain.crypto.AsymmetricKeypair; +import com.jd.blockchain.crypto.HashDigest; import com.jd.blockchain.ledger.core.LedgerManager; +import com.jd.blockchain.storage.service.DbConnectionFactory; import com.jd.blockchain.storage.service.impl.composite.CompositeConnectionFactory; import com.jd.blockchain.tools.initializer.LedgerBindingConfig; public class IntegratedContext { + private HashDigest ledgerHash; + private Map nodes = new HashMap<>(); public int[] getNodeIds() { @@ -25,6 +29,14 @@ public class IntegratedContext { return ids; } + public HashDigest getLedgerHash() { + return ledgerHash; + } + + public void setLedgerHash(HashDigest ledgerHash) { + this.ledgerHash = ledgerHash; + } + public Node getNode(int id) { return nodes.get(id); } @@ -44,7 +56,7 @@ public class IntegratedContext { private LedgerManager ledgerManager; - private CompositeConnectionFactory storageDB; + private DbConnectionFactory storageDB; private LedgerBindingConfig bindingConfig; @@ -60,7 +72,7 @@ public class IntegratedContext { return ledgerManager; } - public CompositeConnectionFactory getStorageDB() { + public DbConnectionFactory getStorageDB() { return storageDB; } @@ -84,7 +96,7 @@ public class IntegratedContext { this.ledgerManager = ledgerManager; } - public void setStorageDB(CompositeConnectionFactory storageDB) { + public void setStorageDB(DbConnectionFactory storageDB) { this.storageDB = storageDB; } diff --git a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/IntegrationTest.java b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/IntegrationTest.java index 0ffcbb3e..8324af7c 100644 --- a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/IntegrationTest.java +++ b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/IntegrationTest.java @@ -7,7 +7,21 @@ import java.io.InputStream; import java.util.Properties; import java.util.Random; import java.util.concurrent.CountDownLatch; - +import java.util.concurrent.atomic.AtomicBoolean; + +import com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider; +import com.jd.blockchain.consensus.bftsmart.service.BftsmartNodeServer; +import com.jd.blockchain.consensus.bftsmart.service.BftsmartServerSettings; +import com.jd.blockchain.consensus.service.*; +import com.jd.blockchain.ledger.*; +import com.jd.blockchain.ledger.core.*; +import com.jd.blockchain.peer.consensus.ConsensusMessageDispatcher; +import com.jd.blockchain.peer.consensus.LedgerStateManager; +import com.jd.blockchain.storage.service.impl.composite.CompositeConnectionFactory; +import com.jd.blockchain.utils.concurrent.ThreadInvoker; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; import org.springframework.core.io.ClassPathResource; import com.jd.blockchain.consensus.ConsensusProvider; @@ -21,24 +35,6 @@ import com.jd.blockchain.crypto.KeyGenUtils; import com.jd.blockchain.crypto.PrivKey; import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.gateway.GatewayConfigProperties.KeyPairConfig; -import com.jd.blockchain.ledger.BlockchainIdentity; -import com.jd.blockchain.ledger.BlockchainKeyGenerator; -import com.jd.blockchain.ledger.BlockchainKeypair; -import com.jd.blockchain.ledger.BytesValue; -import com.jd.blockchain.ledger.DataAccountKVSetOperation; -import com.jd.blockchain.ledger.TypedKVEntry; -import com.jd.blockchain.ledger.LedgerBlock; -import com.jd.blockchain.ledger.LedgerInfo; -import com.jd.blockchain.ledger.LedgerInitProperties; -import com.jd.blockchain.ledger.ParticipantNode; -import com.jd.blockchain.ledger.PreparedTransaction; -import com.jd.blockchain.ledger.TransactionResponse; -import com.jd.blockchain.ledger.TransactionTemplate; -import com.jd.blockchain.ledger.UserInfo; -import com.jd.blockchain.ledger.core.DataAccountQuery; -import com.jd.blockchain.ledger.core.LedgerManage; -import com.jd.blockchain.ledger.core.LedgerManager; -import com.jd.blockchain.ledger.core.LedgerQuery; import com.jd.blockchain.sdk.BlockchainService; import com.jd.blockchain.sdk.client.GatewayServiceFactory; import com.jd.blockchain.storage.service.KVStorageService; @@ -54,6 +50,9 @@ import test.com.jd.blockchain.intgr.IntegratedContext.Node; import test.com.jd.blockchain.intgr.perf.LedgerInitializeWebTest; import test.com.jd.blockchain.intgr.perf.Utils; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doAnswer; + public class IntegrationTest { // 合约测试使用的初始化数据; BlockchainKeypair contractDataKey = BlockchainKeyGenerator.getInstance().generate(); @@ -73,37 +72,52 @@ public class IntegrationTest { private static String memDbConnString = LedgerInitConsensusConfig.memConnectionStrings[0]; - // private static final MQConnectionConfig mqConnConfig = new - // MQConnectionConfig(); - // static { - // mqConnConfig.setServer(MQ_SERVER); - // mqConnConfig.setTopic(MQ_TOPIC); - // } + private static AtomicBoolean isTestTurnOn = new AtomicBoolean(false); + + public static final String PASSWORD = "abc"; + + public static final String PUB_KEYS = "3snPdw7i7Pb3B5AxpSXy6YVruvftugNQ7rB7k2KWukhBwKQhFBFagT"; + public static final String PRIV_KEYS = "177gjtSgSdUF3LwRFGhzbpZZxmXXChsnwbuuLCG1V9KYfVuuxLwXGmZCp5FGUvsenhwBQLV"; + public static void main_(String[] args) { // init ledgers of all nodes ; IntegratedContext context = initLedgers(); + Node node0 = context.getNode(0); Node node1 = context.getNode(1); Node node2 = context.getNode(2); Node node3 = context.getNode(3); + LedgerManager ledgerManagerMock0 = Mockito.spy(node0.getLedgerManager()); + LedgerManager ledgerManagerMock1 = Mockito.spy(node1.getLedgerManager()); + LedgerManager ledgerManagerMock2 = Mockito.spy(node2.getLedgerManager()); + LedgerManager ledgerManagerMock3 = Mockito.spy(node3.getLedgerManager()); + + node0.setLedgerManager(ledgerManagerMock0); + node1.setLedgerManager(ledgerManagerMock1); + node2.setLedgerManager(ledgerManagerMock2); + node3.setLedgerManager(ledgerManagerMock3); + + //todo +// mockNodeServer(context); + NetworkAddress peerSrvAddr0 = new NetworkAddress("127.0.0.1", 10200); - PeerTestRunner peer0 = new PeerTestRunner(peerSrvAddr0, node0.getBindingConfig(), node0.getStorageDB()); + PeerTestRunner peer0 = new PeerTestRunner(peerSrvAddr0, node0.getBindingConfig(), node0.getStorageDB(), node0.getLedgerManager()); NetworkAddress peerSrvAddr1 = new NetworkAddress("127.0.0.1", 10210); - PeerTestRunner peer1 = new PeerTestRunner(peerSrvAddr1, node1.getBindingConfig(), node1.getStorageDB()); + PeerTestRunner peer1 = new PeerTestRunner(peerSrvAddr1, node1.getBindingConfig(), node1.getStorageDB(), node1.getLedgerManager()); NetworkAddress peerSrvAddr2 = new NetworkAddress("127.0.0.1", 10220); - PeerTestRunner peer2 = new PeerTestRunner(peerSrvAddr2, node2.getBindingConfig(), node2.getStorageDB()); + PeerTestRunner peer2 = new PeerTestRunner(peerSrvAddr2, node2.getBindingConfig(), node2.getStorageDB(), node2.getLedgerManager()); NetworkAddress peerSrvAddr3 = new NetworkAddress("127.0.0.1", 10230); - PeerTestRunner peer3 = new PeerTestRunner(peerSrvAddr3, node3.getBindingConfig(), node3.getStorageDB()); + PeerTestRunner peer3 = new PeerTestRunner(peerSrvAddr3, node3.getBindingConfig(), node3.getStorageDB(), node3.getLedgerManager()); - AsyncCallback peerStarting0 = peer0.start(); - AsyncCallback peerStarting1 = peer1.start(); - AsyncCallback peerStarting2 = peer2.start(); - AsyncCallback peerStarting3 = peer3.start(); + ThreadInvoker.AsyncCallback peerStarting0 = peer0.start(); + ThreadInvoker.AsyncCallback peerStarting1 = peer1.start(); + ThreadInvoker.AsyncCallback peerStarting2 = peer2.start(); + ThreadInvoker.AsyncCallback peerStarting3 = peer3.start(); peerStarting0.waitReturn(); peerStarting1.waitReturn(); @@ -116,38 +130,96 @@ public class IntegrationTest { gwkey0.setPubKeyValue(LedgerInitializeWebTest.PUB_KEYS[0]); gwkey0.setPrivKeyValue(LedgerInitializeWebTest.PRIV_KEYS[0]); gwkey0.setPrivKeyPassword(encodedBase58Pwd); - // GatewayTestRunner gateway0 = new GatewayTestRunner("127.0.0.1", 10300, - // gwkey0, peerSrvAddr0); - GatewayTestRunner gateway0 = new GatewayTestRunner("127.0.0.1", 10300, gwkey0, peerSrvAddr0); - // KeyPairConfig gwkey1 = new KeyPairConfig(); - // gwkey1.setPubKeyValue(LedgerInitializeWebTest.PUB_KEYS[1]); - // gwkey1.setPrivKeyValue(LedgerInitializeWebTest.PRIV_KEYS[1]); - // gwkey1.setPrivKeyPassword(encodedBase58Pwd); - // GatewayTestRunner gateway1 = new GatewayTestRunner("127.0.0.1", 10310, - // gwkey1, peerSrvAddr1); + GatewayTestRunner gateway0 = new GatewayTestRunner("127.0.0.1", 10300, gwkey0, peerSrvAddr0, LedgerInitConsensusConfig.bftsmartProvider, null); - AsyncCallback gwStarting0 = gateway0.start(); - // AsyncCallback gwStarting1 = gateway1.start(); + ThreadInvoker.AsyncCallback gwStarting0 = gateway0.start(); gwStarting0.waitReturn(); - // gwStarting1.waitReturn(); // 执行测试用例之前,校验每个节点的一致性; - // testConsistencyAmongNodes(context); +// testConsistencyAmongNodes(context); + + testStorageErrorBlockRollbackSdk(gateway0, context); + + testConsensusFirstTimeoutSdk(gateway0, context); + + testConsensusSecondTimeoutSdk(gateway0, context); + + //todo +// testBlockHashInconsistentSdk(gateway0, context); + + testTransactionRollbackSdk(gateway0, context); + + testInvalidUserSignerSdk(gateway0, context); testSDK(gateway0, context); + System.out.println("------IntegrationTest Ok--------"); + // 执行测试用例之后,校验每个节点的一致性; - // testConsistencyAmongNodes(context); +// testConsistencyAmongNodes(context); } + //todo +// private static void mockNodeServer(IntegratedContext context) { +// +// Bytes nodeAddress0 = AddressEncoding.generateAddress(context.getNode(0).getPartiKeyPair().getPubKey()); +// Bytes nodeAddress1 = AddressEncoding.generateAddress(context.getNode(1).getPartiKeyPair().getPubKey()); +// Bytes nodeAddress2 = AddressEncoding.generateAddress(context.getNode(2).getPartiKeyPair().getPubKey()); +// Bytes nodeAddress3 = AddressEncoding.generateAddress(context.getNode(3).getPartiKeyPair().getPubKey()); +// +// BftsmartConsensusProvider bftsmartProvider0 = new BftsmartConsensusProvider(); +// BftsmartConsensusProvider mockedBftsmartProvider0 = Mockito.spy(bftsmartProvider0); +// +// BftsmartConsensusProvider bftsmartProvider1 = new BftsmartConsensusProvider(); +// BftsmartConsensusProvider mockedBftsmartProvider1 = Mockito.spy(bftsmartProvider1); +// +// BftsmartConsensusProvider bftsmartProvider2 = new BftsmartConsensusProvider(); +// BftsmartConsensusProvider mockedBftsmartProvider2 = Mockito.spy(bftsmartProvider2); +// +// BftsmartConsensusProvider bftsmartProvider3 = new BftsmartConsensusProvider(); +// BftsmartConsensusProvider mockedBftsmartProvider3 = Mockito.spy(bftsmartProvider3); +// +// doAnswer(new Answer() { +// @Override +// public BftsmartNodeServer answer(InvocationOnMock invocation) throws Throwable { +// BftsmartServerSettings serverSettings =(BftsmartServerSettings) invocation.getArguments()[0]; +// +// MessageHandle messageHandle = new ConsensusMessageDispatcher(); +// // mock spy messageHandle +// MessageHandle mockedMessageHandle = Mockito.spy(messageHandle); +// +// StateMachineReplicate stateMachineReplicate = new LedgerStateManager(); +// +// if(nodeAddress0.equals(serverSettings.getReplicaSettings().getAddress())){ +// doAnswer(new Answer() { +// @Override +// public Object answer(InvocationOnMock invocation) throws Throwable { +// +// if (isTestTurnOn.get()) { +// Random random = new Random(); +// byte[] msg = new byte[4]; +// random.nextBytes(msg); +// invocation.getArguments()[0] = msg; +// } +// return invocation.callRealMethod(); +// } +// }).when(mockedMessageHandle).processOrdered(any(), any(), any(), any()); +// } +// +// return new BftsmartNodeServer(serverSettings, mockedMessageHandle, stateMachineReplicate); +// } +// }).when(mockedBftsmartProvider0).getServerFactory().setupServer(any(), any(), any()); +// +// ConsensusProviders.registerProvider(mockedBftsmartProvider0); +// } /** * 检查所有节点之间的账本是否一致; * * @param context */ - private void testConsistencyAmongNodes(IntegratedContext context) { + private static void testConsistencyAmongNodes(IntegratedContext context) { int[] ids = context.getNodeIds(); Node[] nodes = new Node[ids.length]; LedgerQuery[] ledgers = new LedgerQuery[ids.length]; @@ -164,6 +236,180 @@ public class IntegrationTest { } } + private static void testConsensusFirstTimeoutSdk(GatewayTestRunner gateway, IntegratedContext context) { + + AtomicBoolean isTestTurnOn = new AtomicBoolean(true); + + Node node0 = context.getNode(0); + Node node1 = context.getNode(1); + + LedgerManager ledgerManagerMock0 = node0.getLedgerManager(); + LedgerManager ledgerManagerMock1 = node1.getLedgerManager(); + + doAnswer(new Answer() { + @Override + public LedgerRepository answer(InvocationOnMock invocation) throws Throwable { + if (isTestTurnOn.get()) { + Thread.sleep(5000); + } + return (LedgerRepository)invocation.callRealMethod(); + } + }).when(ledgerManagerMock0).getLedger(any()); + + doAnswer(new Answer() { + @Override + public LedgerRepository answer(InvocationOnMock invocation) throws Throwable { + if (isTestTurnOn.get()) { + Thread.sleep(5000); + } + return (LedgerRepository)invocation.callRealMethod(); + } + }).when(ledgerManagerMock1).getLedger(any()); + + testSDK(gateway, context); + + isTestTurnOn.set(false); + } + + private static void testConsensusSecondTimeoutSdk(GatewayTestRunner gateway, IntegratedContext context) { + AtomicBoolean isTestTurnOn = new AtomicBoolean(true); + + Node node0 = context.getNode(0); + Node node1 = context.getNode(1); + + LedgerManager ledgerManagerMock0 = node0.getLedgerManager(); + LedgerManager ledgerManagerMock1 = node1.getLedgerManager(); + + doAnswer(new Answer() { + @Override + public LedgerRepository answer(InvocationOnMock invocation) throws Throwable { + if (isTestTurnOn.get()) { + Thread.sleep(10000); + } + return (LedgerRepository)invocation.callRealMethod(); + } + }).when(ledgerManagerMock0).getLedger(any()); + + doAnswer(new Answer() { + @Override + public LedgerRepository answer(InvocationOnMock invocation) throws Throwable { + if (isTestTurnOn.get()) { + Thread.sleep(10000); + } + return (LedgerRepository)invocation.callRealMethod(); + } + }).when(ledgerManagerMock1).getLedger(any()); + + testSDK(gateway, context); + + isTestTurnOn.set(false); + } + + //todo +// private static void testBlockHashInconsistentSdk(GatewayTestRunner gateway, IntegratedContext context) { +// isTestTurnOn.set(true); +// testSDK(gateway, context); +// isTestTurnOn.set(false); +// +// } + + private static void testStorageErrorBlockRollbackSdk(GatewayTestRunner gateway, IntegratedContext context) { + + ((TestDbFactory)context.getNode(0).getStorageDB()).setErrorSetTurnOn(true); + ((TestDbFactory)context.getNode(1).getStorageDB()).setErrorSetTurnOn(true); + ((TestDbFactory)context.getNode(2).getStorageDB()).setErrorSetTurnOn(true); + ((TestDbFactory)context.getNode(3).getStorageDB()).setErrorSetTurnOn(true); + + testSDK(gateway, context); + + ((TestDbFactory)context.getNode(0).getStorageDB()).setErrorSetTurnOn(false); + ((TestDbFactory)context.getNode(1).getStorageDB()).setErrorSetTurnOn(false); + ((TestDbFactory)context.getNode(2).getStorageDB()).setErrorSetTurnOn(false); + ((TestDbFactory)context.getNode(3).getStorageDB()).setErrorSetTurnOn(false); + + } + + private static void testTransactionRollbackSdk(GatewayTestRunner gateway, IntegratedContext context) { + + // 连接网关; + GatewayServiceFactory gwsrvFact = GatewayServiceFactory.connect(gateway.getServiceAddress()); + BlockchainService bcsrv = gwsrvFact.getBlockchainService(); + + HashDigest[] ledgerHashs = bcsrv.getLedgerHashs(); + + AsymmetricKeypair adminKey = context.getNode(0).getPartiKeyPair(); + + // 注册用户,并验证最终写入; + BlockchainKeypair dataAccount = BlockchainKeyGenerator.getInstance().generate(); + + // 定义交易; + TransactionTemplate txTpl = bcsrv.newTransaction(ledgerHashs[0]); + txTpl.dataAccounts().register(dataAccount.getIdentity()); + + String dataKey = "jd_code"; + String dataVal = "www.jd.com"; + + // Construct error kv version + txTpl.dataAccount(dataAccount.getAddress()).setText(dataKey, dataVal, 1); + + PreparedTransaction prepTx = txTpl.prepare(); + + prepTx.sign(adminKey); + + // 提交并等待共识返回; + TransactionResponse txResp = prepTx.commit(); + + // 验证结果; + Node node0 = context.getNode(0); + LedgerManage ledgerManager = new LedgerManager(); + + KVStorageService storageService = node0.getStorageDB().connect(memDbConnString).getStorageService(); + + LedgerQuery ledgerOfNode0 = ledgerManager.register(ledgerHashs[0], storageService); + + + } + + private static void testInvalidUserSignerSdk(GatewayTestRunner gateway, IntegratedContext context) { + // 连接网关; + GatewayServiceFactory gwsrvFact = GatewayServiceFactory.connect(gateway.getServiceAddress()); + BlockchainService bcsrv = gwsrvFact.getBlockchainService(); + + HashDigest[] ledgerHashs = bcsrv.getLedgerHashs(); + + //Invalid signer + PrivKey privKey = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS, PASSWORD); + PubKey pubKey = KeyGenUtils.decodePubKey(PUB_KEYS); + + AsymmetricKeypair asymmetricKeypair = new AsymmetricKeypair(pubKey, privKey); + + // 注册用户,并验证最终写入; + BlockchainKeypair user = BlockchainKeyGenerator.getInstance().generate(); + + // 定义交易; + TransactionTemplate txTpl = bcsrv.newTransaction(ledgerHashs[0]); + txTpl.users().register(user.getIdentity()); + + // 签名; + PreparedTransaction ptx = txTpl.prepare(); + + HashDigest transactionHash = ptx.getHash(); + + ptx.sign(asymmetricKeypair); + + // 提交并等待共识返回; + TransactionResponse txResp = ptx.commit(); + + // 验证结果; + Node node0 = context.getNode(0); + LedgerManage ledgerManager = new LedgerManager(); + + KVStorageService storageService = node0.getStorageDB().connect(memDbConnString).getStorageService(); + + LedgerQuery ledgerOfNode0 = ledgerManager.register(ledgerHashs[0], storageService); + + } + private static void testSDK(GatewayTestRunner gateway, IntegratedContext context) { // 连接网关; GatewayServiceFactory gwsrvFact = GatewayServiceFactory.connect(gateway.getServiceAddress()); @@ -427,15 +673,15 @@ public class IntegrationTest { return; } - public static ConsensusProvider getConsensusProvider() { - return ConsensusProviders.getProvider("com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider"); + public static ConsensusProvider getConsensusProvider(String providerName) { + return ConsensusProviders.getProvider(providerName); } private static IntegratedContext initLedgers() { Prompter consolePrompter = new PresetAnswerPrompter("N"); // new ConsolePrompter(); LedgerInitProperties initSetting = loadInitSetting_integration(); - Properties props = LedgerInitializeWebTest.loadConsensusSetting(); - ConsensusProvider csProvider = getConsensusProvider(); + Properties props = LedgerInitializeWebTest.loadConsensusSetting(LedgerInitConsensusConfig.bftsmartConfig.getConfigPath()); + ConsensusProvider csProvider = getConsensusProvider(LedgerInitConsensusConfig.bftsmartConfig.getProvider()); ConsensusSettings csProps = csProvider.getSettingsFactory() .getConsensusSettingsBuilder() .createSettings(props, Utils.loadParticipantNodes()); @@ -465,29 +711,39 @@ public class IntegrationTest { CountDownLatch quitLatch = new CountDownLatch(4); + TestDbFactory dbFactory0 = new TestDbFactory(new CompositeConnectionFactory()); + dbFactory0.setErrorSetTurnOn(false); DBConnectionConfig testDb0 = new DBConnectionConfig(); testDb0.setConnectionUri("memory://local/0"); LedgerBindingConfig bindingConfig0 = new LedgerBindingConfig(); AsyncCallback callback0 = nodeCtx0.startInitCommand(privkey0, encodedPassword, initSetting, csProps, - csProvider, testDb0, consolePrompter, bindingConfig0, quitLatch); + csProvider, testDb0, consolePrompter, bindingConfig0, quitLatch, dbFactory0); + + TestDbFactory dbFactory1 = new TestDbFactory(new CompositeConnectionFactory()); + dbFactory1.setErrorSetTurnOn(false); DBConnectionConfig testDb1 = new DBConnectionConfig(); testDb1.setConnectionUri("memory://local/1"); LedgerBindingConfig bindingConfig1 = new LedgerBindingConfig(); AsyncCallback callback1 = nodeCtx1.startInitCommand(privkey1, encodedPassword, initSetting, csProps, - csProvider, testDb1, consolePrompter, bindingConfig1, quitLatch); + csProvider, testDb1, consolePrompter, bindingConfig1, quitLatch, dbFactory1); + + TestDbFactory dbFactory2 = new TestDbFactory(new CompositeConnectionFactory()); + dbFactory2.setErrorSetTurnOn(false); DBConnectionConfig testDb2 = new DBConnectionConfig(); testDb2.setConnectionUri("memory://local/2"); LedgerBindingConfig bindingConfig2 = new LedgerBindingConfig(); AsyncCallback callback2 = nodeCtx2.startInitCommand(privkey2, encodedPassword, initSetting, csProps, - csProvider, testDb2, consolePrompter, bindingConfig2, quitLatch); + csProvider, testDb2, consolePrompter, bindingConfig2, quitLatch, dbFactory2); + TestDbFactory dbFactory3 = new TestDbFactory(new CompositeConnectionFactory()); + dbFactory3.setErrorSetTurnOn(false); DBConnectionConfig testDb3 = new DBConnectionConfig(); testDb3.setConnectionUri("memory://local/3"); LedgerBindingConfig bindingConfig3 = new LedgerBindingConfig(); AsyncCallback callback3 = nodeCtx3.startInitCommand(privkey3, encodedPassword, initSetting, csProps, - csProvider, testDb3, consolePrompter, bindingConfig3, quitLatch); + csProvider, testDb3, consolePrompter, bindingConfig3, quitLatch, dbFactory3); HashDigest ledgerHash0 = callback0.waitReturn(); HashDigest ledgerHash1 = callback1.waitReturn(); @@ -501,6 +757,8 @@ public class IntegrationTest { IntegratedContext context = new IntegratedContext(); + context.setLedgerHash(ledgerHash0); + Node node0 = new Node(0); node0.setConsensusSettings(csProps); node0.setLedgerManager(nodeCtx0.getLedgerManager()); @@ -542,7 +800,7 @@ public class IntegrationTest { } public static LedgerInitProperties loadInitSetting_integration() { - ClassPathResource ledgerInitSettingResource = new ClassPathResource("ledger_init_test_integration.init"); + ClassPathResource ledgerInitSettingResource = new ClassPathResource("ledger_init_test_web2.init"); try (InputStream in = ledgerInitSettingResource.getInputStream()) { LedgerInitProperties setting = LedgerInitProperties.resolve(in); return setting; diff --git a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/PeerTestRunner.java b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/PeerTestRunner.java index c2c552ed..0a0722f0 100644 --- a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/PeerTestRunner.java +++ b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/PeerTestRunner.java @@ -1,5 +1,6 @@ package test.com.jd.blockchain.intgr; +import com.jd.blockchain.ledger.core.LedgerManager; import com.jd.blockchain.peer.PeerServerBooter; import com.jd.blockchain.storage.service.DbConnectionFactory; import com.jd.blockchain.tools.initializer.LedgerBindingConfig; @@ -28,18 +29,18 @@ public class PeerTestRunner { } public PeerTestRunner(NetworkAddress serviceAddress, LedgerBindingConfig ledgerBindingConfig) { - this(serviceAddress, ledgerBindingConfig, null); + this(serviceAddress, ledgerBindingConfig, null, null); } public PeerTestRunner(NetworkAddress serviceAddress, LedgerBindingConfig ledgerBindingConfig, - DbConnectionFactory dbConnectionFactory) { + DbConnectionFactory dbConnectionFactory, LedgerManager ledgerManager) { this.serviceAddress = serviceAddress; this.ledgerBindingConfig = ledgerBindingConfig; if (dbConnectionFactory == null) { this.peerServer = new PeerServerBooter(ledgerBindingConfig, serviceAddress.getHost(), serviceAddress.getPort(),null); }else { this.peerServer = new PeerServerBooter(ledgerBindingConfig, serviceAddress.getHost(), serviceAddress.getPort(),null, - dbConnectionFactory); + dbConnectionFactory, ledgerManager); } } diff --git a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/TestDbFactory.java b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/TestDbFactory.java new file mode 100644 index 00000000..0b9c7ed6 --- /dev/null +++ b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/TestDbFactory.java @@ -0,0 +1,140 @@ +package test.com.jd.blockchain.intgr; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.when; + +import java.util.concurrent.atomic.AtomicBoolean; + +import com.jd.blockchain.storage.service.*; +import com.jd.blockchain.storage.service.utils.MemoryKVStorage; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +public class TestDbFactory implements DbConnectionFactory{ + + private DbConnectionFactory innerDbFactory; + + private AtomicBoolean errorSetTurnOn = new AtomicBoolean(false); + + public TestDbFactory(DbConnectionFactory innerDbFactory) { + this.innerDbFactory = innerDbFactory; + } + + + Answer exKVStorageMockedAnswer = new Answer() { + + @Override + public ExPolicyKVStorage answer(InvocationOnMock invocation) throws Throwable { + + ExPolicyKVStorage reallyExKVStorage = (ExPolicyKVStorage) invocation.callRealMethod(); + + ExPolicyKVStorage mockExKVStorage = Mockito.spy(reallyExKVStorage); + + //按条件开关触发异常; + doAnswer(new Answer() { + + @Override + public Boolean answer(InvocationOnMock invocation) throws Throwable { + if (isErrorSetTurnOn()) { + return false; + } + return (Boolean) invocation.callRealMethod(); + } + }).when(mockExKVStorage).set(any(), any(), any()); + + return mockExKVStorage; + } + }; + + Answer verKVStorageMockedAnswer = new Answer() { + + @Override + public VersioningKVStorage answer(InvocationOnMock invocation) throws Throwable { + + VersioningKVStorage reallyVerKVStorage = (VersioningKVStorage) invocation.callRealMethod(); + + VersioningKVStorage mockVerKVStorage = Mockito.spy(reallyVerKVStorage); + + //按条件开关触发异常; + doAnswer(new Answer() { + + @Override + public Long answer(InvocationOnMock invocation) throws Throwable { + if (isErrorSetTurnOn()) { + return (long)(-1); + } + return (Long) invocation.callRealMethod(); + } + }).when(mockVerKVStorage).set(any(), any(), anyLong()); + + return mockVerKVStorage; + } + }; + + Answer storageMockedAnswer = new Answer() { + + @Override + public KVStorageService answer(InvocationOnMock invocation) throws Throwable { + + KVStorageService reallyStorage = (KVStorageService) invocation.callRealMethod(); + + TestMemoryKVStorage testMemoryKVStorage = new TestMemoryKVStorage((MemoryKVStorage)reallyStorage); + + KVStorageService mockedStorage = Mockito.spy(testMemoryKVStorage); + + doAnswer(exKVStorageMockedAnswer).when(mockedStorage).getExPolicyKVStorage(); + + doAnswer(verKVStorageMockedAnswer).when(mockedStorage).getVersioningKVStorage(); + + return mockedStorage; + } + + }; + + + @Override + public String dbPrefix() { + return innerDbFactory.dbPrefix(); + } + + @Override + public boolean support(String scheme) { + return innerDbFactory.support(scheme); + } + + @Override + public DbConnection connect(String dbConnectionString) { + + DbConnection reallyDbConn = innerDbFactory.connect(dbConnectionString); + + DbConnection mockDbConn = Mockito.spy(reallyDbConn); + + when(mockDbConn.getStorageService()).then(storageMockedAnswer); + return mockDbConn; + } + + @Override + public DbConnection connect(String dbConnectionString, String password) { + return connect(dbConnectionString); + } + + @Override + public void close() { + innerDbFactory.close(); + + } + + public boolean isErrorSetTurnOn() { + return errorSetTurnOn.get(); + } + + public void setErrorSetTurnOn(boolean errorSetTurnOn) { + this.errorSetTurnOn.set(errorSetTurnOn);; + } + + + +} diff --git a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/TestMemoryKVStorage.java b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/TestMemoryKVStorage.java new file mode 100644 index 00000000..15e99f60 --- /dev/null +++ b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/TestMemoryKVStorage.java @@ -0,0 +1,24 @@ +package test.com.jd.blockchain.intgr; + +import com.jd.blockchain.storage.service.ExPolicyKVStorage; +import com.jd.blockchain.storage.service.VersioningKVStorage; +import com.jd.blockchain.storage.service.utils.MemoryKVStorage; + +public class TestMemoryKVStorage extends MemoryKVStorage { + + private MemoryKVStorage memoryKVStorage; + + public TestMemoryKVStorage(MemoryKVStorage memoryKVStorage) { + this.memoryKVStorage = memoryKVStorage; + } + + @Override + public ExPolicyKVStorage getExPolicyKVStorage() { + return memoryKVStorage; + } + + @Override + public VersioningKVStorage getVersioningKVStorage() { + return memoryKVStorage; + } +} diff --git a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/consensus/ConsensusTest.java b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/consensus/ConsensusTest.java index 7c959bc3..e91d804e 100644 --- a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/consensus/ConsensusTest.java +++ b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/consensus/ConsensusTest.java @@ -69,16 +69,16 @@ public class ConsensusTest { Node node3 = context.getNode(3); NetworkAddress peerSrvAddr0 = new NetworkAddress("127.0.0.1", 10200); - PeerTestRunner peer0 = new PeerTestRunner(peerSrvAddr0, node0.getBindingConfig(), node0.getStorageDB()); + PeerTestRunner peer0 = new PeerTestRunner(peerSrvAddr0, node0.getBindingConfig(), node0.getStorageDB(), null); NetworkAddress peerSrvAddr1 = new NetworkAddress("127.0.0.1", 10210); - PeerTestRunner peer1 = new PeerTestRunner(peerSrvAddr1, node1.getBindingConfig(), node1.getStorageDB()); + PeerTestRunner peer1 = new PeerTestRunner(peerSrvAddr1, node1.getBindingConfig(), node1.getStorageDB(), null); NetworkAddress peerSrvAddr2 = new NetworkAddress("127.0.0.1", 10220); - PeerTestRunner peer2 = new PeerTestRunner(peerSrvAddr2, node2.getBindingConfig(), node2.getStorageDB()); + PeerTestRunner peer2 = new PeerTestRunner(peerSrvAddr2, node2.getBindingConfig(), node2.getStorageDB(), null); NetworkAddress peerSrvAddr3 = new NetworkAddress("127.0.0.1", 10230); - PeerTestRunner peer3 = new PeerTestRunner(peerSrvAddr3, node3.getBindingConfig(), node3.getStorageDB()); + PeerTestRunner peer3 = new PeerTestRunner(peerSrvAddr3, node3.getBindingConfig(), node3.getStorageDB(), null); AsyncCallback peerStarting0 = peer0.start(); AsyncCallback peerStarting1 = peer1.start(); diff --git a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/GlobalPerformanceTest.java b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/GlobalPerformanceTest.java index 7f23a276..a7ef9fae 100644 --- a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/GlobalPerformanceTest.java +++ b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/GlobalPerformanceTest.java @@ -67,16 +67,16 @@ public class GlobalPerformanceTest { Node node3 = context.getNode(3); NetworkAddress peerSrvAddr0 = new NetworkAddress("127.0.0.1", 10200); - PeerTestRunner peer0 = new PeerTestRunner(peerSrvAddr0, node0.getBindingConfig(), node0.getStorageDB()); + PeerTestRunner peer0 = new PeerTestRunner(peerSrvAddr0, node0.getBindingConfig(), node0.getStorageDB(), null); NetworkAddress peerSrvAddr1 = new NetworkAddress("127.0.0.1", 10210); - PeerTestRunner peer1 = new PeerTestRunner(peerSrvAddr1, node1.getBindingConfig(), node1.getStorageDB()); + PeerTestRunner peer1 = new PeerTestRunner(peerSrvAddr1, node1.getBindingConfig(), node1.getStorageDB(), null); NetworkAddress peerSrvAddr2 = new NetworkAddress("127.0.0.1", 10220); - PeerTestRunner peer2 = new PeerTestRunner(peerSrvAddr2, node2.getBindingConfig(), node2.getStorageDB()); + PeerTestRunner peer2 = new PeerTestRunner(peerSrvAddr2, node2.getBindingConfig(), node2.getStorageDB(), null); NetworkAddress peerSrvAddr3 = new NetworkAddress("127.0.0.1", 10230); - PeerTestRunner peer3 = new PeerTestRunner(peerSrvAddr3, node3.getBindingConfig(), node3.getStorageDB()); + PeerTestRunner peer3 = new PeerTestRunner(peerSrvAddr3, node3.getBindingConfig(), node3.getStorageDB(), null); AsyncCallback peerStarting0 = peer0.start(); AsyncCallback peerStarting1 = peer1.start(); diff --git a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerInitializeTest.java b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerInitializeTest.java index 36ef321f..71efc4e5 100644 --- a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerInitializeTest.java +++ b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerInitializeTest.java @@ -48,16 +48,17 @@ public class LedgerInitializeTest { public static final String PASSWORD = "abc"; - public static final String[] PUB_KEYS = { "endPsK36koyFr1D245Sa9j83vt6pZUdFBJoJRB3xAsWM6cwhRbna", - "endPsK36sC5JdPCDPDAXUwZtS3sxEmqEhFcC4whayAsTTh8Z6eoZ", - "endPsK36jEG281HMHeh6oSqzqLkT95DTnCM6REDURjdb2c67uR3R", - "endPsK36nse1dck4uF19zPvAMijCV336Y3zWdgb4rQG8QoRj5ktR" }; + public static final String[] PUB_KEYS = { "3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9", + "3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX", + "3snPdw7i7PZi6TStiyc6mzjprnNhgs2atSGNS8wPYzhbKaUWGFJt7x", + "3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk" }; + public static final String[] PRIV_KEYS = { - "177gjsj5PHeCpbAtJE7qnbmhuZMHAEKuMsd45zHkv8F8AWBvTBbff8yRKdCyT3kwrmAjSnY", - "177gjw9u84WtuCsK8u2WeH4nWqzgEoJWY7jJF9AU6XwLHSosrcNX3H6SSBsfvR53HgX7KR2", - "177gk2FpjufgEon92mf2oRRFXDBZkRy8SkFci7Jxc5pApZEJz3oeCoxieWatDD3Xg7i1QEN", - "177gjvv7qvfCAXroFezSn23UFXLVLFofKS3y6DXkJ2DwVWS4LcRNtxRgiqWmQEeWNz4KQ3J" }; + "177gjzHTznYdPgWqZrH43W3yp37onm74wYXT4v9FukpCHBrhRysBBZh7Pzdo5AMRyQGJD7x", + "177gju9p5zrNdHJVEQnEEKF4ZjDDYmAXyfG84V5RPGVc5xFfmtwnHA7j51nyNLUFffzz5UT", + "177gjtwLgmSx5v1hFb46ijh7L9kdbKUpJYqdKVf9afiEmAuLgo8Rck9yu5UuUcHknWJuWaF", + "177gk1pudweTq5zgJTh8y3ENCTwtSFsKyX7YnpuKPo7rKgCkCBXVXh5z2syaTCPEMbuWRns" }; private Map serviceRegisterMap = new ConcurrentHashMap<>(); diff --git a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerInitializeWebTest.java b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerInitializeWebTest.java index 8ee650cc..b687d8f6 100644 --- a/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerInitializeWebTest.java +++ b/source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerInitializeWebTest.java @@ -5,6 +5,11 @@ import java.io.InputStream; import java.util.Properties; import java.util.concurrent.CountDownLatch; +import com.jd.blockchain.ledger.core.*; +import com.jd.blockchain.storage.service.DbConnectionFactory; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; import org.springframework.boot.SpringApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.io.ClassPathResource; @@ -27,12 +32,6 @@ import com.jd.blockchain.ledger.LedgerInitProperties; import com.jd.blockchain.ledger.Operation; import com.jd.blockchain.ledger.TransactionContent; import com.jd.blockchain.ledger.UserRegisterOperation; -import com.jd.blockchain.ledger.core.LedgerInitDecision; -import com.jd.blockchain.ledger.core.LedgerInitProposal; -import com.jd.blockchain.ledger.core.LedgerManager; -import com.jd.blockchain.ledger.core.LedgerQuery; -import com.jd.blockchain.ledger.core.UserAccount; -import com.jd.blockchain.ledger.core.UserAccountQuery; import com.jd.blockchain.storage.service.DbConnection; import com.jd.blockchain.storage.service.impl.composite.CompositeConnectionFactory; //import com.jd.blockchain.storage.service.utils.MemoryBasedDb; @@ -52,6 +51,7 @@ import com.jd.blockchain.utils.io.BytesUtils; import com.jd.blockchain.utils.io.FileUtils; import com.jd.blockchain.utils.net.NetworkAddress; +import test.com.jd.blockchain.intgr.LedgerInitConsensusConfig; import test.com.jd.blockchain.intgr.PresetAnswerPrompter; public class LedgerInitializeWebTest { @@ -73,7 +73,7 @@ public class LedgerInitializeWebTest { // 加载初始化配置; LedgerInitProperties initSetting = loadInitSetting_1(); // 加载共识配置; - Properties props = loadConsensusSetting(); + Properties props = loadConsensusSetting(LedgerInitConsensusConfig.bftsmartConfig.getConfigPath()); // ConsensusProperties csProps = new ConsensusProperties(props); ConsensusProvider csProvider = getConsensusProvider(); ConsensusSettings csProps = csProvider.getSettingsFactory() @@ -242,7 +242,7 @@ public class LedgerInitializeWebTest { Prompter consolePrompter = new PresetAnswerPrompter("N"); // new ConsolePrompter(); LedgerInitProperties initSetting = loadInitSetting_2(); - Properties props = loadConsensusSetting(); + Properties props = loadConsensusSetting(LedgerInitConsensusConfig.bftsmartConfig.getConfigPath()); // ConsensusProperties csProps = new ConsensusProperties(props); ConsensusProvider csProvider = getConsensusProvider(); ConsensusSettings csProps = csProvider.getSettingsFactory() @@ -340,8 +340,8 @@ public class LedgerInitializeWebTest { } } - public static Properties loadConsensusSetting() { - ClassPathResource ledgerInitSettingResource = new ClassPathResource("bftsmart.config"); + public static Properties loadConsensusSetting(String configPath) { + ClassPathResource ledgerInitSettingResource = new ClassPathResource(configPath); try (InputStream in = ledgerInitSettingResource.getInputStream()) { return FileUtils.readProperties(in); } catch (IOException e) { @@ -365,7 +365,7 @@ public class LedgerInitializeWebTest { private volatile LedgerManager ledgerManager; - private volatile CompositeConnectionFactory db; + private volatile DbConnectionFactory db; private int id; @@ -401,9 +401,14 @@ public class LedgerInitializeWebTest { // dbConnConfig.getPassword()); DbConnection conn = db.connect(dbConnConfig.getUri()); LedgerQuery ledgerRepo = ledgerManager.register(ledgerHash, conn.getStorageService()); + return ledgerRepo; } + public LedgerRepository ledgerRepository(HashDigest ledgerHash) { + return ledgerManager.getLedger(ledgerHash); + } + public SignatureDigest createPermissionRequestSignature(int requesterId, PrivKey privKey) { return controller.signPermissionRequest(requesterId, privKey); } @@ -429,21 +434,14 @@ public class LedgerInitializeWebTest { return invoker.start(); } - // public AsyncCallback startInitCommand(PrivKey privKey, String - // base58Pwd, LedgerInitProperties ledgerSetting, ConsensusSettings csProps, - // DBConnectionConfig dbConnConfig, - // Prompter prompter, LedgerBindingConfig conf, CountDownLatch quitLatch) { - // return startInitCommand(privKey, base58Pwd, ledgerSetting, csProps, - // dbConnConfig, prompter, conf, quitLatch); - // } public AsyncCallback startInitCommand(PrivKey privKey, String base58Pwd, - LedgerInitProperties ledgerSetting, ConsensusSettings csProps, ConsensusProvider csProvider, - DBConnectionConfig dbConnConfig, Prompter prompter, LedgerBindingConfig conf, - CountDownLatch quitLatch) { - this.db = new CompositeConnectionFactory(); + LedgerInitProperties ledgerSetting, ConsensusSettings csProps, ConsensusProvider csProvider, + DBConnectionConfig dbConnConfig, Prompter prompter, LedgerBindingConfig conf, + CountDownLatch quitLatch, DbConnectionFactory db) { this.dbConnConfig = dbConnConfig; // this.mqConnConfig = mqConnConfig; + this.db = db; ThreadInvoker invoker = new ThreadInvoker() { @Override @@ -451,7 +449,11 @@ public class LedgerInitializeWebTest { LedgerInitCommand initCmd = new LedgerInitCommand(); HashDigest ledgerHash = initCmd.startInit(id, privKey, base58Pwd, ledgerSetting, dbConnConfig, prompter, conf, db); - NodeWebContext.this.ledgerManager = initCmd.getLedgerManager(); + + LedgerManager lm = initCmd.getLedgerManager(); + + NodeWebContext.this.ledgerManager = lm; + quitLatch.countDown(); return ledgerHash; } @@ -460,6 +462,7 @@ public class LedgerInitializeWebTest { return invoker.start(); } + public LedgerInitProposal preparePermision(PrivKey privKey, LedgerInitConfiguration initConfig) { return controller.prepareLocalPermission(id, privKey, initConfig); } @@ -517,7 +520,7 @@ public class LedgerInitializeWebTest { // return ctx.getBean(LedgerManager.class); } - public CompositeConnectionFactory getStorageDB() { + public DbConnectionFactory getStorageDB() { return db; } } diff --git a/source/test/test-integration/src/main/resources/bftsmart.config b/source/test/test-integration/src/main/resources/bftsmart.config index df811663..80ed0f6a 100644 --- a/source/test/test-integration/src/main/resources/bftsmart.config +++ b/source/test/test-integration/src/main/resources/bftsmart.config @@ -14,58 +14,36 @@ # limitations under the License. -############################################ -###### Consensus Commit Block Parameters: transaction count ###### -############################################ -system.block.txsize=15 - -############################################ -###### Consensus Commit Block Parameters: delay time ###### -############################################ -system.block.maxdelay=500 - ############################################ ###### Consensus Participant0 ###### ############################################ -system.server.0.pubkey=3snPdw7i7PapsDoW185c3kfK6p8s6SwiJAdEUzgnfeuUox12nxgzXu system.server.0.network.host=127.0.0.1 - system.server.0.network.port=8910 - system.server.0.network.secure=false ############################################ ###### #Consensus Participant1 ###### ############################################ -system.server.1.pubkey=3snPdw7i7Ph1SYLQt9uqVEqiuvNXjxCdGvEdN6otJsg5rbr7Aze7kf system.server.1.network.host=127.0.0.1 - system.server.1.network.port=8920 - system.server.1.network.secure=false ############################################ ###### #Consensus Participant2 ###### ############################################ -system.server.2.pubkey=3snPdw7i7PezptA6dNBkotPjmKEbTkY8fmusLBnfj8Cf7eFwhWDwKr system.server.2.network.host=127.0.0.1 - system.server.2.network.port=8930 - system.server.2.network.secure=false ############################################ ###### Consensus Participant3 ###### ############################################ -system.server.3.pubkey=3snPdw7i7PerZYfRzEB61SAN9tFK4yHm9wUSRtkLSSGXHkQRbB5PkS system.server.3.network.host=127.0.0.1 - system.server.3.network.port=8940 - system.server.3.network.secure=false ############################################ @@ -94,7 +72,7 @@ system.servers.num = 4 #system.servers.f = 1 #Timeout to asking for a client request -system.totalordermulticast.timeout = 2000 +system.totalordermulticast.timeout = 5000 #Maximum batch size (in number of messages) @@ -174,5 +152,4 @@ system.ttp.id = 7002 system.bft = true #Custom View Storage; -#view.storage.handler=bftsmart.reconfiguration.views.DefaultViewStorage - +#view.storage.handler=bftsmart.reconfiguration.views.DefaultViewStorage \ No newline at end of file diff --git a/source/test/test-integration/src/main/resources/ledger_init_test_web2.init b/source/test/test-integration/src/main/resources/ledger_init_test_web2.init index 00fc9da1..5be0e69d 100644 --- a/source/test/test-integration/src/main/resources/ledger_init_test_web2.init +++ b/source/test/test-integration/src/main/resources/ledger_init_test_web2.init @@ -2,7 +2,10 @@ ledger.seed=932dfe23-fe23232f-283f32fa-dd32aa76-8322ca2f-56236cda-7136b322-cb323ffe #账本的描述名称;此属性不参与共识,仅仅在当前参与方的本地节点用于描述用途; -ledger.name= +ledger.name==myledger + +#声明的账本创建时间;格式为 “yyyy-MM-dd HH:mm:ss.SSSZ”,表示”年-月-日 时:分:秒:毫秒时区“;例如:“2019-08-01 14:26:58.069+0800”,其中,+0800 表示时区是东8区 +created-time=2019-08-01 14:26:58.069+0800 #共识服务提供者;必须; consensus.service-provider=com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java index 37c792f2..a109e456 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBase.java @@ -103,6 +103,36 @@ public class IntegrationBase { return keyPairResponse; } + public static KeyPairResponse testSDK_BlockFullRollBack(AsymmetricKeypair adminKey, HashDigest ledgerHash, + BlockchainService blockchainService) { + + BlockchainKeypair user = BlockchainKeyGenerator.getInstance().generate(); + + TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); + + //Register user account + txTpl.users().register(user.getIdentity()); + + PreparedTransaction prepTx = txTpl.prepare(); + + HashDigest transactionHash = prepTx.getHash(); + + prepTx.sign(adminKey); + + //Commit transaction + TransactionResponse transactionResponse = prepTx.commit(); + + //The whole block will rollback, due to storage error + assertEquals(transactionResponse.getExecutionState().CODE, TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK.CODE); + + KeyPairResponse keyPairResponse = new KeyPairResponse(); + keyPairResponse.keyPair = user; + keyPairResponse.txResp = transactionResponse; + keyPairResponse.txHash = transactionHash; + return keyPairResponse; + } + + public static KeyPairResponse testSDK_RegisterDataAccount(AsymmetricKeypair adminKey, HashDigest ledgerHash, BlockchainService blockchainService) { // 注册数据账户,并验证最终写入; diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBaseTest.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBaseTest.java index d28a2b45..4d9cf522 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBaseTest.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationBaseTest.java @@ -47,16 +47,16 @@ public class IntegrationBaseTest { Node node3 = context.getNode(3); NetworkAddress peerSrvAddr0 = new NetworkAddress("127.0.0.1", 13200); - PeerTestRunner peer0 = new PeerTestRunner(peerSrvAddr0, node0.getBindingConfig(), node0.getStorageDB()); + PeerTestRunner peer0 = new PeerTestRunner(peerSrvAddr0, node0.getBindingConfig(), node0.getStorageDB(), null); NetworkAddress peerSrvAddr1 = new NetworkAddress("127.0.0.1", 13210); - PeerTestRunner peer1 = new PeerTestRunner(peerSrvAddr1, node1.getBindingConfig(), node1.getStorageDB()); + PeerTestRunner peer1 = new PeerTestRunner(peerSrvAddr1, node1.getBindingConfig(), node1.getStorageDB(), null); NetworkAddress peerSrvAddr2 = new NetworkAddress("127.0.0.1", 13220); - PeerTestRunner peer2 = new PeerTestRunner(peerSrvAddr2, node2.getBindingConfig(), node2.getStorageDB()); + PeerTestRunner peer2 = new PeerTestRunner(peerSrvAddr2, node2.getBindingConfig(), node2.getStorageDB(), null); NetworkAddress peerSrvAddr3 = new NetworkAddress("127.0.0.1", 13230); - PeerTestRunner peer3 = new PeerTestRunner(peerSrvAddr3, node3.getBindingConfig(), node3.getStorageDB()); + PeerTestRunner peer3 = new PeerTestRunner(peerSrvAddr3, node3.getBindingConfig(), node3.getStorageDB(), null); AsyncCallback peerStarting0 = peer0.start(); AsyncCallback peerStarting1 = peer1.start(); diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest2.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest2.java index 683ed91f..3512d6b0 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest2.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTest2.java @@ -64,16 +64,16 @@ public class IntegrationTest2 { Node node3 = context.getNode(3); NetworkAddress peerSrvAddr0 = new NetworkAddress("127.0.0.1", 13200); - PeerTestRunner peer0 = new PeerTestRunner(peerSrvAddr0, node0.getBindingConfig(), node0.getStorageDB()); + PeerTestRunner peer0 = new PeerTestRunner(peerSrvAddr0, node0.getBindingConfig(), node0.getStorageDB(), null); NetworkAddress peerSrvAddr1 = new NetworkAddress("127.0.0.1", 13210); - PeerTestRunner peer1 = new PeerTestRunner(peerSrvAddr1, node1.getBindingConfig(), node1.getStorageDB()); + PeerTestRunner peer1 = new PeerTestRunner(peerSrvAddr1, node1.getBindingConfig(), node1.getStorageDB(), null); NetworkAddress peerSrvAddr2 = new NetworkAddress("127.0.0.1", 13220); - PeerTestRunner peer2 = new PeerTestRunner(peerSrvAddr2, node2.getBindingConfig(), node2.getStorageDB()); + PeerTestRunner peer2 = new PeerTestRunner(peerSrvAddr2, node2.getBindingConfig(), node2.getStorageDB(), null); NetworkAddress peerSrvAddr3 = new NetworkAddress("127.0.0.1", 13230); - PeerTestRunner peer3 = new PeerTestRunner(peerSrvAddr3, node3.getBindingConfig(), node3.getStorageDB()); + PeerTestRunner peer3 = new PeerTestRunner(peerSrvAddr3, node3.getBindingConfig(), node3.getStorageDB(), null); AsyncCallback peerStarting0 = peer0.start(); AsyncCallback peerStarting1 = peer1.start(); diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestDataAccount.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestDataAccount.java index e029dc09..c62ee9c4 100644 --- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestDataAccount.java +++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/IntegrationTestDataAccount.java @@ -78,16 +78,16 @@ public class IntegrationTestDataAccount { Node node3 = context.getNode(3); NetworkAddress peerSrvAddr0 = new NetworkAddress("127.0.0.1", 14200); - PeerTestRunner peer0 = new PeerTestRunner(peerSrvAddr0, node0.getBindingConfig(), node0.getStorageDB()); + PeerTestRunner peer0 = new PeerTestRunner(peerSrvAddr0, node0.getBindingConfig(), node0.getStorageDB(), null); NetworkAddress peerSrvAddr1 = new NetworkAddress("127.0.0.1", 14210); - PeerTestRunner peer1 = new PeerTestRunner(peerSrvAddr1, node1.getBindingConfig(), node1.getStorageDB()); + PeerTestRunner peer1 = new PeerTestRunner(peerSrvAddr1, node1.getBindingConfig(), node1.getStorageDB(), null); NetworkAddress peerSrvAddr2 = new NetworkAddress("127.0.0.1", 14220); - PeerTestRunner peer2 = new PeerTestRunner(peerSrvAddr2, node2.getBindingConfig(), node2.getStorageDB()); + PeerTestRunner peer2 = new PeerTestRunner(peerSrvAddr2, node2.getBindingConfig(), node2.getStorageDB(), null); NetworkAddress peerSrvAddr3 = new NetworkAddress("127.0.0.1", 14230); - PeerTestRunner peer3 = new PeerTestRunner(peerSrvAddr3, node3.getBindingConfig(), node3.getStorageDB()); + PeerTestRunner peer3 = new PeerTestRunner(peerSrvAddr3, node3.getBindingConfig(), node3.getStorageDB(), null); AsyncCallback peerStarting0 = peer0.start(); AsyncCallback peerStarting1 = peer1.start();